using DS.Module.Core; using DS.Module.Core.Constants; using DS.Module.DjyServiceStatus; using DS.Module.SqlSugar; using DS.Module.UserModule; using DS.WMS.Core.Info.Interface; using DS.WMS.Core.Map.Dtos; using DS.WMS.Core.Map.Interface; using DS.WMS.Core.Op.Dtos; using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Op.Interface; using DS.WMS.Core.Sys.Interface; using DS.WMS.Core.TaskPlat.Dtos; using DS.WMS.Core.TaskPlat.Entity; using DS.WMS.Core.TaskPlat.Interface; using Mapster; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace DS.WMS.Core.TaskPlat.Method { /// /// 任务台-BC子任务 /// public class TaskManageBCService : TaskManageBaseService, ITaskManageBCService { private readonly IConfigService configService; private readonly IClientInfoService clientInfoService; private readonly IMappingCarrierService mappingCarrierService; private readonly IBookingSlotService bookingSlotService; private readonly IOpFileService opFileService; public TaskManageBCService(IUser user, ILogger logger, ISaasDbService saasDbService, IServiceProvider serviceProvider, IWebHostEnvironment environment, IConfigService configService, IClientInfoService clientInfoService, IMappingCarrierService mappingCarrierService, IOpFileService opFileService) : base(user, logger, saasDbService, serviceProvider, environment) { this.configService = configService; this.clientInfoService = clientInfoService; this.mappingCarrierService = mappingCarrierService; this.opFileService = opFileService; } /// /// 通过任务信息(BC)生成订舱或舱位 /// /// 生成订舱或者舱位请求 /// 返回回执 public async Task> CreateBookingAndSlot(BookingOrSlotGenerateDto model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); logger.LogInformation($"接收生成订舱或舱位请求,参数{JsonConvert.SerializeObject(model)}"); try { /* 1、GEN_BOOKING_SLOT-生成舱位和订舱 (1)生成舱位 (2)生成海运订舱 (3)更新舱位库存 (4)更新BC任务 2、GEN_BOOKING-只生成订舱 (1)生成海运订舱 (4)更新BC任务 3、GEN_SLOT-只生成舱位 (1)生成舱位 (4)更新BC任务 3、GEN_SLOT-只生成舱位 (1)查找订舱记录 (3)更新舱位库存 (4)更新BC任务 */ if (model.BCTaskId == 0) throw new Exception($"BC任务主键不能为空"); //生成方式(GEN_BOOKING_SLOT-生成舱位和订舱;GEN_BOOKING-只生成订舱;GEN_SLOT-只生成舱位;GEN_EXIST_BOOKING-匹配指定的订舱) if (string.IsNullOrWhiteSpace(model.GenerateMethod)) throw new Exception($"生成方式不能为空,需要指定一种生成方式"); var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId); var bcTaskInfo = await tenantDb.Queryable().Where(u => u.Id == model.BCTaskId).FirstAsync(); if (bcTaskInfo == null) { throw new Exception($"任务主键{model.BCTaskId}无法获取业务信息"); } var bcOrder = await tenantDb.Queryable().Where(a => a.TASK_ID == bcTaskInfo.Id).FirstAsync(); if (bcOrder == null) throw new Exception($"任务主键{model.BCTaskId}无法获取BC业务信息"); var bcCtnList = await tenantDb.Queryable().Where(a => a.P_ID == bcOrder.Id).ToListAsync(); var fileList = await tenantDb.Queryable().Where(a => a.TASK_PKID == bcTaskInfo.Id).ToListAsync(); if (model.GenerateMethod != "UPD_BOOKING") { if (bcOrder.BOOKING_ORDER_ID.HasValue && bcOrder.BOOKING_ORDER_ID.Value > 0) { throw new Exception($"当前BC任务已生成订舱订单,不能重复生成"); } } if (model.GenerateMethod == "GEN_BOOKING_SLOT") { #region 推送舱位、推送订舱 //推送舱位 //long bookingSlotId = 0; BookingSlotBase? bookingSlot = null; if (bcOrder.BOOKING_SLOT_ID.HasValue && bcOrder.BOOKING_SLOT_ID.Value > 0) { //bookingSlotId = bcOrder.BOOKING_SLOT_ID.Value; throw new Exception($"生成舱位失败,舱位已存在"); } //这里增加委托单位联系人的校验,重新从后台拉取了委托单位相关联系人,如果比对不一致跳出异常终止执行 var paramConfig = configService.GetConfig(TenantParamCode.CONST_CREATE_BOOKING_NEED_CONTACT, long.Parse(user.TenantId), false).GetAwaiter().GetResult()?.Data?.Value; if (model.CustomerContactList != null && model.CustomerContactList.Count > 0) { //取委托客户下面所有的联系人列表 var djyCustomerInfo = clientInfoService.GetClientInfoWithContact(new Info.Dtos.QueryClientInfo { ClientId = model.CustomerId.Value, IsController = true }).GetAwaiter().GetResult().Data; if (djyCustomerInfo == null) { logger.LogInformation($"委托单位{model.CustomerName} 获取失败,委托单位不存在或已作废 SlotId={model.SlotId.Value}"); //委托单位{0} 获取失败,委托单位不存在或已作废 throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotCreateContaNull)), model.CustomerName)); } if (djyCustomerInfo.ClientContactList == null && djyCustomerInfo.ClientContactList.Count < 1) { logger.LogInformation($"委托单位{model.CustomerName} 获取相关联系人失败,委托单位相关联系人为空 SlotId={model.SlotId.Value}"); //委托单位{0} 获取相关联系人失败,委托单位相关联系人为空 throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotCreateCustomerContractInfoNull)), model.CustomerName)); } model.CustomerContactList.ForEach(contact => { var djyCustomerContactMan = djyCustomerInfo.ClientContactList .FirstOrDefault(a => a.Id == contact.CustomerContactId); if (djyCustomerContactMan == null) { logger.LogInformation($"委托单位{model.CustomerName} 联系人 {contact.Name}获取失败,联系人不存在或已作废 SlotId={model.SlotId.Value}"); //委托单位 {0} 联系人 {1} 获取失败,联系人不存在或已作废 throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotCreateCustomerContractDeletedOrNoExists)), model.CustomerName, contact.Name)); } }); } else { if (paramConfig != null && paramConfig.Equals("ENABLE", StringComparison.OrdinalIgnoreCase)) { //生成订舱时往来单位联系人必填,请修改 throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotCreateCustomerContractNotNull))); } } //触发生成舱位 bookingSlot = await GenerateBookingSlotByTaskBcInfo(bcOrder, bcCtnList, fileList); logger.LogInformation($"生成舱位完成,bookingSlotId={bookingSlot?.Id} taskid={bcOrder.TASK_ID}"); if (bookingSlot == null || bookingSlot.Id == 0) throw new Exception($"生成舱位失败"); var slotFileList = opFileService.GetOpFileList(bookingSlot.Id.ToString()).Data; //推送订舱订单 var bookingOrderId = await bookingSlotService.GenerateBookingOrder(bookingSlot, slotFileList, model, null); logger.LogInformation($"生成订舱订单完成,bookingOrderId={bookingOrderId} taskid={bcOrder.TASK_ID}"); if (bookingOrderId < 1) throw new Exception($"生成订舱订单失败"); List slots = new List(); //检索舱位信息 var slotInfo = (await bookingSlotService.Detail(bookingSlot.Id)).Data; BookingSlotBaseWithCtnDto baseInfo = slotInfo.Adapt(); baseInfo.Id = bookingSlot.Id; baseInfo.CtnList = slotInfo.CtnList.Adapt>(); slots.Add(baseInfo); //对应订舱和舱位关系 //var allocRlt = await bookingSlotService.ImportSlots(slots, bookingOrderId, false); //_logger.LogInformation($"生成订舱和舱位关系完成,allocRlt={JSON.Serialize(allocRlt)} taskid={bcOrder.TASK_ID}"); //if (!allocRlt.isSuccess) //{ // throw Oops.Oh($"生成订舱和舱位关系失败"); //} //var bcEntity = _taskBCInfoRepository.AsQueryable().First(a => a.PK_ID == bcOrder.PK_ID); //if (bcEntity == null) //{ // throw Oops.Oh($"未获取有效任务BC失败,更新失败"); //} //bcEntity.BOOKING_ORDER_ID = bookingOrderId; //bcEntity.BOOKING_SLOT_ID = bookingSlotId; //bcEntity.UpdatedTime = DateTime.Now; //bcEntity.UpdatedUserId = UserManager.UserId; //bcEntity.UpdatedUserName = UserManager.Name; ////更新任务BC //await _taskBCInfoRepository.AsUpdateable(bcEntity).UpdateColumns(it => new //{ // it.BOOKING_ORDER_ID, // it.BOOKING_SLOT_ID, // it.UpdatedTime, // it.UpdatedUserId, // it.UpdatedUserName //}).ExecuteCommandAsync(); //var taskEntity = _taskBaseRepository.AsQueryable().First(u => u.PK_ID == bcEntity.TASK_ID); //if (taskEntity == null) //{ // throw Oops.Oh($"未获取有效任务记录,更新失败"); //} //#region 更新任务 ////如果是公共任务,需要变成个人任务 RealUserId = 当前操作人 //if (taskEntity.IS_PUBLIC == 1) //{ // taskEntity.IS_PUBLIC = 0; // taskEntity.RealUserId = UserManager.UserId; // taskEntity.RealUserName = UserManager.Name; // taskEntity.UpdatedTime = DateTime.Now; // taskEntity.UpdatedUserId = UserManager.UserId; // taskEntity.UpdatedUserName = UserManager.Name; // taskEntity.IS_COMPLETE = 1; // taskEntity.COMPLETE_DATE = DateTime.Now; // taskEntity.COMPLETE_DEAL = "MANUAL"; // taskEntity.COMPLETE_DEAL = "手工"; // await _taskBaseRepository.AsUpdateable(taskEntity).UpdateColumns(it => new // { // it.IS_PUBLIC, // it.UpdatedTime, // it.UpdatedUserId, // it.UpdatedUserName, // it.RealUserId, // it.RealUserName, // it.IS_COMPLETE, // it.COMPLETE_DATE, // it.COMPLETE_DEAL, // it.COMPLETE_DEAL_NAME // }).ExecuteCommandAsync(); //} //else //{ // taskEntity.UpdatedTime = DateTime.Now; // taskEntity.UpdatedUserId = UserManager.UserId; // taskEntity.UpdatedUserName = UserManager.Name; // taskEntity.IS_COMPLETE = 1; // taskEntity.COMPLETE_DATE = DateTime.Now; // taskEntity.COMPLETE_DEAL = "MANUAL"; // taskEntity.COMPLETE_DEAL = "手工"; // await _taskBaseRepository.AsUpdateable(taskEntity).UpdateColumns(it => new // { // it.UpdatedTime, // it.UpdatedUserId, // it.UpdatedUserName, // it.IS_COMPLETE, // it.COMPLETE_DATE, // it.COMPLETE_DEAL, // it.COMPLETE_DEAL_NAME // }).ExecuteCommandAsync(); //} //#endregion //var currBCOrder = _taskBCInfoRepository.AsQueryable().First(a => a.PK_ID == bcEntity.PK_ID); //if (currBCOrder != null && model.IsDirectSend) //{ // //异步推送邮件 // var mailRlt = await GenerateSendEmail(currBCOrder, bcTaskInfo, model.usePersonalEmailSend); // if (!mailRlt.succ) // { // throw Oops.Oh($"邮件推送失败,原因:{mailRlt.msg},可以任务编辑页面重新发送邮件"); // } //} #endregion } return DataResult.Success(result); } catch (Exception ex) { result.succ = false; result.msg = $"生成订舱或舱位失败,原因:{ex.Message}"; return DataResult.FailedData(result); } } /// /// 通过任务主键获取BC详情 /// /// BC任务主键 public async Task> GetInfoByTaskId(long taskId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var tenantDb = saasDbService.GetBizDbScopeById(user.TenantId); var taskBase = await tenantDb.Queryable().FirstAsync(a => a.Id == taskId); if (taskBase == null) throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TaskBaseEmpty))); var bcOrder = await tenantDb.Queryable().FirstAsync(a => a.TASK_ID == taskId); if (bcOrder == null) throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.TaskBCInfoEmpty))); var bcCtnList = await tenantDb.Queryable().Where(a => a.P_ID == bcOrder.Id).ToListAsync(); TaskBCShowBaseDto model = bcOrder.Adapt(); if (bcCtnList.Count > 0) model.CtnList = bcCtnList.Adapt>(); var fileList = await tenantDb.Queryable().Where(a => a.TASK_PKID == bcOrder.TASK_ID).ToListAsync(); if (fileList.Count > 0) model.FileList = fileList.Adapt>(); model.taskStatus = taskBase.STATUS; //生成关键信息 #region 生成关键信息 model.Keywords = new List(); if (bcOrder.CARRIAGE_TYPE == "DIRECT_SHIP") { model.Keywords.Add(new TaskBCShowBaseKeywordDto() { Name = $"承运方式:{bcOrder.CARRIAGE_TYPE_NAME}", Background = "#FFFF80", Icon = "icon-yunshu1" }); } else if (bcOrder.CARRIAGE_TYPE == "TRANSFER_SHIP") { model.Keywords.Add(new TaskBCShowBaseKeywordDto() { Name = $"承运方式:{bcOrder.CARRIAGE_TYPE_NAME}", Background = "#CAF982", Icon = "icon-shuaxin" }); } if (bcOrder.BOOKING_SLOT_TYPE == "CONTRACT_ORDER") { model.Keywords.Add(new TaskBCShowBaseKeywordDto() { Name = $"订舱方式:{bcOrder.BOOKING_SLOT_TYPE_NAME}", Background = "#81D3F8", Icon = "icon-touzijilu" }); } else if (bcOrder.BOOKING_SLOT_TYPE == "SPOT_ORDER") { model.Keywords.Add(new TaskBCShowBaseKeywordDto() { Name = $"订舱方式:{bcOrder.BOOKING_SLOT_TYPE_NAME}", Background = "#FACD91", Icon = "icon-beizhu1" }); } #endregion //await SetTaskStatus([taskId], x => x.IS_PUBLIC == 1, x => x.IS_EXCEPT == 0); //await SetTaskOwner([taskId], new List() //{ // new RecvUserInfo(111,"231312321"), // new RecvUserInfo(222,"affsdfdsf"), //}); result.succ = true; result.ext = model; //如果当前BC有对应记录,则读取订舱详情 //0726:经确认页面上没有用到订舱详情,所以暂时不返回 //if (bcOrder.BOOKING_ORDER_ID.HasValue) //{ // var bkOrder = await _bookingOrderRepository.AsQueryable(). // FirstAsync(a => a.Id == bcOrder.BOOKING_ORDER_ID.Value); // if (bkOrder != null) // { // var showBKOrder = bkOrder.Adapt(); // var ctnList = await _bookingCtnRepository.AsQueryable(). // Where(a => a.BILLID == bkOrder.Id).ToListAsync(); // if (ctnList.Count > 0) // showBKOrder.ctnInputs = ctnList.Adapt>(); // result.ext2 = showBKOrder; // } //} } catch (Exception ex) { result.succ = false; result.msg = $"获取BC详情异常,原因:{ex.Message}"; } return DataResult.Success(result); } #region 根据BC任务信息生成舱位 /// /// 根据BC任务信息,生成舱位(调用的) /// /// BC任务详情 /// BC任务集装箱列表 /// BC任务附件列表 /// 返回舱位ID private async Task GenerateBookingSlotByTaskBcInfo(TaskBCInfo taskBCInfo, List taskBCCtnList, List taskFileList, string opType = "add") { //long id = 0; try { var allMapCarrierList = await mappingCarrierService.GetAllList(); MappingCarrierRes? carrierInfo = null; if (allMapCarrierList.Succeeded) { carrierInfo = allMapCarrierList.Data.Where(t => t.MapCode.Equals(taskBCInfo.CARRIERID, StringComparison.OrdinalIgnoreCase) && t.Module == MappingModuleConst.CONST_MAPPING_CARRIER_MODULE).FirstOrDefault(); } BookingSlotBaseApiDto slotModel = new BookingSlotBaseApiDto { DataObj = new BookingSlotBaseApiSaveDto { CarrierId = carrierInfo?.LinkId, CarrierCode = carrierInfo?.MapCode, Carrier = carrierInfo?.MapName, SlotBookingNo = taskBCInfo.MBL_NO, BookingParty = taskBCInfo.BOOKING_PARTY, BookingSlotType = taskBCInfo.BOOKING_SLOT_TYPE, BookingSlotTypeName = taskBCInfo.BOOKING_SLOT_TYPE_NAME, Vessel = taskBCInfo.VESSEL, Voyno = taskBCInfo.VOYNO, VGMSubmissionCutDate = taskBCInfo.VGM_CUTOFF_TIME, //WeekAt = taskBCInfoDto.WEEK_AT, CarriageType = taskBCInfo.CARRIAGE_TYPE, CarriageTypeName = taskBCInfo.CARRIAGE_TYPE_NAME, ContractNo = taskBCInfo.CONTRACTNO, CtnStat = taskBCInfo.CTN_STAT, CYCutDate = taskBCInfo.CY_CUTOFF_TIME, DetensionFreeDays = taskBCInfo.DETENSION_FREE_DAYS, ETD = taskBCInfo.ETD, ETA = taskBCInfo.ETA, LaneCode = taskBCInfo.LANECODE, LaneName = taskBCInfo.LANENAME, ManifestCutDate = taskBCInfo.MANIFEST_CUT_DATE, MDGFCutDate = taskBCInfo.MDGF_CUT_DATE, PlaceDelivery = taskBCInfo.PLACEDELIVERY, PlaceReceipt = taskBCInfo.PLACERECEIPT, PortDischarge = taskBCInfo.PORTDISCHARGE, PortLoad = taskBCInfo.PORTLOAD, SICutDate = taskBCInfo.SI_CUT_DATE, CustomSICutDate = taskBCInfo.CUSTOM_SI_CUT_DATE, TransferPort1 = taskBCInfo.TRANSFER_PORT_1, TransferPort2 = taskBCInfo.TRANSFER_PORT_2, PriceCalculationDate = taskBCInfo.PRICE_CALCULATION_DATE, CtnList = new List() }, OpType = "add" }; if (int.TryParse(taskBCInfo.WEEK_AT, out int _weekat)) { slotModel.DataObj.WeekAt = _weekat; } //var ctnCodeList = _cache.GetAllCodeCtn().GetAwaiter().GetResult().ToList(); if (taskBCCtnList.Count > 0) { taskBCCtnList.ForEach(t => { //var ctnCode = ctnCodeList.FirstOrDefault(a => !string.IsNullOrWhiteSpace(a.Name) && //a.Name.Equals(t.CTNALL, StringComparison.OrdinalIgnoreCase)); BookingSlotCtnSaveInput ctn = new BookingSlotCtnSaveInput { //CTNCODE = ctnCode?.Code, CtnAll = t.CTNALL, CtnNum = t.CTNNUM.HasValue ? t.CTNNUM.Value : 1 }; slotModel.DataObj.CtnList.Add(ctn); }); } var basePath = AppSetting.app(new string[] { "FileSettings", "BasePath" }); DynameFileInfo dynameFile = null; DynameFileInfo dynameNoticeFile = null; if (taskFileList.Any(t => t.FILE_CATEGORY == TaskFileCategoryEnum.BC.ToString())) { var fileInfo = taskFileList.FirstOrDefault(t => t.FILE_CATEGORY == TaskFileCategoryEnum.BC.ToString()); string fileFullPath; if (string.IsNullOrEmpty(basePath)) { fileFullPath = Path.Combine(environment.WebRootPath ?? "", fileInfo.FILE_PATH); } else { fileFullPath = Path.Combine(basePath, fileInfo.FILE_PATH); } dynameFile = new DynameFileInfo { FileBytes = File.ReadAllBytes(fileFullPath), FileName = Path.GetFileName(fileFullPath) }; } if (taskFileList.Any(t => t.FILE_CATEGORY == TaskFileCategoryEnum.BC_NOTICE.ToString())) { var fileInfo = taskFileList.FirstOrDefault(t => t.FILE_CATEGORY == TaskFileCategoryEnum.BC.ToString()); string fileFullPath; if (string.IsNullOrEmpty(basePath)) { fileFullPath = Path.Combine(environment.WebRootPath ?? "", fileInfo.FILE_PATH); } else { fileFullPath = Path.Combine(basePath, fileInfo.FILE_PATH); } dynameNoticeFile = new DynameFileInfo { FileBytes = File.ReadAllBytes(fileFullPath), FileName = Path.GetFileName(fileFullPath) }; } var result = await bookingSlotService.InnerApiReceive(slotModel, dynameFile, dynameNoticeFile); return result.Data; } catch (Exception ex) { logger.LogError($"任务BC MBLNO:{taskBCInfo.MBL_NO} 生成舱位异常,原因:{ex.Message}"); throw new Exception($"MBLNO:{taskBCInfo.MBL_NO} 生成舱位异常,原因:{ex.Message}"); } } #endregion //public virtual async Task<(bool canCompelete, string? msg)> CompleteAsync(long taskId) //{ // return (true, null); //} } }