diff --git a/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs b/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs index 7a1133db..5f8981c7 100644 --- a/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs +++ b/ds-wms-service/DS.Module.Core/Constants/MultiLanguageConst.cs @@ -1173,5 +1173,108 @@ public static class MultiLanguageConst [Description("合约作废未提供主键ID")] public const string BookingContractDeleteIdsNull = "BookingContract_Delete_IdsNull"; + /// + /// 部分舱位信息提取失败,请确认舱位是否存在或已作废 + /// + [Description("部分舱位信息提取失败,请确认舱位是否存在或已作废")] + public const string BookingSlotMergeCheckPartRecordDeletedOrNoExists = "BookingContract_MergeCheck_PartRecord_DeletedOrNoExists"; + + /// + /// 舱位合票校验失败,部分舱位的以下信息船公司、船名场次、合约号、承运方式、订舱方式、装货地、卸货地有空值情况 + /// + [Description("舱位合票校验失败,部分舱位的以下信息船公司、船名场次、合约号、承运方式、订舱方式、装货地、卸货地有空值情况")] + public const string BookingSlotMergeCheckPartRecordNoConsistent = "BookingContract_MergeCheck_PartRecord_NoConsistent"; + + /// + /// 舱位合票校验失败,船公司、船名场次、合约号、承运方式、订舱方式、装货地、卸货地不统一不能合票 + /// + [Description("舱位合票校验失败,船公司、船名场次、合约号、承运方式、订舱方式、装货地、卸货地不统一不能合票")] + public const string BookingSlotMergeCheckPartRecordNoConsistentFail = "BookingContract_MergeCheck_PartRecord_NoConsistent_Fail"; + + /// + /// 舱位合票失败,校验库存为不可用,请确认正确的库存 + /// + [Description("舱位合票失败,校验库存为不可用,请确认正确的库存")] + public const string BookingSlotMergeCheckStockEmpty = "BookingContract_MergeCheck_StockEmpty"; + + /// + /// 舱位合票失败,舱位提单号:{0} 缺少库存 + /// + [Description("舱位合票失败,舱位提单号:{0} 缺少库存")] + public const string BookingSlotMergeFailShortStock = "BookingContract_MergeFail_ShortStock"; + + /// + /// 单号【{0}】含有 {1} + /// + [Description("单号【{0}】含有 {1}")] + public const string BookingSlotMergeSpecialNotice = "BookingContract_Merge_SpecialNotice"; + + /// + /// 请选择委托单位 + /// + [Description("请选择委托单位")] + public const string BookingSlotCreateCustomerNull = "BookingSlot_Create_CustomerNull"; + + /// + /// 请选择要使用的箱信息 + /// + [Description("请选择要使用的箱信息")] + public const string BookingSlotCreateContaNull = "BookingSlot_Create_ContaNull"; + + /// + /// 舱位ID不能为空 + /// + [Description("舱位ID不能为空")] + public const string BookingSlotCreateSlotIdNull = "BookingSlot_Create_SlotIdNull"; + + /// + /// 舱位数据不存在或已作废 + /// + [Description("舱位数据不存在或已作废")] + public const string BookingSlotCreateRecordDeletedOrNoExists = "BookingSlot_Create_Recrod_DeleteOr_NoExists"; + + /// + /// 委托单位{0} 获取失败,委托单位不存在或已作废 + /// + [Description("委托单位{0} 获取失败,委托单位不存在或已作废")] + public const string BookingSlotCreateCustomerDeletedOrNoExists = "BookingSlot_Create_Customer_DeleteOr_NoExists"; + + /// + /// 委托单位{0} 获取相关联系人失败,委托单位相关联系人为空 + /// + [Description("委托单位{0} 获取相关联系人失败,委托单位相关联系人为空")] + public const string BookingSlotCreateCustomerContractInfoNull = "BookingSlot_Create_Customer_ContractInfoNull"; + + /// + /// 委托单位 {0} 联系人 {1} 获取失败,联系人不存在或已作废 + /// + [Description("委托单位 {0} 联系人 {1} 获取失败,联系人不存在或已作废")] + public const string BookingSlotCreateCustomerContractDeletedOrNoExists = "BookingSlot_Create_Customer_ContractDeletedOrNoExists"; + + /// + /// 生成订舱时往来单位联系人必填,请修改 + /// + [Description("生成订舱时往来单位联系人必填,请修改")] + public const string BookingSlotCreateCustomerContractNotNull = "BookingSlot_Create_Customer_ContractNotNull"; + + /// + /// 订舱主键{0}已引用舱位 + /// + [Description("订舱主键{0}已引用舱位")] + public const string BookingSlotHasImportSlots = "BookingSlot_HasImportSlots"; + + /// + /// 获取的历史拆票后缀异常,maxChar={0} + /// + [Description("订舱主键{0}已引用舱位")] + public const string BookingSlotSplitMergeCheckError = "BookingSlot_SplitMerge_CheckError"; + + /// + /// 舱位提单号:{0} 已有订舱记录不能重复操作 + /// + [Description("舱位提单号:{0} 已有订舱记录不能重复操作")] + public const string BookingSlotSplitMergeHasOrder = "BookingSlot_SplitMerge_HasOrder"; + + #endregion } \ No newline at end of file diff --git a/ds-wms-service/DS.WMS.Core/Info/Dtos/ClientInfoRes.cs b/ds-wms-service/DS.WMS.Core/Info/Dtos/ClientInfoRes.cs index 9b393f63..7a828e5e 100644 --- a/ds-wms-service/DS.WMS.Core/Info/Dtos/ClientInfoRes.cs +++ b/ds-wms-service/DS.WMS.Core/Info/Dtos/ClientInfoRes.cs @@ -400,4 +400,9 @@ public class ClientInfoRes /// 客户标识 /// public ClientTagRes ClientTag { get; set; } + + /// + /// 联系人列表 + /// + public List ClientContactList { get; set; } } \ No newline at end of file diff --git a/ds-wms-service/DS.WMS.Core/Info/Dtos/QueryClientInfo.cs b/ds-wms-service/DS.WMS.Core/Info/Dtos/QueryClientInfo.cs new file mode 100644 index 00000000..6e4488d2 --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Info/Dtos/QueryClientInfo.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DS.WMS.Core.Info.Dtos +{ + /// + /// 检索往来单位 + /// + public class QueryClientInfo + { + /// + /// 客户Id + /// + public long ClientId { get; set; } + + /// + /// Desc:是否特批放单客户 + /// + public bool IsSpecialApproval { get; set; } = false; + /// + /// Desc:是否船公司 + /// + public bool IsCarrier { get; set; } = false; + + /// + /// Desc:是否订舱公司 + /// + public bool IsBooking { get; set; } = false; + + /// + /// Desc:是否场站 + /// + public bool IsYard { get; set; } = false; + + /// + /// Desc:是否车队 + /// + public bool IsTruck { get; set; } = false; + + /// + /// Desc:是否委托单位 + /// + public bool IsController { get; set; } = false; + + /// + /// Desc:是否报关行 + /// + public bool IsCustom { get; set; } = false; + + /// + /// Desc:是否代理(国外) + /// + public bool IsAgent { get; set; } = false; + + /// + /// Desc:是否代理(国内) + /// + public bool IsAgentCn { get; set; } = false; + + /// + /// Desc:是否快递公司 + /// + public bool IsExpress { get; set; } = false; + + /// + /// Desc:是否航空公司 + /// + public bool IsAirLines { get; set; } = false; + + /// + /// Desc:是否发货人 + /// + public bool IsShipper { get; set; } = false; + + /// + /// Desc:是否收货人 + /// + public bool IsConsignee { get; set; } = false; + + /// + /// Desc:是否通知人 + /// + public bool IsNotifyParty { get; set; } = false; + + /// + /// Desc:是否仓库 + /// + public bool IsWareHouse { get; set; } = false; + + + /// + /// Desc:是否码头 + /// + public bool IsWharf { get; set; } = false; + + /// + /// Desc:是否保险公司 + /// + public bool IsInsurer { get; set; } = false; + + /// + /// Desc:是否租箱公司 + /// + public bool IsLeasing { get; set; } = false; + + /// + /// Desc:是否贸易代理 + /// + public bool IsTradingAgency { get; set; } = false; + + /// + /// Desc:是否其他 + /// + public bool IsOther { get; set; } = false; + + /// + /// Desc:其他类型 + /// + public string Others { get; set; } + + + /// + /// Desc:是否船代 + /// + public bool IsShipAgency { get; set; } = false; + + /// + /// Desc:是否经营单位 + /// + public bool IsEnterprise { get; set; } = false; + } +} diff --git a/ds-wms-service/DS.WMS.Core/Info/Interface/IClientInfoService.cs b/ds-wms-service/DS.WMS.Core/Info/Interface/IClientInfoService.cs index f253a54e..9b11d75c 100644 --- a/ds-wms-service/DS.WMS.Core/Info/Interface/IClientInfoService.cs +++ b/ds-wms-service/DS.WMS.Core/Info/Interface/IClientInfoService.cs @@ -36,4 +36,11 @@ public interface IClientInfoService /// /// public DataResult BatchDelClientInfo(IdModel req); + + /// + /// 获取往来单位详情(含有联系人列表) + /// + /// 查询往来单位 + /// 返回往来单位详情 + Task> GetClientInfoWithContact(QueryClientInfo query); } \ No newline at end of file diff --git a/ds-wms-service/DS.WMS.Core/Info/Method/ClientInfoService.cs b/ds-wms-service/DS.WMS.Core/Info/Method/ClientInfoService.cs index 596a4ba9..9b74c09f 100644 --- a/ds-wms-service/DS.WMS.Core/Info/Method/ClientInfoService.cs +++ b/ds-wms-service/DS.WMS.Core/Info/Method/ClientInfoService.cs @@ -13,6 +13,7 @@ using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Sys.Entity; using Mapster; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Owin.Security.Provider; using SqlSugar; namespace DS.WMS.Core.Info.Method; @@ -176,4 +177,61 @@ public class ClientInfoService : IClientInfoService } return DataResult.Successed("删除成功!", MultiLanguageConst.DataDelSuccess); } + + #region 获取往来单位详情(含有联系人列表) + /// + /// 获取往来单位详情(含有联系人列表) + /// + /// 查询往来单位 + /// 返回往来单位详情 + public async Task> GetClientInfoWithContact(QueryClientInfo query) + { + var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + + var data = await tenantDb.Queryable().InnerJoin((c,t)=> c.Id == t.ClientId) + .Where((c,t)=> c.Id == query.ClientId) + .WhereIF(query.IsController,(c,t)=>t.IsController.HasValue && t.IsController.HasValue) + .WhereIF(query.IsSpecialApproval, (c, t) => t.IsSpecialApproval.HasValue && t.IsSpecialApproval.HasValue) + .WhereIF(query.IsCarrier, (c, t) => t.IsCarrier.HasValue && t.IsCarrier.HasValue) + .WhereIF(query.IsBooking, (c, t) => t.IsBooking.HasValue && t.IsBooking.HasValue) + .WhereIF(query.IsYard, (c, t) => t.IsYard.HasValue && t.IsYard.HasValue) + .WhereIF(query.IsTruck, (c, t) => t.IsTruck.HasValue && t.IsTruck.HasValue) + .WhereIF(query.IsController, (c, t) => t.IsController.HasValue && t.IsController.HasValue) + .WhereIF(query.IsCustom, (c, t) => t.IsCustom.HasValue && t.IsCustom.HasValue) + .WhereIF(query.IsAgent, (c, t) => t.IsAgent.HasValue && t.IsAgent.HasValue) + .WhereIF(query.IsAgentCn, (c, t) => t.IsAgentCn.HasValue && t.IsAgentCn.HasValue) + .WhereIF(query.IsExpress, (c, t) => t.IsExpress.HasValue && t.IsExpress.HasValue) + .WhereIF(query.IsAirLines, (c, t) => t.IsAirLines.HasValue && t.IsAirLines.HasValue) + .WhereIF(query.IsShipper, (c, t) => t.IsShipper.HasValue && t.IsShipper.HasValue) + .WhereIF(query.IsConsignee, (c, t) => t.IsConsignee.HasValue && t.IsConsignee.HasValue) + .WhereIF(query.IsNotifyParty, (c, t) => t.IsNotifyParty.HasValue && t.IsNotifyParty.HasValue) + .WhereIF(query.IsWareHouse, (c, t) => t.IsWareHouse.HasValue && t.IsWareHouse.HasValue) + .WhereIF(query.IsWharf, (c, t) => t.IsWharf.HasValue && t.IsWharf.HasValue) + .WhereIF(query.IsInsurer, (c, t) => t.IsInsurer.HasValue && t.IsInsurer.HasValue) + .WhereIF(query.IsLeasing, (c, t) => t.IsLeasing.HasValue && t.IsLeasing.HasValue) + .WhereIF(query.IsTradingAgency, (c, t) => t.IsTradingAgency.HasValue && t.IsTradingAgency.HasValue) + .WhereIF(query.IsOther, (c, t) => t.IsOther.HasValue && t.IsOther.HasValue) + .WhereIF(!string.IsNullOrWhiteSpace(query.Others), (c, t) => t.Others == query.Others) + .WhereIF(query.IsShipAgency, (c, t) => t.IsShipAgency.HasValue && t.IsShipAgency.HasValue) + .WhereIF(query.IsEnterprise, (c, t) => t.IsEnterprise.HasValue && t.IsEnterprise.HasValue) + + .Select((c,t)=> new { Client = c, tag = t }) + .FirstAsync(); + + var clientInfo = data.Client.Adapt(); + + clientInfo.ClientTag = data.tag.Adapt(); + + var contactList = tenantDb.Queryable() + .Where(a => a.ClientId == clientInfo.Id && a.Status == StatusEnum.Enable).ToList(); + + if (contactList.Count > 0) + clientInfo.ClientContactList = contactList.Adapt>(); + + if (clientInfo == null) + return DataResult.FailedData(clientInfo); + + return DataResult.Success(clientInfo); + } + #endregion } \ No newline at end of file diff --git a/ds-wms-service/DS.WMS.Core/Op/Dtos/BookingSlot/SqlSugarPagedList.cs b/ds-wms-service/DS.WMS.Core/Op/Dtos/BookingSlot/SqlSugarPagedList.cs new file mode 100644 index 00000000..e477b567 --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Op/Dtos/BookingSlot/SqlSugarPagedList.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DS.WMS.Core.Op.Dtos +{ + /// + /// 分页泛型集合 + /// + /// + public class SqlSugarPagedList + { + /// + /// 页码 + /// + public int PageIndex { get; set; } + + /// + /// 页容量 + /// + public int PageSize { get; set; } + + /// + /// 总条数 + /// + public int TotalCount { get; set; } + + /// + /// 总页数 + /// + public int TotalPages { get; set; } + + /// + /// 当前页集合 + /// + public IEnumerable Items { get; set; } + + /// + /// 是否有上一页 + /// + public bool HasPrevPages { get; set; } + + /// + /// 是否有下一页 + /// + public bool HasNextPages { get; set; } + } + + /// + /// 分页集合 + /// + public class PagedModel : SqlSugarPagedList + { + } +} diff --git a/ds-wms-service/DS.WMS.Core/Op/Dtos/SeaExportReq.cs b/ds-wms-service/DS.WMS.Core/Op/Dtos/SeaExportReq.cs index 4fe79af7..bafab208 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Dtos/SeaExportReq.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Dtos/SeaExportReq.cs @@ -1024,6 +1024,11 @@ public class SeaExportReq /// 预付地点Id /// public long PayableAtId { get; set; } + + /// + /// 拆票或合票标志 1-拆票 2-合票 + /// + public int SplitOrMergeFlag { get; set; } } /// diff --git a/ds-wms-service/DS.WMS.Core/Op/Entity/BookingSlot/BookingSlotBase.cs b/ds-wms-service/DS.WMS.Core/Op/Entity/BookingSlot/BookingSlotBase.cs index a3f4a166..59c6d111 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Entity/BookingSlot/BookingSlotBase.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Entity/BookingSlot/BookingSlotBase.cs @@ -97,7 +97,13 @@ namespace DS.WMS.Core.Op.Entity /// 收货地代码 /// [SqlSugar.SugarColumn(ColumnDescription = "收货地代码", Length = 10, IsNullable = true)] - public string PlaceReceiptId { get; set; } + public string PlaceReceiptCode { get; set; } + + /// + /// 收货地主键 + /// + [SqlSugar.SugarColumn(ColumnDescription = "收货地主键", IsNullable = true)] + public Nullable PlaceReceiptId { get; set; } /// /// 收货地名称 @@ -109,7 +115,13 @@ namespace DS.WMS.Core.Op.Entity /// 交货地代码 /// [SqlSugar.SugarColumn(ColumnDescription = "交货地代码", Length = 10, IsNullable = true)] - public string PlaceDeliveryId { get; set; } + public string PlaceDeliveryCode { get; set; } + + /// + /// 交货地主键 + /// + [SqlSugar.SugarColumn(ColumnDescription = "交货地主键", IsNullable = true)] + public Nullable PlaceDeliveryId { get; set; } /// /// 交货地名称 @@ -121,7 +133,13 @@ namespace DS.WMS.Core.Op.Entity /// 装货港代码 /// [SqlSugar.SugarColumn(ColumnDescription = "装货港代码", Length = 10, IsNullable = true)] - public string PortLoadId { get; set; } + public string PortLoadCode { get; set; } + + /// + /// 装货港主键 + /// + [SqlSugar.SugarColumn(ColumnDescription = "装货港主键", Length = 10, IsNullable = true)] + public Nullable PortLoadId { get; set; } /// /// 装货港 @@ -133,7 +151,13 @@ namespace DS.WMS.Core.Op.Entity /// 卸货港代码 /// [SqlSugar.SugarColumn(ColumnDescription = "卸货港代码", Length = 10, IsNullable = true)] - public string PortDischargeId { get; set; } + public string PortDischargeCode { get; set; } + + /// + /// 卸货港主键 + /// + [SqlSugar.SugarColumn(ColumnDescription = "卸货港主键", Length = 10, IsNullable = true)] + public Nullable PortDischargeId { get; set; } /// /// 卸货港 @@ -153,6 +177,12 @@ namespace DS.WMS.Core.Op.Entity [SqlSugar.SugarColumn(ColumnDescription = "卸货港国家名称", Length = 120, IsNullable = true)] public string PortDischargeCountry { get; set; } + /// + /// 卸货港国家主键 + /// + [SqlSugar.SugarColumn(ColumnDescription = "卸货港国家主键", Length = 120, IsNullable = true)] + public Nullable PortDischargeCountryId { get; set; } + /// /// 中转港1 /// diff --git a/ds-wms-service/DS.WMS.Core/Op/Entity/BusinessOrderContact.cs b/ds-wms-service/DS.WMS.Core/Op/Entity/BusinessOrderContact.cs index 1204df34..3601a38c 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Entity/BusinessOrderContact.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Entity/BusinessOrderContact.cs @@ -52,5 +52,11 @@ namespace DS.WMS.Core.Op.Entity /// [SugarColumn(ColumnDescription = "邮箱", Length = 50, IsNullable = true)] public string Email { get; set; } + + /// + /// 联系人ID + /// + [SugarColumn(ColumnDescription = "联系人ID", IsNullable = true)] + public long CustomerContactId { get; set; } } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Entity/SeaExport.cs b/ds-wms-service/DS.WMS.Core/Op/Entity/SeaExport.cs index 71269f23..58103ae1 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Entity/SeaExport.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Entity/SeaExport.cs @@ -1344,4 +1344,11 @@ public class SeaExport : BaseOrgModel /// [SqlSugar.SugarColumn(ColumnDescription = "StartETA", IsNullable = true)] public DateTime? StartETA { get; set; } + + + /// + /// 拆票或合票标志 1-拆票 2-合票 + /// + [SqlSugar.SugarColumn(ColumnDescription = "拆票或合票标志 1-拆票 2-合票", IsNullable = true,DefaultValue = "0")] + public int SplitOrMergeFlag { get; set; } } \ No newline at end of file diff --git a/ds-wms-service/DS.WMS.Core/Op/Interface/BookingLabel/IBookingLabelService.cs b/ds-wms-service/DS.WMS.Core/Op/Interface/BookingLabel/IBookingLabelService.cs index 9e8b7593..14be1fec 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Interface/BookingLabel/IBookingLabelService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Interface/BookingLabel/IBookingLabelService.cs @@ -41,5 +41,12 @@ namespace DS.WMS.Core.Op.Interface /// 标签主键组 /// Task> Delete(long[] ids); + + /// + /// 标签管理台账 + /// + /// 查询条件 + /// 返回台账列表 + Task>> GetPageAsync(PageRequest QuerySearch); } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Interface/BookingSlot/IBookingSlotService.cs b/ds-wms-service/DS.WMS.Core/Op/Interface/BookingSlot/IBookingSlotService.cs index e14b0ecf..7b331d2e 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Interface/BookingSlot/IBookingSlotService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Interface/BookingSlot/IBookingSlotService.cs @@ -85,7 +85,7 @@ namespace DS.WMS.Core.Op.Interface /// /// 舱位主键 /// 返回附件列表 - Task> GetFile(long id); + Task>> GetFile(long id); /// /// 分页查询订舱舱位 diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/BookingLabel/BookingLabelService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/BookingLabel/BookingLabelService.cs index 18b6a33a..2e20744d 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/BookingLabel/BookingLabelService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/BookingLabel/BookingLabelService.cs @@ -22,6 +22,7 @@ using NLog; using DS.Module.RedisModule; using MySqlConnector.Logging; using Newtonsoft.Json; +using DS.Module.Core.Extensions; namespace DS.WMS.Core.Op.Method { @@ -125,20 +126,24 @@ namespace DS.WMS.Core.Op.Method } #endregion + #region 标签管理台账 + /// + /// 标签管理台账 + /// + /// 查询条件 + /// 返回台账列表 + public async Task>> GetPageAsync(PageRequest QuerySearch) + { + var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + //序列化查询条件 + var whereList = db.ConfigQuery.Context.Utilities.JsonToConditionalModels(QuerySearch.QueryCondition); - ///// - ///// 分页获取全部或指定范围类型的标签列表 - ///// - //public async Task> PageList(BookingLabelPageListInput input) - //{ - // var list = await _rep.AsQueryable() - // .WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name.Contains(input.Name)) - // .WhereIF(input.Scope != null, x => x.Scope == input.Scope) - // .ToPagedListAsync(input.PageNo, input.PageSize); - - // var result = list.Adapt>(); - // return result; - //} + var data = tenantDb.Queryable() + .Where(whereList) + .Select().ToQueryPage(QuerySearch.PageCondition); + return data; + } + #endregion #region 保存标签 /// diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotService.cs index 8bf03768..4e1cde58 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotService.cs @@ -32,6 +32,15 @@ using DS.WMS.Core.Code.Entity; using DS.WMS.Core.Map.Entity; using DS.WMS.Core.Code.Dtos; using System.Net.Http.Headers; +using DS.Module.DjyServiceStatus; +using NPOI.SS.UserModel; +using DS.WMS.Core.Info.Interface; +using Microsoft.Extensions.FileSystemGlobbing; +using DS.WMS.Core.Info.Entity; +using DS.WMS.Core.Info.Dtos; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using AngleSharp.Dom.Events; namespace DS.WMS.Core.Op.Method { @@ -47,6 +56,13 @@ namespace DS.WMS.Core.Op.Method private readonly ISysCacheService _sysCacheService; private readonly ISysFileService _sysFileService; private readonly IBookingSlotStockService _bookingSlotStockService; + private readonly IOpFileService _opFileService; + private readonly IConfigService _configService; + private readonly IClientContactService _clientContactService; + private readonly IClientInfoService _clientInfoService; + private readonly IDjyServiceStatusService _djyServiceStatusService; + private readonly IWebHostEnvironment _environment; + private readonly string bcCompareUrl; private static readonly NLog.Logger Logger = LogManager.GetCurrentClassLogger(); @@ -69,6 +85,11 @@ namespace DS.WMS.Core.Op.Method //交货地名称解析卸货港港口 const string DELIVERY_TO_PORT = "DeliveryToPort"; + //BC任务或舱位生成订舱订单时客户联系人必填 + const string CONST_CREATE_BOOKING_NEED_CONTACT = "BC_TASK_OR_SLOT_BOOKING_NEED_CONTACT"; + + //船公司基础映射模块 + const string CONST_MAPPING_CARRIER_MODULE = "CarrierBaseMapping"; public BookingSlotService(IServiceProvider serviceProvider) @@ -83,6 +104,10 @@ namespace DS.WMS.Core.Op.Method _sysCacheService = _serviceProvider.GetRequiredService(); _sysFileService = _serviceProvider.GetRequiredService(); _bookingSlotStockService = _serviceProvider.GetRequiredService(); + _opFileService = _serviceProvider.GetRequiredService(); + _configService = _serviceProvider.GetRequiredService(); + _djyServiceStatusService = _serviceProvider.GetRequiredService(); + _environment = _serviceProvider.GetRequiredService(); bcCompareUrl = AppSetting.app(new string[] { "BCCompare", "Url" }); } @@ -121,8 +146,8 @@ namespace DS.WMS.Core.Op.Method || oldObj.Voyno != model.Voyno || oldObj.BookingSlotType != model.BookingSlotType || oldObj.CarrierCode != model.CarrierCode - || oldObj.PortLoadId != model.PortLoadId - || oldObj.PortDischargeId != model.PortDischargeId) + || oldObj.PortLoadId != model.PortLoadCode + || oldObj.PortDischargeId != model.PortDischargeCode) { isNeedUpdateOldStock = true; } @@ -316,14 +341,14 @@ namespace DS.WMS.Core.Op.Method { DataObj = new BookingSlotBaseApiSaveDto { - PortDischargeId = model.PortDischargeId, + PortDischargeId = model.PortDischargeCode, PortDischarge = model.PortDischarge, - PortLoadId = model.PortLoadId, + PortLoadId = model.PortLoadCode, PortLoad = model.PortLoad, PlaceDelivery = model.PlaceDelivery, - PlaceDeliveryId = model.PlaceDeliveryId, + PlaceDeliveryId = model.PlaceDeliveryCode, PlaceReceipt = model.PlaceReceipt, - PlaceReceiptId = model.PlaceReceiptId, + PlaceReceiptId = model.PlaceReceiptCode, } }; @@ -1104,8 +1129,8 @@ namespace DS.WMS.Core.Op.Method || oldObj.Voyno != model.Voyno || oldObj.BookingSlotType != model.BookingSlotType || oldObj.CarrierId != model.CarrierId - || oldObj.PortLoadId != model.PortLoadId - || oldObj.PortDischargeId != model.PortDischargeId) + || oldObj.PortLoadId != model.PortLoadCode + || oldObj.PortDischargeId != model.PortDischargeCode) { isNeedUpdateOldStock = true; } @@ -1260,8 +1285,8 @@ namespace DS.WMS.Core.Op.Method ContractNo = model.ContractNo, Vessel = model.Vessel, Voyno = model.Voyno, - PortLoadId = model.PortLoadId, - PortDischargeId = model.PortDischargeId, + PortLoadId = model.PortLoadCode, + PortDischargeId = model.PortDischargeCode, TenantId = long.Parse(user.TenantId) }); } @@ -1278,7 +1303,6 @@ namespace DS.WMS.Core.Op.Method } #endregion - #region 异步写入附件表 /// /// 异步写入附件表 @@ -1560,5 +1584,957 @@ namespace DS.WMS.Core.Op.Method return model; } #endregion + + #region 获取合票详情(生成合票需要先调此方法) + /// + /// 获取合票详情(生成合票需要先调此方法) + /// + /// + /// + public async Task GetMergeList(QueryMergeSlotDto model) + { + BookingSlotMergeResultDto rlt = new BookingSlotMergeResultDto(); + + var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + + List slotList = new List(); + if (model != null) + { + /* + 合票时需要校对的内容 + */ + //船公司、船名场次、合约号、承运方式(直达、中转)、订舱方式(合约订舱)、装货地、卸货地 + slotList = tenantDb.Queryable().Where(a => model.MergeList.Contains(a.Id) && a.Deleted == false).ToList(); + + //校验查询结果 + if (model.MergeList.Count != slotList.Count) + { + var lostArg = model.MergeList.GroupJoin(slotList, l => l, r => r.Id, (l, r) => + { + var currList = r.ToList(); + + if (currList.Count == 0) + return 0; + + return l; + }).Where(a => a > 0).ToArray(); + + //部分舱位信息提取失败,请确认舱位是否存在或已作废 + throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotMergeCheckPartRecordDeletedOrNoExists))); + } + + if (slotList.Any(a => string.IsNullOrWhiteSpace(a.CarrierCode) + || string.IsNullOrWhiteSpace(a.Vessel) || string.IsNullOrWhiteSpace(a.Voyno) || (!a.BookingSlotType.Equals("SPOT_ORDER") && string.IsNullOrWhiteSpace(a.ContractNo)) + || string.IsNullOrWhiteSpace(a.CarriageType) || string.IsNullOrWhiteSpace(a.BookingSlotType) + || string.IsNullOrWhiteSpace(a.PortLoadCode) || string.IsNullOrWhiteSpace(a.PortDischargeCode))) + { + //舱位合票校验失败,部分舱位的以下信息船公司、船名场次、合约号、承运方式、订舱方式、装货地、卸货地有空值情况 + throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotMergeCheckPartRecordNoConsistent))); + } + + var checkList = slotList.Select(a => new + { + key = $"{a.CarrierCode}_{a.Vessel}_{a.Voyno}_{a.ContractNo}_{a.CarriageType}_{a.BookingSlotType}_{a.PortLoadCode}_{a.PortDischargeCode}", + obj = a + }).ToList(); + + //如果汇总去重不惟一,不能进行合票操作 + if (checkList.GroupBy(a => a.key).Count() > 1) + { + //舱位合票校验失败,船公司、船名场次、合约号、承运方式、订舱方式、装货地、卸货地不统一不能合票 + throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotMergeCheckPartRecordNoConsistentFail))); + } + } + + var list = await GetAvailableSlots(null, model.MergeList, null); + + //舱位合票失败,校验库存为不可用,请确认正确的库存 + if (list.Count == 0) + throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotMergeCheckStockEmpty))); + + //这里取完库存后,在跟请求的舱位做匹配,如果舱位没有库存了,提示错误终止合票 + var stockCheckList = slotList.GroupJoin(list, l => l.Id, r => r.Id, (l, r) => + { + var currList = r.ToList(); + + if (currList.Count == 0) + return new { Succ = false, No = l.SlotBookingNo }; + + return new { Succ = true, No = l.SlotBookingNo }; + }).Where(a => !a.Succ).ToList(); + + if (stockCheckList.Count > 0) + { + //舱位合票失败,舱位提单号:{string.Join(",", stockCheckList.Select(a => a.No).ToArray())} 缺少库存 + throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotMergeCheckPartRecordNoConsistentFail)), string.Join(",", stockCheckList.Select(a => a.No).ToArray()))); + } + + rlt.slotDetailList = list; + + string ctnStat = string.Empty; + + if (list.Count > 0) + { + rlt.ctnStat = string.Join(",", list.SelectMany(a => a.CtnList).OrderBy(a => a.CtnAll).GroupBy(a => a.CtnAll) + .Select(a => $"{a.Key}*{a.Sum(b => b.CtnNum)}").ToArray()); + } + + if (slotList.Any(a => !string.IsNullOrWhiteSpace(a.LoadGuaranteeFlag))) + { + rlt.importantNotes = string.Join(";", slotList.Where(a => !string.IsNullOrWhiteSpace(a.LoadGuaranteeFlag)) + .GroupBy(a => a.LoadGuaranteeFlagName) + .Select(a => string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotMergeCheckPartRecordNoConsistentFail)), string.Join(",", a.Select(b => b.SlotBookingNo).ToArray()), a.Key)).ToArray()); + } + + + // 查询可用舱位及箱子列表 + return rlt; + } + #endregion + + #region 舱位引入 + /// + /// 分页查询可用的舱位及箱子列表 + /// + /// 可选:舱位查询条件 + /// 可选:分页信息 + public async Task> GetAvailableSlots([FromQuery] BookingSlotBaseDto input, + [FromQuery] PageWithTotal pageInfo) + { + var result = await GetAvailableSlots(input, null, pageInfo); + + SqlSugarPagedList pageResult = new() + { + PageIndex = pageInfo.PageNo, + PageSize = pageInfo.PageSize, + TotalCount = pageInfo.Total, + Items = result, + }; + return pageResult; + } + #endregion + + #region 查询可用的舱位及箱子列表 + /// + /// 查询可用的舱位及箱子列表 + /// + /// 筛选条件1:舱位信息、箱型 + /// 筛选条件2:舱位主键列表 + /// 筛选条件3:分页 + /// 可用的舱位列表(含可用的箱子列表) + [NonAction] + public async Task> GetAvailableSlots(BookingSlotBaseDto slotInput = null, + List slotIdListInput = null, + PageWithTotal pageInfo = null) + { + slotInput ??= new(); + slotIdListInput ??= new(); + + string[] ctnCodeList = null; + if (!string.IsNullOrEmpty(slotInput.CtnStat)) + { + ctnCodeList = slotInput.CtnStat.Split(','); + } + + var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + + // 1. 【舱位基础表】与【箱子表】做关联,并根据【舱位主键】、【箱型】做分组,统计出【总的箱量】,作为queryable1 + var queryable1 = tenantDb.Queryable((bas, ctn) => bas.Id == ctn.SlotId) + .Where(bas => bas.IsCancellation == false) + .WhereIF(!string.IsNullOrEmpty(slotInput.SlotBookingNo), bas => bas.SlotBookingNo == slotInput.SlotBookingNo) + .WhereIF(!string.IsNullOrEmpty(slotInput.PortLoad), bas => bas.PortLoad.Contains(slotInput.PortLoad)) + .WhereIF(!string.IsNullOrEmpty(slotInput.PortDischarge), bas => bas.PortDischarge.Contains(slotInput.PortDischarge)) + .WhereIF(!string.IsNullOrEmpty(slotInput.Vessel), bas => bas.Vessel.Contains(slotInput.Vessel)) + .WhereIF(!string.IsNullOrEmpty(slotInput.Voyno), bas => bas.Voyno.Contains(slotInput.Voyno)) + .WhereIF(!string.IsNullOrEmpty(slotInput.CarriageType), bas => bas.CarriageType == slotInput.CarriageType) + .WhereIF(!string.IsNullOrEmpty(slotInput.BookingSlotType), bas => bas.BookingSlotType == slotInput.BookingSlotType) + .WhereIF(ctnCodeList != null, (bas, ctn) => ctnCodeList.Contains(ctn.CtnCode)) + .WhereIF(slotIdListInput.Any(), (bas) => slotIdListInput.Contains(bas.Id)) + .GroupBy((bas, ctn) => new + { + bas.Id, + ctn.CtnCode + }) + .Select((bas, ctn) => new + { + id = bas.Id, + ctnCode = ctn.CtnCode, + numAll = SqlFunc.AggregateSum(ctn.CtnNum) + }) + .MergeTable(); + + // 2. 【已引入舱位表】与【已使用的箱子表】做关联,并根据【舱位主键】、【箱型】做分组,统计出【已使用的箱量】,作为queryable2 + var queryable2 = tenantDb.Queryable((alc, ctn) => alc.Id == ctn.SlotAllocId) + .WhereIF(slotIdListInput.Any(), (alc, ctn) => slotIdListInput.Contains(alc.BookingSlotId)) + .GroupBy((alc, ctn) => new + { + alc.BookingSlotId, + ctn.CtnCode + }) + .Select((alc, ctn) => new + { + id = alc.BookingSlotId, + ctnCode = ctn.CtnCode, + numUse = SqlFunc.AggregateSum(ctn.CtnNum) + }) + .MergeTable(); + + // 3. 将queryable1 左连接 queryable2,使用【总的箱量】减去【已使用的箱量】,得到【剩余的箱量】,添加【剩余的箱量】> 0 的条件,作为queryable3 + var queryable3 = queryable1.LeftJoin(queryable2, (q1, q2) => q1.id == q2.id && q1.ctnCode == q2.ctnCode) + .Select((q1, q2) => new + { + q1.id, + q1.ctnCode, + q1.numAll, + numResidue = SqlFunc.IsNull(q1.numAll - q2.numUse, q1.numAll) + }) + .MergeTable() + .Where(r => r.numResidue > 0); + + // 4. 执行ToList(),得到可用的【舱位主键】、【箱型】、【箱量】列表 + RefAsync total = 0; + var canUselist = pageInfo == null + ? await queryable3.ToListAsync() + : await queryable3.ToPageListAsync(pageInfo.PageNo, pageInfo.PageSize, total); + + if (pageInfo != null) + { + pageInfo.Total = total; + } + + // 查询舱位列表 + var baseIdList = canUselist.Select(c => c.id); + List baseList = await tenantDb.Queryable() + .Where(u => baseIdList.Contains(u.Id)) + .ToListAsync(); + + List ctnCodeCache = new List(); + + var allCtnist = await _sysCacheService.GetAllCommonCodeFromCache(SysCacheKeyEnum.CommonCodeCtn); + + if (allCtnist.Succeeded) + { + ctnCodeCache = allCtnist.Data; + } + + // 构建结果 + List result = baseList.Adapt>(); + foreach (var item in result) + { + var ctnList = canUselist.Where(c => c.id == item.Id).ToList(); + if (ctnList?.Any() == true) + { + item.CtnList = ctnList.Select(c => new BookingSlotCtnDto() + { + CtnCode = c.ctnCode, + CtnNum = c.numResidue, + TotalNum = c.numAll, + CtnAll = ctnCodeCache.FirstOrDefault(e => $"{e.CtnSize}{e.CtnType}" == c.ctnCode)?.CtnName ?? throw new Exception($"舱位信息中存在未收录的箱型:{c.ctnCode},需要在箱型字典中补充"), + }).ToList(); + } + } + + return result; + } + #endregion + + #region 获取附件 + /// + /// 获取附件 + /// + /// 舱位主键 + /// 返回附件列表 + public async Task>> GetFile(long id) + { + return _opFileService.GetOpFileList(id.ToString()) ; + } + #endregion + + #region 检查指定订舱记录,是否可以引入舱位列表 + /// + /// 检查指定订舱记录,是否可以引入舱位列表 + /// + /// 待引入的舱位列表 + /// 待关联的订舱记录 + /// isExists:指定订舱记录是否已经引入过舱位数据,isEnough:现有舱位及箱子是否满足需求,message:提示信息 + public async Task<(bool isExists, bool isEnough, string message)> CheckImportSlots(List slots, long bookingOrderId) + { + slots ??= new List(); + + var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + + // 判断是否已存在引用关系 + if (bookingOrderId != 0 && await tenantDb.Queryable().AnyAsync(a => a.BookingId == bookingOrderId)) + { + //订舱主键{bookingOrderId}已引用舱位 + return (true, false, string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotCreateContaNull)), bookingOrderId)); + } + var slotIdList = slots.Select(s => s.Id).ToList(); + + // 查询可用舱位及箱子列表 + var latestSlotList = await GetAvailableSlots(null, slotIdList); + + // 判断余量是否满足需求 + foreach (var inSlotItem in slots) + { + var latestSlot = latestSlotList.FirstOrDefault(b => b.Id == inSlotItem.Id); + if (latestSlot == null) + { + //订舱编号为{inSlotItem.SlotBookingNo}的舱位已被占用或取消,请重新引入 + return (false, false, $"订舱编号为{inSlotItem.SlotBookingNo}的舱位已被占用或取消,请重新引入"); + } + if (inSlotItem.CtnList?.Any() == false) + { + //每个舱位至少选择一个箱子,订舱编号:{inSlotItem.SlotBookingNo} + return (false, false, $"每个舱位至少选择一个箱子,订舱编号:{inSlotItem.SlotBookingNo}"); + } + foreach (var inCtnItem in inSlotItem.CtnList) + { + var latestCtn = latestSlot.CtnList.FirstOrDefault(c => c.CtnCode == inCtnItem.CtnCode); + if (latestCtn == null) + { + //订舱编号为{latestSlot.SlotBookingNo}的舱位中,箱型为{inCtnItem.CtnAll}的箱子已被占用或取消,请重新引入 + return (false, false, $"订舱编号为{latestSlot.SlotBookingNo}的舱位中,箱型为{inCtnItem.CtnAll}的箱子已被占用或取消,请重新引入"); + } + if (latestCtn.CtnNum < inCtnItem.CtnNum) + { + //订舱编号为{latestSlot.SlotBookingNo}的舱位中,箱型为{inCtnItem.CtnAll}的箱子当前剩余{latestCtn.CtnNum}个,少于所需的{inCtnItem.CtnNum}个,请重新引入 + return (false, false, $"订舱编号为{latestSlot.SlotBookingNo}的舱位中,箱型为{inCtnItem.CtnAll}的箱子当前剩余{latestCtn.CtnNum}个,少于所需的{inCtnItem.CtnNum}个,请重新引入"); + } + } + } + //可以引入 + return (false, true, $"可以引入"); + } + public static object ImportLockObj = new object(); + #endregion + + #region 生成订舱订单 + /// + /// 生成订舱订单 + /// + /// 生成订舱订单请求 + /// 返回回执 + public async Task> CreateBookingOrder(BookingGenerateDto model) + { + if (model.CustomerId == null || string.IsNullOrWhiteSpace(model.CustomerName)) + { + //请选择委托单位 + throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotCreateCustomerNull))); + } + + if (model.CtnList == null || !model.CtnList.Any()) + { + //请选择要使用的箱信息 + throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotCreateContaNull))); + } + + //舱位ID不能为空 + if (!model.SlotId.HasValue || model.SlotId.Value < 1) + throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotCreateSlotIdNull))); + + var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + + var slotInfo = await tenantDb.Queryable() + .FirstAsync(a => a.Id == model.SlotId.Value); + + //舱位信息不存在或已作废 + if (slotInfo == null) + throw new Exception(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotCreateRecordDeletedOrNoExists))); + + // 判断是否已存在引用关系 + //if (_repAllocation.IsExists(a => a.BOOKING_SLOT_ID == slotInfo.Id + // && a.BOOKING_ID > 0 && a.IsDeleted == false)) + //{ + // throw Oops.Oh($"舱位已有对应的订舱订单,不能重复执行"); + //} + + //var ctnList = _repCtn.AsQueryable().Where(a => a.SLOT_ID == slotInfo.Id && a.IsDeleted == false) + // .ToList(); + + var fileList = _opFileService.GetOpFileList(slotInfo.Id.ToString()).Data; + + var paramConfig = _configService.GetConfig(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.Log(NLog.LogLevel.Info, $"委托单位{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.Log(NLog.LogLevel.Info, $"委托单位{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.Log(NLog.LogLevel.Info, $"委托单位{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))); + } + } + + var bookingOrderId = await GenerateBookingOrder(slotInfo, fileList, model, null); + + return DataResult.Success(bookingOrderId, MultiLanguageConst.DataCreateSuccess); + } + #endregion + + #region 生成订舱 + /// + /// 生成订舱 + /// + /// 舱位详情 + /// 舱位附件列表 + /// 订舱请求详情 + /// 合票的主舱位提单号(合票时必传) + /// 返回订舱ID + private async Task GenerateBookingOrder(BookingSlotBase bookingSlotBase, + List bookingSlotFileList, + BookingGenerateDto generateModel, string masterBookingSlotNo) + { + long id = 0; + + try + { + var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + + /* + 1、新增订舱 + 2、推送服务项目 + 3、推送附件 + */ + var allMapCarrierList = await _sysCacheService.GetAllCommonCodeFromCache(SysCacheKeyEnum.CommonMappingCarrier); + + MappingCarrierRes carrierInfo = null; + + if (allMapCarrierList.Succeeded) + { + carrierInfo = allMapCarrierList.Data.FirstOrDefault(t => t.LinkId == bookingSlotBase.CarrierId.Value && t.Module == CONST_MAPPING_CARRIER_MODULE); + } + + var custNo = bookingSlotBase.SlotBookingNo.Trim(); + + SeaExportReq bkModel = new SeaExportReq + { + CustomerId = generateModel.CustomerId.Value, + CustomerName = generateModel.CustomerName, + Carrier = carrierInfo?.MapName?.Trim(), + CarrierId = bookingSlotBase.CarrierId.Value, + BookingNo = custNo, + //MBLNO = bookingSlotBase.SLOT_BOOKING_NO.Trim(), + ContractNo = !string.IsNullOrWhiteSpace(bookingSlotBase.ContractNo) ? bookingSlotBase.ContractNo : "", + Vessel = bookingSlotBase.Vessel?.ToUpper()?.Trim(), + Voyno = bookingSlotBase.Voyno?.ToUpper()?.Trim(), + InnerVoyno = bookingSlotBase.Voyno?.ToUpper()?.Trim(), + ETD = bookingSlotBase.ETD, + ETA = bookingSlotBase.ETA, + SaleId = generateModel.SaleId.HasValue? generateModel.SaleId.Value:0, + Sale = generateModel.SaleName, + OperatorId = generateModel.OpId.HasValue ? generateModel.OpId.Value : 0, + //op = generateModel.OpName, + Doc = generateModel.DocId.HasValue ? generateModel.DocId.Value : 0, + //DOC = generateModel.DocName, + //ROUTEID = generateModel.RouteID?.ToString(), + //ROUTE = generateModel.Route, + //CZRemark = generateModel.CZRemark, + //ShenQingXiangShi = generateModel.ShenQingXiangShi, + //LineManageID = generateModel.LineManageID?.ToString(), + //LineName = generateModel.LineManage, + //CLOSEVGMDATE = bookingSlotBase.VGMSubmissionCutDate, + ClosingDate = bookingSlotBase.CYCutDate, + CloseDocDate = bookingSlotBase.SICutDate, + CustomerService = generateModel.CustServiceId.HasValue ? generateModel.CustServiceId.Value : 0, + //CUSTSERVICE = generateModel.CustServiceName, + + LoadPort = bookingSlotBase.PortLoad, + LoadPortId = bookingSlotBase.PortLoadId.HasValue? bookingSlotBase.PortLoadId.Value:0, + DischargePortId = bookingSlotBase.PortDischargeId.HasValue ? bookingSlotBase.PortLoadId.Value : 0, + DischargePort = bookingSlotBase.PortDischarge, + + ReceiptPlace = bookingSlotBase.PlaceReceipt, + ReceiptPlaceId = bookingSlotBase.PlaceReceiptId.HasValue ? bookingSlotBase.PlaceReceiptId.Value : 0, + DeliveryPlace = bookingSlotBase.PlaceDelivery, + DeliveryPlaceId = bookingSlotBase.PlaceDeliveryId.HasValue ? bookingSlotBase.PlaceDeliveryId.Value : 0, + + CtnInfo = new List() + }; + + // 判断是否为拆票的舱位,如果为拆票,提单号需要加上ABCD... + var selectNum = generateModel.CtnList.Sum(x => x.CtnNum); + Logger.Log(NLog.LogLevel.Info, "根据舱位生成订舱,selectNum:{selectNum}", selectNum); + + var allNum = await tenantDb.Queryable().Where(x => x.SlotId == generateModel.SlotId).SumAsync(x => x.CtnNum); + + Logger.Log(NLog.LogLevel.Info, "根据舱位生成订舱,allNum:{allNum}", allNum); + //bkModel.IsSplit = selectNum != allNum; + bkModel.SplitOrMergeFlag = selectNum != allNum ? 1 : 0; + + if (!string.IsNullOrWhiteSpace(masterBookingSlotNo)) + bkModel.SplitOrMergeFlag = 2; + + //拆票逻辑 + if (bkModel.SplitOrMergeFlag == 1) + { + //var sql = _repBookingOrder.AsQueryable().Where(" MBLNO like @mblno ", new { mblno = custNo + '_' }).OrderByDescending(x => x.Id).Select(x => x.MBLNO).ToSqlString(); + //var currentMblno = await _repBookingOrder.AsQueryable().Where(" MBLNO like @mblno ", new { mblno = custNo + '_' }) + // .OrderByDescending(x => x.Id) + // .Select(x => x.MBLNO) + // .FirstAsync(); + + //获取所有订舱编号是舱位提单号,并且是已经拆单的订舱记录 + var orderList = tenantDb.Queryable().Where(a => a.BookingNo == custNo && a.SplitOrMergeFlag == 1 && a.Deleted == false).ToList(); + + if (orderList.Count == 0) + { + bkModel.MBLNO = $"{custNo}A"; + bkModel.BookingNo = custNo; + bkModel.HBLNO = custNo; + } + else + { + var maxChar = orderList.Select(a => + { + var startIndx = a.BookingNo.Length; + return a.MBLNO.Substring(startIndx); + }).Max(); + + //获取的历史拆票后缀异常,maxChar={maxChar} + if (maxChar.Length != 1 || !Regex.IsMatch(maxChar, "[A-Z]{1}")) + throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotCreateCustomerContractNotNull)), maxChar)); + + bkModel.MBLNO = $"{custNo}{LetterIndexUtil.GetNextLetter(maxChar[0])}"; + bkModel.BookingNo = custNo; + bkModel.HBLNO = custNo; + } + //if (currentMblno == null) + //{ + // bkModel.MBLNO = custNo + "A"; + + + //} + //else + //{ + // var lastLetter = currentMblno.Substring(currentMblno.Length - 1, 1)[0]; + // var newMblno = custNo + LetterIndexUtil.GetNextLetter(lastLetter); + // bkModel.MBLNO = newMblno; + //} + } + else if (bkModel.SplitOrMergeFlag == 2) + { + //合票 + var orderList = tenantDb.Queryable().Where(a => a.BookingNo == custNo && a.SplitOrMergeFlag == 2 + && a.MBLNO == custNo && a.Deleted == false).ToList(); + + if (orderList.Count == 0) + { + bkModel.MBLNO = custNo; + bkModel.BookingNo = custNo; + bkModel.HBLNO = masterBookingSlotNo; + } + else + { + //舱位提单号:{custNo} 已有订舱记录不能重复操作 + throw new Exception(string.Format(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.BookingSlotSplitMergeHasOrder)), custNo)); + + } + } + else + { + bkModel.MBLNO = bookingSlotBase.SlotBookingNo.Trim(); + } + Logger.Log(NLog.LogLevel.Info, "根据舱位生成订舱,得到MBLNO:{MBLNO}", bkModel.MBLNO); + + List ctnCodeList = new List(); + + var ctnCacheRlt = await _sysCacheService.GetAllCommonCodeFromCache(SysCacheKeyEnum.CommonMappingCarrier); + + if (ctnCacheRlt.Succeeded) + { + ctnCodeList = ctnCacheRlt.Data; + } + + if (generateModel.CtnList != null && generateModel.CtnList.Count > 0) + { + generateModel.CtnList.ForEach(t => + { + var ctnCode = ctnCodeList.FirstOrDefault(a => !string.IsNullOrWhiteSpace(a.CtnName) && + a.CtnName.Equals(t.CtnAll, StringComparison.OrdinalIgnoreCase)); + + OpCtnReq ctn = new OpCtnReq + { + CtnCode = $"{ctnCode?.CtnSize}{ctnCode?.CtnType}", + CtnAll = t.CtnAll, + CtnNum = t.CtnNum + }; + + bkModel.CtnInfo.Add(ctn); + }); + } + + // 验证舱位是否可用 + var slotInfo = bookingSlotBase.Adapt(); + slotInfo.CtnList = generateModel.CtnList; + var importSlots = new List() { slotInfo }; + var checkResult = await CheckImportSlots(importSlots, 0); + if (!checkResult.isEnough) + { + throw new Exception(checkResult.message); + } + + Logger.Log(NLog.LogLevel.Info, "根据舱位生成订舱,开始调用Save保存订舱"); + + var bkRlt = await _seaExportService.EditSeaExport(bkModel); + + Logger.Log(NLog.LogLevel.Info, $"根据舱位生成订舱,调用Save保存订舱完成,id:{bkRlt.Data}"); + + id = long.Parse(bkRlt.Data.ToString()); + + string batchNo = GuidHelper.GetSnowflakeId(); + + if (id > 0) + { + ////对应订舱和舱位关系 + var allocRlt = await ImportSlots(importSlots, id, false, generateModel); + Logger.Log(NLog.LogLevel.Info, "根据舱位生成订舱,引入订舱关系完成"); + + //更新舱位的拆合单标记 + var slotEntity = tenantDb.Queryable().First(a => a.Id == bookingSlotBase.Id && a.Deleted == false); + + if (slotEntity != null) + { + slotEntity.SplitOrMergeFlag = bkModel.SplitOrMergeFlag; + + //更新舱位的拆合单标记 + await tenantDb.Updateable(slotEntity).UpdateColumns(a => new { a.SplitOrMergeFlag }).ExecuteCommandAsync(); + } + + //这里如果指定了委托单位的邮件联系人,则推送订舱联系人 + if (generateModel.CustomerContactList != null && generateModel.CustomerContactList.Count > 0) + { + var bookingContactList = tenantDb.Queryable() + .Where(a => a.BusinessId == id && a.Deleted == false).ToList(); + + var djyCustomerInfo = _clientInfoService.GetClientInfoWithContact(new Info.Dtos.QueryClientInfo { ClientId = generateModel.CustomerId.Value, IsController = true }) + .GetAwaiter().GetResult().Data; + + + generateModel.CustomerContactList.ForEach(contact => + { + ClientContactRes djyCustomerContactMan = null; + + if (djyCustomerInfo.ClientContactList != null && djyCustomerInfo.ClientContactList.Count > 0) + { + djyCustomerContactMan = djyCustomerInfo.ClientContactList.FirstOrDefault(a => + a.Id == contact.CustomerContactId); + } + + if (djyCustomerContactMan != null) + { + var bookingContact = bookingContactList + .FirstOrDefault(x => x.Email.Equals(djyCustomerContactMan.Email, StringComparison.OrdinalIgnoreCase)); + + if (bookingContact == null) + { + bookingContact = new BusinessOrderContact + { + Name = djyCustomerContactMan.ShortName, + BusinessId = id, + Email = djyCustomerContactMan.Email, + Note = djyCustomerContactMan.Note, + CreateTime = DateTime.Now, + CreateBy = long.Parse(user.UserId), + //CreatedUserName = UserManager.Name + }; + + tenantDb.Insertable(bookingContact).ExecuteCommand(); + //_bookingOrderContactRepository.Insert(bookingContact); + } + else + { + bookingContact.Name = djyCustomerContactMan.ShortName; + bookingContact.Email = djyCustomerContactMan.Email; + bookingContact.Note = djyCustomerContactMan.Note; + bookingContact.UpdateTime = DateTime.Now; + bookingContact.UpdateBy = long.Parse(user.UserId); + //bookingContact.UpdatedUserName = UserManager.Name; + + tenantDb.Updateable(bookingContact).UpdateColumns(it => new + { + it.Name, + it.Email, + it.Note, + it.UpdateTime, + it.UpdateBy, + //it.UpdatedUserName + + }).ExecuteCommand(); + } + } + }); + + } + + if (generateModel.ProjectList != null && generateModel.ProjectList.Count > 0) + { + //写入服务项目 + var prjRlt = _djyServiceStatusService.SaveServiceProject(new EmbedServiceProjectDto + { + BusinessId = id.ToString(), + ProjectCodes = generateModel.ProjectList.Distinct().ToArray(), + }); + + Logger.Log(NLog.LogLevel.Info, $"推送订舱的服务项目完成 id={id} rlt={JsonConvert.SerializeObject(prjRlt)}"); + } + + //var opt = App.GetOptions(); + //var dirAbs = opt.basePath; + //if (string.IsNullOrEmpty(dirAbs)) + //{ + // dirAbs = App.WebHostEnvironment.WebRootPath; + //} + + var basePath = AppSetting.app(new string[] { "FileSettings", "BasePath" }); + var relativePath = AppSetting.app(new string[] { "FileSettings", "RelativePath" }); + var dirAbs = string.Empty; + var fileRelaPath = string.Empty; + var fileAbsPath = string.Empty; + if (string.IsNullOrEmpty(basePath)) + { + dirAbs = Path.Combine(_environment.WebRootPath, relativePath); + } + else + { + dirAbs = Path.Combine(basePath, relativePath); + } + + if (bookingSlotFileList.Any(a => a.TypeCode.Equals("bc", StringComparison.OrdinalIgnoreCase))) + { + var file = bookingSlotFileList.OrderByDescending(a => a.CreateTime) + .FirstOrDefault(a => a.TypeCode.Equals("bc", StringComparison.OrdinalIgnoreCase)); + + var fileFullPath = Path.Combine(dirAbs, file.FilePath); + + if (File.Exists(fileFullPath)) + { + //如果确认文件读取成功 + var bookFilePath = _sysFileService.MoveFile(id.ToString(), fileFullPath, batchNo + , false, null, true).GetAwaiter().GetResult().Data; + + //将格式单附件写入订舱的附件 + SaveEDIFile(id, bookFilePath, new System.IO.FileInfo(bookFilePath).Name, long.Parse(user.TenantId), + CONST_BC_FILE_CODE, CONST_BC_FILE_NAME).GetAwaiter(); + } + } + + if (bookingSlotFileList.Any(a => a.TypeCode.Equals("bc_notice", StringComparison.OrdinalIgnoreCase))) + { + var file = bookingSlotFileList.OrderByDescending(a => a.CreateTime) + .FirstOrDefault(a => a.TypeCode.Equals("bc_notice", StringComparison.OrdinalIgnoreCase)); + + var fileFullPath = Path.Combine(dirAbs, file.FilePath); + + if (File.Exists(fileFullPath)) + { + //如果确认文件读取成功 + var bookFilePath = _sysFileService.MoveFile(id.ToString(), fileFullPath, batchNo + , false, "bcnoticefile", true).GetAwaiter().GetResult().Data; + + //将格式单附件写入订舱的附件 + SaveEDIFile(id, bookFilePath, new System.IO.FileInfo(bookFilePath).Name, long.Parse(user.TenantId), + CONST_BC_FILE_CODE, CONST_BC_FILE_NAME).GetAwaiter(); + } + } + } + + Logger.Log(NLog.LogLevel.Info, $"MBLNO:{bookingSlotBase.SlotBookingNo} 生成订舱订单成功 id={id}"); + + } + catch (Exception ex) + { + Logger.Log(NLog.LogLevel.Info, $"MBLNO:{bookingSlotBase.SlotBookingNo} 生成订舱订单异常,原因:{ex.Message}"); + throw; + } + + + return id; + } + #endregion + + /// + /// 为指定订舱记录引入舱位信息 + /// + /// 待引入的舱位列表 + /// 待关联的订舱记录 + /// 是否进行剩余量检查 + /// 额外的用于生成管理记录的信息 + /// isSuccess:检查(余量及已引用检查)是否成功通过,message:提示信息 + [NonAction] + public async Task<(bool isSuccess, string message)> ImportSlots(List slots, + long bookingOrderId, + bool isCheck, + BookingGenerateDto generateModel = null) + { + slots ??= new List(); + + var tenantDb = saasService.GetBizDbScopeById(user.TenantId); + + Monitor.Enter(ImportLockObj); + try + { + if (isCheck) + { + (bool isExists, bool isEnough, string message) checkResult = await CheckImportSlots(slots, bookingOrderId); + + if (checkResult.isExists || !checkResult.isEnough) + return (false, checkResult.message); + } + + var slotIdList = slots.Select(s => s.Id).ToList(); + List latestSlotList = await tenantDb.Queryable().Where(b => slotIdList.Contains(b.Id)).ToListAsync(); + foreach (var inSlotItem in slots) + { + var latestSlot = latestSlotList.First(b => b.Id == inSlotItem.Id); + + // 保存关联信息 + var config = new TypeAdapterConfig(); + config.ForType() + .Ignore(dest => dest.CreateTime) + .Ignore(dest => dest.UpdateTime) + .Ignore(dest => dest.CreateBy) + .Ignore(dest => dest.UpdateBy); + //.Ignore(dest => dest.CreatedUserName) + //.Ignore(dest => dest.UpdatedUserName) + //.Ignore(dest => dest.TenantId) + //.Ignore(dest => dest.TenantName); + + var newSlotAllocation = latestSlot.Adapt(config); + newSlotAllocation.Id = 0; + newSlotAllocation.BookingSlotId = latestSlot.Id; + newSlotAllocation.BookingId = bookingOrderId; + newSlotAllocation.AlloBillNo = latestSlot.SlotBookingNo; + newSlotAllocation.FinalBillNo = latestSlot.SlotBookingNo; + + if (generateModel != null) + { + newSlotAllocation.CustomerId = generateModel.CustomerId; + newSlotAllocation.CustomerName = generateModel.CustomerName; + newSlotAllocation.CustServiceId = generateModel.CustServiceId?.ToString(); + newSlotAllocation.CustService = generateModel.CustServiceName; + newSlotAllocation.SaleId = generateModel.SaleId?.ToString(); + newSlotAllocation.Sale = generateModel.SaleName; + newSlotAllocation.DocId = generateModel.DocId?.ToString(); + newSlotAllocation.Doc = generateModel.DocName; + newSlotAllocation.OpId = generateModel.OpId?.ToString(); + newSlotAllocation.Op = generateModel.OpName; + newSlotAllocation.Business = generateModel.BUSINESS; + newSlotAllocation.BusinessId = generateModel.BUSINESSID; + newSlotAllocation.SaleTime = generateModel.SALE_TIME; + newSlotAllocation.Shipper = generateModel.SHIPPER; + newSlotAllocation.GoodsName = generateModel.GOODSNAME; + newSlotAllocation.SellingPrice = generateModel.SELLING_PRICE; + newSlotAllocation.SplitOrMergeFlag = generateModel.SplitOrMerge; + + if (generateModel.SplitOrMerge == 1 || generateModel.SplitOrMerge == 2) + { + newSlotAllocation.AlloBillNo = generateModel.NewMBlNo; + } + } + + await tenantDb.Insertable(newSlotAllocation).ExecuteReturnEntityAsync(); + + // 保存关联的箱信息 + var insertCtnList = inSlotItem.CtnList.Select(c => new BookingSlotAllocationCtn() + { + SlotAllocId = newSlotAllocation.Id, + CtnCode = c.CtnCode, + CtnAll = c.CtnAll, + CtnNum = c.CtnNum + }); + await tenantDb.Insertable(insertCtnList).ExecuteCommandAsync(); + + // 为订舱保存附件信息 + var lastestBcFile = await tenantDb.Queryable().Where(x => (x.TypeCode == "bc" || x.TypeCode == "bc_notice") && x.LinkId == latestSlot.Id) + .OrderByDescending(x => x.Id) + .FirstAsync(); + if (lastestBcFile != null) + { + var file = lastestBcFile.Adapt(); + file.Id = 0; + file.LinkId = bookingOrderId; + await tenantDb.Insertable(file).ExecuteCommandAsync(); + } + + await _bookingSlotStockService.BookingSlotStock(new BookingSlotStockUpdateModel + { + BookingSlotType = latestSlot.BookingSlotType, + CarrierId = latestSlot.CarrierId.HasValue? latestSlot.CarrierId.Value:0, + ContractNo = latestSlot.ContractNo, + Vessel = latestSlot.Vessel, + Voyno = latestSlot.Voyno, + PortDischargeId = latestSlot.PortLoadCode, + //PORTDISCHARGEID = latestSlot.PORTDISCHARGEID, + }); + // 更新库存 + //await _publisher.PublishAsync(new ChannelEventSource("BookingSlotStock:Update", new Event.BookingSlotStockUpdateModel + //{ + // BOOKING_SLOT_TYPE = latestSlot.BOOKING_SLOT_TYPE, + // CARRIERID = latestSlot.CARRIERID, + // CONTRACT_NO = latestSlot.CONTRACT_NO, + // VESSEL = latestSlot.VESSEL, + // VOYNO = latestSlot.VOYNO, + // PORTLOADID = latestSlot.PORTLOADID, + // PORTDISCHARGEID = latestSlot.PORTDISCHARGEID, + // TenantId = latestSlot.TenantId, + //})); + } + } + finally + { + Monitor.Exit(ImportLockObj); + } + + return (true, "引入成功"); + } + } + + public static class LetterIndexUtil + { + /// + /// 根据当前字母获取它在26个英文字母中的下一个字母 + /// + public static char GetNextLetter(char currentLetter) + { + if (currentLetter == 'z') return 'a'; + if (currentLetter == 'Z') return 'A'; + return (char)(currentLetter + 1); + } } } diff --git a/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotStockService.cs b/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotStockService.cs index 1be4c6dc..1be505b4 100644 --- a/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotStockService.cs +++ b/ds-wms-service/DS.WMS.Core/Op/Method/BookingSlot/BookingSlotStockService.cs @@ -72,8 +72,8 @@ namespace DS.WMS.Core.Op.Method && x.ContractNo == paraObj.ContractNo && x.BookingSlotType == paraObj.BookingSlotType && x.CarrierCode == paraObj.CarrierCode - && x.PortLoadId == paraObj.PortLoadId - && x.PortDischargeId == paraObj.PortDischargeId) + && x.PortLoadCode == paraObj.PortLoadId + && x.PortDischargeCode == paraObj.PortDischargeId) .OrderByDescending(x => x.UpdateTime) .ToListAsync(); diff --git a/ds-wms-service/DS.WMS.Core/Sys/Interface/ISysFileService.cs b/ds-wms-service/DS.WMS.Core/Sys/Interface/ISysFileService.cs index dae8c314..3fcb1be3 100644 --- a/ds-wms-service/DS.WMS.Core/Sys/Interface/ISysFileService.cs +++ b/ds-wms-service/DS.WMS.Core/Sys/Interface/ISysFileService.cs @@ -38,5 +38,19 @@ namespace DS.WMS.Core.Sys.Interface /// Task> SaveFileDirect(string fileDictKey, byte[] fileBytes, string batchNo, string fileName, string attachFileType); + + + /// + /// 转移文件 + /// + /// 文件目录KEY + /// 源文件完整路径 + /// 批次号 + /// 是否生成本地文件 + /// 附件类型 bcfiles-BC文件 + /// 是否保留原文件 + /// 返回新的文件路径 + Task> MoveFile(string fileDictKey, string sourceFilePath, string batchNo, + bool isLocalTempFile = false, string attachFileType = "bcfiles", bool isKeepSource = false); } } diff --git a/ds-wms-service/DS.WMS.Core/Sys/Method/SysFileService.cs b/ds-wms-service/DS.WMS.Core/Sys/Method/SysFileService.cs index ab89dbd1..04112267 100644 --- a/ds-wms-service/DS.WMS.Core/Sys/Method/SysFileService.cs +++ b/ds-wms-service/DS.WMS.Core/Sys/Method/SysFileService.cs @@ -176,5 +176,103 @@ namespace DS.WMS.Core.Sys.Method return DataResult.Success(bookFilePath); } + + #region 转移文件 + /// + /// 转移文件 + /// + /// 文件目录KEY + /// 源文件完整路径 + /// 批次号 + /// 是否生成本地文件 + /// 附件类型 bcfiles-BC文件 + /// 是否保留原文件 + /// 返回新的文件路径 + public async Task> MoveFile(string fileDictKey, string sourceFilePath, string batchNo, + bool isLocalTempFile = false, string attachFileType = "bcfiles", bool isKeepSource = false) + { + string fileRoot = AppSetting.app(new string[] { "FileSettings", "BasePath" }); + + string relativePath = AppSetting.app(new string[] { "FileSettings", "RelativePath" }); + + if (!string.IsNullOrWhiteSpace(attachFileType)) + relativePath += $"\\{attachFileType}"; + + if (!string.IsNullOrWhiteSpace(fileDictKey)) + relativePath += $"\\{fileDictKey}"; + + relativePath += $"\\{DateTime.Now.ToString("yyyyMMddHHmmss")}"; + + string filePath = $"{fileRoot}\\{relativePath}"; + + string fileFullName = $"{filePath}\\{new System.IO.FileInfo(sourceFilePath).Name}"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + relativePath = relativePath.Replace("\\", "/"); + filePath = filePath.Replace("\\", "/"); + fileFullName = fileFullName.Replace("\\", "/"); + } + + Logger.Log(NLog.LogLevel.Info, $"批次={batchNo} 生成文件保存路径完成 路由={filePath} 服务器系统={RuntimeInformation.OSDescription}"); + + //预先创建目录 + if (!Directory.Exists(filePath)) + { + Directory.CreateDirectory(filePath); + } + + if (sourceFilePath.StartsWith("http", StringComparison.OrdinalIgnoreCase) || + sourceFilePath.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + //var bcStream = await sourceFilePath.GetAsStreamAsync(); + + //using (var fileStream = File.Create(fileFullName)) + //{ + // await bcStream.CopyToAsync(fileStream); + //} + } + else + { + System.IO.FileStream file = new System.IO.FileStream(sourceFilePath, FileMode.Open, FileAccess.Read); + + using (var fileStream = File.Create(fileFullName)) + { + await file.CopyToAsync(fileStream); + } + + file.Close(); + + + try + { + if (!isKeepSource) + { + //删除原文件 + System.IO.File.Delete(sourceFilePath); + } + } + catch (Exception delEx) + { + Logger.Log(NLog.LogLevel.Info, $"批次={batchNo} 删除文件异常 filepath={fileFullName} ex={delEx.Message}"); + } + } + + Logger.Log(NLog.LogLevel.Info, $"批次={batchNo} 完成文件保存 filepath={fileFullName}"); + + string bookFilePath = string.Empty; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("/", "\\/") + ".*").Value; + } + else + { + bookFilePath = System.Text.RegularExpressions.Regex.Match(fileFullName, relativePath.Replace("\\", "\\\\") + ".*").Value; + } + + return DataResult.Success(bookFilePath); + } + #endregion } } diff --git a/ds-wms-service/DS.WMS.OpApi/Controllers/BookingLabelController.cs b/ds-wms-service/DS.WMS.OpApi/Controllers/BookingLabelController.cs new file mode 100644 index 00000000..47a8e30b --- /dev/null +++ b/ds-wms-service/DS.WMS.OpApi/Controllers/BookingLabelController.cs @@ -0,0 +1,90 @@ +using DS.Module.Core; +using DS.WMS.Core.Op.Dtos; +using DS.WMS.Core.Op.Interface; +using Microsoft.AspNetCore.Mvc; + +namespace DS.WMS.OpApi.Controllers +{ + /// + /// 舱位标签管理 + /// + public class BookingLabelController : Controller + { + private readonly IBookingLabelService _bookingLabelService; + + public BookingLabelController(IBookingLabelService bookingLabelService) + { + _bookingLabelService = bookingLabelService; + } + + #region 获取全部或指定范围类型的标签列表 + /// + /// 获取全部或指定范围类型的标签列表 + /// + /// 标签使用范围 空-全部 1-舱位管理台账 + /// 返回列表 + [HttpGet] + [Route("List")] + public async Task>> List([FromQuery] int? scope) + { + return await _bookingLabelService.List(scope); + } + #endregion + + #region 设定标签 + /// + /// 设定标签 + /// + /// 请求参数 + /// 返回回执 + [HttpPost] + [Route("SetLabel")] + public async Task> SetLabel([FromBody] BindLabelDto input) + { + return await _bookingLabelService.SetLabel(input); + } + #endregion + + #region 保存标签 + /// + /// 保存标签 + /// + /// 请求参数 + /// 返回标签主键 + [HttpPost] + [Route("Save")] + public async Task> Save([FromBody] BookingLabelBaseDto input) + { + return await _bookingLabelService.Save(input); + } + #endregion + + #region 删除标签信息 + /// + /// 删除标签信息 + /// + /// 标签主键组 + /// + [HttpPost] + [Route("Delete")] + public async Task> Delete([FromBody] long[] ids) + { + return await _bookingLabelService.Delete(ids); + } + #endregion + + #region 标签管理台账 + /// + /// 标签管理台账 + /// + /// 查询条件 + /// 返回台账列表 + [HttpPost] + [Route("GetPage")] + public async Task>> GetPageAsync([FromBody] PageRequest QuerySearch) + { + return await _bookingLabelService.GetPageAsync(QuerySearch); + } + #endregion + } +} diff --git a/ds-wms-service/DS.WMS.OpApi/Properties/PublishProfiles/FolderProfile.pubxml.user b/ds-wms-service/DS.WMS.OpApi/Properties/PublishProfiles/FolderProfile.pubxml.user index 21240daa..5930d587 100644 --- a/ds-wms-service/DS.WMS.OpApi/Properties/PublishProfiles/FolderProfile.pubxml.user +++ b/ds-wms-service/DS.WMS.OpApi/Properties/PublishProfiles/FolderProfile.pubxml.user @@ -6,7 +6,7 @@ <_PublishTargetUrl>D:\Code\PublishCopy\ds8-opapi - True|2024-07-17T08:13:32.9037697Z||;True|2024-07-17T15:40:21.2550083+08:00||;True|2024-07-17T14:03:08.1814323+08:00||;True|2024-07-15T13:43:42.6073130+08:00||;True|2024-07-15T11:53:40.6498579+08:00||;True|2024-07-15T11:53:03.1652559+08:00||;True|2024-07-15T11:42:33.0154478+08:00||;True|2024-07-15T10:20:03.3925876+08:00||;True|2024-07-15T10:13:28.1415352+08:00||;True|2024-07-08T14:33:12.6884426+08:00||;True|2024-07-08T09:56:58.4995696+08:00||; + True|2024-07-17T09:44:18.4741963Z||;True|2024-07-17T17:42:47.2735071+08:00||;True|2024-07-17T16:13:32.9037697+08:00||;True|2024-07-17T15:40:21.2550083+08:00||;True|2024-07-17T14:03:08.1814323+08:00||;True|2024-07-15T13:43:42.6073130+08:00||;True|2024-07-15T11:53:40.6498579+08:00||;True|2024-07-15T11:53:03.1652559+08:00||;True|2024-07-15T11:42:33.0154478+08:00||;True|2024-07-15T10:20:03.3925876+08:00||;True|2024-07-15T10:13:28.1415352+08:00||;True|2024-07-08T14:33:12.6884426+08:00||;True|2024-07-08T09:56:58.4995696+08:00||; \ No newline at end of file diff --git a/ds-wms-service/DS.WMS.Test/SaasTest.cs b/ds-wms-service/DS.WMS.Test/SaasTest.cs index 60d72acc..2308ec09 100644 --- a/ds-wms-service/DS.WMS.Test/SaasTest.cs +++ b/ds-wms-service/DS.WMS.Test/SaasTest.cs @@ -180,19 +180,19 @@ public class SaasTest { var tenantDb = saasService.GetBizDbScopeById("1750335377144680448"); StaticConfig.CodeFirst_MySqlCollate = "utf8mb4_0900_ai_ci";//较高版本支持 - tenantDb.CodeFirst.InitTables(typeof(SpaceBookingOrder)); - tenantDb.CodeFirst.InitTables(typeof(SpaceBookingOrderCtn)); - tenantDb.CodeFirst.InitTables(typeof(SpaceBookingOrderShipSchedule)); - tenantDb.CodeFirst.InitTables(typeof(BookingSlotBase)); - tenantDb.CodeFirst.InitTables(typeof(BookingSlotCtn)); - tenantDb.CodeFirst.InitTables(typeof(BookingSlotStock)); - tenantDb.CodeFirst.InitTables(typeof(BookingSlotAllocation)); - tenantDb.CodeFirst.InitTables(typeof(BookingSlotAllocationCtn)); - tenantDb.CodeFirst.InitTables(typeof(BookingSlotDemand)); - tenantDb.CodeFirst.InitTables(typeof(BookingSlotDemandCtn)); - tenantDb.CodeFirst.InitTables(typeof(BookingSlotCompare)); - - + //tenantDb.CodeFirst.InitTables(typeof(SpaceBookingOrder)); + //tenantDb.CodeFirst.InitTables(typeof(SpaceBookingOrderCtn)); + //tenantDb.CodeFirst.InitTables(typeof(SpaceBookingOrderShipSchedule)); + //tenantDb.CodeFirst.InitTables(typeof(BookingSlotBase)); + //tenantDb.CodeFirst.InitTables(typeof(BookingSlotCtn)); + //tenantDb.CodeFirst.InitTables(typeof(BookingSlotStock)); + //tenantDb.CodeFirst.InitTables(typeof(BookingSlotAllocation)); + //tenantDb.CodeFirst.InitTables(typeof(BookingSlotAllocationCtn)); + //tenantDb.CodeFirst.InitTables(typeof(BookingSlotDemand)); + //tenantDb.CodeFirst.InitTables(typeof(BookingSlotDemandCtn)); + //tenantDb.CodeFirst.InitTables(typeof(BookingSlotCompare)); + tenantDb.CodeFirst.InitTables(typeof(BookingContractNoManage)); + //tenantDb.CodeFirst.InitTables(typeof(CodeThirdParty)); //tenantDb.CodeFirst.InitTables(typeof(CheckBillAutoDetail)); //db.CodeFirst.InitTables(typeof(OpBusinessTruckCtn));