using Furion.DependencyInjection; using Furion.DynamicApiController; using Furion.FriendlyException; using Furion.RemoteRequest.Extensions; using Furion.UnifyResult; using Mapster; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Myshipping.Application.Entity; using Myshipping.Application.Service.ExpressDelivery.Dto; using Myshipping.Core; using Myshipping.Core.Attributes; using Myshipping.Core.Service; using Newtonsoft.Json.Linq; using SqlSugar; using StackExchange.Profiling.Internal; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace Myshipping.Application { /// /// 快递订单服务 /// [ApiDescriptionSettings("Application", Name = "ExpressDelivery", Description = "快递订单服务", Order = 20)] [Route("/ExpressDelivery")] public class ExpressDeliveryService : IExpressDeliveryService, IDynamicApiController, ITransient { private const string STATUS_ASSOCIATION = "关联快递订单"; private const string STATUS_DISASSOCIATION = "取消关联快递订单"; private const string STATUS_DELETE = "关联快递订单已删除"; private const string STATUS_SEND = "快递下单"; private const string STATUS_CANCEL = "快递消单"; private readonly ILogger _logger; private readonly ISysCacheService _cache; private readonly SqlSugarRepository _bookingStatuslogRep; private readonly SqlSugarRepository _bookingOrderRep; private readonly SqlSugarRepository _orderRep; private readonly SqlSugarRepository _businessRep; private readonly SqlSugarRepository _statusRep; private readonly SqlSugarRepository _addressRep; public ExpressDeliveryService(ILogger logger, ISysCacheService cache, SqlSugarRepository bookingStatuslogRep, SqlSugarRepository bookingOrderRep, SqlSugarRepository orderRep, SqlSugarRepository businessRep, SqlSugarRepository statusRep, SqlSugarRepository templeteRep) { _logger = logger; _cache = cache; _orderRep = orderRep; _businessRep = businessRep; _statusRep = statusRep; _bookingStatuslogRep = bookingStatuslogRep; _bookingOrderRep = bookingOrderRep; _addressRep = templeteRep; } /// /// 分页查询快递主表 /// /// /// [HttpGet("Page")] public async Task Page([FromQuery] ExpressDeliveryInput input) { var entities = await _orderRep.AsQueryable().Filter(null, true) .Where(x => x.TenantId == UserManager.TENANT_ID && x.IsDeleted == false) .WhereIF(!string.IsNullOrWhiteSpace(input.KDNO), u => u.KDNO.Contains(input.KDNO)) .WhereIF(!string.IsNullOrWhiteSpace(input.SJCompany), u => u.KDNO.Contains(input.SJCompany)) .WhereIF(!string.IsNullOrWhiteSpace(input.SJPeople), u => u.KDNO.Contains(input.SJPeople)) .WhereIF(!string.IsNullOrWhiteSpace(input.SJTel), u => u.KDNO.Contains(input.SJTel)) .WhereIF(!string.IsNullOrWhiteSpace(input.FJCompany), u => u.KDNO.Contains(input.FJCompany)) .WhereIF(!string.IsNullOrWhiteSpace(input.FJPeople), u => u.KDNO.Contains(input.FJPeople)) .WhereIF(!string.IsNullOrWhiteSpace(input.FJTel), u => u.KDNO.Contains(input.FJTel)) .WhereIF(!string.IsNullOrWhiteSpace(input.VESSEL), u => u.KDNO.Contains(input.VESSEL)) .WhereIF(!string.IsNullOrWhiteSpace(input.VOYNO), u => u.KDNO.Contains(input.VOYNO)) .WhereIF(input.BDate != null, u => u.Date >= input.BDate) .WhereIF(input.EDate != null, u => u.Date <= input.EDate) .OrderBy(PageInputOrder.OrderBuilder(input.SortField, input.DescSort)) .ToPagedListAsync(input.PageNo, input.PageSize); var list = entities.Adapt>(); foreach (var item in list.Items) { item.Business = await _businessRep.AsQueryable().Filter(null, true).Where(x => x.PId == item.Id).ToListAsync(); } return list; } /// /// 保存并返回数据 /// /// [HttpPost("Save")] [JoinValidateMessge] public async Task Save(ExpressDeliveryDto input) { var entity = input.Adapt(); string logGuid = Guid.NewGuid().ToString(); _logger.LogInformation($"快递订单保存操作开始,{logGuid}"); if (input.Id == 0) { entity.CurrentStateCode = "DJY01"; entity.CurrentStateDesc = "新建"; _logger.LogInformation($"快递订单新增操作开始,{logGuid}"); await _orderRep.InsertAsync(entity); if (input.Business != null && input.Business.Count > 0) { #region 保存关联的业务信息 _logger.LogInformation($"快递订单新增关联的业务信息,{logGuid}"); input.Business.ForEach(b => b.PId = entity.Id); await _businessRep.InsertAsync(input.Business); #endregion #region 向与快递关联的订舱列表中添加动态 List mblNoList = input.Business.Select(b => b.MBLNO).ToList(); await InsertNewBookingStatusWithMblnoList(mblNoList, STATUS_ASSOCIATION); #endregion } // 添加快递动态 _logger.LogInformation($"快递订单新增快递动态,{logGuid}"); var status = new ExpressDeliveryStatus() { OrderId = entity.Id, MailNo = "", StatusCode = entity.CurrentStateCode, StatusDesc = entity.CurrentStateDesc }; await _statusRep.InsertAsync(status); } else { _logger.LogInformation($"快递订单修改操作开始,{logGuid}"); await _orderRep.AsUpdateable(entity).IgnoreColumns(it => new { it.CurrentStateCode, it.CurrentStateDesc, it.TenantId, it.CreatedTime, it.CreatedUserId, it.CreatedUserName, }).ExecuteCommandAsync(); #region 向与快递关联的订舱列表中添加动态,并新增或更新业务信息 List businessList = await _businessRep.AsQueryable().Where(x => x.PId == input.Id).ToListAsync(); if (businessList.Count == 0) { if (input.Business?.Count != 0) { // 直接得到:要关联快递的提单号列表 List mblNoList = input.Business.Select(b => b.MBLNO).ToList(); await InsertNewBookingStatusWithMblnoList(mblNoList, STATUS_ASSOCIATION); // 直接得到:要新增的业务信息 input.Business.ForEach(b => b.PId = entity.Id); await _businessRep.InsertAsync(input.Business); } } else { if (input.Business?.Count == 0) { // 直接得到:要取消关联快递的提单号列表 List mblNoList = businessList.Select(b => b.MBLNO).ToList(); await InsertNewBookingStatusWithMblnoList(mblNoList, STATUS_DISASSOCIATION); // 直接得到:要删除的业务信息 await _businessRep.DeleteAsync(x => x.PId == entity.Id); } else { // 分析对比,判断哪些关联,哪些取消关联 List oldMblnoList = businessList.Select(b => b.MBLNO).ToList(); List newMblnoList = input.Business.Select(b => b.MBLNO).ToList(); // 新增关联的提单号列表: List addMblnoList = newMblnoList.Except(oldMblnoList).ToList(); await InsertNewBookingStatusWithMblnoList(addMblnoList, STATUS_ASSOCIATION); // 取消关联的提单号列表 List cancelMblnoList = oldMblnoList.Except(newMblnoList).ToList(); await InsertNewBookingStatusWithMblnoList(cancelMblnoList, STATUS_DISASSOCIATION); // 先删除,再新增业务信息 await _businessRep.DeleteAsync(x => x.PId == entity.Id); input.Business.ForEach(b => b.PId = entity.Id); await _businessRep.InsertAsync(input.Business); } } #endregion } return Get(entity.Id); } /// /// 删除单据 /// /// /// [SqlSugarUnitOfWork] [HttpPost("Delete")] public async Task Delete(string Ids) { var arr = Ids.Split(","); if (arr.Length > 0) { foreach (var ar in arr) { long Id = Convert.ToInt64(ar); ExpressDeliveryOrder order = await _orderRep.AsQueryable(e => e.Id == Id).FirstAsync() ?? throw Oops.Bah("未找到快递订单"); // 添加快递动态 var status = new ExpressDeliveryStatus() { OrderId = Id, MailNo = order.KDNO, StatusCode = "DJY04", StatusDesc = "快递单已删除" }; await _statusRep.InsertAsync(status); // 更新快递订单表 await _orderRep.UpdateAsync(x => x.Id == Id, x => new ExpressDeliveryOrder { IsDeleted = true, CurrentStateCode = status.StatusCode, CurrentStateDesc = status.StatusDesc }); // 快递关联的订舱添加动态 List mblnoList = await _businessRep.AsQueryable(x => x.PId == Id).Select(b => b.MBLNO).ToListAsync(); await InsertNewBookingStatusWithMblnoList(mblnoList, STATUS_DELETE); // 删除快递关联的业务表数据 await _businessRep.DeleteAsync(x => x.PId == Id); } } else { throw Oops.Bah("请上传正确参数"); } } /// /// 获取详情 /// /// /// [HttpPost("Get")] public async Task Get(long Id) { ExpressDeliveryDto ordOut = new ExpressDeliveryDto(); var main = await _orderRep.FirstOrDefaultAsync(u => u.Id == Id); if (main != null) { ordOut = main.Adapt(); var business = await _businessRep.AsQueryable().Where(x => x.PId == Id).ToListAsync(); ordOut.Business = business; } return ordOut; } /// /// 发送快递 /// /// /// [HttpPost("SendBooking")] public async Task SendBooking(long Id) { var rt = String.Empty; SFSendBooking sFSend = new SFSendBooking(); var order = _orderRep.FirstOrDefault(x => x.Id == Id); if (order == null) { throw Oops.Bah("请选择正确数据!"); } sFSend.orderId = Id.ToString(); sFSend.language = "zh_CN"; List cargo = new List(); cargo.Add(new CargoDetailsItem { count = (int)order.KDNum, name = order.GOODSNAME }); List contactList = new List(); contactList.Add(new ContactInfoListItem { address = $"{order.FJProvince}{order.FJCity}{order.FJAddress}", contact = order.FJPeople, contactType = 1, country = "CN", //postCode = order.FJPostCode, tel = order.FJTel, }); contactList.Add(new ContactInfoListItem { address = $"{order.SJProvince}{order.SJCity}{order.SJAddress}", contact = order.SJPeople, contactType = 2, country = "CN", //postCode = order.SJPostCode, tel = order.SJTel, }); sFSend.contactInfoList = contactList; sFSend.cargoDetails = cargo; (string url, Dictionary dict) apiParam = await CreateSFApiParams("EXP_RECE_CREATE_ORDER", sFSend); _logger.LogInformation("调用顺丰下单接口,参数:" + apiParam.dict.ToJson()); var strRtn = await apiParam.url.SetBody(apiParam.dict, "application/x-www-form-urlencoded").PostAsStringAsync(); //var strRtn = "{\"apiErrorMsg\":\"\",\"apiResponseID\":\"00018BF4CE37D63FDF38696876F68A3F\",\"apiResultCode\":\"A1000\",\"apiResultData\":\"{\\\"success\\\":true,\\\"errorCode\\\":\\\"S0000\\\",\\\"errorMsg\\\":null,\\\"msgData\\\":{\\\"orderId\\\":\\\"485172445380677\\\",\\\"originCode\\\":\\\"759\\\",\\\"destCode\\\":\\\"886\\\",\\\"filterResult\\\":2,\\\"remark\\\":\\\"\\\",\\\"url\\\":null,\\\"paymentLink\\\":null,\\\"isUpstairs\\\":null,\\\"isSpecialWarehouseService\\\":null,\\\"mappingMark\\\":null,\\\"agentMailno\\\":null,\\\"returnExtraInfoList\\\":null,\\\"waybillNoInfoList\\\":[{\\\"waybillType\\\":1,\\\"waybillNo\\\":\\\"SF7444473840720\\\",\\\"boxNo\\\":null,\\\"length\\\":null,\\\"width\\\":null,\\\"height\\\":null,\\\"weight\\\":null,\\\"volume\\\":null}],\\\"routeLabelInfo\\\":[{\\\"code\\\":\\\"1000\\\",\\\"routeLabelData\\\":{\\\"waybillNo\\\":\\\"SF7444473840720\\\",\\\"sourceTransferCode\\\":\\\"759VA\\\",\\\"sourceCityCode\\\":\\\"759\\\",\\\"sourceDeptCode\\\":\\\"759\\\",\\\"sourceTeamCode\\\":\\\"\\\",\\\"destCityCode\\\":\\\"886\\\",\\\"destDeptCode\\\":\\\"886\\\",\\\"destDeptCodeMapping\\\":\\\"\\\",\\\"destTeamCode\\\":\\\"\\\",\\\"destTeamCodeMapping\\\":\\\"\\\",\\\"destTransferCode\\\":\\\"886WA\\\",\\\"destRouteLabel\\\":\\\"886WA-886\\\",\\\"proName\\\":\\\"\\\",\\\"cargoTypeCode\\\":\\\"C201\\\",\\\"limitTypeCode\\\":\\\"T4\\\",\\\"expressTypeCode\\\":\\\"B1\\\",\\\"codingMapping\\\":\\\"WU\\\",\\\"codingMappingOut\\\":\\\"\\\",\\\"xbFlag\\\":\\\"0\\\",\\\"printFlag\\\":\\\"000000000\\\",\\\"twoDimensionCode\\\":\\\"MMM={'k1':'886WA','k2':'886','k3':'','k4':'T4','k5':'SF7444473840720','k6':'','k7':'ce37f885'}\\\",\\\"proCode\\\":\\\"特快\\\",\\\"printIcon\\\":\\\"00000000\\\",\\\"abFlag\\\":\\\"\\\",\\\"destPortCode\\\":null,\\\"destCountry\\\":null,\\\"destPostCode\\\":null,\\\"goodsValueTotal\\\":\\\"\\\",\\\"currencySymbol\\\":null,\\\"cusBatch\\\":\\\"\\\",\\\"goodsNumber\\\":null,\\\"errMsg\\\":\\\"\\\",\\\"checkCode\\\":\\\"ce37f885\\\",\\\"proIcon\\\":\\\"\\\",\\\"fileIcon\\\":\\\"\\\",\\\"fbaIcon\\\":\\\"\\\",\\\"icsmIcon\\\":\\\"\\\",\\\"destGisDeptCode\\\":\\\"886\\\",\\\"newIcon\\\":null,\\\"sendAreaCode\\\":null,\\\"destinationStationCode\\\":null,\\\"sxLabelDestCode\\\":null,\\\"sxDestTransferCode\\\":null,\\\"sxCompany\\\":null,\\\"newAbFlag\\\":null,\\\"destAddrKeyWord\\\":\\\"\\\",\\\"rongType\\\":null,\\\"waybillIconList\\\":null},\\\"message\\\":\\\"SF7444473840720:\\\"}],\\\"contactInfoList\\\":null,\\\"sendStartTm\\\":null,\\\"customerRights\\\":null,\\\"expressTypeId\\\":null}}\"}"; _logger.LogInformation("调用顺丰下单接口,返回:" + strRtn); var jobj = strRtn.ToJObject(); if (jobj.GetStringValue("apiResultCode") == "A1000") { var resultDataObj = jobj.GetStringValue("apiResultData").ToJObject(); bool isSuccess = resultDataObj.GetBooleanValue("success"); if (isSuccess) { rt = "下单成功!"; var waybillNoInfoObj = resultDataObj.GetJObjectValue("msgData").GetJArrayValue("waybillNoInfoList")[0].Value(); var waybillNo = waybillNoInfoObj.GetStringValue("waybillNo"); string statusDesc = $"{STATUS_SEND}(单号:{waybillNo})"; #region 添加快递动态 var status = new ExpressDeliveryStatus() { OrderId = Id, MailNo = waybillNo, StatusCode = "DJY02", StatusDesc = statusDesc }; await _statusRep.InsertAsync(status); #endregion UnifyContext.Fill(new { KDNO = waybillNo, currentStateCode = status.StatusCode, currentStateDesc = status.StatusDesc }); #region 为与快递关联的订舱添加动态 List mblnoList = await _businessRep.AsQueryable(b => b.PId == Id).Select(b => b.MBLNO).ToListAsync(); await InsertNewBookingStatusWithMblnoList(mblnoList, statusDesc); #endregion #region 向快递订单表反写快递单号与状态 ExpressDeliveryOrder updateOrder = new ExpressDeliveryOrder() { Id = Id, KDNO = waybillNo, CurrentStateCode = status.StatusCode, CurrentStateDesc = status.StatusDesc, }; await _orderRep.AsUpdateable(updateOrder) .UpdateColumns(o => new { o.KDNO, o.CurrentStateCode, o.CurrentStateDesc }) .ExecuteCommandAsync(); #endregion #region 地址簿维护 await SaveOrUpdateAddress(new ExpressDeliveryAddressDto() { Address = order.SJAddress, City = order.SJCity, Company = order.SJCompany, People = order.SJPeople, Province = order.SJProvince, ProvinceId = order.SJProvinceId, Tel = order.SJTel }); await SaveOrUpdateAddress(new ExpressDeliveryAddressDto() { Address = order.FJAddress, City = order.FJCity, Company = order.FJCompany, People = order.FJPeople, Province = order.FJProvince, ProvinceId = order.FJProvinceId, Tel = order.FJTel }); #endregion } else { var errorMsg = resultDataObj.GetStringValue("errorMsg"); _logger.LogInformation("调用顺丰下单接口,返回异常,errorMsg:" + errorMsg); throw Oops.Bah(errorMsg); } } else { var apiErrorMsg = jobj.GetStringValue("apiErrorMsg"); _logger.LogInformation("调用顺丰下单接口,返回异常,apiErrorMsg:" + apiErrorMsg); throw Oops.Bah(apiErrorMsg); } return rt; } /// /// 取消快递下单 /// /// /// [HttpPost("CancelBooking")] public async Task CancelBooking(long Id) { var param = new { dealType = 2, orderId = Id }; (string url, Dictionary dict) apiParam = await CreateSFApiParams("EXP_RECE_UPDATE_ORDER", param); _logger.LogInformation("调用顺丰订单取消接口,参数:" + apiParam.dict.ToJson()); var strRtn = await apiParam.url.SetBody(apiParam.dict, "application/x-www-form-urlencoded").PostAsStringAsync(); //var strRtn = "{\"apiErrorMsg\":\"\",\"apiResponseID\":\"00018BF5250ADD3FEE59BC8A2F42CE3F\",\"apiResultCode\":\"A1000\",\"apiResultData\":\"{\\\"success\\\":true,\\\"errorCode\\\":\\\"S0000\\\",\\\"errorMsg\\\":null,\\\"msgData\\\":{\\\"orderId\\\":\\\"485172445380677\\\",\\\"waybillNoInfoList\\\":[{\\\"waybillType\\\":1,\\\"waybillNo\\\":\\\"SF7444473840720\\\"}],\\\"resStatus\\\":2,\\\"extraInfoList\\\":null}}\"}"; _logger.LogInformation("调用顺丰订单取消接口,返回:" + strRtn); var jobj = strRtn.ToJObject(); if (jobj.GetStringValue("apiResultCode") == "A1000") { var resultDataObj = jobj.GetStringValue("apiResultData").ToJObject(); if (resultDataObj.GetBooleanValue("success")) { ExpressDeliveryOrder order = await _orderRep.AsQueryable(e => e.Id == Id).FirstAsync(); #region 添加快递动态 var status = new ExpressDeliveryStatus() { OrderId = Id, MailNo = order.KDNO, StatusCode = "DJY03", StatusDesc = STATUS_CANCEL }; await _statusRep.InsertAsync(status); #endregion #region 为与快递关联的订舱添加动态 List mblnoList = await _businessRep.AsQueryable(b => b.PId == Id).Select(b => b.MBLNO).ToListAsync(); await InsertNewBookingStatusWithMblnoList(mblnoList, STATUS_CANCEL); #endregion #region 更新快递订单状态 ExpressDeliveryOrder updateOrder = new ExpressDeliveryOrder() { Id = Id, CurrentStateCode = status.StatusCode, CurrentStateDesc = status.StatusDesc, }; await _orderRep.AsUpdateable(updateOrder) .UpdateColumns(o => new { o.CurrentStateCode, o.CurrentStateDesc }) .ExecuteCommandAsync(); #endregion return "取消成功"; } else { var errorMsg = resultDataObj.GetStringValue("errorMsg"); _logger.LogInformation("顺丰取消快递下单接口,返回异常,errorMsg:" + errorMsg); throw Oops.Bah(errorMsg); } } else { var apiErrorMsg = jobj.GetStringValue("apiErrorMsg"); _logger.LogInformation("顺丰取消快递下单接口,返回异常:" + apiErrorMsg); throw Oops.Bah(apiErrorMsg); } } /// /// 订单结果查询接口 /// /// /// [HttpPost("QueryKDSchedule")] public async Task QueryKDSchedule(long Id) { var rt = String.Empty; var json = new { orderId = Id.ToString() }; (string url, Dictionary dict) apiParam = await CreateSFApiParams("EXP_RECE_SEARCH_ORDER_RESP", json); _logger.LogInformation("调用顺丰订单结果查询接口,参数:" + apiParam.dict.ToJson()); var strRtn = await apiParam.url.SetBody(apiParam.dict, "application/x-www-form-urlencoded").PostAsStringAsync(); _logger.LogInformation("调用顺丰订单结果查询接口,返回:" + strRtn); var jobj = strRtn.ToJObject(); if (jobj.GetStringValue("apiResultCode") == "A1000") { var resultDataObj = jobj.GetStringValue("apiResultData").ToJObject(); if (resultDataObj.GetBooleanValue("success")) { rt = jobj.GetStringValue("apiResultData").ToJsonString(); } else { throw Oops.Bah(resultDataObj.GetStringValue("errorMsg")); } } else { throw Oops.Bah(jobj.GetStringValue("apiErrorMsg")); } return rt; } /// /// 获取顺丰API接口调用参数 /// /// [NonAction] private async Task<(string url, Dictionary param)> CreateSFApiParams(string serviceCode, object msgData) { var cacheDictData = await _cache.GetAllDictData(); var url = cacheDictData.FirstOrDefault(x => x.TypeCode == "url_set" && x.Code == "sf_api_url")?.Value; if (string.IsNullOrEmpty(url)) { throw Oops.Bah("需配置顺丰Api接口字典参数:url地址(sf_api_url)"); } var partnerId = cacheDictData.FirstOrDefault(x => x.TypeCode == "SFCode" && x.Code == "partnerId")?.Value; if (string.IsNullOrEmpty(partnerId)) { throw Oops.Bah("需配置顺丰Api接口字典参数:合作伙伴编码,即顾客编码(partnerId)"); } string accessToken; if (_cache.Exists($"SFToken{UserManager.TENANT_ID}")) { accessToken = _cache.Get($"SFToken{UserManager.TENANT_ID}"); } else { var secret = cacheDictData.FirstOrDefault(x => x.TypeCode == "SFCode" && x.Code == "secret")?.Value; if (string.IsNullOrEmpty(partnerId)) { throw Oops.Bah("需配置顺丰Api接口字典参数:合作伙伴密钥,即校验码(secret)"); } var getTokenParam = new Dictionary() { { "partnerID",partnerId }, { "grantType", "password"}, { "secret", secret} }; _logger.LogInformation("调用顺丰Token查询接口,参数:" + getTokenParam.ToJson()); var strRtn = await (url + "/oauth2/accessToken").SetBody(getTokenParam, "application/x-www-form-urlencoded").PostAsStringAsync(); _logger.LogInformation("调用顺丰Token查询接口,返回:" + strRtn); var jobj = strRtn.ToJObject(); if (jobj.GetStringValue("apiResultCode") == "A1000") { accessToken = jobj.GetStringValue("accessToken"); //设置token过期时间2小时 await _cache.SetTimeoutAsync($"SFToken{UserManager.TENANT_ID}", accessToken, TimeSpan.FromHours(2)); } else { throw Oops.Bah("调用顺丰Token查询接口时发生异常:" + jobj.GetStringValue("apiErrorMsg")); } } var dict = new Dictionary() { { "partnerID", partnerId }, { "serviceCode", serviceCode}, { "requestID", Guid.NewGuid().ToString()}, { "timestamp", DateTimeOffset.Now.ToUnixTimeSeconds()}, { "accessToken", accessToken}, { "msgData", msgData} }; return (url + "/std/service", dict); } /// /// 根据提单号列表,向与之快递关联的订舱动态中,添加快递动态 /// /// 需要添加快递动态的提单号列表 /// 快递动态描述 /// 日志标志 [NonAction] private async Task InsertNewBookingStatusWithMblnoList(List mblnoList, string status, string logGuid = "") { if (mblnoList == null || mblnoList.Count == 0) { _logger.LogInformation($"快递订单关联订舱增加动态,{logGuid},mblNoList为空,return"); return; } _logger.LogInformation($"快递订单关联订舱增加动态,{logGuid},mblNoList:{string.Join(',', mblnoList)}"); List filteredList = mblnoList.Where(m => !string.IsNullOrWhiteSpace(m)).ToList(); // 如果提单号为空,则不进行处理 if (filteredList == null || filteredList.Count == 0) { return; } var bookingIdMapMblnoList = await _bookingOrderRep.AsQueryable(o => o.ParentId == 0 && filteredList.Contains(o.MBLNO)) .Select(o => new { o.Id, o.MBLNO }) .ToListAsync(); var bookingStatusLogList = new List(); foreach (string mblNo in filteredList) { var bookingOrderIdListTemp = bookingIdMapMblnoList.Where(o => o.MBLNO == mblNo); if (bookingOrderIdListTemp == null) { _logger.LogInformation($"根据提单号{mblNo}查询订舱记录主键结果为空,{logGuid}"); continue; } else if (bookingOrderIdListTemp.Count() > 1) { _logger.LogInformation($"根据提单号{mblNo}查询订舱记录主键时查出多条记录,ids:{string.Join(',', bookingOrderIdListTemp.Select(b => b.Id).ToArray())},{logGuid}"); continue; } long? bookingOrderId = bookingOrderIdListTemp.First().Id; _logger.LogInformation($"根据提单号{mblNo}查询订舱记录主键为{bookingOrderId},{logGuid}"); bookingStatusLogList.Add(new BookingStatusLog() { BookingId = bookingOrderId, Status = status, Category = "kuaidi", OpTime = DateTime.Now, MBLNO = mblNo }); } if (bookingStatusLogList.Count > 0) { await _bookingStatuslogRep.InsertAsync(bookingStatusLogList); } } /// /// 接收顺丰推送的快递动态 /// [AllowAnonymous] [NonUnify] [HttpPost("AddSfStatus")] public async Task AddSfStatus(SFAddOrderStatus orderStatus) { string logGuid = Guid.NewGuid().ToString(); _logger.LogInformation($"接收到顺丰运踪动态,{logGuid},入参:{orderStatus?.ToJsonString()}"); var expressDeliveryStatusList = new List(); foreach (WaybillRoute item in orderStatus.Body.WaybillRoute) { expressDeliveryStatusList.Add(new ExpressDeliveryStatus() { OrderId = long.Parse(item.Orderid), AcceptAddress = item.AcceptAddress, AcceptTime = string.IsNullOrEmpty(item.AcceptTime) ? null : DateTime.Parse(item.AcceptTime), ErrorCode = item.ReasonCode, ErrorDesc = item.ReasonName, MailNo = item.Mailno, StatusId = item.Id, StatusCode = item.OpCode, StatusDesc = item.Remark }); } IEnumerable> statusGroupList = expressDeliveryStatusList.GroupBy(e => e.OrderId); foreach (IGrouping item in statusGroupList) { long? orderId = item.Key; ExpressDeliveryStatus lastStatus = item.MaxBy(e => e.StatusId); ExpressDeliveryOrder order = await _orderRep.AsQueryable(e => e.Id == orderId) .Filter(null, true) .FirstAsync(); if (order == null) { _logger.LogInformation($"未找到相应的快递订单,{logGuid},Id:{orderId}"); continue; } #region 更新快递订单当前的状态 _logger.LogInformation($"当前快递订单的状态,{logGuid},Code:{order.CurrentStateCode},Desc:{order.CurrentStateDesc}"); // 因为此方法为匿名方法,所以需要手动设置一下租户Id expressDeliveryStatusList.Where(s => s.OrderId == orderId).ToList().ForEach(e => e.TenantId = order.TenantId); Lazy> waitUpdate = new(() => _orderRep.Context.Updateable()); if (order.CurrentStateCode != lastStatus.StatusCode) { waitUpdate.Value.SetColumns(o => o.CurrentStateCode == lastStatus.StatusCode); } if (order.CurrentStateDesc != lastStatus.StatusDesc) { waitUpdate.Value.SetColumns(o => o.CurrentStateDesc == lastStatus.StatusDesc); } if (waitUpdate.IsValueCreated) { _logger.LogInformation($"快递订单的状态更新为,{logGuid},Code:{lastStatus.StatusCode},Desc:{lastStatus.StatusDesc}"); await waitUpdate.Value.Where(e => e.Id == orderId).ExecuteCommandAsync(); } #endregion #region 向与快递关联的订舱列表中添加动态(如果一票快递关联了多条订舱,则每条订舱都要添加动态) List mblNoList = await _businessRep.AsQueryable(b => b.PId == orderId && b.TenantId == order.TenantId).Filter(null, true).Select(b => b.MBLNO).ToListAsync(); List filteredList = mblNoList.Where(m => !string.IsNullOrWhiteSpace(m)).ToList(); if (filteredList == null) { _logger.LogInformation($"根据快递订单主键查询关联业务表的提单号,查询结果为空,{logGuid}"); } else { _logger.LogInformation($"根据快递订单主键查询关联业务表的提单号,共查出以下记录,MblNos:{string.Join(',', filteredList)},{logGuid}"); var bookingIdMapMblnoList = await _bookingOrderRep.AsQueryable(o => o.ParentId == 0 && o.TenantId == order.TenantId && filteredList.Contains(o.MBLNO)) .Filter(null, true) .Select(o => new { o.Id, o.MBLNO }) .ToListAsync(); var bookingStatusLogList = new List(); foreach (string mblnoItem in filteredList) { var bookingOrderIdListTemp = bookingIdMapMblnoList.Where(o => o.MBLNO == mblnoItem); if (bookingOrderIdListTemp == null) { _logger.LogInformation($"根据提单号{mblnoItem}查询订舱记录主键结果为空,{logGuid}"); continue; } else if (bookingOrderIdListTemp.Count() > 1) { _logger.LogInformation($"根据提单号{mblnoItem}查询订舱记录主键时查出多条记录,ids:{string.Join(',', bookingOrderIdListTemp.Select(b => b.Id).ToArray())},{logGuid}"); continue; } long? bookingOrderId = bookingOrderIdListTemp.First().Id; _logger.LogInformation($"根据提单号{mblnoItem}查询订舱记录主键为{bookingOrderId},{logGuid}"); foreach (ExpressDeliveryStatus statusItem in item) { bookingStatusLogList.Add(new BookingStatusLog() { BookingId = bookingOrderId, Status = statusItem.StatusDesc, Category = "kuaidi", OpTime = DateTime.Now, MBLNO = bookingOrderIdListTemp.First().MBLNO, TenantId = order.TenantId }); } } await _bookingStatuslogRep.InsertAsync(bookingStatusLogList); } #endregion } #region 保存快递动态 // 如果租户Id不为null或0,说明有相应的快递订单,这种情况再进行新增 expressDeliveryStatusList = expressDeliveryStatusList.Where(e => e.TenantId != null && e.TenantId != 0).ToList(); if (expressDeliveryStatusList != null && expressDeliveryStatusList.Count > 0) { await _statusRep.InsertAsync(expressDeliveryStatusList); } #endregion return new { return_code = "0000", return_msg = "成功" }; } #region 地址簿相关 /// /// 获取快递地址簿列表 /// [HttpGet("GetAddressList")] public async Task> GetAddressList() { var modelList = await _addressRep.ToListAsync(); var result = modelList.Adapt>(); return result; } /// /// 删除快递地址簿 /// [HttpPost("DeleteAddress")] public async Task DeleteAddress([Required] string ids) { long[] idArr = ids.Split(',').Adapt(); await _addressRep.DeleteAsync(a => idArr.Contains(a.Id)); } /// /// 新增或修改地址簿(根据联系人名称和手机号确定唯一) /// [HttpPost("SaveOrUpdateAddress")] public async Task SaveOrUpdateAddress(ExpressDeliveryAddressDto input) { if (input == null) return; var existsAddress = await _addressRep.FirstOrDefaultAsync(a => a.People == input.People && a.Tel == input.Tel); if (existsAddress == null) { // 新增 var model = input.Adapt(); await _addressRep.InsertAsync(model); } else { // 更新 var model = input.Adapt(); model.Id = existsAddress.Id; await _addressRep.AsUpdateable(model) .IgnoreColumns(a => a.TenantId) .ExecuteCommandAsync(); } } #endregion } }