From ff13a8e1fceec9227e5085eb1334a2a1ca2d963b Mon Sep 17 00:00:00 2001 From: zhouhongjun <565221961@qq.com> Date: Tue, 14 May 2024 08:27:36 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E8=A3=85=E9=85=8D=E5=8F=AB=E6=96=99?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AssembleIssueJobPermissions.cs | 8 +- .../DTOs/AssembleIssueJobDTO.cs | 2 + .../IAssembleIssueJobAppService.cs | 10 +- .../Inputs/AssembleIssueJobEditInput.cs | 3 +- .../AssembleIssueNotePermissions.cs | 15 +- .../DTOs/AssembleIssueNoteDTO.cs | 1 + .../IAssembleIssueNoteAppService.cs | 1 - .../Inputs/AssembleIssueNoteEditInput.cs | 4 +- .../Inputs/AssembleIssueNoteImportInput.cs | 2 + .../KittingIssueNotePermissions.cs | 8 +- .../AssembleIssueRequestPermissions.cs | 10 +- .../DTOs/AssembleIssueRequestDTO.cs | 4 +- .../DTOs/AssembleIssueRequestDetailDTO.cs | 71 +- .../IAssembleIssueRequestAppService.cs | 2 + .../Inputs/AssembleIssueRequestEditInput.cs | 7 +- .../Inputs/AssembleIssueRequestImportInput.cs | 12 +- .../AssembleIssueJobAppService.cs | 479 ++++++++++-- .../AssembleIssueNoteAppService.cs | 21 +- .../AssembleIssueRequestAppService.cs | 250 ++++++- .../AssembleIssueJobs/AssembleIssueJob.cs | 3 +- .../AssembleIssueJobDetail.cs | 2 +- .../AssembleIssueJobManager.cs | 5 +- .../AssembleIssueNotes/AssembleIssueNote.cs | 8 +- .../AssembleIssueRequest.cs | 9 +- .../AssembleIssueRequestDetail.cs | 2 +- .../AssembleIssueRequestManager.cs | 34 +- ...RequestDbContextModelCreatingExtensions.cs | 4 +- .../Jobs/AssembleJobAutoMapperProfile.cs | 9 + .../Notes/AssembleNoteAutoMapperProfile.cs | 1 - .../AssembleIssueRequestAutoMapperProfile.cs | 39 +- .../Jobs/AssembleIssueJobEventHandler.cs | 146 ++-- .../AssembleIssueRequestEventHandler.cs | 692 +++++++++++------- 32 files changed, 1321 insertions(+), 543 deletions(-) diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobPermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobPermissions.cs index def0b7ecd..e3827f3b2 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobPermissions.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobPermissions.cs @@ -16,10 +16,10 @@ public static class AssembleIssueJobPermissions public static void AddAssembleIssueJobPermission(this PermissionGroupDefinition permissionGroup) { - var AssembleIssueJobPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueJob))); - AssembleIssueJobPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr)); - AssembleIssueJobPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr)); - AssembleIssueJobPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr)); + var assembleIssueJobPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueJob))); + assembleIssueJobPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr)); + assembleIssueJobPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr)); + assembleIssueJobPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr)); permissionGroup.AddPermission(AutoAssembleIssueJob, StorePermissionDefinitionProvider.L(nameof(AutoAssembleIssueJob))); diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/DTOs/AssembleIssueJobDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/DTOs/AssembleIssueJobDTO.cs index 791161af2..e05f8d4b4 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/DTOs/AssembleIssueJobDTO.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/DTOs/AssembleIssueJobDTO.cs @@ -36,4 +36,6 @@ public class AssembleIssueJobDTO : SfsJobDTOBase [Display(Name = "使用在途库")] public bool UseOnTheWayLocation { get; set; } + public EnumIssueSendType EnumIssueSendType { get; set; } + } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/IAssembleIssueJobAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/IAssembleIssueJobAppService.cs index c922d9050..ab78d78ac 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/IAssembleIssueJobAppService.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/IAssembleIssueJobAppService.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -8,8 +9,15 @@ namespace Win_in.Sfs.Wms.Store.Application.Contracts; public interface IAssembleIssueJobAppService : ISfsJobAppServiceBase { - Task CancelByMaterialRequestAsync(string assembleNumber); + Task CancelByMaterialRequestAsync(string requestNumber); Task> GetByRequestNumberAsync(string requestNumber); + /// + /// 执行任务明细 + /// + /// + Task ExecuteDetailAsync(Guid masterId, Guid detailId, AssembleIssueJobDetailDTO issueJobDetailDto); + + Task CompleteAsync(Guid id); } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/Inputs/AssembleIssueJobEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/Inputs/AssembleIssueJobEditInput.cs index 92f6458ff..fdf1a372d 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/Inputs/AssembleIssueJobEditInput.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/Inputs/AssembleIssueJobEditInput.cs @@ -58,12 +58,13 @@ public class AssembleIssueJobEditInput : SfsJobCreateUpdateInputBase, ISfsJobCre [Display(Name = "任务明细")] [Required(ErrorMessage = "{0}是必填项")] public List Details { get; set; } = new(); - /// /// 使用在途库 /// [Display(Name = "使用在途库")] public bool UseOnTheWayLocation { get; set; } + + public EnumIssueSendType EnumIssueSendType { get; set; } #endregion } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNotePermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNotePermissions.cs index 8624c5c4b..7902ff771 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNotePermissions.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNotePermissions.cs @@ -5,26 +5,19 @@ namespace Win_in.Sfs.Wms.Store.Application.Contracts; public static class AssembleIssueNotePermissions { - public const string Default = StorePermissions.GroupName + "." + nameof(AssembleIssueNote); public const string Create = Default + "." + StorePermissions.CreateStr; public const string Update = Default + "." + StorePermissions.UpdateStr; public const string Delete = Default + "." + StorePermissions.DeleteStr; - //自动发料记录 - public const string AutoAssembleIssueNote = StorePermissions.GroupName + "." + nameof(AutoAssembleIssueNote); - //直接发料 - public const string DirectAssembleIssueNote = StorePermissions.GroupName + "." + nameof(DirectAssembleIssueNote); public static void AddAssembleIssueNotePermission(this PermissionGroupDefinition permissionGroup) { - var AssembleIssueNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueNote))); - AssembleIssueNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr)); - AssembleIssueNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr)); - AssembleIssueNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr)); + var assembleIssueNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueNote))); + assembleIssueNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr)); + assembleIssueNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr)); + assembleIssueNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr)); - permissionGroup.AddPermission(AutoAssembleIssueNote, StorePermissionDefinitionProvider.L(nameof(AutoAssembleIssueNote))); - permissionGroup.AddPermission(DirectAssembleIssueNote, StorePermissionDefinitionProvider.L(nameof(DirectAssembleIssueNote))); } } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/DTOs/AssembleIssueNoteDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/DTOs/AssembleIssueNoteDTO.cs index 5662ecd0b..e071a27f0 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/DTOs/AssembleIssueNoteDTO.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/DTOs/AssembleIssueNoteDTO.cs @@ -44,4 +44,5 @@ public class AssembleIssueNoteDTO : SfsStoreDTOBase, [Display(Name = "确认时间")] public DateTime? ConfirmTime { get; set; } + public EnumIssueSendType EnumIssueSendType { get; set; } } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/IAssembleIssueNoteAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/IAssembleIssueNoteAppService.cs index 9e08af906..adcc01df6 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/IAssembleIssueNoteAppService.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/IAssembleIssueNoteAppService.cs @@ -12,5 +12,4 @@ public interface IAssembleIssueNoteAppService : ISfsStoreMasterReadOnlyAppServic Task ConfirmAsync(Guid id); - } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteEditInput.cs index ac5e63b64..491308905 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteEditInput.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteEditInput.cs @@ -27,7 +27,7 @@ public class AssembleIssueNoteEditInput : SfsStoreCreateOrUpdateInputBase /// [Display(Name = "任务ID")] [Required(ErrorMessage = "{0}是必填项")] - public string JobNumber { get; set; } + public string JobNumber { get; set; } /// /// 明细列表 @@ -52,5 +52,7 @@ public class AssembleIssueNoteEditInput : SfsStoreCreateOrUpdateInputBase /// [Display(Name = "使用在途库")] public bool UseOnTheWayLocation { get; set; } + + public EnumIssueSendType EnumIssueSendType { get; set; } #endregion } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteImportInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteImportInput.cs index 6c43288f4..04b31439f 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteImportInput.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteImportInput.cs @@ -31,4 +31,6 @@ public class AssembleIssueNoteImportInput : SfsStoreImportInputBase, IHasJobNumb [Display(Name = "使用在途库")] [Required(ErrorMessage = "{0}是必填项")] public bool UseOnTheWayLocation { get; set; } + + public EnumIssueSendType EnumIssueSendType { get; set; } } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/KittingIssueNotes/KittingIssueNotePermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/KittingIssueNotes/KittingIssueNotePermissions.cs index 9a633fdd9..3afd47039 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/KittingIssueNotes/KittingIssueNotePermissions.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/KittingIssueNotes/KittingIssueNotePermissions.cs @@ -15,10 +15,10 @@ public static class KittingIssueNotePermissions public static void AddKittingIssueNotePermission(this PermissionGroupDefinition permissionGroup) { - var injectionNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(KittingIssueNote))); - injectionNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr)); - injectionNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr)); - injectionNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr)); + var kittingIssueNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(KittingIssueNote))); + kittingIssueNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr)); + kittingIssueNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr)); + kittingIssueNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr)); } } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/AssembleIssueRequestPermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/AssembleIssueRequestPermissions.cs index 582e47097..588253297 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/AssembleIssueRequestPermissions.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/AssembleIssueRequestPermissions.cs @@ -10,15 +10,13 @@ public static class AssembleIssueRequestPermissions public const string Create = Default + "." + StorePermissions.CreateStr; public const string Update = Default + "." + StorePermissions.UpdateStr; public const string Delete = Default + "." + StorePermissions.DeleteStr; - public static void AddAssembleIssueRequestPermission(this PermissionGroupDefinition permissionGroup) { - var AssembleIssueRequestPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueRequest))); - AssembleIssueRequestPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr)); - AssembleIssueRequestPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr)); - AssembleIssueRequestPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr)); - + var assembleIssueRequestPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueRequest))); + assembleIssueRequestPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr)); + assembleIssueRequestPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr)); + assembleIssueRequestPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr)); } } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDTO.cs index de36cc057..a8a2d45fa 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDTO.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDTO.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using Win_in.Sfs.Shared.Domain.Shared.Enums.Store; namespace Win_in.Sfs.Wms.Store.Application.Contracts; @@ -8,8 +9,7 @@ public class AssembleIssueRequestDTO : SfsStoreRequestDTOBase [Display(Name = "叫料类型")] - public string Type { get; set; } - + public EnumIssueRequestType IssueRequestType { get; set; } /// /// 是否使用在途库 /// diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDetailDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDetailDTO.cs index b83de6cb9..534e25fb6 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDetailDTO.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDetailDTO.cs @@ -8,49 +8,92 @@ namespace Win_in.Sfs.Wms.Store.Application.Contracts; public class AssembleIssueRequestDetailDTO : SfsStoreDetailWithQtyDTOBase { + #region 目标库位信息 + + /// + /// 目标库位 + /// + [Display(Name = "目标库位")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string ToLocationCode { get; set; } + + /// + /// 目标库区 + /// + [Display(Name = "目标库区")] + public string ToLocationArea { get; set; } + /// - /// 已发数量 + /// 目标库位组 + /// + [Display(Name = "目标库位组")] + public string ToLocationGroup { get; set; } + + /// + /// 目标ERP储位 + /// + [Display(Name = "目标ERP储位")] + public string ToLocationErpCode { get; set; } + + /// + /// 目标仓库 + /// + [Display(Name = "目标仓库")] + public string ToWarehouseCode { get; set; } + + #endregion + + /// + /// 生产线 + /// + public string ProdLine { get; set; } + + /// + /// 已发数量 /// - [Display(Name = "已发数量")] public decimal IssuedQty { get; set; } /// - /// 已收数量 + /// 已收数量 /// - [Display(Name = "已收数量")] public decimal ReceivedQty { get; set; } /// - /// 明细状态 + /// 明细状态 /// - [Display(Name = "明细状态")] public EnumStatus Status { get; set; } /// - /// 请求未发 + /// 请求未发 还未发送的数量 /// - [Display(Name = "请求未发")] [NotMapped] public decimal ToBeIssuedQty => Qty - IssuedQty; /// - /// 已发未收 + /// 已发未收 /// - [Display(Name = "已发未收")] [NotMapped] public decimal ToBeReceivedQty => IssuedQty - ReceivedQty; /// - /// 请求未收 + /// 请求未收 /// - [Display(Name = "请求未收")] [NotMapped] public decimal NotFinishQty => Qty - ReceivedQty; /// - /// 需求箱数量 + /// 位置码 + /// + public string PositionCode { get; set; } + + /// + /// 推荐类型 + /// + public EnumRecommendType RecommendType { get; set; } + + /// + /// 需求箱数量 /// [Display(Name = "需求箱数量")] public decimal BoxQty { get; set; } - } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/IAssembleIssueRequestAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/IAssembleIssueRequestAppService.cs index 1a4a83ad6..8ad90aad7 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/IAssembleIssueRequestAppService.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/IAssembleIssueRequestAppService.cs @@ -10,4 +10,6 @@ public interface IAssembleIssueRequestAppService { Task CreateAndHandleAsync(AssembleIssueRequestEditInput input); + Task UpdateStatusCompletedAsync(string number); + Task IsHasNewJobAsync(string requestNumber, List jobNumber); } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestEditInput.cs index 3de838e38..55f171b01 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestEditInput.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestEditInput.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Win_in.Sfs.Shared.Domain; +using Win_in.Sfs.Shared.Domain.Shared.Enums.Store; namespace Win_in.Sfs.Wms.Store.Application.Contracts; @@ -9,10 +10,10 @@ public class AssembleIssueRequestEditInput : SfsStoreRequestCreateOrUpdateInputB #region Base /// - /// 叫料类型 + /// 叫料类型 /// [Display(Name = "叫料类型")] - public string Type { get; set; } + public EnumIssueRequestType IssueRequestType { get; set; } /// /// 使用在途库 @@ -24,7 +25,7 @@ public class AssembleIssueRequestEditInput : SfsStoreRequestCreateOrUpdateInputB /// 明细列表 /// [Display(Name = "明细列表")] - public List Details { get; set; } = new List(); + public List Details { get; set; } = new List(); #endregion #region Create diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestImportInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestImportInput.cs index 6f6470dc3..27fb71914 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestImportInput.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestImportInput.cs @@ -1,22 +1,18 @@ using System.ComponentModel.DataAnnotations; using Win_in.Sfs.Shared.Application.Contracts; using Win_in.Sfs.Shared.Domain.Shared; +using Win_in.Sfs.Shared.Domain.Shared.Enums.Store; namespace Win_in.Sfs.Wms.Store.Application.Contracts; -[Display(Name = "叫料申请")] +[Display(Name = "叫料申请导入")] public class AssembleIssueRequestImportInput : SfsStoreImportInputBase { - /// - /// 叫料类型 + /// 叫料类型 /// [Display(Name = "叫料类型")] - [Required(ErrorMessage = "{0}是必填项")] - [ImporterHeader(Name = "叫料类型")] - [ExporterHeader(DisplayName = "叫料类型")] - [ValueMapping("人工拉动", EnumMaterialRequestType.Issue_Manual)] - public string Type { get; set; } + public EnumIssueRequestType IssueRequestType { get; set; } /// /// 物品代码 diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobAppService.cs index b28529921..5ce16111c 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobAppService.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobAppService.cs @@ -3,21 +3,29 @@ using System.Collections.Generic; using System.Data; using System.Linq; using System.Linq.Expressions; +using System.Net.Http.Headers; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Castle.Components.DictionaryAdapter; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using MyNamespace; using Volo.Abp; using Volo.Abp.Application.Dtos; using Win_in.Sfs.Basedata.Application.Contracts; using Win_in.Sfs.Basedata.Domain.Shared; using Win_in.Sfs.Shared.Domain; using Win_in.Sfs.Shared.Domain.Shared; +using Win_in.Sfs.Shared.Domain.Shared.Enums.Store; +using Win_in.Sfs.Wms.Inventory.Application.Contracts; using Win_in.Sfs.Wms.Store.Application.Contracts; using Win_in.Sfs.Wms.Store.Domain; using Win_in.Sfs.Wms.Store.Domain.Shared; +using Win_in.Sfs.Wms.Store.Jobs.IssueJobs.proxy; using Win_in.Sfs.Wms.Store.Notes; +using Win_in.Sfs.Wms.Store.Options; namespace Win_in.Sfs.Wms.Store.Application; @@ -28,17 +36,36 @@ public class AssembleIssueJobAppService AssembleIssueJobCheckInput, AssembleIssueJobEditInput>, IAssembleIssueJobAppService, ITransferLibCallback { - private readonly IAssembleIssueJobManager _assembleJobManager; + private readonly IAssembleIssueJobManager _assembleIssueJobManager; private readonly ILocationAppService _locationAppService; private readonly ITransferLibJobAppService _transferLibJobAppService; + private readonly IAssembleIssueNoteAppService _assembleIssueNoteAppService; + private readonly IExpectOutAppService _expectOutAppService; + private readonly IHttpClientFactory _httpClientFactory; + private readonly IOptions _options; + + protected IAssembleIssueRequestAppService AssembleIssueRequestAppService => + LazyServiceProvider.LazyGetRequiredService(); public AssembleIssueJobAppService( - IAssembleIssueJobRepository repository, IAssembleIssueJobManager assembleJobManager, - ILocationAppService locationAppService, ITransferLibJobAppService transferLibJobAppService) : base(repository, assembleJobManager) + IAssembleIssueJobRepository repository, IAssembleIssueJobManager assembleIssueJobManager, + ILocationAppService locationAppService, ITransferLibJobAppService transferLibJobAppService, + IAssembleIssueNoteAppService assembleIssueNoteAppService, IExpectOutAppService expectOutAppService + , IHttpClientFactory httpClientFactory + , IOptions options + + + + ) : base( + repository, assembleIssueJobManager) { - _assembleJobManager = assembleJobManager; + _assembleIssueJobManager = assembleIssueJobManager; _locationAppService = locationAppService; _transferLibJobAppService = transferLibJobAppService; + _assembleIssueNoteAppService = assembleIssueNoteAppService; + _expectOutAppService = expectOutAppService; + _httpClientFactory = httpClientFactory; + _options = options; } [HttpPost("add-many")] @@ -47,17 +74,183 @@ public class AssembleIssueJobAppService foreach (var input in inputs) { await CheckMinRowAndSetStatusAsync(input).ConfigureAwait(false); + await CheckDimensionalStorehouseAsync(input).ConfigureAwait(false); + } + + var assembleIssueJobDtos = await base.CreateManyAsync(inputs).ConfigureAwait(false); + foreach (var assembleIssueJobDto in assembleIssueJobDtos) + { + await CheckDimensionalStorehouseAsync(assembleIssueJobDto).ConfigureAwait(false); } - return await base.CreateManyAsync(inputs).ConfigureAwait(false); + return assembleIssueJobDtos; } [HttpPost("")] public override async Task CreateAsync(AssembleIssueJobEditInput input) { await CheckMinRowAndSetStatusAsync(input).ConfigureAwait(false); + await CheckDimensionalStorehouseAsync(input).ConfigureAwait(false); + + var assembleIssueJobDto = await base.CreateAsync(input).ConfigureAwait(false); + await CheckDimensionalStorehouseAsync(assembleIssueJobDto).ConfigureAwait(false); + + return assembleIssueJobDto; + } + + [HttpPost("invalid")] + public override async Task CancelAsync(Guid id) + { + var injectionJob = await _repository.GetAsync(id).ConfigureAwait(false); + if (injectionJob == null) + { + throw new UserFriendlyException($"未找到ID为 {id} 的任务"); + } + + await _assembleIssueJobManager.CancelAsync(injectionJob).ConfigureAwait(false); + } + + [HttpPost("cancel-by-request/{requestNumber}")] + public virtual async Task CancelByMaterialRequestAsync(string requestNumber) + { + var entities = await _repository.GetListAsync(p => p.AssembleRequestNumber == requestNumber) + .ConfigureAwait(false); + foreach (var entity in entities) + { + await _assembleIssueJobManager.CancelAsync(entity).ConfigureAwait(false); + } + } - return await base.CreateAsync(input).ConfigureAwait(false); + [HttpPost("by-request-number/{requestNumber}")] + public virtual async Task> GetByRequestNumberAsync(string requestNumber) + { + var entitys = await _repository.GetListAsync(p => p.AssembleRequestNumber == requestNumber) + .ConfigureAwait(false); + return ObjectMapper.Map, List>(entitys); + } + + /// + /// 库移回调 + /// + /// + /// + [HttpPost("Do-Call-Back")] + public async Task DoTransferLibCallbackAsync(TransferLibJobDTO dto) + { + var job = await _repository.FindAsync(p => p.Number == dto.CallJobNumber).ConfigureAwait(false); + + var transferLibJobDto = await _transferLibJobAppService.GetByNumberAsync(dto.Number).ConfigureAwait(false); + + var transferLibNoteDetail = dto.Details.First(); + + var jobDetail = job.Details.First(); + job.JobStatus = EnumJobStatus.Open; + + jobDetail.TransferLibFromArriveDate = transferLibNoteDetail.HandledFromArriveDate; + jobDetail.TransferLibFromContainerCode = transferLibNoteDetail.HandledFromContainerCode; + jobDetail.TransferLibFromExpireDate = transferLibNoteDetail.HandledFromExpireDate; + jobDetail.TransferLibFromLocationArea = transferLibNoteDetail.HandledFromLocationArea; + jobDetail.TransferLibFromLocationCode = transferLibNoteDetail.HandledFromLocationCode; + jobDetail.TransferLibFromLocationErpCode = transferLibNoteDetail.HandledFromLocationErpCode; + jobDetail.TransferLibFromLocationGroup = transferLibNoteDetail.HandledFromLocationGroup; + jobDetail.TransferLibFromLot = transferLibNoteDetail.HandledFromLot; + jobDetail.TransferLibFromPackingCode = transferLibNoteDetail.HandledFromPackingCode; + jobDetail.TransferLibFromProduceDate = transferLibNoteDetail.HandledFromProduceDate; + jobDetail.TransferLibFromQty = transferLibNoteDetail.HandledFromQty; + jobDetail.TransferLibFromSupplierBatch = transferLibNoteDetail.HandledFromSupplierBatch; + jobDetail.TransferLibFromWarehouseCode = transferLibNoteDetail.HandledFromWarehouseCode; + + jobDetail.TransferLibToArriveDate = transferLibNoteDetail.HandledToArriveDate; + jobDetail.TransferLibToContainerCode = transferLibNoteDetail.HandledToContainerCode; + jobDetail.TransferLibToExpireDate = transferLibNoteDetail.HandledToExpireDate; + jobDetail.TransferLibToLocationArea = transferLibNoteDetail.HandledToLocationArea; + jobDetail.TransferLibToLocationCode = transferLibNoteDetail.HandledToLocationCode; + jobDetail.TransferLibToLocationErpCode = transferLibNoteDetail.HandledToLocationErpCode; + jobDetail.TransferLibToLocationGroup = transferLibNoteDetail.HandledToLocationGroup; + jobDetail.TransferLibToLot = transferLibNoteDetail.HandledToLot; + jobDetail.TransferLibToPackingCode = transferLibNoteDetail.HandledToPackingCode; + jobDetail.TransferLibToProduceDate = transferLibNoteDetail.HandledToProduceDate; + jobDetail.TransferLibToQty = transferLibNoteDetail.HandledToQty; + jobDetail.TransferLibToSupplierBatch = transferLibNoteDetail.HandledToSupplierBatch; + jobDetail.TransferLibToWarehouseCode = transferLibNoteDetail.HandledToWarehouseCode; + + await _repository.UpdateAsync(job).ConfigureAwait(false); + } + + /// + /// 执行任务明细 + /// + /// + [HttpPost("ExecuteDetail/{masterId}")] + public async Task ExecuteDetailAsync(Guid masterId, Guid detailId, AssembleIssueJobDetailDTO issueJobDetailDto) + { + var assembleIssueJob = await _repository.GetAsync(masterId).ConfigureAwait(false); + assembleIssueJob.JobStatus = EnumJobStatus.Doing; + + var assembleIssueJobDto = ObjectMapper.Map(assembleIssueJob); + assembleIssueJobDto.Details = new List { issueJobDetailDto }; + var assembleIssueNoteEditInput = await BuildAssembleIssueNoteAsync(assembleIssueJobDto).ConfigureAwait(false); + await _assembleIssueNoteAppService.CreateAsync(assembleIssueNoteEditInput).ConfigureAwait(false); + + var issueJobDetail = ObjectMapper.Map(issueJobDetailDto); + var entityDetail = assembleIssueJob.Details.Find(p => p.Id == detailId); + issueJobDetail.HandledFromQty = entityDetail.HandledFromQty; + issueJobDetail.HandledToQty = entityDetail.HandledToQty; + + issueJobDetail.HandledToQty += issueJobDetailDto.HandledToQty; + issueJobDetail.HandledFromQty += issueJobDetailDto.HandledFromQty; + assembleIssueJob.Details = new EditableList() { issueJobDetail }; + + if (assembleIssueJob.EnumIssueSendType == EnumIssueSendType.BoxQtyType) //按箱叫料 因为任务只有1箱 所以可以直接完成 + { + await UpdateRequestAndjobStatusDoneAsync(assembleIssueJob, issueJobDetailDto, issueJobDetailDto.HandledToQty).ConfigureAwait(false); + } + else + { + var detail = assembleIssueJob.Details.First(p => p.Id == issueJobDetailDto.Id); + if (issueJobDetail.HandledToQty >= detail.RequestQty) + { + await UpdateRequestAndjobStatusDoneAsync(assembleIssueJob, issueJobDetailDto, issueJobDetailDto.HandledToQty).ConfigureAwait(false); + } + } + + await _repository.UpdateAsync(assembleIssueJob).ConfigureAwait(false); + } + + [HttpPost("CompleteAsync/{id}")] + public async Task CompleteAsync(Guid id) + { + var assembleIssueJob = await _repository.FindAsync(id).ConfigureAwait(false); + + assembleIssueJob.JobStatus = EnumJobStatus.Done; + + await _expectOutAppService.RemoveByNumberAndInventoryAsync(assembleIssueJob.Number, + assembleIssueJob.Details.First().ItemCode, + assembleIssueJob.Details.First().HandledToLocationCode, assembleIssueJob.Details.First().HandledToPackingCode, + assembleIssueJob.Details.First().Status, assembleIssueJob.Details.First().HandledToLot, + assembleIssueJob.Details.First().HandledToQty).ConfigureAwait(false); + + await _expectOutAppService.RemoveByNumberAsync(assembleIssueJob.Number).ConfigureAwait(false); + + await _repository.UpdateAsync(assembleIssueJob).ConfigureAwait(false); + } + + #region 私有 + + /// + /// 创建补料记录实体 + /// + /// + /// + private async Task BuildAssembleIssueNoteAsync(AssembleIssueJobDTO assembleIssueJobDto) + { + var assembleIssueNoteCreateInput = + ObjectMapper.Map(assembleIssueJobDto); + assembleIssueNoteCreateInput.JobNumber = assembleIssueJobDto.Number; + + await Task.CompletedTask.ConfigureAwait(false); + + return assembleIssueNoteCreateInput; } /// @@ -75,7 +268,9 @@ public class AssembleIssueJobAppService if (loctionDto.Type == EnumLocationType.RAW && loctionDto.RowCode != 1) { input.JobStatus = EnumJobStatus.Wait; - + } + else if (loctionDto.Type == EnumLocationType.RAW && loctionDto.RowCode == 1) + { jobDetailInputdetail.TransferLibFromArriveDate = jobDetailInputdetail.RecommendFromArriveDate; jobDetailInputdetail.TransferLibFromContainerCode = jobDetailInputdetail.RecommendFromContainerCode; jobDetailInputdetail.TransferLibFromExpireDate = jobDetailInputdetail.RecommendFromExpireDate; @@ -93,101 +288,247 @@ public class AssembleIssueJobAppService jobDetailInputdetail.TransferLibToArriveDate = jobDetailInputdetail.RecommendToArriveDate; jobDetailInputdetail.TransferLibToContainerCode = jobDetailInputdetail.RecommendToContainerCode; jobDetailInputdetail.TransferLibToExpireDate = jobDetailInputdetail.RecommendToExpireDate; - jobDetailInputdetail.TransferLibToLocationArea = jobDetailInputdetail.RecommendToLocationArea; - jobDetailInputdetail.TransferLibToLocationCode = jobDetailInputdetail.RecommendToLocationCode; - jobDetailInputdetail.TransferLibToLocationErpCode = jobDetailInputdetail.RecommendToLocationErpCode; - jobDetailInputdetail.TransferLibToLocationGroup = jobDetailInputdetail.RecommendToLocationGroup; jobDetailInputdetail.TransferLibToLot = jobDetailInputdetail.RecommendToLot; jobDetailInputdetail.TransferLibToPackingCode = jobDetailInputdetail.RecommendToPackingCode; jobDetailInputdetail.TransferLibToProduceDate = jobDetailInputdetail.RecommendToProduceDate; jobDetailInputdetail.TransferLibToQty = jobDetailInputdetail.RecommendToQty; jobDetailInputdetail.TransferLibToSupplierBatch = jobDetailInputdetail.RecommendToSupplierBatch; - jobDetailInputdetail.TransferLibToWarehouseCode = jobDetailInputdetail.RecommendToWarehouseCode; + jobDetailInputdetail.TransferLibToWarehouseCode = jobDetailInputdetail.TransferLibFromWarehouseCode; + jobDetailInputdetail.TransferLibToLocationArea = jobDetailInputdetail.TransferLibFromLocationArea; + jobDetailInputdetail.TransferLibToLocationCode = jobDetailInputdetail.TransferLibFromLocationCode; + jobDetailInputdetail.TransferLibToLocationErpCode = jobDetailInputdetail.TransferLibFromLocationErpCode; + jobDetailInputdetail.TransferLibToLocationGroup = jobDetailInputdetail.TransferLibFromLocationGroup; } } - [HttpPost("cancel-by-request/{assembleRequestNumber}")] - public virtual async Task CancelByMaterialRequestAsync(string assembleNumber) + /// + /// 判断是不是在立体库 + /// + /// + /// + private async Task CheckDimensionalStorehouseAsync(AssembleIssueJobEditInput input) { - var entities = await _repository.GetListAsync(p => p.AssembleRequestNumber == assembleNumber) + var jobDetailInputdetail = input.Details.FirstOrDefault(); + + var loctionDto = await _locationAppService.GetByCodeAsync(jobDetailInputdetail.RecommendFromLocationCode) .ConfigureAwait(false); - foreach (var entity in entities) + + if (loctionDto.Type == EnumLocationType.DimensionalStorehouse) { - await _assembleJobManager.CancelAsync(entity).ConfigureAwait(false); + input.JobStatus = EnumJobStatus.Wait; } } - [HttpPost("invalid")] - public override async Task CancelAsync(Guid id) + /// + /// 判断是不是在立体库 + /// + /// + /// + private async Task CheckDimensionalStorehouseAsync(AssembleIssueJobDTO assembleIssueJobDto) { - var assembleJob = await _repository.GetAsync(id).ConfigureAwait(false); - if (assembleJob == null) + var jobDetailInputdetail = assembleIssueJobDto.Details.FirstOrDefault(); + + var loctionDto = await _locationAppService.GetByCodeAsync(jobDetailInputdetail.RecommendFromLocationCode) + .ConfigureAwait(false); + + if (loctionDto.Type == EnumLocationType.DimensionalStorehouse) { - throw new UserFriendlyException($"未找到ID为 {id} 的任务"); + //TODO 立体库 + var ret = await SyncIssueJobStereoAsync(new List { assembleIssueJobDto }, loctionDto.Code).ConfigureAwait(false); + if (ret.Code != "1") + { + throw new UserFriendlyException($"调用立体库不成功!原因:{ret.Message}"); + } } - await _assembleJobManager.CancelAsync(assembleJob).ConfigureAwait(false); + } - [HttpPost("by-request-number/{requestNumber}")] - public virtual async Task> GetByRequestNumberAsync(string requestNumber) + /// + /// 修改当前任务状态 和 该任务的请求状态 + /// + /// + /// + /// + /// + private async Task UpdateRequestAndjobStatusDoneAsync(AssembleIssueJob assembleIssueJob, + AssembleIssueJobDetailDTO assembleIssueJobDetailDto, decimal handledToQty) { - var entitys = await _repository.GetListAsync(p => p.AssembleRequestNumber == requestNumber) + if (assembleIssueJob.JobStatus is EnumJobStatus.Closed or EnumJobStatus.Cancelled or EnumJobStatus.None + or EnumJobStatus.Done) //需要考虑下 多次提交的问题 所以不判断 进行中 + { + throw new UserFriendlyException( + $"任务状态错误:编号为【{assembleIssueJob.Number}】的任务状态为【{assembleIssueJob.JobStatus.GetDisplayName()}】"); + } + + assembleIssueJob.JobStatus = EnumJobStatus.Done; + + await _expectOutAppService.RemoveByNumberAndInventoryAsync(assembleIssueJob.Number, + assembleIssueJobDetailDto.ItemCode, + assembleIssueJobDetailDto.HandledToLocationCode, assembleIssueJobDetailDto.HandledToPackingCode, + assembleIssueJobDetailDto.Status, assembleIssueJobDetailDto.HandledToLot, + handledToQty).ConfigureAwait(false); + + //await _expectOutAppService.RemoveByNumberAsync(assembleIssueJob.Number).ConfigureAwait(false); + + await AssembleIssueRequestAppService.UpdateStatusCompletedAsync(assembleIssueJob.AssembleRequestNumber) .ConfigureAwait(false); - return ObjectMapper.Map, List>(entitys); + + await Task.CompletedTask.ConfigureAwait(false); } - [HttpPost("Do-Call-Back")] - public async Task DoTransferLibCallbackAsync(TransferLibJobDTO dto) - { - var job = await _repository.FindAsync(p => p.Number == dto.JobNumber).ConfigureAwait(false); - //todo 等云峰写好换成真实的 - var transferLibJobDto = await _transferLibJobAppService.GetByNumberAsync("AAA").ConfigureAwait(false); - var transferLibNote = new TransferLibNote(); - var transferLibNoteDetail = transferLibNote.Details.First(); - var jobDetail = job.Details.First(); - job.JobStatus = EnumJobStatus.Open; + /// + /// 立体库同步 + /// + /// + /// + /// + [HttpPost("sync-issue-job-stereo")] - jobDetail.TransferLibFromArriveDate = transferLibNoteDetail.HandledFromArriveDate; - jobDetail.TransferLibFromContainerCode = transferLibNoteDetail.HandledFromContainerCode; - jobDetail.TransferLibFromExpireDate = transferLibNoteDetail.HandledFromExpireDate; - jobDetail.TransferLibFromLocationArea = transferLibNoteDetail.HandledFromLocationArea; - jobDetail.TransferLibFromLocationCode = transferLibNoteDetail.HandledFromLocationCode; - jobDetail.TransferLibFromLocationErpCode = transferLibNoteDetail.HandledFromLocationErpCode; - jobDetail.TransferLibFromLocationGroup = transferLibNoteDetail.HandledFromLocationGroup; - jobDetail.TransferLibFromLot = transferLibNoteDetail.HandledFromLot; - jobDetail.TransferLibFromPackingCode = transferLibNoteDetail.HandledFromPackingCode; - jobDetail.TransferLibFromProduceDate = transferLibNoteDetail.HandledFromProduceDate; - jobDetail.TransferLibFromQty = transferLibNoteDetail.HandledFromQty; - jobDetail.TransferLibFromSupplierBatch = transferLibNoteDetail.HandledFromSupplierBatch; - jobDetail.TransferLibFromWarehouseCode = transferLibNoteDetail.HandledFromWarehouseCode; + public async Task SyncIssueJobStereoAsync(List input, string p_loc) + { + ReusltObject ret = new ReusltObject(); + ret.Code = "1"; + ret.Message = "操作成功"; + ret.OperateTime = DateTime.Now.ToString("yyyy-MM-dd"); + try + { + List IssueJobToRestoDetailDTOs = new List(); + IssueJobToRestoDTO main = new IssueJobToRestoDTO(); + main.OperatorName = CurrentUser.UserName; + foreach (var job in input) + { + foreach (var jobitem in job.Details) + { + IssueJobToRestoDetailDTOs.Add(new IssueJobToRestoDetailDTO() + { + Count = jobitem.HandledToQty, + ProductNo = jobitem.ItemCode, + NeedSite = p_loc, + WorkNo = job.Number, + TaskNo = job.Number + }); + } + } + main.Details = IssueJobToRestoDetailDTOs; + var httpclient = _httpClientFactory.CreateClient(); +#if DEBUG - jobDetail.TransferLibToArriveDate = transferLibNoteDetail.HandledToArriveDate; - jobDetail.TransferLibToContainerCode = transferLibNoteDetail.HandledToContainerCode; - jobDetail.TransferLibToExpireDate = transferLibNoteDetail.HandledToExpireDate; - jobDetail.TransferLibToLocationArea = transferLibNoteDetail.HandledToLocationArea; - jobDetail.TransferLibToLocationCode = transferLibNoteDetail.HandledToLocationCode; - jobDetail.TransferLibToLocationErpCode = transferLibNoteDetail.HandledToLocationErpCode; - jobDetail.TransferLibToLocationGroup = transferLibNoteDetail.HandledToLocationGroup; - jobDetail.TransferLibToLot = transferLibNoteDetail.HandledToLot; - jobDetail.TransferLibToPackingCode = transferLibNoteDetail.HandledToPackingCode; - jobDetail.TransferLibToProduceDate = transferLibNoteDetail.HandledToProduceDate; - jobDetail.TransferLibToQty = transferLibNoteDetail.HandledToQty; - jobDetail.TransferLibToSupplierBatch = transferLibNoteDetail.HandledToSupplierBatch; - jobDetail.TransferLibToWarehouseCode = transferLibNoteDetail.HandledToWarehouseCode; + string json = System.Text.Json.JsonSerializer.Serialize(main); + _options.Value.Address = "http://localhost:59094/";//测试地址 + _options.Value.Token = "";//测试token + _options.Value.UserName = "";//测试用户名 + _options.Value.Password = "";//测试密码 - await _repository.UpdateAsync(job).ConfigureAwait(false); +#endif + if (!string.IsNullOrEmpty(_options.Value.Token)) + { + var token = _options.Value.Token; + httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + } + if (!string.IsNullOrEmpty(_options.Value.UserName) && !string.IsNullOrEmpty(_options.Value.Password)) + { + var username = _options.Value.UserName; + var password = _options.Value.Password; + httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{username}:{password}"))); + } + + IssueJobToRestoClient client = new IssueJobToRestoClient(_options.Value.Address, httpclient); + ret = await client.SyncIssueJobStereoAsync(main).ConfigureAwait(false); + } + catch (Exception ex) + { + ret = new ReusltObject(); + ret.Code = "2"; + ret.Message = ex.Message; + ret.OperateTime = DateTime.Now.ToString("yyyy-MM-dd"); + } + + return ret; - return; } - [HttpPost("test")] - public virtual async Task Test() + [HttpPost("receive-issue-job-stereo")] + public virtual async Task SyncReciveIssueJobStereoAsync(IssueRequestFromRestoDTO input) { - Console.WriteLine("FuAZCZXVZXVXZVZ"); - await Task.CompletedTask; + +#if DEBUG + var json = System.Text.Json.JsonSerializer.Serialize(input); +#endif + List errors = new List(); + var ret = new ReusltObject() + { + Code = "1", + OperateTime = DateTime.Now.ToString("yyyy-MM-dd"), + Message = "操作成功" + }; + try + { + + if (input.Jobs.Count > 0) + { + var jobs = input.Jobs; + var numbers = jobs.Select(p => p.JobNumber); + var query = _repository.WithDetails() + .Where(p => numbers.Contains(p.Number)); + var entities = query.ToList(); + var dtos = ObjectMapper.Map, List>(entities); + if (input.Jobs.Count == entities.Count) + { + errors.Add("立体库提交出库任务和WMS任务不符,请核对! \n"); + } + foreach (var itm in dtos) + { + var first = jobs.FirstOrDefault(p => p.JobNumber == itm.Number); + var itmDetails = itm.Details.ToList(); + List details = new List(); + foreach (var detail in first.Details) + { + var entity = itmDetails.FirstOrDefault(p => p.ItemCode == detail.ItemCode); + AssembleIssueJobDetailDTO dto = new AssembleIssueJobDetailDTO(); + dto.HandledFromLocationCode = entity.HandledFromLocationCode; + dto.HandledToLocationCode = entity.HandledToLocationCode; + dto.ItemCode = detail.ItemCode; + dto.RecommendFromQty = detail.Qty; + dto.RecommendToQty = detail.Qty; + dto.HandledFromQty = detail.Qty; + dto.HandledToQty = detail.Qty; + dto.Status = entity.Status; + details.Add(dto); + } + itm.Details = details; + await CompleteAsync(itm.Id, itm).ConfigureAwait(false); + } + } + else + { + errors.Add("立体库确认单据里无数据! \n"); + } + } + catch (Exception ex) + { + ret = new ReusltObject() + { + Code = "2", + OperateTime = DateTime.Now.ToString("yyyy-MM-dd"), + Message = ex.Message + }; + return ret; + } + if (errors.Count > 0) + { + + ret = new ReusltObject() + { + Code = "2", + OperateTime = DateTime.Now.ToString("yyyy-MM-dd"), + Message = string.Join(",", errors.ToArray()) + }; + } + return ret; } + #endregion } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNoteAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNoteAppService.cs index 36ce2a342..ec42d0293 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNoteAppService.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNoteAppService.cs @@ -18,20 +18,20 @@ using Win_in.Sfs.Wms.Store.Domain.Shared; namespace Win_in.Sfs.Wms.Store.Application; [Authorize] -[Route($"{StoreConsts.RootPath}assemble-note")] +[Route($"{StoreConsts.RootPath}assemble-issue-note")] public class AssembleIssueNoteAppService : SfsStoreWithDetailsAppServiceBase, IAssembleIssueNoteAppService { - private readonly IAssembleIssueNoteManager _assembleNoteManager; + private readonly IAssembleIssueNoteManager _assembleIssueNoteManager; public AssembleIssueNoteAppService( IAssembleIssueNoteRepository repository, - IAssembleIssueNoteManager assembleNoteManager + IAssembleIssueNoteManager assembleIssueNoteManager ) : base(repository) { - _assembleNoteManager = assembleNoteManager; + _assembleIssueNoteManager = assembleIssueNoteManager; } [HttpPost("")] @@ -39,7 +39,7 @@ public class AssembleIssueNoteAppService : public override async Task CreateAsync(AssembleIssueNoteEditInput input) { var entity = ObjectMapper.Map(input); - await _assembleNoteManager.CreateAsync(entity).ConfigureAwait(false); + await _assembleIssueNoteManager.CreateAsync(entity).ConfigureAwait(false); var dto = ObjectMapper.Map(entity); return dto; } @@ -52,10 +52,11 @@ public class AssembleIssueNoteAppService : [HttpPost("confirm/{id}")] public virtual async Task ConfirmAsync(Guid id) { - var assembleNote= await _repository.GetAsync(id).ConfigureAwait(false); - assembleNote.Confirmed = true; - assembleNote=await _repository.UpdateAsync(assembleNote).ConfigureAwait(false); - await LocalEventBus.PublishAsync(new SfsConfirmedEntityEventData(assembleNote), false).ConfigureAwait(false); - return ObjectMapper.Map(assembleNote); + var assembleIssueNote = await _repository.GetAsync(id).ConfigureAwait(false); + assembleIssueNote.Confirmed = true; + assembleIssueNote = await _repository.UpdateAsync(assembleIssueNote).ConfigureAwait(false); + await LocalEventBus.PublishAsync(new SfsConfirmedEntityEventData(assembleIssueNote), false).ConfigureAwait(false); + return ObjectMapper.Map(assembleIssueNote); } + } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/IssuelRequests/AssembleIssueRequests/AssembleIssueRequestAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/IssuelRequests/AssembleIssueRequests/AssembleIssueRequestAppService.cs index e673737eb..e101cd276 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/IssuelRequests/AssembleIssueRequests/AssembleIssueRequestAppService.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/IssuelRequests/AssembleIssueRequests/AssembleIssueRequestAppService.cs @@ -1,7 +1,11 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; +using Castle.Components.DictionaryAdapter; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using NUglify.Helpers; using Volo.Abp; using Win_in.Sfs.Basedata.Application.Contracts; using Win_in.Sfs.Shared.Domain.Shared; @@ -12,39 +16,38 @@ using Win_in.Sfs.Wms.Store.Domain.Shared; namespace Win_in.Sfs.Wms.Store.Application; /// -/// 装配叫料 +/// 装配叫料申请 /// [Authorize] -[Route($"{StoreConsts.RootPath}assemble-request")] -public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase, IAssembleIssueRequestAppService { - private readonly IAssembleIssueRequestManager _assembleRequestManager; + private readonly IAssembleIssueRequestManager _assembleIssueRequestManager; private readonly IItemStoreRelationAppService _itemStoreRelationApp; private readonly IAreaAppService _areaApp; private readonly ILocationAppService _locationAppService; private readonly IItemBasicAppService _itemBasicAppService; private readonly IProductionLineAppService _productionLineAppService; + private readonly IAssembleIssueJobAppService _assembleIssueJobAppService; + private readonly ITransactionTypeAppService _transactionTypeAppService; public AssembleIssueRequestAppService( IAssembleIssueRequestRepository repository, - IAssembleIssueRequestManager assembleRequestManager, + IAssembleIssueRequestManager assembleIssueRequestManager, IPreparationPlanManager preparationPlanManager, IItemStoreRelationAppService itemStoreRelationApp, IAreaAppService areaApp, ILocationAppService locationAppService, IItemBasicAppService itemBasicAppService, IProductionLineAppService productionLineAppService, - ITransactionTypeAppService transactionTypeAppService - ) - : base(repository, assembleRequestManager) + ITransactionTypeAppService transactionTypeAppService, IAssembleIssueJobAppService assembleIssueJobAppService) + : base(repository, assembleIssueRequestManager) { - _assembleRequestManager = assembleRequestManager; + _assembleIssueRequestManager = assembleIssueRequestManager; _itemStoreRelationApp = itemStoreRelationApp; _areaApp = areaApp; _locationAppService = locationAppService; @@ -52,13 +55,12 @@ public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase HandleAsync(Guid id) { - await Task.CompletedTask.ConfigureAwait(false); - return null; + return await base.HandleAsync(id).ConfigureAwait(false); } [HttpPost("")] @@ -72,18 +74,21 @@ public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase(input); - var result = await _assembleRequestManager.CreateByNumberAsync(entity).ConfigureAwait(false); + var result = await _assembleIssueRequestManager.CreateByNumberAsync(entity).ConfigureAwait(false); var dto = ObjectMapper.Map(result); @@ -127,16 +133,210 @@ public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase CreateAndHandleAsync(AssembleIssueRequestEditInput input) { - var assembleRequestDto = await CreateAsync(input).ConfigureAwait(false); + var assembleIssueRequestDto = await CreateAsync(input).ConfigureAwait(false); - await HandleAsync(assembleRequestDto.Id).ConfigureAwait(false); + //await HandleAsync(assembleIssueRequestDto.Id).ConfigureAwait(false); + + return assembleIssueRequestDto; + } + + public override async Task CancelAsync(Guid id) + { + var request = await _repository.GetAsync(id).ConfigureAwait(false); + + var list = await _assembleIssueJobAppService.GetByRequestNumberAsync(request.Number).ConfigureAwait(false); + if (list.Any()) + { + foreach (var assembleIssueJobDto in list) + { + if (assembleIssueJobDto.JobStatus == EnumJobStatus.Open || + assembleIssueJobDto.JobStatus == EnumJobStatus.Partial || + assembleIssueJobDto.JobStatus == EnumJobStatus.Doing || + assembleIssueJobDto.JobStatus == EnumJobStatus.Wait) + { + await _assembleIssueJobAppService.CancelAsync(assembleIssueJobDto.Id).ConfigureAwait(false); + } + } + } - return assembleRequestDto; + return await base.CancelAsync(id).ConfigureAwait(false); } + [HttpPost("UpdateStatusCompleted")] + public async Task UpdateStatusCompletedAsync(string number) + { + var assembleIssueRequest = await _repository.FindAsync(p => p.Number == number).ConfigureAwait(false); + + await UpdateAssembleIssueRequestDetailQtyAsync(assembleIssueRequest, new EditableList()).ConfigureAwait(false); + + var assembleIssueJobDtos = await _assembleIssueJobAppService.GetByRequestNumberAsync(assembleIssueRequest.Number).ConfigureAwait(false); + + if (assembleIssueJobDtos.Any(p => + p.JobStatus == EnumJobStatus.Open || p.JobStatus == EnumJobStatus.Doing || + p.JobStatus == EnumJobStatus.Partial)) + { + return; + } + else + { + bool flag = true; + + foreach (var detail in assembleIssueRequest.Details) + { + if (detail.Qty >= detail.IssuedQty) + { + flag = false; + return; + } + } + + if (flag) + { + CheckStatus(EnumRequestStatus.Completed, assembleIssueRequest.RequestStatus); + assembleIssueRequest.RequestStatus = EnumRequestStatus.Completed; + await _repository.UpdateAsync(assembleIssueRequest).ConfigureAwait(false); + } + } + } + + /// + /// 修改请求的 已发 已收数量 + /// + /// + /// + /// + private async Task UpdateAssembleIssueRequestDetailQtyAsync(AssembleIssueRequest assembleIssueRequest, + List addAssembleIssueJobDtos) + { + //原有任务 + var existAssembleIssueJobDtos = await _assembleIssueJobAppService.GetByRequestNumberAsync(assembleIssueRequest.Number) + .ConfigureAwait(false); + + //新增的任务和已有的任务总和 + var allAssembleIssueJobDtos = new List(); + allAssembleIssueJobDtos.AddRange(addAssembleIssueJobDtos); + allAssembleIssueJobDtos.AddRange(existAssembleIssueJobDtos); + + var groupByItemCodeLocationCode = assembleIssueRequest.Details.GroupBy(p => + new { p.ItemCode, p.ToLocationCode }); + foreach (var group in groupByItemCodeLocationCode) + { + foreach (var requestDetail in group) + { + //所有已发数量 + decimal allIssuedQty = 0; + + //所有已发数量 + decimal allReceivedQty = 0; + + foreach (var allAssembleIssueJobDto in allAssembleIssueJobDtos) + { + var jobDetailDtos = allAssembleIssueJobDto.Details.Where(p => + p.ItemCode == group.Key.ItemCode && p.RequestLocationCode == group.Key.ToLocationCode); + //所有已发数量 + allIssuedQty += jobDetailDtos.Sum(p => p.RequestQty); + //所有已发数量 + allReceivedQty += jobDetailDtos.Sum(p => p.HandledToQty); + } + + requestDetail.IssuedQty += allIssuedQty; + requestDetail.ReceivedQty += allReceivedQty; + } + } + + await _repository.UpdateAsync(assembleIssueRequest).ConfigureAwait(false); + } + + [HttpPost("IsHasNewJob")] + public async Task IsHasNewJobAsync(string requestNumber, List jobNumber) + { + var joblIssueJobDtos = await _assembleIssueJobAppService.GetByRequestNumberAsync(requestNumber).ConfigureAwait(false); + if (joblIssueJobDtos != null && joblIssueJobDtos.Any()) + { + var jobNumberList = joblIssueJobDtos.Select(p => p.Number); + + var difference = jobNumberList.Except(jobNumber); + if (difference.Any()) + { + var result = "已生成任务号"; + difference.ForEach(p => result += "【" + p + "】"); + result += "的任务"; + return result; + } + else + { + return "无任务生成,请检查库存"; + } + } + else + { + return "无任务生成,请检查库存"; + } + } #region 校验 + private void CheckStatus(EnumRequestStatus targetStatus, EnumRequestStatus nowStatus) + { + var validSourceStatuses = new List(); + switch (targetStatus) + { + case EnumRequestStatus.None: + break; + case EnumRequestStatus.New: + break; + case EnumRequestStatus.Reviewing: + validSourceStatuses = new List { EnumRequestStatus.New }; + break; + case EnumRequestStatus.Refused: + validSourceStatuses = new List { EnumRequestStatus.Reviewing }; + break; + case EnumRequestStatus.Agreed: + validSourceStatuses = new List { EnumRequestStatus.Reviewing }; + break; + case EnumRequestStatus.Handling: + validSourceStatuses = new List + { + EnumRequestStatus.Agreed, EnumRequestStatus.Partial, + }; + break; + case EnumRequestStatus.Completed: + validSourceStatuses = new List + { + EnumRequestStatus.Handling, EnumRequestStatus.Partial, + }; + break; + case EnumRequestStatus.Cancelled: + validSourceStatuses = new List + { + EnumRequestStatus.New, EnumRequestStatus.Reviewing, EnumRequestStatus.Agreed, + }; + break; + case EnumRequestStatus.Abort: + validSourceStatuses = new List + { + EnumRequestStatus.Handling, EnumRequestStatus.Partial, + }; + break; + case EnumRequestStatus.Partial: + { + validSourceStatuses = new List + { + EnumRequestStatus.Handling, EnumRequestStatus.Partial, + }; + break; + } + default: + throw new ArgumentOutOfRangeException(nameof(targetStatus), targetStatus, null); + } + + if (!validSourceStatuses.Contains(nowStatus)) + { + throw new UserFriendlyException( + $"当前状态为 {nowStatus.GetDisplayName()} ,无法变更为 {targetStatus.GetDisplayName()}"); + } + } + private void CheckItemBasic(ItemBasicDTO itemBasicDto, string itemCode) { if (itemBasicDto == null) @@ -158,5 +358,13 @@ public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase { - /// /// 叫料类型 /// @@ -44,6 +43,6 @@ public class AssembleIssueJob : SfsJobAggregateRootBase /// [IgnoreUpdate] public override List Details { get; set; } = new List(); - + public EnumIssueSendType EnumIssueSendType { get; set; } } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobDetail.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobDetail.cs index fd8a045b0..f14d1f76c 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobDetail.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobDetail.cs @@ -8,7 +8,6 @@ namespace Win_in.Sfs.Wms.Store.Domain; public class AssembleIssueJobDetail : SfsDetailEntityBase { - #region 库存基础信息 /// @@ -522,4 +521,5 @@ public class AssembleIssueJobDetail : SfsDetailEntityBase { this.Id = id; } + } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobManager.cs index 043623119..f7cab0c71 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobManager.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobManager.cs @@ -18,7 +18,9 @@ public class AssembleIssueJobManager : SfsJobManagerBase /// 明细列表 /// - [IgnoreUpdate] public override List Details { get; set; } = new List(); - [IgnoreUpdate] public string RequestNumber { get; set; } - /// /// 叫料类型 /// @@ -36,14 +33,12 @@ public class AssembleIssueNote : SfsStoreAggregateRootBase /// 使用在途库 /// - [IgnoreUpdate] public bool UseOnTheWayLocation { get; set; } /// /// 确认时间 /// [Display(Name = "确认时间")] - [IgnoreUpdate] public DateTime? ConfirmTime { get; set; } /// @@ -52,6 +47,8 @@ public class AssembleIssueNote : SfsStoreAggregateRootBase { /// - /// 叫料类型 + /// 叫料类型 /// [Display(Name = "叫料类型")] public EnumIssueRequestType IssueRequestType { get; set; } @@ -20,10 +20,5 @@ public class AssembleIssueRequest : SfsStoreRequestAggregateRootBase public bool UseOnTheWayLocation { get; set; } - - /// - /// 明细列表 - /// - [IgnoreUpdate] - public override List Details { get; set; } = new List(); + } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDetail.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDetail.cs index eef610f9d..0a811be58 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDetail.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDetail.cs @@ -11,7 +11,6 @@ namespace Win_in.Sfs.Wms.Store.Domain; /// public class AssembleIssueRequestDetail : SfsStoreDetailWithQtyEntityBase, IHasToLocation { - #region 目标库位信息 /// @@ -47,6 +46,7 @@ public class AssembleIssueRequestDetail : SfsStoreDetailWithQtyEntityBase, IHasT #endregion + /// /// 生产线 /// diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestManager.cs index c1e38f15f..f4e0adb6d 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestManager.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestManager.cs @@ -14,29 +14,24 @@ public class AssembleIssueRequestManager , IAssembleIssueRequestManager { private readonly IAssembleIssueRequestRepository _repository; - public AssembleIssueRequestManager( IAssembleIssueRequestRepository repository - - ) : base(repository) + ) : base(repository) { _repository = repository; - } - #region 东阳V2 - - #endregion - /// - /// 创建 + /// 创建 同时 直接赋值Number 为了返回Number /// /// /// public virtual async Task CreateByNumberAsync(AssembleIssueRequest entity) { - var number = string.IsNullOrEmpty(entity.Number) ? await GenerateNumberAsync(nameof(AssembleIssueRequest), entity.ActiveDate).ConfigureAwait(false) : entity.Number; + var number = string.IsNullOrEmpty(entity.Number) + ? await GenerateNumberAsync(nameof(AssembleIssueRequest), entity.ActiveDate).ConfigureAwait(false) + : entity.Number; entity.SetIdAndNumberWithDetails(GuidGenerator, number); entity.Submit(); entity.Agree(); @@ -47,7 +42,6 @@ public class AssembleIssueRequestManager return entity; } - public virtual async Task CompleteAsync(string number) { var entity = await GetByNumberAsync(number).ConfigureAwait(false); @@ -56,23 +50,9 @@ public class AssembleIssueRequestManager await CompleteAsync(entity).ConfigureAwait(false); } } - - - #region 导入 - /// - /// 执行导入 - /// - public virtual async Task ImportDataAsync(List mergeEntities, List deleteEntities = null) + public Task ImportDataAsync(List entities, List deleteEntities = null) { - if (deleteEntities != null && deleteEntities.Count > 0) - { - await _repository.BulkDeleteAsync(deleteEntities).ConfigureAwait(false); - } - - await CreateManyAsync(mergeEntities).ConfigureAwait(false); + throw new System.NotImplementedException(); } - - #endregion - } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDbContextModelCreatingExtensions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDbContextModelCreatingExtensions.cs index b3f8e9b0d..1aa15142d 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDbContextModelCreatingExtensions.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDbContextModelCreatingExtensions.cs @@ -43,8 +43,8 @@ public static class AssembleIssueRequestDbContextModelCreatingExtensions b.Property(q => q.ToLocationErpCode).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength); b.Property(q => q.ToWarehouseCode).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength); b.Property(q => q.ToLocationArea).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength); - b.Property(q => q.ToLocationGroup).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength); - b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength); + b.Property(q => q.ToLocationGroup).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength); + b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength); b.Property(q => q.IssuedQty).HasPrecision(18, 6); b.Property(q => q.ReceivedQty).HasPrecision(18, 6); b.Property(q => q.Status).HasMaxLength(SfsPropertyConst.NameLength).HasConversion(); diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/AssembleJobAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/AssembleJobAutoMapperProfile.cs index 0b1c937e0..af95c0e84 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/AssembleJobAutoMapperProfile.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/AssembleJobAutoMapperProfile.cs @@ -33,5 +33,14 @@ public partial class StoreEventAutoMapperProfile : Profile ; CreateMap() ; + + CreateMap() + .ForMember(x => x.RequestNumber, y => y.MapFrom(d => d.AssembleRequestNumber)) + .Ignore(x => x.Confirmed) + .Ignore(x => x.JobNumber) + .Ignore(x => x.ActiveDate) + ; + CreateMap() + ; } } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Notes/AssembleNoteAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Notes/AssembleNoteAutoMapperProfile.cs index 9838ad5a2..b4b816da9 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Notes/AssembleNoteAutoMapperProfile.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Notes/AssembleNoteAutoMapperProfile.cs @@ -48,5 +48,4 @@ public partial class StoreEventAutoMapperProfile : Profile ; } - } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/AssembleIssueRequestAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/AssembleIssueRequestAutoMapperProfile.cs index 428b1dc99..c96d98feb 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/AssembleIssueRequestAutoMapperProfile.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/AssembleIssueRequestAutoMapperProfile.cs @@ -12,25 +12,26 @@ public partial class StoreEventAutoMapperProfile : Profile private void AssembleIssueRequestAutoMapperProfile() { CreateMap() - .ForMember(x => x.AssembleRequestNumber, y => y.MapFrom(d => d.Number)) - .Ignore(x => x.WarehouseCode) - .Ignore(x => x.UpStreamJobNumber) - .Ignore(x => x.JobType) - .Ignore(x => x.IsAutoComplete) - .Ignore(x => x.ExpiredTime) - .Ignore(x => x.JobDescription) - .Ignore(x => x.JobStatus) - .Ignore(x => x.WorkGroupCode) - .Ignore(x => x.Priority) - .Ignore(x => x.PriorityIncrement) - .Ignore(x => x.AcceptUserId) - .Ignore(x => x.AcceptTime) - .Ignore(x => x.AcceptUserName) - .Ignore(x => x.CompleteUserId) - .Ignore(x => x.CompleteUserName) - .Ignore(x => x.CompleteTime) - .Ignore(x => x.Details) - ; + .ForMember(x => x.AssembleRequestNumber, y => y.MapFrom(d => d.Number)) + .Ignore(x => x.WarehouseCode) + .Ignore(x => x.UpStreamJobNumber) + .Ignore(x => x.JobType) + .Ignore(x => x.IsAutoComplete) + .Ignore(x => x.ExpiredTime) + .Ignore(x => x.JobDescription) + .Ignore(x => x.JobStatus) + .Ignore(x => x.WorkGroupCode) + .Ignore(x => x.Priority) + .Ignore(x => x.PriorityIncrement) + .Ignore(x => x.AcceptUserId) + .Ignore(x => x.AcceptTime) + .Ignore(x => x.AcceptUserName) + .Ignore(x => x.CompleteUserId) + .Ignore(x => x.CompleteUserName) + .Ignore(x => x.CompleteTime) + .Ignore(x => x.Details) + .Ignore(x => x.EnumIssueSendType) + ; } } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/AssembleIssueJobEventHandler.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/AssembleIssueJobEventHandler.cs index 2474e5fbc..ceeb213f7 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/AssembleIssueJobEventHandler.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/AssembleIssueJobEventHandler.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Castle.Components.DictionaryAdapter; using Volo.Abp.EventBus; using Volo.Abp.Uow; using Win_in.Sfs.Basedata.Application.Contracts; @@ -18,16 +19,16 @@ public class AssembleIssueJobEventHandler : , ILocalEventHandler> , ILocalEventHandler>> { - private readonly IAssembleIssueNoteAppService _assembleNoteAppService; + private readonly IAssembleIssueNoteAppService _assembleIssueNoteAppService; private readonly IExpectOutAppService _expectOutAppService; private readonly ILocationAppService _locationAppService; private readonly ITransferLibRequestAppService _transferLibRequestAppService; - public AssembleIssueJobEventHandler(IAssembleIssueNoteAppService assembleNoteAppService, + public AssembleIssueJobEventHandler(IAssembleIssueNoteAppService assembleIssueNoteAppService, IExpectOutAppService expectOutAppService, ILocationAppService locationAppService, ITransferLibRequestAppService transferLibRequestAppService) { - _assembleNoteAppService = assembleNoteAppService; + _assembleIssueNoteAppService = assembleIssueNoteAppService; _expectOutAppService = expectOutAppService; _locationAppService = locationAppService; _transferLibRequestAppService = transferLibRequestAppService; @@ -41,9 +42,7 @@ public class AssembleIssueJobEventHandler : [UnitOfWork] public virtual async Task HandleEventAsync(SfsCompletedEntityEventData eventData) { - var entity = eventData.Entity; - var assembleNote = await BuildAssembleIssueNoteAsync(entity).ConfigureAwait(false); - await _assembleNoteAppService.CreateAsync(assembleNote).ConfigureAwait(false); + await Task.CompletedTask.ConfigureAwait(false); } /// @@ -123,65 +122,72 @@ public class AssembleIssueJobEventHandler : /// 根据是否在 第一层 来创建 是否生成库移任务 /// /// - private async Task CreateTransferLibAsync(AssembleIssueJob assembleJob) + private async Task CreateTransferLibAsync(AssembleIssueJob assembleIssueJob) { - if (!await IsMinRowAsync(assembleJob).ConfigureAwait(false)) + foreach (var detail in assembleIssueJob.Details) { - foreach (var detail in assembleJob.Details) + var locationDto = await _locationAppService.GetByCodeAsync(detail.RecommendFromLocationCode) + .ConfigureAwait(false); + if (locationDto.Type == EnumLocationType.RAW) { - var input = new TransferLibRequestEditInput(); - input.CallBusinessType = nameof(IAssembleIssueJobAppService); - input.CallJobNumber = assembleJob.Number; - input.CallRequestNumber = assembleJob.AssembleRequestNumber; - input.CallServerName = "Win_in.Sfs.Wms.Store.Application.AssembleIssueJobAppService"; - input.Type = "Transfer_Warehouse"; - input.UseOnTheWayLocation = true; - - var detailInput = new TransferLibRequestDetailInput(); - detailInput.CallBusinessType = nameof(IAssembleIssueJobAppService); - detailInput.CallRequestNumber = assembleJob.AssembleRequestNumber; - detailInput.CallServerName = "Win_in.Sfs.Wms.Store.Application.AssembleIssueJobAppService"; - detailInput.CallJobNumber = assembleJob.Number; - - detailInput.JobStatus = EnumJobStatus.Open; - detailInput.ItemCode = detail.ItemCode; - detailInput.StdPackQty = detail.StdPackQty; - detailInput.Uom = detail.Uom; - detailInput.Status = detail.Status; - - detailInput.RecommendFromQty = detail.RecommendFromQty; - detailInput.RecommendFromLot = detail.RecommendFromLot; - detailInput.RecommendFromPackingCode = detailInput.RecommendFromPackingCode; - detailInput.RecommendToLot = detail.RecommendToLot; - - detailInput.RecommendFromArriveDate = detail.RecommendFromArriveDate; - detailInput.RecommendFromExpireDate = detail.RecommendFromExpireDate; - detailInput.RecommendFromProduceDate = detail.RecommendFromProduceDate; - detailInput.RecommendFromSupplierBatch = detail.RecommendFromSupplierBatch; - - detailInput.RecommendFromLocationCode = detail.RecommendFromLocationCode; - detailInput.RecommendFromLocationGroup = detail.RecommendFromLocationGroup; - detailInput.RecommendFromLocationArea = detail.RecommendFromLocationArea; - detailInput.RecommendFromLocationErpCode = detail.RecommendFromLocationErpCode; - detailInput.RecommendFromWarehouseCode = detail.RecommendFromWarehouseCode; - - detailInput.RecommendToQty = detail.RecommendToQty; - detailInput.RecommendToLot = detail.RecommendToLot; - detailInput.RecommendToPackingCode = detailInput.RecommendToPackingCode; - detailInput.RecommendToLot = detail.RecommendToLot; - - detailInput.RecommendToArriveDate = detail.RecommendToArriveDate; - detailInput.RecommendToExpireDate = detail.RecommendToExpireDate; - detailInput.RecommendToProduceDate = detail.RecommendToProduceDate; - detailInput.RecommendToSupplierBatch = detail.RecommendToSupplierBatch; - - detailInput.RecommendToLocationCode = detail.RecommendToLocationCode; - detailInput.RecommendToLocationGroup = detail.RecommendToLocationGroup; - detailInput.RecommendToLocationArea = detail.RecommendToLocationArea; - detailInput.RecommendToLocationErpCode = detail.RecommendToLocationErpCode; - detailInput.RecommendToWarehouseCode = detail.RecommendToWarehouseCode; - - await _transferLibRequestAppService.CreateAsync(input).ConfigureAwait(false); + if (!await IsMinRowAsync(assembleIssueJob).ConfigureAwait(false)) + { + var input = new TransferLibRequestEditInput(); + input.CallBusinessType = nameof(IAssembleIssueJobAppService); + input.CallJobNumber = assembleIssueJob.Number; + input.CallRequestNumber = assembleIssueJob.AssembleRequestNumber; + input.CallServerName = "Win_in.Sfs.Wms.Store.Application.AssembleIssueJobAppService"; + input.Type = "Transfer_Warehouse"; + input.UseOnTheWayLocation = true; + + var detailInput = new TransferLibRequestDetailInput(); + detailInput.CallBusinessType = nameof(IAssembleIssueJobAppService); + detailInput.CallRequestNumber = assembleIssueJob.AssembleRequestNumber; + detailInput.CallServerName = "Win_in.Sfs.Wms.Store.Application.AssembleIssueJobAppService"; + detailInput.CallJobNumber = assembleIssueJob.Number; + + detailInput.JobStatus = EnumJobStatus.Open; + detailInput.ItemCode = detail.ItemCode; + detailInput.StdPackQty = detail.StdPackQty; + detailInput.Uom = detail.Uom; + detailInput.Status = detail.Status; + + detailInput.RecommendFromQty = detail.RecommendFromQty; + detailInput.RecommendFromLot = detail.RecommendFromLot; + detailInput.RecommendFromPackingCode = detailInput.RecommendFromPackingCode; + detailInput.RecommendToLot = detail.RecommendToLot; + + detailInput.RecommendFromArriveDate = detail.RecommendFromArriveDate; + detailInput.RecommendFromExpireDate = detail.RecommendFromExpireDate; + detailInput.RecommendFromProduceDate = detail.RecommendFromProduceDate; + detailInput.RecommendFromSupplierBatch = detail.RecommendFromSupplierBatch; + + detailInput.RecommendFromLocationCode = detail.RecommendFromLocationCode; + detailInput.RecommendFromLocationGroup = detail.RecommendFromLocationGroup; + detailInput.RecommendFromLocationArea = detail.RecommendFromLocationArea; + detailInput.RecommendFromLocationErpCode = detail.RecommendFromLocationErpCode; + detailInput.RecommendFromWarehouseCode = detail.RecommendFromWarehouseCode; + + detailInput.RecommendToQty = detail.RecommendToQty; + detailInput.RecommendToLot = detail.RecommendToLot; + detailInput.RecommendToPackingCode = detailInput.RecommendToPackingCode; + detailInput.RecommendToLot = detail.RecommendToLot; + + detailInput.RecommendToArriveDate = detail.RecommendToArriveDate; + detailInput.RecommendToExpireDate = detail.RecommendToExpireDate; + detailInput.RecommendToProduceDate = detail.RecommendToProduceDate; + detailInput.RecommendToSupplierBatch = detail.RecommendToSupplierBatch; + + detailInput.RecommendToLocationCode = detail.RecommendToLocationCode; + detailInput.RecommendToLocationGroup = detail.RecommendToLocationGroup; + detailInput.RecommendToLocationArea = detail.RecommendToLocationArea; + detailInput.RecommendToLocationErpCode = detail.RecommendToLocationErpCode; + detailInput.RecommendToWarehouseCode = detail.RecommendToWarehouseCode; + + input.Details = new EditableList() { detailInput }; + + await _transferLibRequestAppService.CreateAsync(input).ConfigureAwait(false); + } } } } @@ -193,26 +199,26 @@ public class AssembleIssueJobEventHandler : /// private async Task BuildAssembleIssueNoteAsync(AssembleIssueJob entity) { - var assembleNoteCreateInput = ObjectMapper.Map(entity); - assembleNoteCreateInput.JobNumber = entity.Number; + var assembleIssueNoteCreateInput = ObjectMapper.Map(entity); + assembleIssueNoteCreateInput.JobNumber = entity.Number; await Task.CompletedTask.ConfigureAwait(false); - return assembleNoteCreateInput; + return assembleIssueNoteCreateInput; } /// /// 判断是不是在最底层 如果不是则把状态变更为等待 /// - /// + /// /// - private async Task IsMinRowAsync(AssembleIssueJob assembleJob) + private async Task IsMinRowAsync(AssembleIssueJob assembleIssueJob) { - var detail = assembleJob.Details.FirstOrDefault(); + var detail = assembleIssueJob.Details.FirstOrDefault(); - var loctionDto = await _locationAppService.GetByCodeAsync(detail.RecommendFromLocationCode) + var locationDto = await _locationAppService.GetByCodeAsync(detail.RecommendFromLocationCode) .ConfigureAwait(false); - if (loctionDto.RowCode == 1) + if (locationDto.Type == EnumLocationType.RAW && locationDto.RowCode == 1) { return true; } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/AssembleIssueRequestEventHandler.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/AssembleIssueRequestEventHandler.cs index fdb4e5d3f..f42900984 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/AssembleIssueRequestEventHandler.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/AssembleIssueRequestEventHandler.cs @@ -3,8 +3,10 @@ using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; +using AutoMapper; using Castle.Components.DictionaryAdapter; using Volo.Abp; +using Volo.Abp.AutoMapper; using Volo.Abp.EventBus; using Win_in.Sfs.Basedata.Application.Contracts; using Win_in.Sfs.Shared.Domain.Shared; @@ -25,22 +27,27 @@ public class AssembleIssueRequestEventHandler , ILocalEventHandler> , ILocalEventHandler>> { - private readonly IAssembleIssueJobAppService _assembleJobAppService; + private readonly IAssembleIssueJobAppService _assembleIssueJobAppService; private readonly IProductionLineAppService _productionLineAppService; private readonly IProductionLineItemAppService _productionLineItemAppService; private readonly ILocationAppService _locationAppService; private readonly IBalanceAppService _balanceAppService; + private IMapper _mapper; + //private readonly IAssembleIssueRequestManager _assembleIssueRequestManager; public AssembleIssueRequestEventHandler( - IAssembleIssueJobAppService assembleJobAppService, IProductionLineAppService productionLineAppService, + IAssembleIssueJobAppService assembleIssueJobAppService, IProductionLineAppService productionLineAppService, ILocationAppService locationAppService, - IBalanceAppService balanceAppService, IProductionLineItemAppService productionLineItemAppService) + IBalanceAppService balanceAppService, IProductionLineItemAppService productionLineItemAppService + //, IAssembleIssueRequestManager assembleIssueRequestManager + ) { - _assembleJobAppService = assembleJobAppService; + _assembleIssueJobAppService = assembleIssueJobAppService; _productionLineAppService = productionLineAppService; _locationAppService = locationAppService; _balanceAppService = balanceAppService; _productionLineItemAppService = productionLineItemAppService; + //_assembleIssueRequestManager = assembleIssueRequestManager; } /// @@ -49,7 +56,9 @@ public class AssembleIssueRequestEventHandler /// Event data public virtual async Task HandleEventAsync(SfsCreatedEntityEventData eventData) { - await Task.CompletedTask.ConfigureAwait(false); + var entity = eventData.Entity; + + await CreateAllAssembleIssueJobAsync(entity).ConfigureAwait(false); } /// @@ -58,6 +67,8 @@ public class AssembleIssueRequestEventHandler /// Event data public virtual async Task HandleEventAsync(SfsCreatedEntityEventData> eventData) { + var entity = eventData.Entity; + await Task.CompletedTask.ConfigureAwait(false); } @@ -70,22 +81,7 @@ public class AssembleIssueRequestEventHandler { var entity = eventData.Entity; - List assembleJobs = new EditableList(); - - //switch (entity.Type) - //{ - // case nameof(EnumIssueType.BoxQty): - // assembleJobs = await CreateAssembleIssueJobWithBoxQtyTypeAsync(entity).ConfigureAwait(false); - // break; - // case nameof(EnumIssueType.Qty): - // assembleJobs = await CreateAssembleIssueJobWithQtyTypeAsync(entity).ConfigureAwait(false); - // break; - //} - - if (assembleJobs.Any()) - { - await _assembleJobAppService.CreateManyAsync(assembleJobs).ConfigureAwait(false); - } + await CreateAllAssembleIssueJobAsync(entity).ConfigureAwait(false); } /// @@ -106,7 +102,7 @@ public class AssembleIssueRequestEventHandler public virtual async Task HandleEventAsync(SfsCompletedEntityEventData eventData) { _ = eventData.Entity; - // await _assembleJobAppService.CompleteByAssembleIssueRequestAsync(entity.Number); + // await _assembleIssueJobAppService.CompleteByAssembleIssueRequestAsync(entity.Number); await Task.CompletedTask.ConfigureAwait(false); } @@ -116,194 +112,135 @@ public class AssembleIssueRequestEventHandler #region 按数量叫料 /// - /// 创建注塑任务 + /// 创建注塑任务-按数量 /// - /// + /// + /// + /// + /// /// /// private async Task> CreateAssembleIssueJobWithQtyTypeAsync - (AssembleIssueRequest assembleRequest) + (AssembleIssueRequest assembleIssueRequest, List assembleIssueRequestDetails, + List recommendbalanceDtos, + List useBalanceList) { var jobs = new List(); + //用来临时存放所有未生成任务的发料集合 如果生成完了再这里去掉 + var tempDetailDtos = + ObjectMapper.Map, List>( + assembleIssueRequestDetails); - var toLocationCodes = assembleRequest.Details.Select(p => p.ToLocationCode).Distinct().ToList(); //所有发送库位的集合 - var toLocations = await _locationAppService.GetByCodesAsync(toLocationCodes).ConfigureAwait(false); //所有库位的集合 + var assembleIssueJobDetailInputs = new List(); - var assembleRequestDetails = assembleRequest.Details.Where(p => p.ToBeIssuedQty > 0); //所有还没发送物品的集合 - foreach (var assembleRequestDetail in assembleRequestDetails) //如果有还有剩余未叫料的数量 则创建新的任务 + if (recommendbalanceDtos != null && recommendbalanceDtos.Count > 0) { - var toLocation = - toLocations.FirstOrDefault(p => p.Code == assembleRequestDetail.ToLocationCode); //判断目标库位是否存在 - Check.NotNull(toLocation, "库位代码", $"库位 {assembleRequestDetail.ToLocationCode} 不存在"); - - //创建详情 - var jobDetails = - await CreateAssembleIssueJobDetailInputsWithQtyTypeAsync(assembleRequest, assembleRequestDetail, - toLocation.LocationGroupCode).ConfigureAwait(false); - if (!jobDetails.Any()) + var queue = new Queue(recommendbalanceDtos); + while (queue.TryDequeue(out var balanceDto)) { - continue; - } + var next = false; - var fromLocationCode = jobDetails[0].RecommendFromLocationCode; - var fromLocation = await _locationAppService.GetByCodeAsync(fromLocationCode).ConfigureAwait(false); - var job = jobs.FirstOrDefault(p => p.WorkGroupCode == fromLocation?.WorkGroupCode); - if (job == null || job.Details.Any(p => p.RecommendToLocationCode != assembleRequestDetail.ToLocationCode)) - { - job = await BuildAssembleIssueJobCreateInputWithQtyTypeAsync(assembleRequest, fromLocation) - .ConfigureAwait(false); - jobs.Add(job); - } + var temp = tempDetailDtos.ToList(); - job.Details.AddRange(jobDetails); - if (assembleRequestDetail.ToBeIssuedQty < 0) - { - assembleRequestDetail.Status = EnumStatus.Close; - } - } - - jobs = jobs.Where(p => p.Details.Any()).ToList(); + foreach (var tempDetailDto in tempDetailDtos) + { + //未发送的数量 + tempDetailDto.Qty = tempDetailDto.Qty - tempDetailDto.IssuedQty; + + if (tempDetailDto.Qty > balanceDto.Qty) //需求量大于 这条推荐库存的余额 + { + tempDetailDto.Qty -= balanceDto.Qty; + } + else if (tempDetailDto.Qty <= balanceDto.Qty) + { + temp.Remove(tempDetailDto); + balanceDto.Qty = tempDetailDto.Qty; + } + + assembleIssueJobDetailInputs.Add( + await BuildAssembleIssueJobDetailWithQtyTypeAsync(tempDetailDto, balanceDto) + .ConfigureAwait(false)); + useBalanceList.Add(balanceDto); + + if (balanceDto.Qty <= 0) + { + next = true; + break; + } + } - var openRequestDetails = - assembleRequest.Details.Where(p => p.Status != EnumStatus.Close).ToList(); + tempDetailDtos = temp; - if (!openRequestDetails.Any()) - { - return jobs; + if (next) + { + } + } } - - var enableMultipleCreateAssembleIssueJob = await SettingManager - .IsTrueAsync(StoreSettings.MaterialRequest.EnableMultipleCreateIssueJob).ConfigureAwait(false); - if (enableMultipleCreateAssembleIssueJob) + if (assembleIssueJobDetailInputs.Any()) { - //assembleRequest.Partial(); - } - else - { - var sb = new StringBuilder(); - foreach (var openRequestDetail in openRequestDetails) - { - sb.AppendLine( - $"{openRequestDetail.ItemCode}请求数量 {openRequestDetail.Qty},可用库存数量 {openRequestDetail.IssuedQty}"); - } - - throw new UserFriendlyException($"{sb} 可用库存数量不足, 无法生成发料任务"); + var assembleIssueJobEditInput = new AssembleIssueJobEditInput(); + assembleIssueJobEditInput = await BuildAssembleIssueJobCreateInputWithQtyTypeAsync(assembleIssueRequest, + assembleIssueRequestDetails.First()).ConfigureAwait(false); + assembleIssueJobEditInput.Details = assembleIssueJobDetailInputs; + jobs.Add(assembleIssueJobEditInput); } return jobs; } /// - /// 构造注塑任务 + /// 构造注塑任务-按数量 /// - /// - /// + /// + /// /// private async Task BuildAssembleIssueJobCreateInputWithQtyTypeAsync( - AssembleIssueRequest assembleRequest, - LocationDTO fromLocation) + AssembleIssueRequest assembleIssueRequest, AssembleIssueRequestDetail requestDetailInput) { - AssembleIssueJobEditInput job; - job = ObjectMapper.Map(assembleRequest); + var job = ObjectMapper.Map(assembleIssueRequest); job.JobType = EnumJobType.IssueJob; job.JobStatus = EnumJobStatus.Open; - job.WorkGroupCode = fromLocation.WorkGroupCode; - job.WarehouseCode = fromLocation.WarehouseCode; - job.Worker = assembleRequest.Worker; - if (string.IsNullOrEmpty(job.Worker)) - { - job.Worker = "admin"; - } - - job.AssembleRequestNumber = assembleRequest.Number; + job.WorkGroupCode = requestDetailInput.ToLocationGroup; + job.WarehouseCode = requestDetailInput.ToWarehouseCode; + job.Worker = assembleIssueRequest.Worker; + job.AssembleRequestNumber = assembleIssueRequest.Number; + job.EnumIssueSendType = EnumIssueSendType.QtyType; await Task.CompletedTask.ConfigureAwait(false); return job; } - /// - /// 创建注塑任务明细 - /// - /// - /// - /// - /// - /// - private async Task> CreateAssembleIssueJobDetailInputsWithQtyTypeAsync( - AssembleIssueRequest assembleRequest, - AssembleIssueRequestDetail assembleRequestDetail, string toLocationGroupCode) - { - var jobDetails = new List(); - - //获取推荐库存 - var productionLineDto = await _productionLineAppService - .GetByLocationCodeAsync(assembleRequestDetail.ToLocationCode).ConfigureAwait(false); - var productionLineItemDtos = await _productionLineItemAppService - .GetByProductLineCodeAsync(productionLineDto.Code).ConfigureAwait(false); - if (productionLineItemDtos == null) - { - throw new UserFriendlyException($"物品代码【{assembleRequestDetail.ItemCode}】没有对应的【生产线物品关系】"); - } - - var productionLineItemDto = - productionLineItemDtos.FirstOrDefault(p => p.ItemCode == assembleRequestDetail.ItemCode); - var input = new RecommendBalanceRequestInput - { - ItemCode = assembleRequestDetail.ItemCode, - Qty = assembleRequestDetail.ToBeIssuedQty, - //LocationTypes = transactionType.OutLocationTypes, productionLineItemDto.RawLocationCodeListJson - Statuses = new EditableList { EnumInventoryStatus.OK }, - Locations = JsonSerializer.Deserialize>(productionLineItemDto.RawLocationCodeListJson) - }; - - var recommendList = await _balanceAppService.GetRecommendBalancesByLocationsAsync(input).ConfigureAwait(false); - //没有推荐库存时 跳过此明细 不生成任务 - if (recommendList.Count != 0) - { - foreach (var recommend in recommendList) - { - //拿走需求量 - var detail = - await BuildAssembleIssueJobDetailWithQtyTypeAsync(assembleRequestDetail, recommend, - toLocationGroupCode) - .ConfigureAwait(false); - if (assembleRequest.UseOnTheWayLocation) - { - //获取在途库 - var locationDto = await _locationAppService.GetFirstByTypeAsync(EnumLocationType.TRANSPORT) - .ConfigureAwait(false); - - detail.OnTheWayLocationCode = locationDto.Code; - } - - jobDetails.Add(detail); - assembleRequestDetail.IssuedQty += recommend.Qty; - - //await _assembleRequestManager.UpdateDetailsAsync(assembleRequest).ConfigureAwait(false); - } - } - - return jobDetails; - } /// - /// 构造注塑任务明细 + /// 构造注塑任务明细-按数量 /// - /// + /// /// - /// /// private async Task BuildAssembleIssueJobDetailWithQtyTypeAsync( - AssembleIssueRequestDetail assembleRequestDetail, BalanceDTO balance, string toLocationGroupCode) + AssembleIssueRequestDetailDTO assembleIssueRequestDetail, BalanceDTO balance) { - //ProductionLineDTO prodLine = await _productionLineAppService.GetByLocationGroupCodeAsync(toLocationGroupCode).ConfigureAwait(false); - - var detail = ObjectMapper.Map(balance); - detail.RequestLocationCode = assembleRequestDetail.ToLocationCode; - detail.PositionCode = assembleRequestDetail.PositionCode; - detail.RecommendType = assembleRequestDetail.RecommendType; + var detail = new AssembleIssueJobDetailInput(); + detail.RequestLocationCode = assembleIssueRequestDetail.ToLocationCode; + detail.PositionCode = assembleIssueRequestDetail.PositionCode; + detail.RecommendType = assembleIssueRequestDetail.RecommendType; + detail.Uom = balance.Uom; + detail.ItemCode = balance.ItemCode; + detail.ItemDesc2 = balance.ItemDesc2; + detail.ItemDesc1 = balance.ItemDesc1; + detail.ItemName = balance.ItemName; + detail.ProdLine = assembleIssueRequestDetail.ProdLine; + detail.RequestQty = balance.Qty; + detail.StdPackQty = assembleIssueRequestDetail.StdPackQty; + detail.Status = balance.Status; + + detail.RequestLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode; + detail.RequestLocationArea = assembleIssueRequestDetail.ToLocationArea; + detail.RequestWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; + detail.RequestLocationGroup = assembleIssueRequestDetail.ToLocationGroup; + detail.RequestLocationCode = assembleIssueRequestDetail.ToLocationCode; detail.RecommendFromPackingCode = balance.PackingCode; detail.RecommendFromContainerCode = balance.ContainerCode; @@ -313,21 +250,69 @@ public class AssembleIssueRequestEventHandler detail.RecommendFromLot = balance.Lot; detail.RecommendFromProduceDate = balance.ProduceDate; detail.RecommendFromArriveDate = balance.ArriveDate; + detail.RecommendFromQty = balance.Qty; + detail.RecommendFromContainerCode = balance.ContainerCode; + detail.RecommendFromPackingCode = balance.PackingCode; + + detail.RecommendToPackingCode = balance.PackingCode; + detail.RecommendToContainerCode = balance.ContainerCode; + detail.RecommendToSupplierBatch = balance.SupplierBatch; + detail.RecommendToProduceDate = balance.ProduceDate; + detail.RecommendToExpireDate = balance.ExpireDate; + detail.RecommendToLot = balance.Lot; + detail.RecommendToProduceDate = balance.ProduceDate; + detail.RecommendToArriveDate = balance.ArriveDate; + detail.RecommendToQty = balance.Qty; + detail.RecommendToContainerCode = balance.ContainerCode; + detail.RecommendToPackingCode = balance.PackingCode; + detail.RecommendFromLocationArea = balance.LocationArea; detail.RecommendFromLocationCode = balance.LocationCode; detail.RecommendFromLocationErpCode = balance.LocationErpCode; detail.RecommendFromLocationGroup = balance.LocationGroup; detail.RecommendFromWarehouseCode = balance.WarehouseCode; - detail.RecommendFromQty = balance.Qty; - detail.Uom = balance.Uom; - detail.RecommendToLocationCode = assembleRequestDetail.ToLocationCode; - detail.RecommendToLocationErpCode = assembleRequestDetail.ToLocationErpCode; - detail.RecommendToLocationArea = assembleRequestDetail.ToLocationArea; - detail.RecommendToWarehouseCode = assembleRequestDetail.ToWarehouseCode; + detail.RecommendToLocationCode = assembleIssueRequestDetail.ToLocationCode; + detail.RecommendToLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode; + detail.RecommendToLocationArea = assembleIssueRequestDetail.ToLocationArea; + detail.RecommendToWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; + detail.RecommendToLocationGroup = assembleIssueRequestDetail.ToLocationGroup; + + detail.TransferLibFromPackingCode = balance.PackingCode; + detail.TransferLibFromContainerCode = balance.ContainerCode; + detail.TransferLibFromSupplierBatch = balance.SupplierBatch; + detail.TransferLibFromProduceDate = balance.ProduceDate; + detail.TransferLibFromExpireDate = balance.ExpireDate; + detail.TransferLibFromLot = balance.Lot; + detail.TransferLibFromProduceDate = balance.ProduceDate; + detail.TransferLibFromArriveDate = balance.ArriveDate; + detail.TransferLibFromQty = balance.Qty; + detail.TransferLibFromContainerCode = balance.ContainerCode; + detail.TransferLibFromPackingCode = balance.PackingCode; + + detail.TransferLibToPackingCode = balance.PackingCode; + detail.TransferLibToContainerCode = balance.ContainerCode; + detail.TransferLibToSupplierBatch = balance.SupplierBatch; + detail.TransferLibToProduceDate = balance.ProduceDate; + detail.TransferLibToExpireDate = balance.ExpireDate; + detail.TransferLibToLot = balance.Lot; + detail.TransferLibToProduceDate = balance.ProduceDate; + detail.TransferLibToArriveDate = balance.ArriveDate; + detail.TransferLibToQty = balance.Qty; + detail.TransferLibToPackingCode = balance.PackingCode; + + detail.TransferLibFromLocationArea = balance.LocationArea; + detail.TransferLibFromLocationCode = balance.LocationCode; + detail.TransferLibFromLocationErpCode = balance.LocationErpCode; + detail.TransferLibFromLocationGroup = balance.LocationGroup; + detail.TransferLibFromWarehouseCode = balance.WarehouseCode; + + detail.TransferLibToLocationCode = assembleIssueRequestDetail.ToLocationCode; + detail.TransferLibToLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode; + detail.TransferLibToLocationArea = assembleIssueRequestDetail.ToLocationArea; + detail.TransferLibToWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; + detail.TransferLibToLocationGroup = assembleIssueRequestDetail.ToLocationGroup; - //detail.ProdLine = prodLine == null ? toLocationGroupCode : prodLine.Code; - detail.ProdLine = toLocationGroupCode; await Task.CompletedTask.ConfigureAwait(false); return detail; } @@ -337,72 +322,71 @@ public class AssembleIssueRequestEventHandler #region 按箱叫料 /// - /// 创建注塑任务 + /// 创建注塑任务 按箱叫料-按箱 /// - /// + /// + /// + /// + /// /// /// private async Task> CreateAssembleIssueJobWithBoxQtyTypeAsync - (AssembleIssueRequest assembleRequest) + ( + AssembleIssueRequest assembleIssueRequest, + List assembleIssueRequestDetailList, + List recommendbalanceDtos, + List useBalanceList) { var inputJobs = new List(); - var inputExpectOutEditInput = new ExpectOutEditInput(); - //已用的库存的箱码集合 - var useBalanceList = new List(); - var groupByItemCodeAndLocationCode = - assembleRequest.Details.GroupBy(p => new { p.ItemCode, p.ToLocationCode }); + //已用的库存的集合 + useBalanceList = useBalanceList; - foreach (var locationCodeItemCodeGroup in groupByItemCodeAndLocationCode) + foreach (var detail in assembleIssueRequestDetailList) { - var inputDetails = assembleRequest.Details.Where(p => - p.ItemCode == locationCodeItemCodeGroup.Key.ItemCode && - p.ToLocationCode == locationCodeItemCodeGroup.Key.ToLocationCode); - var inputDetailTemplate = inputDetails.First(); + //当前零件的集合 + var inputDetails = assembleIssueRequestDetailList; //获取请求下 这个零件和这个库位一个需要多少箱 - var sumBoxQty = inputDetails.Sum(p => p.BoxQty); + var sumBoxQty = inputDetails.Sum(p => p.BoxQty - p.IssuedQty); //获取生产线 var productionLineDto = await _productionLineAppService .GetByLocationCodeAsync(inputDetails.First().ToLocationCode).ConfigureAwait(false); - if (productionLineDto == null) - { - throw new UserFriendlyException($"库位【{inputDetailTemplate.ToLocationCode}】没有对应的【生产线】"); - } + var productLineCodeAndItemCode = await _productionLineItemAppService - .GetByProductLineCodeAndItemCodeAsync(productionLineDto.Code, inputDetailTemplate.ItemCode) + .GetByProductLineCodeAndItemCodeAsync(productionLineDto.Code, detail.ItemCode) .ConfigureAwait(false); if (productLineCodeAndItemCode == null) { throw new UserFriendlyException( - $"物品代码【{inputDetailTemplate.ItemCode}】在生产线【{productionLineDto.Code}】中没有对应的【生产线物品关系】"); + $"物品代码【{detail.ItemCode}】在生产线【{productionLineDto.Code}】中没有对应的【生产线物品关系】"); } - //获取可用库存 - var input = new RecommendBalanceRequestInput - { - ItemCode = locationCodeItemCodeGroup.Key.ItemCode, - Qty = decimal.MaxValue, - Statuses = new EditableList { EnumInventoryStatus.OK }, - Locations = JsonSerializer.Deserialize>(productLineCodeAndItemCode - .RawLocationCodeListJson) - }; - var usableList = await _balanceAppService.GetUsableListAsync(input).ConfigureAwait(false); - usableList = usableList.Where(p => !useBalanceList.Contains(p.PackingCode)).ToList(); + //可用库存 + var usableList = recommendbalanceDtos; + usableList = usableList.Where(p => !useBalanceList.Select(p => p.PackingCode).Contains(p.PackingCode)) + .ToList(); if (usableList.Any()) { for (var i = 0; i < sumBoxQty; i++) { - var firstUsable = usableList.First(); - useBalanceList.Add(firstUsable.PackingCode); - usableList.Remove(firstUsable); - - var assembleJobEditInput = - await BuildAssembleIssueJobCreateInputWithBoxQtyTypeAsync(assembleRequest, inputDetailTemplate, - firstUsable) - .ConfigureAwait(false); - - inputJobs.Add(assembleJobEditInput); + if (usableList.Any()) + { + var firstUsable = usableList.First(); + useBalanceList.Add((BalanceDTO)firstUsable); + usableList.Remove(firstUsable); + + var assembleIssueJobEditInput = + await BuildAssembleIssueJobCreateInputWithBoxQtyTypeAsync(assembleIssueRequest, + detail, firstUsable) + .ConfigureAwait(false); + + inputJobs.Add(assembleIssueJobEditInput); + } + else + { + break; + } } } } @@ -411,25 +395,26 @@ public class AssembleIssueRequestEventHandler } /// - /// 构造注塑任务 + /// 构造注塑任务-按箱 /// - /// - /// + /// + /// /// /// private async Task BuildAssembleIssueJobCreateInputWithBoxQtyTypeAsync( - AssembleIssueRequest assembleRequest, - AssembleIssueRequestDetail assembleRequestDetail, BalanceDTO balanceDtos) + AssembleIssueRequest assembleIssueRequest, + AssembleIssueRequestDetail assembleIssueRequestDetail, BalanceDTO balanceDtos) { - var job = ObjectMapper.Map(assembleRequest); + var job = ObjectMapper.Map(assembleIssueRequest); job.JobType = EnumJobType.IssueJob; job.JobStatus = EnumJobStatus.Open; - job.WorkGroupCode = assembleRequestDetail.ToLocationGroup; - job.WarehouseCode = assembleRequestDetail.ToWarehouseCode; - job.Worker = assembleRequest.Worker; - job.AssembleRequestNumber = assembleRequest.Number; + job.WorkGroupCode = assembleIssueRequestDetail.ToLocationGroup; + job.WarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; + job.Worker = assembleIssueRequest.Worker; + job.AssembleRequestNumber = assembleIssueRequest.Number; + job.EnumIssueSendType = EnumIssueSendType.BoxQtyType; - job.Details.Add(await BuildAssembleIssueJobDetailWithBoxQtyTypeAsync(assembleRequestDetail, balanceDtos) + job.Details.Add(await BuildAssembleIssueJobDetailWithBoxQtyTypeAsync(assembleIssueRequestDetail, balanceDtos) .ConfigureAwait(false)); await Task.CompletedTask.ConfigureAwait(false); @@ -438,30 +423,31 @@ public class AssembleIssueRequestEventHandler } /// - /// 构造注塑任务明细 + /// 构造注塑任务明细-按箱 /// - /// + /// /// /// /// private async Task BuildAssembleIssueJobDetailWithBoxQtyTypeAsync( - AssembleIssueRequestDetail assembleRequestDetail, BalanceDTO balance) + AssembleIssueRequestDetail assembleIssueRequestDetail, BalanceDTO balance) { var detail = new AssembleIssueJobDetailInput(); - detail.RequestLocationCode = assembleRequestDetail.ToLocationCode; - detail.RequestLocationGroup = assembleRequestDetail.ToLocationGroup; - detail.RequestLocationArea = assembleRequestDetail.ToLocationArea; - detail.RequestLocationErpCode = assembleRequestDetail.ToLocationErpCode; - detail.RequestWarehouseCode = assembleRequestDetail.ToWarehouseCode; - - detail.PositionCode = assembleRequestDetail.PositionCode; - detail.RecommendType = assembleRequestDetail.RecommendType; - detail.ProdLine = assembleRequestDetail.ToLocationCode; - - detail.ItemCode = assembleRequestDetail.ItemCode; - detail.ItemName = assembleRequestDetail.ItemName; - detail.ItemDesc1 = assembleRequestDetail.ItemDesc1; - detail.ItemDesc2 = assembleRequestDetail.ItemDesc2; + detail.RequestLocationCode = assembleIssueRequestDetail.ToLocationCode; + detail.RequestLocationGroup = assembleIssueRequestDetail.ToLocationGroup; + detail.RequestLocationArea = assembleIssueRequestDetail.ToLocationArea; + detail.RequestLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode; + detail.RequestWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; + detail.RequestQty = 1; + + detail.PositionCode = assembleIssueRequestDetail.PositionCode; + detail.RecommendType = assembleIssueRequestDetail.RecommendType; + detail.ProdLine = assembleIssueRequestDetail.ToLocationCode; + + detail.ItemCode = assembleIssueRequestDetail.ItemCode; + detail.ItemName = assembleIssueRequestDetail.ItemName; + detail.ItemDesc1 = assembleIssueRequestDetail.ItemDesc1; + detail.ItemDesc2 = assembleIssueRequestDetail.ItemDesc2; detail.Status = EnumInventoryStatus.OK; detail.Uom = balance.Uom; @@ -496,11 +482,11 @@ public class AssembleIssueRequestEventHandler detail.RecommendToProduceDate = balance.ProduceDate; detail.RecommendToArriveDate = balance.ArriveDate; - detail.RecommendToLocationCode = assembleRequestDetail.ToLocationCode; - detail.RecommendToLocationErpCode = assembleRequestDetail.ToLocationErpCode; - detail.RecommendToLocationArea = assembleRequestDetail.ToLocationArea; - detail.RecommendToWarehouseCode = assembleRequestDetail.ToWarehouseCode; - detail.RecommendToLocationGroup = assembleRequestDetail.ToLocationGroup; + detail.RecommendToLocationCode = assembleIssueRequestDetail.ToLocationCode; + detail.RecommendToLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode; + detail.RecommendToLocationArea = assembleIssueRequestDetail.ToLocationArea; + detail.RecommendToWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; + detail.RecommendToLocationGroup = assembleIssueRequestDetail.ToLocationGroup; await Task.CompletedTask.ConfigureAwait(false); return detail; @@ -509,4 +495,210 @@ public class AssembleIssueRequestEventHandler #endregion #endregion + + //创建任务 + private async Task> CreateAllAssembleIssueJobAsync( + AssembleIssueRequest assembleIssueRequest) + { + var assembleIssueJobEditInputs = new List(); + + //已用的库存的集合 + var useBalanceList = new List(); + + foreach (var groupbyItemCodeAndProdLine in assembleIssueRequest.Details.GroupBy(p => + new { p.ItemCode })) + { + foreach (var assembleIssueRequestDetail in groupbyItemCodeAndProdLine) + { + var productionLineItemDto = await _productionLineItemAppService.GetByProductLineCodeAndItemCodeAsync( + assembleIssueRequestDetail.ProdLine, + groupbyItemCodeAndProdLine.Key.ItemCode).ConfigureAwait(false); + + if (productionLineItemDto == null) + { + throw new UserFriendlyException( + $"未在生产线【{assembleIssueRequestDetail.ProdLine}】物品【{groupbyItemCodeAndProdLine.Key.ItemCode}】的关系,请查看【生产线物品关系】"); + } + + //原料 + if (!string.IsNullOrEmpty(productionLineItemDto.RawLocationCodeListJson)) //因为一个零件 要不是原料 要不是半成品 + { + var usableLocationCode = + JsonSerializer.Deserialize>(productionLineItemDto.RawLocationCodeListJson); + if (usableLocationCode.Any()) + { + //获取可用库存 + var input = new RecommendBalanceRequestInput + { + ItemCode = assembleIssueRequestDetail.ItemCode, + Qty = decimal.MaxValue, + Statuses = new EditableList { EnumInventoryStatus.OK }, + Locations = + JsonSerializer.Deserialize>(productionLineItemDto.RawLocationCodeListJson), + IsPackingCode = true + }; + var usableList = await _balanceAppService.GetUsableListAsync(input).ConfigureAwait(false); + var sortByFifoAsync = await SortByFifoAsync(usableList).ConfigureAwait(false); + + //因为是按箱叫料 先把值赋值给箱数量上 + assembleIssueRequestDetail.BoxQty = assembleIssueRequestDetail.Qty; + + if (usableList.Any()) + { + //因为是原料所以按箱叫料 + assembleIssueJobEditInputs.AddRange( + await CreateAssembleIssueJobWithBoxQtyTypeAsync(assembleIssueRequest, + new EditableList { assembleIssueRequestDetail }, + sortByFifoAsync, + useBalanceList).ConfigureAwait(false)); + } + } + } + + //半成品 + if (!string.IsNullOrEmpty(productionLineItemDto.ProductLocationCodeListJson)) //因为一个零件 要不是原料 要不是半成品 + { + var usableLocationCode = + JsonSerializer.Deserialize>(productionLineItemDto.ProductLocationCodeListJson); + if (usableLocationCode.Any()) + { + //获取可用库存 + var input = new RecommendBalanceRequestInput + { + ItemCode = groupbyItemCodeAndProdLine.Key.ItemCode, + Qty = assembleIssueRequestDetail.Qty, + Statuses = new EditableList { EnumInventoryStatus.OK }, + Locations = + JsonSerializer.Deserialize>(productionLineItemDto + .ProductLocationCodeListJson), + IsPackingCode = false + }; + var usableList = await _balanceAppService.GetUsableListAsync(input).ConfigureAwait(false); + var temp = usableList.ToList(); + + foreach (var balanceDto in usableList) //计算已经用过的库存 + { + var useBalanceDto = useBalanceList.Where(p => + p.ItemCode == balanceDto.ItemCode && p.LocationCode == balanceDto.LocationCode && + p.Lot == balanceDto.Lot && p.Status == balanceDto.Status && + p.PackingCode == balanceDto.PackingCode); + if (useBalanceDto.Any()) //如果不为NULL,就是用过了的库存 需要减去使用量 + { + balanceDto.Qty -= useBalanceDto.Sum(p => p.Qty); + if (balanceDto.Qty <= 0) + { + temp.Remove(balanceDto); + } + } + } + + usableList = temp; + + assembleIssueJobEditInputs.AddRange( + await CreateAssembleIssueJobWithQtyTypeAsync(assembleIssueRequest, + new List { assembleIssueRequestDetail }, temp, + useBalanceList).ConfigureAwait(false)); + } + } + } + } + + if (assembleIssueJobEditInputs.Count > 0) //有库存 可以创建任务 + { + //新增任务 + var addAssembleIssueJobDtos = await _assembleIssueJobAppService.CreateManyAsync(assembleIssueJobEditInputs) + .ConfigureAwait(false); + + await UpdateAssembleIssueRequestDetailQtyAsync(assembleIssueRequest, addAssembleIssueJobDtos) + .ConfigureAwait(false); + + return addAssembleIssueJobDtos; + } + + return new List(); + } + + /// + /// 修改请求的 已发 已收数量 + /// + /// + /// + /// + private async Task UpdateAssembleIssueRequestDetailQtyAsync(AssembleIssueRequest assembleIssueRequest, + List addAssembleIssueJobDtos) + { + //原有任务 + var existAssembleIssueJobDtos = await _assembleIssueJobAppService + .GetByRequestNumberAsync(assembleIssueRequest.Number) + .ConfigureAwait(false); + + //新增的任务和已有的任务总和 + var allAssembleIssueJobDtos = new List(); + allAssembleIssueJobDtos.AddRange(addAssembleIssueJobDtos); + allAssembleIssueJobDtos.AddRange(existAssembleIssueJobDtos); + + var groupByItemCodeLocationCode = assembleIssueRequest.Details.GroupBy(p => + new { p.ItemCode, p.ToLocationCode }); + foreach (var group in groupByItemCodeLocationCode) + { + foreach (var requestDetail in group) + { + //所有已发数量 + decimal allIssuedQty = 0; + + //所有已发数量 + decimal allReceivedQty = 0; + + foreach (var allAssembleIssueJobDto in allAssembleIssueJobDtos) + { + var jobDetailDtos = allAssembleIssueJobDto.Details.Where(p => + p.ItemCode == group.Key.ItemCode && p.RequestLocationCode == group.Key.ToLocationCode); + //所有已发数量 + allIssuedQty += jobDetailDtos.Sum(p => p.RequestQty); + //所有已发数量 + allReceivedQty += jobDetailDtos.Sum(p => p.HandledToQty); + } + + requestDetail.IssuedQty += allIssuedQty; + requestDetail.ReceivedQty += allReceivedQty; + } + } + + //await _assembleIssueRequestManager.UpdateAsync(assembleIssueRequest).ConfigureAwait(false); + } + + /// + /// 排序规则 1.批次正序 2.底层 3.到货日期正序 4.数量倒序(整箱优先) 5.库位正序 6.箱码正序 + /// + /// + /// + public async Task> SortByFifoAsync(List balances) + { + var sortBalances = new List(); + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap() + .Ignore(x => x.LocationRow); + }); + _mapper = new Mapper(config); + + var resultBalances = _mapper.Map, List>(balances); + foreach (var resultBalance in resultBalances) + { + var locationDto = await _locationAppService.GetByCodeAsync(resultBalance.LocationCode).ConfigureAwait(false); + resultBalance.LocationRow = locationDto.RowCode; + } + + resultBalances + .OrderBy(p => p.Lot) + .ThenBy(p => p.LocationRow) + .ThenBy(p => p.PutInTime) + .ThenBy(p => p.Qty)//2023-9-14 苑静雯 从小数开始发料 + .ThenBy(p => p.LocationCode) + .ThenBy(p => p.PackingCode) + .ToList(); + + return resultBalances; + } } + From 2c52e4d7fe36a35d46589323feb3e95d00fe8038 Mon Sep 17 00:00:00 2001 From: zhouhongjun <565221961@qq.com> Date: Tue, 14 May 2024 09:15:06 +0800 Subject: [PATCH 2/2] =?UTF-8?q?pda=E5=A2=9E=E5=8A=A0=E8=A3=85=E9=85=8D?= =?UTF-8?q?=E5=8F=AB=E6=96=99=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IssueJobs/AssembleIssueJobsController.cs | 187 ++++++++++++++++++ .../IssueRequest/AssembleRequestController.cs | 135 +++++++++++++ 2 files changed, 322 insertions(+) create mode 100644 be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Jobs/IssueJobs/AssembleIssueJobsController.cs create mode 100644 be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Stores/IssueRequest/AssembleRequestController.cs diff --git a/be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Jobs/IssueJobs/AssembleIssueJobsController.cs b/be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Jobs/IssueJobs/AssembleIssueJobsController.cs new file mode 100644 index 000000000..c484b667b --- /dev/null +++ b/be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Jobs/IssueJobs/AssembleIssueJobsController.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc; +using Win_in.Sfs.Auth.Application.Contracts; +using Win_in.Sfs.Shared.Domain; +using Win_in.Sfs.Shared.Domain.Shared; +using Win_in.Sfs.Wms.Store.Application.Contracts; + +namespace Win_in.Sfs.Wms.Pda.Controllers.Jobs.IssueJobs; + +/// +/// +[ApiController] +[Route($"{PdaHostConst.ROOT_ROUTE}job/assemble-issue")] +public class AssembleIssueJobsController : AbpController +{ + private readonly IAssembleIssueJobAppService _assembleIssueJobAppService; + + private readonly IUserWorkGroupAppService _userWorkGroupAppService; + + public AssembleIssueJobsController(IAssembleIssueJobAppService assembleIssueJobAppService, IUserWorkGroupAppService userWorkGroupAppService) + { + _assembleIssueJobAppService = assembleIssueJobAppService; + _userWorkGroupAppService = userWorkGroupAppService; + } + + /// + /// 获取列表 + /// + /// + /// + /// + /// + [HttpPost("list")] + public virtual async Task> GetListAsync(int pageSize, int pageIndex, + bool isFinished) + { + var status = new List(); + if (isFinished) + { + status.Add((int)EnumJobStatus.Done); + } + else + { + status.Add((int)EnumJobStatus.Open); + status.Add((int)EnumJobStatus.Wait); + status.Add((int)EnumJobStatus.Doing); + status.Add((int)EnumJobStatus.Partial); + } + + var jsonStatus = JsonSerializer.Serialize(status); + + var request = new SfsJobRequestInputBase + { + MaxResultCount = pageSize, + SkipCount = (pageIndex - 1) * pageSize, + Sorting = $"{nameof(ContainerJobDTO.CreationTime)} ASC", + Condition = new Condition + { + Filters = new List { new(nameof(ContainerJobDTO.JobStatus), jsonStatus, "In") } + } + }; + + var list = await _assembleIssueJobAppService.GetPagedListByFilterAsync(request, true).ConfigureAwait(false); + + return list; + } + + /// + /// 承接任务 + /// + /// + /// + [HttpPost("take/{id}")] + public virtual async Task TakeAsync(Guid id) + { + await _assembleIssueJobAppService.AcceptAsync(id).ConfigureAwait(false); + } + + /// + /// 取消承接任务 + /// + /// + /// + [HttpPost("cancel-take/{id}")] + public virtual async Task CancelTakeAsync(Guid id) + { + await _assembleIssueJobAppService.CancelAcceptAsync(id).ConfigureAwait(false); + } + + /// + /// 执行任务明细 + /// + /// + [HttpPost("ExecuteDetail/{masterId}")] + public async Task ExecuteDetailAsync(Guid masterId, Guid detailId, AssembleIssueJobDetailDTO issueJobDetailDto) + { + await _assembleIssueJobAppService.ExecuteDetailAsync(masterId, detailId, issueJobDetailDto).ConfigureAwait(false); + } + + /// + /// 获取任务数量 + /// + /// + [HttpGet("count")] + public virtual async Task> CountAsync() + { + var status = new List + { + (int)EnumJobStatus.Open, (int)EnumJobStatus.Doing, (int)EnumJobStatus.Partial, (int)EnumJobStatus.Wait + }; + var jsonStatus = JsonSerializer.Serialize(status); + + var request = new SfsJobRequestInputBase + { + Sorting = $"{nameof(InspectJobDTO.Priority)} ASC", + Condition = new Condition + { + Filters = new List + { + //new(nameof(InspectJobDTO.WorkGroupCode),jsonCodes,"In"), + new(nameof(InspectJobDTO.JobStatus), jsonStatus, "In") + } + } + }; + + var count = await _assembleIssueJobAppService.GetCountByFilterAsync(request).ConfigureAwait(false); + + return Ok(count); + } + + /// + /// 获取任务详情 + /// + /// + /// + [HttpGet("{id}")] + public virtual async Task> GetAsync(Guid id) + { + var result = await _assembleIssueJobAppService.GetAsync(id).ConfigureAwait(false); + return Ok(result); + } + + /// + /// 根据Job Number 获取盘点任务列表 + /// + /// + /// + [HttpGet("by-number/{jobNumber}")] + public virtual async Task> GetByNumberAsync(string jobNumber) + { + var jobDto = await _assembleIssueJobAppService.GetByNumberAsync(jobNumber).ConfigureAwait(false); + if (jobDto == null) + { + throw new UserFriendlyException($"未找到编号为 {jobNumber} 的任务"); + } + + var wlgCodes = await _userWorkGroupAppService.GetCodsOfCurrentUserAsync().ConfigureAwait(false); + if (!wlgCodes.Contains(jobDto.WorkGroupCode)) + { + return new NotFoundObjectResult($"任务属于工作组 {jobDto.WorkGroupCode}"); + } + + if (jobDto.JobStatus == EnumJobStatus.Doing && jobDto.AcceptUserId != CurrentUser.Id) + { + return new NotFoundObjectResult($"任务正在被 {jobDto.AcceptUserName} 处理"); + } + + return jobDto; + } + + /// + /// + /// + /// + /// + [HttpPost("by-request-number/{requestNumber}")] + public virtual async Task> GetByRequestNumberAsync(string requestNumber) + { + return await _assembleIssueJobAppService.GetByRequestNumberAsync(requestNumber).ConfigureAwait(false); + } +} diff --git a/be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Stores/IssueRequest/AssembleRequestController.cs b/be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Stores/IssueRequest/AssembleRequestController.cs new file mode 100644 index 000000000..1e2900989 --- /dev/null +++ b/be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Stores/IssueRequest/AssembleRequestController.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc; +using Win_in.Sfs.Auth.Application.Contracts; +using Win_in.Sfs.Shared.Domain; +using Win_in.Sfs.Shared.Domain.Shared; +using Win_in.Sfs.Wms.Store.Application.Contracts; + +namespace Win_in.Sfs.Wms.Pda.Controllers.Stores; + +/// +/// 装配叫料请求 +/// +[ApiController] +[Route($"{PdaHostConst.ROOT_ROUTE}store/assemble-request")] +public class AssembleRequestController : AbpController +{ + private readonly IAssembleIssueRequestAppService _assembleIssueRequestAppService; + + private readonly IUserWorkGroupAppService _userWorkGroupAppService; + + /// + /// + /// + public AssembleRequestController(IAssembleIssueRequestAppService assembleIssueRequestAppService, + IUserWorkGroupAppService userWorkGroupAppService) + { + _assembleIssueRequestAppService = assembleIssueRequestAppService; + _userWorkGroupAppService = userWorkGroupAppService; + } + + /// + /// Kitting叫料申请 + /// + /// + /// + [HttpPost("")] + public virtual async Task CreateAsync(AssembleIssueRequestEditInput input) + { + await _assembleIssueRequestAppService.CreateAndHandleAsync(input).ConfigureAwait(false); + } + + /// + /// + /// + /// + /// + /// + [HttpPost("list")] + public virtual async Task> GetListAsync(int pageSize, int pageIndex, + bool isFinished) + { + var status = new List(); + if (isFinished) + { + status.Add((int)EnumRequestStatus.Completed); + } + else + { + status.Add((int)EnumRequestStatus.Partial); + status.Add((int)EnumRequestStatus.Handling); + status.Add((int)EnumRequestStatus.New); + } + + var jsonStatus = JsonSerializer.Serialize(status); + + var request = new SfsStoreRequestInputBase + { + MaxResultCount = pageSize, + SkipCount = (pageIndex - 1) * pageSize, + Sorting = $"{nameof(AssembleIssueRequestDTO.CreationTime)} ASC", + Condition = new Condition + { + Filters = new List { new(nameof(AssembleIssueRequestDTO.RequestStatus), jsonStatus, "In") } + } + }; + + var list = await _assembleIssueRequestAppService.GetPagedListByFilterAsync(request, true).ConfigureAwait(false); + + return list; + } + + /// + /// + /// + [HttpPost("handle/{id}")] + public virtual async Task HandleAsync(Guid id) + { + await _assembleIssueRequestAppService.HandleAsync(id).ConfigureAwait(false); + } + + /// + /// 根据Job Number 获取盘点任务列表 + /// + /// + /// + [HttpGet("by-number/{requestNumber}")] + public virtual async Task> GetByNumberAsync(string requestNumber) + { + var jobDto = await _assembleIssueRequestAppService.GetByNumberAsync(requestNumber).ConfigureAwait(false); + if (jobDto == null) + { + throw new UserFriendlyException($"未找到编号为 {requestNumber} 的请求"); + } + + return jobDto; + } + + /// + /// 获取任务详情 + /// + /// + /// + [HttpGet("{id}")] + public virtual async Task> GetAsync(Guid id) + { + var result = await _assembleIssueRequestAppService.GetAsync(id).ConfigureAwait(false); + return Ok(result); + } + + /// + /// + /// + /// + [HttpPost("IsHasNewJob")] + public virtual async Task IsHasNewJobAsync(string requestNumber, List jobNumber) + { + return await _assembleIssueRequestAppService.IsHasNewJobAsync(requestNumber, jobNumber).ConfigureAwait(false); + } +}