diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/AssembleJobPermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/AssembleJobPermissions.cs
new file mode 100644
index 000000000..ec726a250
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/AssembleJobPermissions.cs
@@ -0,0 +1,27 @@
+using Volo.Abp.Authorization.Permissions;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public static class AssembleJobPermissions
+{
+
+ public const string Default = StorePermissions.GroupName + "." + nameof(AssembleJob);
+ public const string Create = Default + "." + StorePermissions.CreateStr;
+ public const string Update = Default + "." + StorePermissions.UpdateStr;
+ public const string Delete = Default + "." + StorePermissions.DeleteStr;
+
+ //自动发料任务
+ public const string AutoAssembleJob = StorePermissions.GroupName + "." + nameof(AutoAssembleJob);
+
+ public static void AddAssembleJobPermission(this PermissionGroupDefinition permissionGroup)
+ {
+ var AssembleJobPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleJob)));
+ AssembleJobPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
+ AssembleJobPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
+ AssembleJobPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
+
+ permissionGroup.AddPermission(AutoAssembleJob, StorePermissionDefinitionProvider.L(nameof(AutoAssembleJob)));
+
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/DTOs/AssembleJobDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/DTOs/AssembleJobDTO.cs
new file mode 100644
index 000000000..3e1f8691f
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/DTOs/AssembleJobDTO.cs
@@ -0,0 +1,46 @@
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+///
+/// 装配发料任务
+///
+[Display(Name = "装配发料任务")]
+public class AssembleJobDTO : SfsJobDTOBase
+{
+ ///
+ /// 叫料请求类型
+ ///
+ [Display(Name = "叫料请求类型")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string RequestType { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [Display(Name = "生产线")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 要货单号
+ ///
+ [Display(Name = "要货单号")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string AssembleRequestNumber { get; set; }
+
+ ///
+ /// 车间
+ ///
+ [Display(Name = "车间")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string Workshop { get; set; }
+
+ ///
+ /// 使用在途库
+ ///
+ [Display(Name = "使用在途库")]
+ public bool UseOnTheWayLocation { get; set; }
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/DTOs/AssembleJobDetailDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/DTOs/AssembleJobDetailDTO.cs
new file mode 100644
index 000000000..c89aa7d8f
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/DTOs/AssembleJobDetailDTO.cs
@@ -0,0 +1,112 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleJobDetailDTO : SfsJobRecommendFromDetailDTOBase, IHasToLocation
+{
+
+ ///
+ /// 请求库位
+ ///
+ [Display(Name = "请求库位")]
+ public string RequestLocationCode { get; set; }
+
+ ///
+ /// 到库位
+ ///
+ [Display(Name = "到库位")]
+ 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; }
+
+ ///
+ /// 在途库库位
+ ///
+ [Display(Name = "在途库库位")]
+ public string OnTheWayLocationCode { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [Display(Name = "生产线")]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 工作中心
+ ///
+ [Display(Name = "工作中心")]
+ public string WorkStation { get; set; }
+
+ ///
+ /// 过期时间
+ ///
+ [Display(Name = "过期时间")]
+ public DateTime ExpiredTime { get; set; }
+
+ ///
+ /// 工序
+ ///
+ [Display(Name = "工序")]
+ public string Operation { get; set; }
+
+ ///
+ /// 配送方式
+ ///
+ [Display(Name = "配送方式")]
+ public EnumDistributionType DistributionType { get; set; }
+
+ ///
+ /// 取整方式
+ ///
+ [Display(Name = "取整方式")]
+ public EnumTruncType TruncType { get; set; }
+
+ ///
+ /// 取整后数量
+ ///
+ [Display(Name = "取整后数量")]
+ public decimal RoundedQty { get; set; }
+
+ ///
+ /// 计划拆分规则
+ ///
+ [Display(Name = "计划拆分规则")]
+ public EnumPlannedSplitRule PlannedSplitRule { get; set; }
+
+ ///
+ /// 计划开始时间
+ ///
+ [Display(Name = "计划开始时间")]
+ public DateTime PlanBeginTime { get; set; }
+
+ ///
+ /// 每次配送数量
+ ///
+ [Display(Name = "每次配送数量")]
+ public decimal DeliveryQty { get; set; }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/IAssembleJobAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/IAssembleJobAppService.cs
new file mode 100644
index 000000000..fae62f6c7
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/IAssembleJobAppService.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Volo.Abp.Application.Dtos;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public interface IAssembleJobAppService
+ : ISfsJobAppServiceBase
+{
+ Task> CheckJobExistByItemCodeAndLocationCode(string itemCode, string locationCode);
+
+ Task CancelByMaterialRequestAsync(string assembleNumber);
+
+ Task> GetListByTypeAsync(SfsJobRequestInputBase requestInput, string requestType,
+ bool includeDetails = false, CancellationToken cancellationToken = default);
+
+ Task> GetByRequestNumberAsync(string requestNumber);
+
+ ///
+ /// 保存拆箱时涉及的明细修改
+ ///
+ ///
+ Task SaveDetail_SplitPackingAsync(SplitPacking_UpdateJobDetailInput input);
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/Inputs/AssembleJobCheckInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/Inputs/AssembleJobCheckInput.cs
new file mode 100644
index 000000000..ef75e7d73
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/Inputs/AssembleJobCheckInput.cs
@@ -0,0 +1,6 @@
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleJobCheckInput : SfsJobCheckInputBase
+{
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/Inputs/AssembleJobDetailInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/Inputs/AssembleJobDetailInput.cs
new file mode 100644
index 000000000..18b59ae9d
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/Inputs/AssembleJobDetailInput.cs
@@ -0,0 +1,134 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleJobDetailInput : SfsJobRecommendFromDetailInputBase, IHasToLocation
+{
+
+ ///
+ /// 请求库位
+ ///
+ [Display(Name = "请求库位")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string RequestLocationCode { get; set; }
+
+ ///
+ /// 到库位
+ ///
+ [Display(Name = "到库位")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ [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库位")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string ToLocationErpCode { get; set; }
+
+ ///
+ /// 到仓库
+ ///
+ [Display(Name = "到仓库")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string ToWarehouseCode { get; set; }
+
+ ///
+ /// 在途库库位
+ ///
+ [Display(Name = "在途库库位")]
+ public string OnTheWayLocationCode { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [Display(Name = "生产线")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 工作中心
+ ///
+ [Display(Name = "工作中心")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string WorkStation { get; set; }
+
+ ///
+ /// 过期时间
+ ///
+ [Display(Name = "过期时间")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ public DateTime ExpiredTime { get; set; }
+
+ ///
+ /// 工序
+ ///
+ [Display(Name = "工序")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string Operation { get; set; }
+
+ ///
+ /// 配送方式
+ ///
+ [Display(Name = "配送方式")]
+ public EnumDistributionType DistributionType { get; set; }
+
+ ///
+ /// 取整方式
+ ///
+ [Display(Name = "取整方式")]
+ public EnumTruncType TruncType { get; set; }
+
+ ///
+ /// 取整后数量
+ ///
+ [Display(Name = "取整后数量")]
+ public decimal RoundedQty { get; set; }
+
+ ///
+ /// 计划拆分规则
+ ///
+ [Display(Name = "计划拆分规则")]
+ public EnumPlannedSplitRule PlannedSplitRule { get; set; }
+
+ ///
+ /// 计划开始时间
+ ///
+ [Display(Name = "计划开始时间")]
+ public DateTime PlanBeginTime { get; set; }
+
+ ///
+ /// 每次配送数量
+ ///
+ [Display(Name = "每次配送数量")]
+ public decimal DeliveryQty { get; set; }
+
+ ///
+ /// 位置码
+ ///
+ public string PositionCode { get; set; }
+
+ ///
+ /// 推荐类型
+ ///
+ public EnumRecommendType RecommendType { get; set; }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/Inputs/AssembleJobEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/Inputs/AssembleJobEditInput.cs
new file mode 100644
index 000000000..8e719283c
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleJobs/Inputs/AssembleJobEditInput.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleJobEditInput : SfsJobCreateUpdateInputBase, ISfsJobCreateInput
+{
+ #region Create
+ ///
+ /// 上游任务编号
+ ///
+ [Display(Name = "上游任务编号")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string UpStreamJobNumber { get; set; }
+
+ ///
+ /// 要货单号
+ ///
+ [Display(Name = "要货单号")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string AssembleRequestNumber { get; set; }
+
+ ///
+ /// 叫料请求类型
+ ///
+ [Display(Name = "叫料请求类型")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string RequestType { get; set; }
+
+ ///
+ /// 任务类型
+ ///
+ [Display(Name = "任务类型")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ public EnumJobType JobType { get; set; }
+
+ ///
+ /// 是否自动完成
+ ///
+ [Display(Name = "是否自动完成")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ public bool IsAutoComplete { get; set; }
+
+ ///
+ /// 过期时间
+ ///
+ [Display(Name = "过期时间")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ public DateTime ExpiredTime { get; set; }
+
+ ///
+ /// 任务明细
+ ///
+ [Display(Name = "任务明细")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ public List Details { get; set; } = new();
+
+ ///
+ /// 车间
+ ///
+ [Display(Name = "车间")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string Workshop { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [Display(Name = "生产线")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 使用在途库
+ ///
+ [Display(Name = "使用在途库")]
+ public bool UseOnTheWayLocation { get; set; }
+ #endregion
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/AssembleNotePermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/AssembleNotePermissions.cs
new file mode 100644
index 000000000..1b05f191c
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/AssembleNotePermissions.cs
@@ -0,0 +1,30 @@
+using Volo.Abp.Authorization.Permissions;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public static class AssembleNotePermissions
+{
+
+ public const string Default = StorePermissions.GroupName + "." + nameof(AssembleNote);
+ public const string Create = Default + "." + StorePermissions.CreateStr;
+ public const string Update = Default + "." + StorePermissions.UpdateStr;
+ public const string Delete = Default + "." + StorePermissions.DeleteStr;
+
+ //自动发料记录
+ public const string AutoAssembleNote = StorePermissions.GroupName + "." + nameof(AutoAssembleNote);
+
+ //直接发料
+ public const string DirectAssembleNote = StorePermissions.GroupName + "." + nameof(DirectAssembleNote);
+
+ public static void AddAssembleNotePermission(this PermissionGroupDefinition permissionGroup)
+ {
+ var AssembleNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleNote)));
+ AssembleNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
+ AssembleNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
+ AssembleNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
+
+ permissionGroup.AddPermission(AutoAssembleNote, StorePermissionDefinitionProvider.L(nameof(AutoAssembleNote)));
+ permissionGroup.AddPermission(DirectAssembleNote, StorePermissionDefinitionProvider.L(nameof(DirectAssembleNote)));
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/DTOs/AssembleNoteDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/DTOs/AssembleNoteDTO.cs
new file mode 100644
index 000000000..6db88f8bb
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/DTOs/AssembleNoteDTO.cs
@@ -0,0 +1,54 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleNoteDTO : SfsStoreDTOBase, IHasJobNumber, IHasRequestNumber
+{
+
+ ///
+ /// 任务ID
+ ///
+ [Display(Name = "任务ID")]
+ public string JobNumber { get; set; }
+
+ ///
+ /// 车间
+ ///
+ [Display(Name = "车间")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string Workshop { get; set; }
+
+ ///
+ /// 请求代码
+ ///
+ [Display(Name = "请求代码")]
+ public string RequestNumber { get; set; }
+
+ ///
+ /// 叫料请求类型
+ ///
+ [Display(Name = "叫料请求类型")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string RequestType { get; set; }
+
+ ///
+ /// 使用在途库
+ ///
+ [Display(Name = "使用在途库")]
+ public bool UseOnTheWayLocation { get; set; }
+
+ ///
+ /// 已确认
+ ///
+ [Display(Name = "已确认")]
+ public bool Confirmed { get; set; }
+
+ ///
+ /// 确认时间
+ ///
+ [Display(Name = "确认时间")]
+ public DateTime? ConfirmTime { get; set; }
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/DTOs/AssembleNoteDetailDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/DTOs/AssembleNoteDetailDTO.cs
new file mode 100644
index 000000000..cefbe75a5
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/DTOs/AssembleNoteDetailDTO.cs
@@ -0,0 +1,42 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleNoteDetailDTO : SfsStoreRecommendFromDetailWithFromToDTOBase
+{
+
+ ///
+ /// 发料时间
+ ///
+ [Display(Name = "发料时间")]
+ public DateTime IssueTime { get; set; }
+
+ ///
+ /// 过期时间
+ ///
+ [Display(Name = "过期时间")]
+ public DateTime ExpiredTime { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [Display(Name = "生产线")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 工作中心
+ ///
+ [Display(Name = "工作中心")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string WorkStation { get; set; }
+
+ ///
+ /// 在途库库位
+ ///
+ [Display(Name = "在途库库位")]
+ public string OnTheWayLocationCode { get; set; }
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/IAssembleNoteAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/IAssembleNoteAppService.cs
new file mode 100644
index 000000000..af04bbaf4
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/IAssembleNoteAppService.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Volo.Abp.Application.Dtos;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public interface IAssembleNoteAppService : ISfsStoreMasterReadOnlyAppServiceBase
+{
+ Task CreateAsync(AssembleNoteEditInput input);
+
+ Task ConfirmAsync(Guid id);
+
+ Task ConfirmAsync(string number);
+
+ Task> GetListByTypeAsync(SfsStoreRequestInputBase requestInput,
+ string requestType, bool includeDetails = false, CancellationToken cancellationToken = default);
+
+ Task> GetListUnConfirmedByTypeAsync(string requestType);
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/Inputs/AssembleNoteDetailInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/Inputs/AssembleNoteDetailInput.cs
new file mode 100644
index 000000000..4a194dc44
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/Inputs/AssembleNoteDetailInput.cs
@@ -0,0 +1,53 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleNoteDetailInput : SfsStoreRecommendFromDetailWithFromToInputBase
+{
+
+ ///
+ /// 发料时间
+ ///
+ [Display(Name = "发料时间")]
+ public DateTime IssueTime { get; set; }
+
+ ///
+ /// 过期时间
+ ///
+ [Display(Name = "过期时间")]
+ public DateTime ExpiredTime { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [Display(Name = "生产线")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 工作中心
+ ///
+ [Display(Name = "工作中心")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string WorkStation { get; set; }
+
+ ///
+ /// 在途库库位
+ ///
+ [Display(Name = "在途库库位")]
+ public string OnTheWayLocationCode { get; set; }
+
+ ///
+ /// 位置码
+ ///
+ public string PositionCode { get; set; }
+
+ ///
+ /// 推荐类型
+ ///
+ public EnumRecommendType RecommendType { get; set; }
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/Inputs/AssembleNoteEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/Inputs/AssembleNoteEditInput.cs
new file mode 100644
index 000000000..b3c23c67f
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/Inputs/AssembleNoteEditInput.cs
@@ -0,0 +1,63 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleNoteEditInput : SfsStoreCreateOrUpdateInputBase
+{
+ #region Base
+ ///
+ /// 已确认
+ ///
+ [Display(Name = "已确认")]
+ public bool Confirmed { get; set; }
+ #endregion
+
+ #region Create
+ ///
+ /// 发料记录号
+ ///
+ [Display(Name = "发料记录号")]
+ public string Number { get; set; }
+
+ ///
+ /// 任务ID
+ ///
+ [Display(Name = "任务ID")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ public string JobNumber { get; set; }
+
+ ///
+ /// 车间
+ ///
+ [Display(Name = "车间")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string Workshop { get; set; }
+
+ ///
+ /// 明细列表
+ ///
+ [Display(Name = "明细列表")]
+ public List Details { get; set; }
+
+ ///
+ /// 请求号码
+ ///
+ [Display(Name = "请求号码")]
+ public string RequestNumber { get; set; }
+
+ ///
+ /// 叫料请求类型
+ ///
+ [Display(Name = "叫料请求类型")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string RequestType { get; set; }
+
+ ///
+ /// 使用在途库
+ ///
+ [Display(Name = "使用在途库")]
+ public bool UseOnTheWayLocation { get; set; }
+ #endregion
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/Inputs/AssembleNoteImportInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/Inputs/AssembleNoteImportInput.cs
new file mode 100644
index 000000000..415f3334c
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleNotes/Inputs/AssembleNoteImportInput.cs
@@ -0,0 +1,33 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleNoteImportInput : SfsStoreImportInputBase, IHasJobNumber, IHasRequestNumber
+{
+ ///
+ /// 任务ID
+ ///
+ [Display(Name = "任务ID")]
+ public string JobNumber { get; set; }
+
+ ///
+ /// 车间
+ ///
+ [Display(Name = "车间")]
+ public string Workshop { get; set; }
+
+ public string RequestNumber { get; set; }
+
+ ///
+ /// 叫料请求类型
+ ///
+ [Display(Name = "叫料请求类型")]
+ public string RequestType { get; set; }
+
+ ///
+ /// 使用在途库
+ ///
+ [Display(Name = "使用在途库")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ public bool UseOnTheWayLocation { get; set; }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Permissions/StorePermissionDefinitionProvider.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Permissions/StorePermissionDefinitionProvider.cs
index c99e2abe8..52618b9ac 100644
--- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Permissions/StorePermissionDefinitionProvider.cs
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Permissions/StorePermissionDefinitionProvider.cs
@@ -27,9 +27,11 @@ public class StorePermissionDefinitionProvider : PermissionDefinitionProvider
storeGroup.AddPutawayNotePermission();
storeGroup.AddMaterialRequestPermission();
storeGroup.AddInjectionRequestPermission();
+ storeGroup.AddAssembleRequestPermission();
storeGroup.AddContainerRequestPermission();
storeGroup.AddIssueNotePermission();
storeGroup.AddInjectionNotePermission();
+ storeGroup.AddAssembleNotePermission();
storeGroup.AddContainerNotePermission();
storeGroup.AddUnplannedReceiptNotePermission();
storeGroup.AddUnplannedIssueNotePermission();
@@ -93,6 +95,7 @@ public class StorePermissionDefinitionProvider : PermissionDefinitionProvider
storeGroup.AddPutawayJobPermission();
storeGroup.AddIssueJobPermission();
storeGroup.AddInjectionJobPermission();
+ storeGroup.AddAssembleJobPermission();
storeGroup.AddContainerJobPermission();
storeGroup.AddDeliverJobPermission();
storeGroup.AddPurchaseReturnJobPermission();
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/AssembleRequestPermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/AssembleRequestPermissions.cs
new file mode 100644
index 000000000..f7c0f9228
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/AssembleRequestPermissions.cs
@@ -0,0 +1,27 @@
+using Volo.Abp.Authorization.Permissions;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public static class AssembleRequestPermissions
+{
+
+ public const string Default = StorePermissions.GroupName + "." + nameof(AssembleRequest);
+ public const string Create = Default + "." + StorePermissions.CreateStr;
+ public const string Update = Default + "." + StorePermissions.UpdateStr;
+ public const string Delete = Default + "." + StorePermissions.DeleteStr;
+
+ //自动叫料申请
+ public const string AutoAssembleRequest = StorePermissions.GroupName + "." + nameof(AutoAssembleRequest);
+
+ public static void AddAssembleRequestPermission(this PermissionGroupDefinition permissionGroup)
+ {
+ var AssembleRequestPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleRequest)));
+ AssembleRequestPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
+ AssembleRequestPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
+ AssembleRequestPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
+
+ permissionGroup.AddPermission(AutoAssembleRequest, StorePermissionDefinitionProvider.L(nameof(AutoAssembleRequest)));
+
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/DTOs/AssembleRequestDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/DTOs/AssembleRequestDTO.cs
new file mode 100644
index 000000000..7582d35a7
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/DTOs/AssembleRequestDTO.cs
@@ -0,0 +1,40 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleRequestDTO : SfsStoreRequestDTOBase, IHasNumber
+{
+ ///
+ /// 叫料类型
+ ///
+ [Display(Name = "叫料类型")]
+ public string Type { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [Display(Name = "生产线")]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 是否使用在途库
+ ///
+ [Display(Name = "是否使用在途库")]
+ public bool IsUseOnTheWayLocation { get; set; }
+
+ ///
+ /// 可用来源库位Json集合
+ ///
+ public string FromLocationCodeJsonList { get; set; }
+
+ ///
+ /// 叫料库位
+ ///
+ public string ToLocationCode { get; set; }
+
+ ///
+ /// 目标ERP储位
+ ///
+ [Display(Name = "目标ERP储位")]
+ public string ToLocationErpCode { get; set; }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/DTOs/AssembleRequestDetailDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/DTOs/AssembleRequestDetailDTO.cs
new file mode 100644
index 000000000..71a9dbcf0
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/DTOs/AssembleRequestDetailDTO.cs
@@ -0,0 +1,50 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using Win_in.Sfs.Shared.Domain;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleRequestDetailDTO : SfsStoreDetailWithQtyDTOBase
+{
+ ///
+ /// 已发数量
+ ///
+ [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;
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/IAssembleRequestAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/IAssembleRequestAppService.cs
new file mode 100644
index 000000000..34e3ec465
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/IAssembleRequestAppService.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Volo.Abp.Application.Dtos;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public interface IAssembleRequestAppService
+ : ISfsStoreRequestMasterAppServiceBase
+
+{
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/Inputs/AssembleRequestDetailInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/Inputs/AssembleRequestDetailInput.cs
new file mode 100644
index 000000000..befe44e2f
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/Inputs/AssembleRequestDetailInput.cs
@@ -0,0 +1,85 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleRequestDetailInput : SfsStoreDetailWithQtyInputBase
+{
+ ///
+ /// 目标库位
+ ///
+ [Display(Name = "目标库位")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string ToLocationCode { get; set; }
+
+ ///
+ /// 来源库区
+ ///
+ [Display(Name = "来源库区")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string FromLocationArea { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [Display(Name = "生产线")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 工作中心
+ ///
+ [Display(Name = "工作中心")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string WorkStation { get; set; }
+
+ ///
+ /// 过期时间
+ ///
+ [Display(Name = "过期时间")]
+ public DateTime ExpiredTime { get; set; }
+
+ ///
+ /// 状态
+ ///
+ [Display(Name = "状态")]
+ public EnumRequestStatus RequestStatus { get; set; } = EnumRequestStatus.New;
+
+ ///
+ /// ERP储位
+ ///
+ [Display(Name = "ERP储位")]
+ public string ToLocationErpCode { get; set; }
+
+ ///
+ /// 已发数量
+ ///
+ [Display(Name = "已发数量")]
+ public decimal IssuedQty { get; set; }
+
+ ///
+ /// 已收数量
+ ///
+ [Display(Name = "已收数量")]
+ public decimal ReceivedQty { get; set; }
+
+ ///
+ /// 明细状态
+ ///
+ [Display(Name = "明细状态")]
+ public EnumStatus Status { get; set; }
+
+ ///
+ /// 位置码
+ ///
+ public string PositionCode { get; set; }
+
+ ///
+ /// 推荐类型
+ ///
+ public EnumRecommendType RecommendType { get; set; }
+
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/Inputs/AssembleRequestEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/Inputs/AssembleRequestEditInput.cs
new file mode 100644
index 000000000..2dbba1a36
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/Inputs/AssembleRequestEditInput.cs
@@ -0,0 +1,58 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class AssembleRequestEditInput : SfsStoreRequestCreateOrUpdateInputBase
+{
+ #region Base
+ ///
+ /// 车间
+ ///
+ [Display(Name = "车间")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string Workshop { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [Display(Name = "生产线")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 使用在途库
+ ///
+ [Display(Name = "使用在途库")]
+ public bool UseOnTheWayLocation { get; set; }
+ #endregion
+
+ #region Create
+ ///
+ /// 要货单号
+ ///
+ [Display(Name = "要货单号")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string Number { get; set; }
+
+ ///
+ /// 叫料类型
+ ///
+ [Display(Name = "叫料类型")]
+ public string Type { get; set; }
+
+ ///
+ /// 备料计划单号
+ ///
+ [Display(Name = "备料计划单号")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string PreparationPlanNumber { get; set; }
+
+ ///
+ /// 明细列表
+ ///
+ [Display(Name = "明细列表")]
+ public List Details { get; set; } = new List();
+ #endregion
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/Inputs/AssembleRequestImportInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/Inputs/AssembleRequestImportInput.cs
new file mode 100644
index 000000000..d5fe8bc84
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/AssembleRequests/Inputs/AssembleRequestImportInput.cs
@@ -0,0 +1,53 @@
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Application.Contracts;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+[Display(Name = "叫料申请")]
+public class AssembleRequestImportInput : SfsStoreImportInputBase
+{
+ ///
+ /// 叫料类型
+ ///
+ [Display(Name = "叫料类型")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ [ImporterHeader(Name = "叫料类型")]
+ [ExporterHeader(DisplayName = "叫料类型")]
+ [ValueMapping("人工拉动", EnumMaterialRequestType.Issue_Manual)]
+ public string Type { get; set; }
+
+ ///
+ /// 物品代码
+ ///
+ [Display(Name = "物品代码")]
+ [Required]
+ public string ItemCode { get; set; }
+
+ ///
+ /// 目标库位
+ ///
+ [Display(Name = "目标库位")]
+ [Required]
+ public string ToLocationCode { get; set; }
+
+ ///
+ /// 来源库区
+ ///
+ [Display(Name = "调出库区")]
+ [Required]
+ public string FromLocationArea { get; set; }
+
+ ///
+ /// 数量
+ ///
+ [Display(Name = "数量")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ public decimal Qty { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [Display(Name = "备注")]
+ public string Remark { get; set; }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleJobs/AssembleJobAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleJobs/AssembleJobAppService.cs
new file mode 100644
index 000000000..e58d26e1b
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleJobs/AssembleJobAppService.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Volo.Abp;
+using Volo.Abp.Application.Dtos;
+using Volo.Abp.ObjectMapping;
+using Win_in.Sfs.Basedata.Domain.Shared;
+using Win_in.Sfs.Shared.Domain;
+using Win_in.Sfs.Shared.Domain.Shared;
+using Win_in.Sfs.Wms.Store.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Domain;
+using Win_in.Sfs.Wms.Store.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Application;
+
+[Authorize]
+[Route($"{StoreConsts.RootPath}assemble-job")]
+public class AssembleJobAppService
+ : SfsJobAppServiceBase,
+ IAssembleJobAppService
+{
+ private readonly IAssembleJobManager _assembleJobManager;
+
+ public AssembleJobAppService(
+ IAssembleJobRepository repository, IAssembleJobManager assembleJobManager
+ ) : base(repository, assembleJobManager)
+ {
+ _assembleJobManager = assembleJobManager;
+ }
+
+ ///
+ /// 根据物品和库位 检查是否存在发料任务
+ ///
+ ///
+ ///
+ ///
+ ///
+ [Authorize]
+ [HttpGet("check-job-exist")]
+ public virtual async Task> CheckJobExistByItemCodeAndLocationCode(string itemCode,
+ string locationCode)
+ {
+ var entities = await _repository.GetListAsync(c =>
+ c.Details.Any(p =>
+ (p.ItemCode == itemCode && p.RecommendFromLocationCode == locationCode) ||
+ (p.ItemCode == itemCode && p.ToLocationCode == locationCode))
+ && (c.JobStatus == EnumJobStatus.Open || c.JobStatus == EnumJobStatus.Doing), true).ConfigureAwait(false);
+ var dtos = ObjectMapper.Map, List>(entities);
+ return dtos;
+ }
+
+ [HttpPost("cancel-by-request/{assembleNumber}")]
+ public virtual async Task CancelByMaterialRequestAsync(string assembleNumber)
+ {
+ var entities = await _repository.GetListAsync(p => p.AssembleRequestNumber == assembleNumber).ConfigureAwait(false);
+ foreach (var entity in entities)
+ {
+ await _assembleJobManager.CancelAsync(entity).ConfigureAwait(false);
+ }
+ }
+
+ [HttpPost("invalid")]
+ public override async Task CancelAsync(Guid id)
+ {
+ var assembleJob = await _repository.GetAsync(id).ConfigureAwait(false);
+ if (assembleJob == null)
+ {
+ throw new UserFriendlyException($"未找到ID为 {id} 的任务");
+ }
+
+ await _assembleJobManager.CancelAsync(assembleJob).ConfigureAwait(false);
+
+ }
+
+ ///
+ /// 根据叫料请求类型获取发料任务
+ ///
+ ///
+ ///
+ /// 叫料请求类型:
+ /// 人工拉动:Issue_Manual;
+ /// 线边拉动:Issue_WIP;
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("by-type/{requestType}")]
+ public virtual async Task> GetListByTypeAsync(SfsJobRequestInputBase requestInput,
+ string requestType, bool includeDetails = false, CancellationToken cancellationToken = default)
+ {
+ Expression> expression = p => p.RequestType == requestType;
+ if (requestInput.Condition.Filters?.Count > 0)
+ {
+ expression = expression.And(requestInput.Condition.Filters.ToLambda());
+ }
+
+ return await GetPagedListAsync(expression, requestInput.SkipCount, requestInput.MaxResultCount,
+ requestInput.Sorting, includeDetails, cancellationToken).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("save-detail-split-packing")]
+ public virtual async Task SaveDetail_SplitPackingAsync(SplitPacking_UpdateJobDetailInput input)
+ {
+ var job = await _repository.FindAsync(p => p.Number == input.Number).ConfigureAwait(false);
+ AssembleJobDetail detail = job.Details.FirstOrDefault(p => p.RecommendPackingCode == input.FromPackingCode ); /*&& p.HandledQty == input.FromQty*/
+ if (detail == null)
+ {
+ //throw new UserFriendlyException($"根据HandledPackingCode={input.FromPackingCode}取AssembleJobDetail表为空!");
+ throw new UserFriendlyException($"根据RecommendPackingCode={input.FromPackingCode}取AssembleJobDetail表为空!");
+ }
+ //插入目标箱
+ var newDetail = CommonHelper.CloneObj(detail);
+ newDetail.SetId(GuidGenerator.Create());
+ newDetail.RecommendPackingCode = input.ToPackingCode;
+ newDetail.RecommendQty = input.ToQty;
+ newDetail.HandledPackingCode = detail.HandledPackingCode.HasValue() ? input.ToPackingCode : null; //源实际实际箱码有值,则新记录实际箱码有值
+ newDetail.HandledQty = detail.HandledQty > 0 ? input.ToQty : 0;
+ //newDetail.CreationTime = CommonHelper.CurTime;
+ job.Details.Add(newDetail);
+ //修改源箱
+ detail.RecommendQty = input.FromQty - input.ToQty;
+ detail.HandledQty = detail.HandledQty > 0 ? input.FromQty - input.ToQty : 0;
+ var entity = await _repository.UpdateAsync(job).ConfigureAwait(false);
+ var ret = ObjectMapper.Map(entity);
+ return ret;
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleJobs/AssembleJobAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleJobs/AssembleJobAutoMapperProfile.cs
new file mode 100644
index 000000000..d60824554
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleJobs/AssembleJobAutoMapperProfile.cs
@@ -0,0 +1,29 @@
+using AutoMapper;
+using Volo.Abp.AutoMapper;
+using Win_in.Sfs.Wms.Store.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Application;
+
+public partial class StoreApplicationAutoMapperProfile : Profile
+{
+ private void AssembleJobAutoMapperProfile()
+ {
+ CreateMap()
+ .ReverseMap();
+
+ CreateMap()
+ ;
+
+ CreateMap()
+ ;
+
+ CreateMap()
+ .IgnoreAuditedObjectProperties()
+ .Ignore(x => x.MasterID)
+ .Ignore(x => x.TenantId)
+ .Ignore(x => x.Number)
+ .Ignore(x => x.Id);
+
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleNotes/AssembleNoteAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleNotes/AssembleNoteAppService.cs
new file mode 100644
index 000000000..32675638b
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleNotes/AssembleNoteAppService.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Volo.Abp;
+using Volo.Abp.Application.Dtos;
+using Volo.Abp.Domain.Entities;
+using Win_in.Sfs.Shared.Domain;
+using Win_in.Sfs.Shared.Event;
+using Win_in.Sfs.Wms.Store.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Domain;
+using Win_in.Sfs.Wms.Store.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Application;
+
+[Authorize]
+[Route($"{StoreConsts.RootPath}assemble-note")]
+public class AssembleNoteAppService :
+ SfsStoreWithDetailsAppServiceBase,
+ IAssembleNoteAppService
+{
+ private readonly IAssembleNoteManager _assembleNoteManager;
+
+ public AssembleNoteAppService(
+ IAssembleNoteRepository repository,
+ IAssembleNoteManager assembleNoteManager
+ ) : base(repository)
+ {
+ _assembleNoteManager = assembleNoteManager;
+ }
+
+ [HttpPost("")]
+ //[Authorize(AssembleNotePermissions.Create)]
+ public override async Task CreateAsync(AssembleNoteEditInput input)
+ {
+ var entity = ObjectMapper.Map(input);
+ await _assembleNoteManager.CreateAsync(entity).ConfigureAwait(false);
+ var dto = ObjectMapper.Map(entity);
+ return dto;
+ }
+
+ ///
+ /// 确认对应的记录单
+ ///
+ ///
+ ///
+ [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);
+ }
+
+ [HttpPost("confirm-by-number/{number}")]
+ public virtual async Task ConfirmAsync(string number)
+ {
+ var entity = await _repository.FindAsync(p => p.Number == number).ConfigureAwait(false);
+ Check.NotNull(entity, nameof(AssembleNote));
+ var result = await _assembleNoteManager.ConfirmAsync(entity.Id).ConfigureAwait(false);
+ var dto = ObjectMapper.Map(result);
+ return dto;
+ }
+ ///
+ /// 根据叫料请求类型获取发料记录
+ ///
+ ///
+ ///
+ /// 叫料请求类型:
+ /// 人工拉动:Issue_Manual;
+ /// 线边拉动:Issue_WIP;
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("by-type/{requestType}")]
+ public virtual async Task> GetListByTypeAsync(SfsStoreRequestInputBase requestInput,
+ string requestType, bool includeDetails = false, CancellationToken cancellationToken = default)
+ {
+ Expression> expression = p => p.RequestType == requestType;
+ if (requestInput.Condition.Filters?.Count > 0)
+ {
+ expression = expression.And(requestInput.Condition.Filters.ToLambda());
+ }
+
+ return await GetPagedListAsync(expression, requestInput.SkipCount, requestInput.MaxResultCount,
+ requestInput.Sorting, includeDetails, cancellationToken).ConfigureAwait(false);
+ }
+
+ [HttpGet("list/un-confirmed/{requestType}")]
+ public virtual async Task> GetListUnConfirmedByTypeAsync(string requestType)
+ {
+ var entities = await _repository.GetListAsync(c => !c.Confirmed && c.RequestType == requestType)
+ .ConfigureAwait(false);
+
+ var dtos = ObjectMapper.Map, List>(entities);
+
+ return dtos;
+ }
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleNotes/AssembleNoteAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleNotes/AssembleNoteAutoMapperProfile.cs
new file mode 100644
index 000000000..04a6875d3
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleNotes/AssembleNoteAutoMapperProfile.cs
@@ -0,0 +1,31 @@
+using AutoMapper;
+using Volo.Abp.AutoMapper;
+using Win_in.Sfs.Wms.Store.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Application;
+
+public partial class StoreApplicationAutoMapperProfile : Profile
+{
+ private void AssembleNoteAutoMapperProfile()
+ {
+ CreateMap()
+ .ReverseMap();
+
+ CreateMap();
+
+ CreateMap()
+ .IgnoreAuditedObjectProperties()
+ .Ignore(x => x.MasterID)
+ .Ignore(x => x.TenantId)
+ .Ignore(x => x.Number)
+ .Ignore(x => x.Id);
+
+ CreateMap()
+ .IgnoreAuditedObjectProperties()
+ .Ignore(x => x.TenantId)
+ .Ignore(x => x.Number)
+ .Ignore(x => x.Id);
+ ;
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/MaterialRequests/AssembleRequests/AssembleRequestAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/MaterialRequests/AssembleRequests/AssembleRequestAppService.cs
new file mode 100644
index 000000000..567997a51
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/MaterialRequests/AssembleRequests/AssembleRequestAppService.cs
@@ -0,0 +1,302 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading;
+using System.Threading.Tasks;
+using DocumentFormat.OpenXml.Office.PowerPoint.Y2021.M06.Main;
+using IdentityModel;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp;
+using Volo.Abp.Application.Dtos;
+using Volo.Abp.Domain.Entities;
+using Volo.Abp.Domain.Repositories;
+using Volo.Abp.ObjectMapping;
+using Win_in.Sfs.Basedata.Application.Contracts;
+using Win_in.Sfs.Shared.Domain;
+using Win_in.Sfs.Shared.Domain.Shared;
+using Win_in.Sfs.Shared.Event;
+using Win_in.Sfs.Wms.Store.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Domain;
+using Win_in.Sfs.Wms.Store.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Application;
+
+///
+/// 装配叫料
+///
+[Authorize]
+[Route($"{StoreConsts.RootPath}assemble-request")]
+public class AssembleRequestAppService : SfsStoreRequestAppServiceBase,
+ IAssembleRequestAppService
+{
+ private readonly IAssembleRequestManager _assembleRequestManager;
+ private readonly IItemStoreRelationAppService _itemStoreRelationApp;
+ private readonly IAreaAppService _areaApp;
+ private readonly ILocationAppService _locationAppService;
+ private readonly IItemBasicAppService _itemBasicAppService;
+ private readonly IProductionLineAppService _productionLineAppService;
+ private readonly IInjectionJobAppService _issueJobAppService;
+ public AssembleRequestAppService(
+ IAssembleRequestRepository repository,
+ IAssembleRequestManager assembleRequestManager,
+ IPreparationPlanManager preparationPlanManager,
+ IItemStoreRelationAppService itemStoreRelationApp,
+ IAreaAppService areaApp,
+ ILocationAppService locationAppService,
+ IItemBasicAppService itemBasicAppService,
+ IProductionLineAppService productionLineAppService,
+ IInjectionJobAppService issueJobAppService)
+ : base(repository, assembleRequestManager)
+ {
+ _assembleRequestManager = assembleRequestManager;
+ _itemStoreRelationApp = itemStoreRelationApp;
+ _areaApp = areaApp;
+ _locationAppService = locationAppService;
+ _itemBasicAppService = itemBasicAppService;
+ _productionLineAppService = productionLineAppService;
+ _issueJobAppService = issueJobAppService;
+ }
+
+
+ #region 东阳V2
+
+ public override async Task HandleAsync(Guid id)
+ {
+ var entity = await _repository.GetAsync(id).ConfigureAwait(false);
+ await LocalEventBus.PublishAsync(new SfsHandledEntityEventData(entity), false).ConfigureAwait(false);
+ return ObjectMapper.Map(entity);
+ }
+
+ [HttpPost("")]
+ //[Authorize(AssembleRequestPermissions.Create)]
+ public override async Task CreateAsync(AssembleRequestEditInput input)
+ {
+ foreach (var item in input.Details)
+ {
+ if (item.Qty <= 0)
+ {
+ throw new UserFriendlyException($"{item.ItemCode} 物料的需求量必须大于0");
+ }
+ }
+
+ foreach (var detailInput in input.Details) //赋值生产线
+ {
+ var toLocationDto = await _locationAppService.GetByCodeAsync(detailInput.ToLocationCode).ConfigureAwait(false);
+ CheckLocation(toLocationDto, detailInput.ToLocationCode);
+ var itemBasicDto = await _itemBasicAppService.GetByCodeAsync(detailInput.ItemCode).ConfigureAwait(false);
+ CheckItemBasic(itemBasicDto, detailInput.ItemCode);
+
+ detailInput.ProdLine = detailInput.ToLocationCode;
+ detailInput.ToLocationErpCode = toLocationDto.ErpLocationCode;
+ }
+
+ input.AutoSubmit = true;
+ input.AutoAgree = true;
+ input.AutoHandle = true;
+ input.AutoCompleteJob = false;
+ input.DirectCreateNote = false;
+
+ var entity = ObjectMapper.Map(input);
+
+ var result = await _assembleRequestManager.CreateAsync(entity).ConfigureAwait(false);
+
+ var dto = ObjectMapper.Map(result);
+
+ return dto;
+ }
+
+ //[Authorize(AssembleRequestPermissions.Create)]
+ [HttpPost("create-and-handle")]
+ public async Task CreateAndHandleAsync(AssembleRequestEditInput input)
+ {
+ var assembleRequestDto = await CreateAsync(input).ConfigureAwait(false);
+
+ await HandleAsync(assembleRequestDto.Id).ConfigureAwait(false);
+
+ return assembleRequestDto;
+ }
+
+ #endregion
+
+ ///
+ /// 根据类型 获取叫料申请
+ ///
+ ///
+ ///
+ [HttpGet("list/by-type/{type}")]
+ public virtual async Task> GetListByTypeAsync(string type)
+ {
+ var entities = await _repository.GetListAsync(c => c.Type == type).ConfigureAwait(false);
+
+ var dtos = ObjectMapper.Map, List>(entities);
+
+ return dtos;
+ }
+
+ #region 导入
+
+ ///
+ /// 用来重写 导入数据时可以加工数据
+ ///
+ ///
+ ///
+ protected override async Task> ImportProcessingEntityAsync(
+ Dictionary dictionary)
+ {
+ var addList = dictionary.Where(p => p.Value == EntityState.Added).Select(p => p.Key);
+
+ foreach (var assembleRequest in addList)
+ {
+ assembleRequest.Worker = CurrentUser.GetUserName();
+ assembleRequest.CreatorId = CurrentUser.Id;
+ if (assembleRequest.Type == EnumTransSubType.Issue_Manual.GetDisplayName())
+ {
+ assembleRequest.Type = EnumTransSubType.Issue_Manual.ToString();
+ }
+
+ foreach (var detail in assembleRequest.Details)
+ {
+ var locationDto = await _locationAppService.GetByCodeAsync(detail.ToLocationCode).ConfigureAwait(false);
+ CheckLocation(locationDto, detail.ToLocationCode);
+
+ var itemBasicDto = await _itemBasicAppService.GetByCodeAsync(detail.ItemCode).ConfigureAwait(false);
+ CheckItemBasic(itemBasicDto, detail.ItemCode);
+
+ detail.ToLocationArea = locationDto.AreaCode;
+ detail.ToLocationErpCode = locationDto.ErpLocationCode;
+ detail.ToLocationGroup = locationDto.LocationGroupCode;
+ detail.ToWarehouseCode = locationDto.WarehouseCode;
+ detail.ItemDesc1 = itemBasicDto.Desc1;
+ detail.ItemDesc2 = itemBasicDto.Desc2;
+ detail.ItemName = itemBasicDto.Name;
+ detail.Uom = itemBasicDto.BasicUom;
+ }
+ }
+
+ return dictionary;
+ }
+
+ ///
+ /// 导入验证
+ ///
+ ///
+ ///
+ ///
+ protected override async Task ValidateImportModelAsync(AssembleRequestImportInput model,
+ List validationRresult)
+ {
+ _ = new Dictionary();
+ _ = await CheckItemBasicAsync(model, validationRresult).ConfigureAwait(false);
+ _ = await CheckLocationAsync(model, validationRresult).ConfigureAwait(false);
+ await CheckAreaAsync(model, validationRresult).ConfigureAwait(false);
+ await CheckStoreRelationAsync(model, validationRresult).ConfigureAwait(false);
+ }
+
+ #region 校验
+
+ protected override async Task ValidateImportEntities(Dictionary dict)
+ {
+ foreach (var entity in dict.Keys)
+ {
+ var tranType = await TransactionTypeAclService
+ .GetByTransTypeAsync(EnumTransType.Issue, EnumTransSubType.None).ConfigureAwait(false);
+
+ Check.NotNull(tranType, "事务类型", "事务类型不存在");
+
+ entity.AutoCompleteJob = tranType.AutoCompleteJob;
+ entity.AutoSubmit = tranType.AutoSubmitRequest;
+ entity.AutoAgree = tranType.AutoAgreeRequest;
+ entity.AutoHandle = tranType.AutoHandleRequest;
+ entity.DirectCreateNote = tranType.DirectCreateNote;
+ }
+
+ return await base.ValidateImportEntities(dict).ConfigureAwait(false);
+ }
+
+ protected async Task CheckItemBasicAsync(AssembleRequestImportInput importInput,
+ List validationRresult)
+ {
+ var item = await _itemBasicAppService.GetByCodeAsync(importInput.ItemCode).ConfigureAwait(false);
+ if (item == null)
+ {
+ validationRresult.Add(new ValidationResult($"物品代码{importInput.ItemCode}不存在", new[] { "物品代码" }));
+ }
+ else if (item.StdPackQty == 0)
+ {
+ validationRresult.Add(
+ new ValidationResult($"物品代码{importInput.ItemCode}的物品信息中标准包装等于0或不存在", new[] { "标准包装" }));
+ }
+
+ return item;
+ }
+
+ protected async Task CheckLocationAsync(AssembleRequestImportInput importInput,
+ List validationRresult)
+ {
+ var location = await _locationAppService.GetByCodeAsync(importInput.ToLocationCode).ConfigureAwait(false);
+ if (location == null)
+ {
+ validationRresult.Add(new ValidationResult($"目标库位{importInput.ToLocationCode}不存在", new[] { "目标库位" }));
+ }
+
+ return location;
+ }
+
+ protected async Task CheckAreaAsync(AssembleRequestImportInput importInput,
+ List validationRresult)
+ {
+ var area = await _areaApp.GetByCodeAsync(importInput.FromLocationArea).ConfigureAwait(false);
+ if (area == null)
+ {
+ validationRresult.Add(new ValidationResult($"调出库区{importInput.FromLocationArea}不存在", new[] { "调出库区" }));
+ }
+ }
+
+ protected async Task CheckStoreRelationAsync(AssembleRequestImportInput importInput,
+ List validationRresult)
+ {
+ var itemStoreRelation = await _itemStoreRelationApp
+ .GetFirstAsync(importInput.ItemCode, importInput.ToLocationCode).ConfigureAwait(false);
+ if (itemStoreRelation == null)
+ {
+ validationRresult.Add(new ValidationResult(
+ $"物品代码{importInput.ItemCode}与目标库位{importInput.ToLocationCode}不存在对应关", new[] { "物品库位对应关系" }));
+ }
+ }
+
+ #endregion
+
+ #endregion
+
+ #region 校验
+
+ private void CheckItemBasic(ItemBasicDTO ItemBasicDto, string itemCode)
+ {
+ if (ItemBasicDto == null)
+ {
+ throw new UserFriendlyException($"物品代码为【{itemCode}】不存在");
+ }
+ }
+
+ private void CheckLocation(LocationDTO LocationDto, string LocationCode)
+ {
+ if (LocationDto == null)
+ {
+ throw new UserFriendlyException($"库位代码为【{LocationCode}】不存在");
+ }
+
+ if (LocationDto.Type != EnumLocationType.WIP)
+ {
+ throw new UserFriendlyException($"库位代码【{LocationCode}】不是【{EnumLocationType.WIP.GetDisplayName()}】类型");
+ }
+ }
+
+
+ #endregion
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/MaterialRequests/AssembleRequests/AssembleRequestAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/MaterialRequests/AssembleRequests/AssembleRequestAutoMapperProfile.cs
new file mode 100644
index 000000000..182f8a6ed
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/MaterialRequests/AssembleRequests/AssembleRequestAutoMapperProfile.cs
@@ -0,0 +1,72 @@
+using AutoMapper;
+using Volo.Abp.AutoMapper;
+using Win_in.Sfs.Shared.Domain.Shared;
+using Win_in.Sfs.Wms.Store.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Application;
+
+public partial class StoreApplicationAutoMapperProfile : Profile
+{
+ private void AssembleRequestAutoMapperProfile()
+ {
+ CreateMap()
+ .ReverseMap();
+
+ CreateMap()
+ .ReverseMap();
+
+ CreateMap()
+ .IgnoreAuditedObjectProperties()
+ .Ignore(x => x.ToLocationArea)
+ .Ignore(x => x.ToLocationGroup)
+ .Ignore(x => x.ToWarehouseCode)
+ .Ignore(x => x.MasterID)
+ .Ignore(x => x.TenantId)
+ .Ignore(x => x.Number)
+ .Ignore(x => x.Id);
+
+ CreateMap()
+ .IgnoreAuditedObjectProperties()
+ .ForMember(x => x.Type, y => y.MapFrom(t => t.Type.ToString()))
+ .Ignore(x => x.ProdLine)
+ .Ignore(x => x.UseOnTheWayLocation)
+ .Ignore(x => x.Details)
+ .Ignore(x => x.Remark)
+ .Ignore(x => x.TenantId)
+ .Ignore(x => x.Number)
+ .Ignore(x => x.RequestStatus)
+ .Ignore(x => x.ConcurrencyStamp)
+ .Ignore(x => x.ExtraProperties)
+ .Ignore(x => x.ActiveDate)
+ .Ignore(x => x.Remark);
+
+ CreateMap()
+ .IgnoreAuditedObjectProperties()
+ .ForMember(x => x.Status, y => y.MapFrom(t => EnumStatus.Open))
+ .Ignore(x => x.ToLocationErpCode)
+ .Ignore(x => x.ToWarehouseCode)
+ .Ignore(x => x.ToLocationArea)
+ .Ignore(x => x.ToLocationGroup)
+ .Ignore(x => x.ItemName).Ignore(x => x.ItemDesc1).Ignore(x => x.ItemDesc2)
+ .Ignore(x => x.ProdLine)
+ .Ignore(x => x.WorkStation)
+ .Ignore(x => x.ExpiredTime)
+ .Ignore(x => x.IssuedQty)
+ .Ignore(x => x.ReceivedQty)
+ .Ignore(x => x.ToBeIssuedQty)
+ .Ignore(x => x.ToBeReceivedQty)
+ .Ignore(x => x.NotFinishQty)
+ .Ignore(x => x.StdPackQty)
+ .Ignore(x => x.Uom)
+ .Ignore(x => x.TenantId)
+ .Ignore(x => x.MasterID)
+ .Ignore(x => x.Number)
+ .Ignore(x => x.Id)
+ .Ignore(x => x.Remark);
+ CreateMap()
+ .IgnoreAuditedObjectProperties()
+ .Ignore(x => x.RequestStatus)
+ .Ignore(x => x.ConcurrencyStamp).Ignore(x => x.Id);
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/StoreApplicationAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/StoreApplicationAutoMapperProfile.cs
index a6b97f3ea..8c64426d3 100644
--- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/StoreApplicationAutoMapperProfile.cs
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/StoreApplicationAutoMapperProfile.cs
@@ -15,6 +15,7 @@ public partial class StoreApplicationAutoMapperProfile : Profile
ItemTransformRequestAutoMapperProfile();
MaterialRequestAutoMapperProfile();
InjectionRequestAutoMapperProfile();
+ AssembleRequestAutoMapperProfile();
ProductionReturnRequestAutoMapperProfile();
ProductReceiptRequestAutoMapperProfile();
UnplannedIssueRequestAutoMapperProfile();
@@ -66,6 +67,7 @@ public partial class StoreApplicationAutoMapperProfile : Profile
IsolationNoteAutoMapperProfile();
IssueNoteAutoMapperProfile();
InjectionNoteAutoMapperProfile();
+ AssembleNoteAutoMapperProfile();
ContainerNoteAutoMapperProfile();
ItemTransformNoteAutoMapperProfile();
JisDeliverNoteAutoMapperProfile();
@@ -100,6 +102,7 @@ public partial class StoreApplicationAutoMapperProfile : Profile
InspectJobAutoMapperProfile();
IssueJobAutoMapperProfile();
InjectionJobAutoMapperProfile();
+ AssembleJobAutoMapperProfile();
ContainerJobAutoMapperProfile();
JisDeliverJobAutoMapperProfile();
ProductReceiveJobAutoMapperProfile();
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/AssembleJob.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/AssembleJob.cs
new file mode 100644
index 000000000..74b1b7e0d
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/AssembleJob.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Threading.Tasks;
+using Win_in.Sfs.Shared.Domain.Entities;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+///
+/// 装配发料任务
+///
+[Display(Name = "装配发料任务")]
+public class AssembleJob : SfsJobAggregateRootBase
+{
+ ///
+ /// 叫料请求类型
+ ///
+ [IgnoreUpdate]
+ public string RequestType { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [IgnoreUpdate]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 要货单号
+ ///
+ [IgnoreUpdate]
+ public string AssembleRequestNumber { get; set; }
+
+ ///
+ /// 车间
+ ///
+ [IgnoreUpdate]
+ public string Workshop { get; set; }
+
+ ///
+ /// 使用在途库
+ ///
+ [Display(Name = "使用在途库")]
+ [IgnoreUpdate]
+ public bool UseOnTheWayLocation { get; set; }
+
+ ///
+ /// 任务明细
+ ///
+ [IgnoreUpdate]
+ public override List Details { get; set; } = new List();
+
+ ///
+ /// 设置任务明细的实际库位和实际数量
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual async Task BuildDetail(Guid id, string handledLocationCode, string handledLocationErpCode,
+ string handledWarehouseCode, decimal handledQty, string handledSupplierBatch, DateTime handledArriveDate, DateTime handledProduceDate, DateTime handledExpireDate,
+ string handledContainerCode, string handledLot, string handledPackingCode)
+ {
+ var detail = GetDetail(id);
+ detail.HandledFromLocationCode = handledLocationCode;
+ detail.HandledFromLocationErpCode = handledLocationErpCode;
+ detail.HandledFromWarehouseCode = handledWarehouseCode;
+ detail.HandledQty = handledQty;
+ detail.HandledSupplierBatch = handledSupplierBatch;
+ detail.HandledArriveDate = handledArriveDate;
+ detail.HandledProduceDate = handledProduceDate;
+ detail.HandledExpireDate = handledExpireDate;
+ detail.HandledContainerCode = handledContainerCode;
+ detail.HandledLot = handledLot;
+ detail.HandledPackingCode = handledPackingCode;
+ await Task.CompletedTask.ConfigureAwait(false);
+ }
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/AssembleJobDetail.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/AssembleJobDetail.cs
new file mode 100644
index 000000000..02d48d84f
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/AssembleJobDetail.cs
@@ -0,0 +1,108 @@
+using System;
+using Win_in.Sfs.Shared.Domain;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public class AssembleJobDetail : SfsJobRecommendFromDetailEntityBase, IHasToLocation
+{
+ ///
+ /// 请求库位
+ ///
+ public string RequestLocationCode { get; set; }
+
+ ///
+ /// 到库位
+ ///
+ public string ToLocationCode { get; set; }
+
+ ///
+ /// 到库区
+ ///
+ public string ToLocationArea { get; set; }
+
+ ///
+ /// 到库位组
+ ///
+ public string ToLocationGroup { get; set; }
+
+ ///
+ /// 到ERP库位
+ ///
+ public string ToLocationErpCode { get; set; }
+
+ ///
+ /// 到仓库
+ ///
+ public string ToWarehouseCode { get; set; }
+
+ ///
+ /// 在途库库位
+ ///
+ public string OnTheWayLocationCode { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ public string ProdLine { get; set; }
+
+ ///
+ /// 工作中心
+ ///
+ public string WorkStation { get; set; }
+
+ ///
+ /// 过期时间
+ ///
+ public DateTime ExpiredTime { get; set; }
+
+ ///
+ /// 工序
+ ///
+ public string Operation { get; set; }
+
+ ///
+ /// 配送方式
+ ///
+ public EnumDistributionType DistributionType { get; set; }
+
+ ///
+ /// 取整方式
+ ///
+ public EnumTruncType TruncType { get; set; }
+
+ ///
+ /// 取整后数量
+ ///
+ public decimal RoundedQty { get; set; }
+
+ ///
+ /// 计划拆分规则
+ ///
+ public EnumPlannedSplitRule PlannedSplitRule { get; set; }
+
+ ///
+ /// 计划开始时间
+ ///
+ public DateTime PlanBeginTime { get; set; }
+
+ ///
+ /// 每次配送数量
+ ///
+ public decimal DeliveryQty { get; set; }
+
+ ///
+ /// 位置码
+ ///
+ public string PositionCode { get; set; }
+
+ ///
+ /// 推荐类型
+ ///
+ public EnumRecommendType RecommendType { get; set; }
+
+ public void SetId(Guid id)
+ {
+ this.Id = id;
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/AssembleJobManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/AssembleJobManager.cs
new file mode 100644
index 000000000..cd421f475
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/AssembleJobManager.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using Volo.Abp.Users;
+using Volo.Abp.Validation;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public class AssembleJobManager : SfsJobManagerBase, IAssembleJobManager
+{
+
+ public AssembleJobManager(
+ IAssembleJobRepository repository
+ ) : base(repository)
+ {
+ }
+
+ ///
+ /// 执行任务 发料任务
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override async Task CompleteAsync(AssembleJob input, ICurrentUser user)
+ {
+ var entity = await Repository.FindAsync(input.Id).ConfigureAwait(false);
+
+ foreach (var detail in input.Details)
+ {
+ //发料子任务 赋值实际转移
+ await entity.BuildDetail(detail.Id,
+ detail.HandledFromLocationCode,
+ detail.HandledFromLocationErpCode,
+ detail.HandledFromWarehouseCode,
+ detail.HandledQty,
+ detail.HandledSupplierBatch,
+ detail.HandledArriveDate,
+ detail.HandledProduceDate,
+ detail.HandledExpireDate,
+ detail.HandledContainerCode,
+ detail.HandledLot,
+ detail.HandledPackingCode).ConfigureAwait(false);
+ }
+
+ return await base.CompleteAsync(entity, user).ConfigureAwait(false);
+ }
+
+ public override void CheckDetails(AssembleJob entity, AbpValidationResult result)
+ {
+ var details = entity.Details;
+ foreach (var detail in details)
+ {
+ if (detail.HandledFromLocationCode == null)
+ {
+ result.Errors.Add(new ValidationResult($"{detail.HandledFromLocationCode} 不能为空"));
+ }
+
+ }
+ }
+
+ public override async Task> GetWorkingListByPackingAsync(string packingCode)
+ {
+ return await Repository.GetListAsync(c => c.Details.Any(p => p.RecommendPackingCode == packingCode) && c.JobStatus != EnumJobStatus.Closed && c.JobStatus != EnumJobStatus.Cancelled, true).ConfigureAwait(false);
+
+ }
+
+ public override async Task> GetWorkingListByContainerAsync(string containerCode)
+ {
+ return await Repository.GetListAsync(c => c.Details.Any(p => p.RecommendContainerCode == containerCode) && c.JobStatus != EnumJobStatus.Closed && c.JobStatus != EnumJobStatus.Cancelled, true).ConfigureAwait(false);
+
+ }
+
+ public async Task GetAsync(Expression> expression)
+ {
+ return await Repository.FindAsync(expression).ConfigureAwait(false);
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/IAssembleJobManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/IAssembleJobManager.cs
new file mode 100644
index 000000000..480cf0cfd
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/IAssembleJobManager.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public interface IAssembleJobManager : IJobManager
+{
+ Task GetAsync(Expression> expression);
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/IAssembleJobRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/IAssembleJobRepository.cs
new file mode 100644
index 000000000..568570c1e
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleJobs/IAssembleJobRepository.cs
@@ -0,0 +1,6 @@
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public interface IAssembleJobRepository : ISfsJobRepositoryBase
+{
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/AssembleNote.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/AssembleNote.cs
new file mode 100644
index 000000000..6dd11ef37
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/AssembleNote.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using Volo.Abp;
+using Win_in.Sfs.Shared.Domain.Entities;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+///
+/// 装配发料记录
+///
+public class AssembleNote : SfsStoreAggregateRootBase, IHasJobNumber, IHasRequestNumber
+{
+ ///
+ /// 任务ID
+ ///
+ [IgnoreUpdate]
+ public string JobNumber { get; set; }
+
+ ///
+ /// 车间
+ ///
+ [IgnoreUpdate]
+ public string Workshop { get; set; }
+
+ ///
+ /// 明细列表
+ ///
+ [IgnoreUpdate]
+ public override List Details { get; set; } = new List();
+
+ [IgnoreUpdate]
+ public string RequestNumber { get; set; }
+
+ ///
+ /// 叫料请求类型
+ ///
+ [IgnoreUpdate]
+ public string RequestType { get; set; }
+
+ ///
+ /// 使用在途库
+ ///
+ [IgnoreUpdate]
+ public bool UseOnTheWayLocation { get; set; }
+
+ ///
+ /// 确认时间
+ ///
+ [Display(Name = "确认时间")]
+ [IgnoreUpdate]
+ public DateTime? ConfirmTime { get; set; }
+
+ ///
+ /// 已确认
+ ///
+ [Display(Name = "已确认")]
+ public bool Confirmed { get; set; }
+
+ public void Confirm(DateTime confirmTime)
+ {
+
+ CheckStatus(Confirmed);
+ Confirmed = true;
+ ConfirmTime = confirmTime;
+ }
+
+ private static void CheckStatus(bool confirmed)
+ {
+ if (confirmed)
+ {
+ throw new UserFriendlyException($"当前状态为 【已确认】 ,无法再次确认!");
+ }
+
+ }
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/AssembleNoteDetail.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/AssembleNoteDetail.cs
new file mode 100644
index 000000000..ee2f8a389
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/AssembleNoteDetail.cs
@@ -0,0 +1,43 @@
+using System;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public class AssembleNoteDetail : SfsStoreRecommendFromDetailWithFromToEntityBase
+{
+
+ ///
+ /// 发料时间
+ ///
+ public DateTime IssueTime { get; set; }
+
+ ///
+ /// 过期时间
+ ///
+ public DateTime ExpiredTime { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ public string ProdLine { get; set; }
+
+ ///
+ /// 工作中心
+ ///
+ public string WorkStation { get; set; }
+
+ ///
+ /// 在途库库位
+ ///
+ public string OnTheWayLocationCode { get; set; }
+
+ ///
+ /// 位置码
+ ///
+ public string PositionCode { get; set; }
+
+ ///
+ /// 推荐类型
+ ///
+ public EnumRecommendType RecommendType { get; set; }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/AssembleNoteManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/AssembleNoteManager.cs
new file mode 100644
index 000000000..1f658983e
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/AssembleNoteManager.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using Volo.Abp;
+using Volo.Abp.Uow;
+using Win_in.Sfs.Shared.Event;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public class AssembleNoteManager : SfsStoreManagerBase, IAssembleNoteManager
+{
+
+ public AssembleNoteManager(
+ IAssembleNoteRepository repository
+ ) : base(repository)
+ {
+ }
+
+ [UnitOfWork]
+ public virtual async Task ConfirmAsync(Guid id)
+ {
+ var entity = await Repository.FindAsync(id).ConfigureAwait(false);
+ Check.NotNull(entity, EntityClassName);
+ entity.Confirm(Clock.Now);
+ await PublishConfirmedAsync(entity).ConfigureAwait(false);
+ return await Repository.UpdateAsync(entity).ConfigureAwait(false);
+ }
+ private async Task PublishConfirmedAsync(AssembleNote entity)
+ {
+ try
+ {
+ await LocalEventBus.PublishAsync(new SfsConfirmedEntityEventData(entity), false).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ Logger.LogDebug($"{nameof(AssembleNote)} Confirmed Event:{ex.Message}", null);
+ Console.WriteLine(ex.Source);
+ throw;
+ }
+ }
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/IAssembleNoteManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/IAssembleNoteManager.cs
new file mode 100644
index 000000000..9a9ad6da1
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/IAssembleNoteManager.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Threading.Tasks;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public interface IAssembleNoteManager : ISfsStoreManager
+{
+ Task ConfirmAsync(Guid id);
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/IAssembleNoteRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/IAssembleNoteRepository.cs
new file mode 100644
index 000000000..280ab1dfd
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleNotes/IAssembleNoteRepository.cs
@@ -0,0 +1,6 @@
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public interface IAssembleNoteRepository : ISfsStoreRepositoryBase
+{
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/AssembleRequest.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/AssembleRequest.cs
new file mode 100644
index 000000000..579e97ee1
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/AssembleRequest.cs
@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain.Entities;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+///
+/// 装配申请
+///
+public class AssembleRequest : SfsStoreRequestAggregateRootBase
+{
+ ///
+ /// 叫料类型
+ ///
+ [Display(Name = "叫料类型")]
+ [IgnoreUpdate]
+ public string Type { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [IgnoreUpdate]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 使用在途库
+ ///
+ 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/MaterialRequests/AssembleRequests/AssembleRequestDetail.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/AssembleRequestDetail.cs
new file mode 100644
index 000000000..97c0a711d
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/AssembleRequestDetail.cs
@@ -0,0 +1,105 @@
+using System;
+using System.ComponentModel.DataAnnotations.Schema;
+using Win_in.Sfs.Shared.Domain;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+///
+/// 装配申请明细
+///
+public class AssembleRequestDetail : SfsStoreDetailWithQtyEntityBase, IHasToLocation
+{
+ ///
+ /// 到库位
+ ///
+ public string ToLocationCode { get; set; }
+
+ ///
+ /// 到库区
+ ///
+ public string ToLocationArea { get; set; }
+
+ ///
+ /// 到库位组
+ ///
+ public string ToLocationGroup { get; set; }
+
+ ///
+ /// 到ERP库位
+ ///
+ public string ToLocationErpCode { get; set; }
+
+ ///
+ /// 到仓库
+ ///
+ public string ToWarehouseCode { get; set; }
+
+ ///
+ /// 来源库区
+ ///
+ public string FromLocationArea { get; set; }
+
+ // ///
+ // /// 在途库库位
+ // ///
+ // public string OnTheWayLocationCode { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ public string ProdLine { get; set; }
+
+ ///
+ /// 工作中心
+ ///
+ public string WorkStation { get; set; }
+
+ ///
+ /// 过期时间
+ ///
+ public DateTime ExpiredTime { get; set; }
+
+ ///
+ /// 已发数量
+ ///
+ public decimal IssuedQty { get; set; }
+
+ ///
+ /// 已收数量
+ ///
+ public decimal ReceivedQty { get; set; }
+
+ ///
+ /// 明细状态
+ ///
+ public EnumStatus Status { get; set; }
+
+ ///
+ /// 请求未发 还未发送的数量
+ ///
+ [NotMapped]
+ public decimal ToBeIssuedQty => Qty - IssuedQty;
+
+ ///
+ /// 已发未收
+ ///
+ [NotMapped]
+ public decimal ToBeReceivedQty => IssuedQty - ReceivedQty;
+
+ ///
+ /// 请求未收
+ ///
+ [NotMapped]
+ public decimal NotFinishQty => Qty - ReceivedQty;
+
+ ///
+ /// 位置码
+ ///
+ public string PositionCode { get; set; }
+
+ ///
+ /// 推荐类型
+ ///
+ public EnumRecommendType RecommendType { get; set; }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/AssembleRequestManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/AssembleRequestManager.cs
new file mode 100644
index 000000000..94040930d
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/AssembleRequestManager.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using DocumentFormat.OpenXml.Math;
+using Win_in.Sfs.Shared.Domain.Shared;
+using Win_in.Sfs.Shared.Event;
+using static Win_in.Sfs.Wms.Store.Domain.Shared.StoreSettings;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public class AssembleRequestManager
+ : SfsStoreRequestManagerBase
+ , IAssembleRequestManager
+{
+ private readonly IAssembleRequestRepository _repository;
+ private readonly IIssueJobRepository _issueJobRepository;
+
+ public AssembleRequestManager(
+ IAssembleRequestRepository repository
+ , IIssueJobRepository issueJobRepository
+ ) : base(repository)
+ {
+ _repository = repository;
+ _issueJobRepository = issueJobRepository;
+ }
+
+
+ #region 东阳V2
+
+ #endregion
+
+
+ ///
+ /// 创建
+ ///
+ ///
+ ///
+ public virtual async Task CreateBynNumberAsync(AssembleRequest entity)
+ {
+ var number = string.IsNullOrEmpty(entity.Number) ? await GenerateNumberAsync(nameof(AssembleRequest), entity.ActiveDate).ConfigureAwait(false) : entity.Number;
+ entity.SetIdAndNumberWithDetails(GuidGenerator, number);
+ entity.Submit();
+ entity.Agree();
+ entity.RequestStatus = EnumRequestStatus.Partial;
+ await LocalEventBus.PublishAsync(new SfsHandledEntityEventData(entity), false)
+ .ConfigureAwait(false);
+ await _repository.InsertAsync(entity).ConfigureAwait(false);
+ return entity;
+ }
+
+ public virtual async Task UpdateDetailsAsync(AssembleRequest newEntity)
+ {
+ var oldEntity = await Repository.FindAsync(newEntity.Id, true).ConfigureAwait(false);
+ if(oldEntity!=null)
+ {
+ foreach (var newDetail in newEntity.Details)
+ {
+ oldEntity.ReplaceDetail(newDetail.Id, newDetail);
+ }
+
+ foreach (var detail in oldEntity.Details)
+ {
+ SetMaterialRequestDetailStatus(detail);
+ }
+
+ await SetMaterialRequestStatusAsync(oldEntity).ConfigureAwait(false);
+
+ await Repository.UpdateAsync(oldEntity).ConfigureAwait(false);
+ }
+
+ }
+
+ private void SetMaterialRequestDetailStatus(AssembleRequestDetail detail)
+ {
+ if (detail.ReceivedQty >= detail.Qty)//执行的时候 实际收料 多余 要料数
+ {
+ detail.Status = EnumStatus.Close;
+ }
+ else
+ {
+ detail.Status = EnumStatus.Open;
+ }
+ }
+
+ private async Task SetMaterialRequestStatusAsync(AssembleRequest materialRequest)
+ {
+ if (materialRequest.Details.All(p => p.Status == EnumStatus.Close))
+ {
+ materialRequest.RequestStatus = EnumRequestStatus.Completed;
+ }
+ else
+ {
+ var issueJobs = await _issueJobRepository.GetListAsync(t => t.MaterialRequestNumber == materialRequest.Number).ConfigureAwait(false);
+ if (issueJobs.Count > 0)
+ {
+ if (issueJobs.All(t => t.JobStatus is EnumJobStatus.Done or EnumJobStatus.Closed or EnumJobStatus.Cancelled))
+ {
+ if (materialRequest.Details.All(p => p.ReceivedQty >= p.Qty))
+ {
+ materialRequest.RequestStatus = EnumRequestStatus.Completed;
+ }
+ else
+ {
+ materialRequest.RequestStatus = EnumRequestStatus.Partial;
+ }
+ }
+ else
+ {
+ materialRequest.RequestStatus = EnumRequestStatus.Partial;
+ }
+ }
+ else
+ {
+ materialRequest.RequestStatus = EnumRequestStatus.Partial;
+ }
+ }
+ }
+
+ public virtual async Task CompleteAsync(string number)
+ {
+ var entity = await GetByNumberAsync(number).ConfigureAwait(false);
+ if (entity != null && !entity.Details.Any(p => p.ToBeIssuedQty > 0))
+ {
+ await CompleteAsync(entity).ConfigureAwait(false);
+ }
+ }
+
+
+ #region 导入
+
+ ///
+ /// 执行导入
+ ///
+ public virtual async Task ImportDataAsync(List mergeEntities, List deleteEntities = null)
+ {
+ if (deleteEntities != null && deleteEntities.Count > 0)
+ {
+ await _repository.BulkDeleteAsync(deleteEntities).ConfigureAwait(false);
+ }
+
+ await CreateManyAsync(mergeEntities).ConfigureAwait(false);
+ }
+
+ #endregion
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/IAssembleRequestManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/IAssembleRequestManager.cs
new file mode 100644
index 000000000..653efecd3
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/IAssembleRequestManager.cs
@@ -0,0 +1,16 @@
+using System.Threading.Tasks;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+using Win_in.Sfs.Shared.Domain;
+
+public interface IAssembleRequestManager : ISfsStoreRequestManager,
+ IBulkImportService
+{
+
+ Task UpdateDetailsAsync(AssembleRequest entity);
+
+ Task CompleteAsync(string number);
+
+ Task CreateBynNumberAsync(AssembleRequest entity);
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/IAssembleRequestRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/IAssembleRequestRepository.cs
new file mode 100644
index 000000000..a661ff0f8
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/AssembleRequests/IAssembleRequestRepository.cs
@@ -0,0 +1,9 @@
+using Win_in.Sfs.Shared.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public interface IAssembleRequestRepository : ISfsStoreRepositoryBase,
+ ISfsBulkRepositoryBase
+{
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/IStoreDbContext.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/IStoreDbContext.cs
index 33e6c1708..9f178d167 100644
--- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/IStoreDbContext.cs
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/IStoreDbContext.cs
@@ -22,6 +22,7 @@ public interface IStoreDbContext : IEfCoreDbContext
public DbSet ProductReceiptRequests { get; }
public DbSet MaterialRequests { get; }
public DbSet InjectionRequests { get; }
+ public DbSet AssembleRequests { get; }
public DbSet ContainerRequests { get; }
public DbSet DeliverRequests { get; }
public DbSet InspectRequests { get; }
@@ -77,6 +78,7 @@ public interface IStoreDbContext : IEfCoreDbContext
public DbSet WarehouseTransferNotes { get; }
public DbSet IssueNotes { get; }
public DbSet InjectionNotes { get; }
+ public DbSet AssembleNotes { get; }
public DbSet ContainerNotes { get; }
public DbSet UnplannedReceiptNotes { get; }
public DbSet UnplannedIssueNotes { get; }
@@ -103,6 +105,7 @@ public interface IStoreDbContext : IEfCoreDbContext
public DbSet PutawayJobs { get; }
public DbSet IssueJobs { get; }
public DbSet InjectionJobs { get; }
+ public DbSet AssembleJobs { get; }
public DbSet ContainerJobs { get; }
public DbSet DeliverJobs { get; }
public DbSet JisDeliverJobs { get; }
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/AssembleJobs/AssembleJobDbContextModelCreatingExtensions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/AssembleJobs/AssembleJobDbContextModelCreatingExtensions.cs
new file mode 100644
index 000000000..3945e66f1
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/AssembleJobs/AssembleJobDbContextModelCreatingExtensions.cs
@@ -0,0 +1,69 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Modeling;
+using Win_in.Sfs.Shared.Domain.Shared;
+using Win_in.Sfs.Shared.EntityFrameworkCore;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
+
+public static class AssembleJobDbContextModelCreatingExtensions
+{
+ public static void ConfigureAssembleJob(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options)
+ {
+ builder.Entity(b =>
+ {
+ //Configure table & schema name
+ b.ToTable(StoreDbProperties.JobDbTablePrefix + nameof(AssembleJob), options.Schema);
+ //Configure ABP properties
+ b.ConfigureByConvention();
+ //Configure Sfs base properties
+ b.ConfigureSfsBase();
+ //Configure Job base properties
+ b.ConfigureJob();
+ //Properties
+ b.Property(q => q.RequestType).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.AssembleRequestNumber).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.Workshop).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength);
+ //Relations
+ b.HasMany(q => q.Details).WithOne().HasForeignKey(d => d.MasterID).IsRequired();
+ //Indexes
+ b.HasIndex(q => new { q.Number }).IsUnique();
+ });
+
+ builder.Entity(b =>
+ {
+ //Configure table & schema name
+ b.ToTable(StoreDbProperties.JobDbTablePrefix + nameof(AssembleJobDetail), options.Schema);
+ //Configure ABP properties
+ b.ConfigureByConvention();
+ //Configure Sfs base properties
+ b.ConfigureSfsBase();
+ //Configure Job base properties
+ b.ConfigureJobRecommendFromDetail();
+ //Properties
+ b.Property(q => q.ExpiredTime).IsRequired();
+ b.Property(q => q.ToLocationCode).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.ToLocationErpCode).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.ToWarehouseCode).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.ToLocationArea).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.ToLocationGroup).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.RequestLocationCode).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.WorkStation).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.Operation).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.DistributionType).HasMaxLength(SfsPropertyConst.NameLength).HasConversion();
+ b.Property(q => q.TruncType).HasMaxLength(SfsPropertyConst.NameLength).HasConversion();
+ b.Property(q => q.PlannedSplitRule).HasMaxLength(SfsPropertyConst.NameLength).HasConversion();
+ b.Property(q => q.OnTheWayLocationCode).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.PositionCode).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.RecommendType).HasMaxLength(SfsPropertyConst.CodeLength).HasConversion();
+
+ //Relations
+ //None
+
+ //Indexes
+ //b.HasIndex(q => new { q.PackingCode }).IsUnique();
+ });
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/AssembleJobs/AssembleJobEfCoreRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/AssembleJobs/AssembleJobEfCoreRepository.cs
new file mode 100644
index 000000000..6430424b9
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/AssembleJobs/AssembleJobEfCoreRepository.cs
@@ -0,0 +1,11 @@
+using Volo.Abp.EntityFrameworkCore;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
+
+public class AssembleJobEfCoreRepository : SfsJobEfCoreRepositoryBase, IAssembleJobRepository
+{
+ public AssembleJobEfCoreRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider)
+ {
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/AssembleNotes/AssembleNoteDbContextModelCreatingExtensions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/AssembleNotes/AssembleNoteDbContextModelCreatingExtensions.cs
new file mode 100644
index 000000000..f13daeb61
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/AssembleNotes/AssembleNoteDbContextModelCreatingExtensions.cs
@@ -0,0 +1,63 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Modeling;
+using Win_in.Sfs.Shared.Domain.Shared;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
+
+public static class AssembleNoteDbContextModelCreatingExtensions
+{
+ public static void ConfigureAssembleNote(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options)
+ {
+ builder.Entity(b =>
+ {
+ //Configure table & schema name
+ b.ToTable(options.TablePrefix + nameof(AssembleNote), options.Schema);
+ //Configure ABP properties
+ b.ConfigureByConvention();
+ //Configure Sfs base properties
+ b.ConfigureSfsStoreBase();
+
+ //Properties
+ b.Property(q => q.RequestNumber).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.RequestType).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.Workshop).HasMaxLength(SfsPropertyConst.NameLength);
+ b.Property(q => q.Remark).HasMaxLength(SfsPropertyConst.RemarkLength);
+
+ //Relations
+ b.HasMany(q => q.Details).WithOne().HasForeignKey(d => d.MasterID).IsRequired();
+
+ //Indexes
+ b.HasIndex(q => new { q.Number }).IsUnique();
+ });
+
+ builder.Entity(b =>
+ {
+ //Configure table & schema name
+ b.ToTable(options.TablePrefix + nameof(AssembleNoteDetail), options.Schema);
+ //Configure ABP properties
+ b.ConfigureByConvention();
+ //Configure Sfs base properties
+ b.ConfigureSfsStoreBase();
+ //Configure Sfs store detail properties
+ b.ConfigureSfsStoreDetailBase();
+
+ //Properties
+ b.Property(q => q.IssueTime).IsRequired();
+ b.Property(q => q.ExpiredTime).IsRequired();
+ b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.NameLength);
+ b.Property(q => q.WorkStation).HasMaxLength(SfsPropertyConst.NameLength);
+ b.Property(q => q.OnTheWayLocationCode).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.FromStatus).HasMaxLength(SfsPropertyConst.NameLength).HasConversion();
+ b.Property(q => q.ToStatus).HasMaxLength(SfsPropertyConst.NameLength).HasConversion();
+ b.Property(q => q.PositionCode).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.RecommendType).HasMaxLength(SfsPropertyConst.NameLength).HasConversion();
+
+ //Relations
+
+ //Indexes
+ b.HasIndex(q => new { q.Number, q.FromPackingCode, q.FromLocationCode, q.ToLocationCode }).IsUnique();
+ b.HasIndex(q => new { q.FromPackingCode });
+ });
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/AssembleNotes/AssembleNoteEfCoreRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/AssembleNotes/AssembleNoteEfCoreRepository.cs
new file mode 100644
index 000000000..4ab8d2677
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/AssembleNotes/AssembleNoteEfCoreRepository.cs
@@ -0,0 +1,11 @@
+using Volo.Abp.EntityFrameworkCore;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
+
+public class AssembleNoteEfCoreRepository : SfsStoreEfCoreRepositoryBase, IAssembleNoteRepository
+{
+ public AssembleNoteEfCoreRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider)
+ {
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/AssembleRequests/AssembleRequestDbContextModelCreatingExtensions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/AssembleRequests/AssembleRequestDbContextModelCreatingExtensions.cs
new file mode 100644
index 000000000..8d53f0ac3
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/AssembleRequests/AssembleRequestDbContextModelCreatingExtensions.cs
@@ -0,0 +1,65 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Modeling;
+using Win_in.Sfs.Shared.Domain.Shared;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
+
+public static class AssembleRequestDbContextModelCreatingExtensions
+{
+ public static void ConfigureAssembleRequest(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options)
+ {
+ builder.Entity(b =>
+ {
+ //Configure table & schema name
+ b.ToTable(options.TablePrefix + nameof(AssembleRequest), options.Schema);
+ //Configure ABP properties
+ b.ConfigureByConvention();
+ //Configure Sfs base properties
+ b.ConfigureSfsStoreBase();
+
+ //Properties
+ b.Property(q => q.Type).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.RequestStatus).HasMaxLength(SfsPropertyConst.NameLength).HasConversion();
+
+ //Relations
+ b.HasMany(q => q.Details).WithOne().HasForeignKey(d => d.MasterID).IsRequired();
+
+ //Indexes
+ b.HasIndex(q => new { q.Number }).IsUnique();
+ });
+
+ builder.Entity(b =>
+ {
+ //Configure table & schema name
+ b.ToTable(options.TablePrefix + nameof(AssembleRequestDetail), options.Schema);
+ //Configure ABP properties
+ b.ConfigureByConvention();
+ //Configure Sfs base properties
+ b.ConfigureSfsStoreBase();
+ //Configure Sfs store detail properties
+ b.ConfigureSfsStoreDetailBase();
+ //Properties
+ b.Property(q => q.ToLocationCode).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength);
+ 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.ExpiredTime).IsRequired();
+ b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.WorkStation).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();
+ b.Property(q => q.PositionCode).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.RecommendType).HasMaxLength(SfsPropertyConst.NameLength).HasConversion();
+
+ //Relations
+
+ //Indexes
+ b.HasIndex(q => new { q.Number, q.ItemCode, q.ToLocationCode }).IsUnique();
+ b.HasIndex(q => new { q.ItemCode });
+ });
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/AssembleRequests/AssembleRequestEfCoreRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/AssembleRequests/AssembleRequestEfCoreRepository.cs
new file mode 100644
index 000000000..7541df1ec
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/AssembleRequests/AssembleRequestEfCoreRepository.cs
@@ -0,0 +1,11 @@
+using Volo.Abp.EntityFrameworkCore;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
+
+public class AssembleRequestEfCoreRepository : SfsStoreEfCoreRepositoryBase, IAssembleRequestRepository
+{
+ public AssembleRequestEfCoreRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider)
+ {
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContext.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContext.cs
index 78760e319..714637c10 100644
--- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContext.cs
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContext.cs
@@ -22,6 +22,7 @@ public class StoreDbContext : AbpDbContext, IStoreDbContext
public DbSet ProductReceiptRequests { get; set; }
public DbSet MaterialRequests { get; set; }
public DbSet InjectionRequests { get; set; }
+ public DbSet AssembleRequests { get; set; }
public DbSet ContainerRequests { get; set; }
public DbSet DeliverRequests { get; set; }
public DbSet InspectRequests { get; set; }
@@ -77,6 +78,7 @@ public class StoreDbContext : AbpDbContext, IStoreDbContext
public DbSet WarehouseTransferNotes { get; set; }
public DbSet IssueNotes { get; set; }
public DbSet InjectionNotes { get; set; }
+ public DbSet AssembleNotes { get; set; }
public DbSet ContainerNotes { get; set; }
public DbSet UnplannedReceiptNotes { get; set; }
public DbSet UnplannedIssueNotes { get; set; }
@@ -103,6 +105,7 @@ public class StoreDbContext : AbpDbContext, IStoreDbContext
public DbSet PutawayJobs { get; set; }
public DbSet IssueJobs { get; set; }
public DbSet InjectionJobs { get; set; }
+ public DbSet AssembleJobs { get; set; }
public DbSet ContainerJobs { get; set; }
public DbSet DeliverJobs { get; set; }
public DbSet JisDeliverJobs { get; set; }
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContextModelCreatingExtensions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContextModelCreatingExtensions.cs
index b9229727a..cd0750295 100644
--- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContextModelCreatingExtensions.cs
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContextModelCreatingExtensions.cs
@@ -48,6 +48,7 @@ public static class StoreDbContextModelCreatingExtensions
builder.ConfigurePurchaseReceiptRequest(options);
builder.ConfigureMaterialRequest(options);
builder.ConfigureInjectionRequest(options);
+ builder.ConfigureAssembleRequest(options);
builder.ConfigureDeliverRequest(options);
builder.ConfigureContainerRequest(options);
builder.ConfigureInspectRequest(options);
@@ -84,6 +85,7 @@ public static class StoreDbContextModelCreatingExtensions
builder.ConfigureWarehouseTransferNote(options);
builder.ConfigureIssueNote(options);
builder.ConfigureInjectionNote(options);
+ builder.ConfigureAssembleNote(options);
builder.ConfigureContainerNote(options);
builder.ConfigureUnplannedReceiptNote(options);
builder.ConfigureUnplannedIssueNote(options);
@@ -110,6 +112,7 @@ public static class StoreDbContextModelCreatingExtensions
builder.ConfigurePutawayJob(options);
builder.ConfigureIssueJob(options);
builder.ConfigureInjectionJob(options);
+ builder.ConfigureAssembleJob(options);
builder.ConfigureContainerJob(options);
builder.ConfigureDeliverJob(options);
builder.ConfigureJisDeliverJob(options);
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreEntityFrameworkCoreModule.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreEntityFrameworkCoreModule.cs
index 4dfd83642..997949441 100644
--- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreEntityFrameworkCoreModule.cs
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreEntityFrameworkCoreModule.cs
@@ -59,6 +59,7 @@ public class StoreEntityFrameworkCoreModule : AbpModule
context.Services.AddTransient();
context.Services.AddTransient();
context.Services.AddTransient();
+ context.Services.AddTransient();
context.Services.AddTransient();
context.Services.AddTransient();
context.Services.AddTransient();
@@ -100,6 +101,7 @@ public class StoreEntityFrameworkCoreModule : AbpModule
context.Services.AddTransient();
context.Services.AddTransient();
context.Services.AddTransient();
+ context.Services.AddTransient();
context.Services.AddTransient();
context.Services.AddTransient();
context.Services.AddTransient();
@@ -128,6 +130,7 @@ public class StoreEntityFrameworkCoreModule : AbpModule
context.Services.AddTransient();
context.Services.AddTransient();
context.Services.AddTransient();
+ context.Services.AddTransient();
context.Services.AddTransient();
context.Services.AddTransient();
context.Services.AddTransient();
@@ -193,6 +196,8 @@ public class StoreEntityFrameworkCoreModule : AbpModule
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
+ options.Entity(orderOptions =>
+ orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity(orderOptions =>
@@ -246,6 +251,8 @@ public class StoreEntityFrameworkCoreModule : AbpModule
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
+ options.Entity(orderOptions =>
+ orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity(orderOptions =>
@@ -319,6 +326,8 @@ public class StoreEntityFrameworkCoreModule : AbpModule
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
+ options.Entity(orderOptions =>
+ orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity(orderOptions =>
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
new file mode 100644
index 000000000..f1cecd7c7
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/AssembleJobAutoMapperProfile.cs
@@ -0,0 +1,92 @@
+using System;
+using AutoMapper;
+using Volo.Abp.AutoMapper;
+using Win_in.Sfs.Shared.Application;
+using Win_in.Sfs.Wms.Inventory.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Event;
+
+public partial class StoreEventAutoMapperProfile : Profile
+{
+ private void AssembleJobAutoMapperProfile()
+ {
+
+ CreateMap()
+ .ForMember(x => x.JobNumber, y => y.MapFrom(d => d.Number))
+ .ForMember(x => x.RequestNumber, y => y.MapFrom(d => d.AssembleRequestNumber))
+ .ForMember(x => x.ActiveDate, y => y.MapFrom(d => DateTime.Now))
+ .ForMember(x => x.Worker, y => y.MapFrom(d => d.CompleteUserName))
+ .Ignore(x => x.Confirmed)
+ .Ignore(x => x.Number)
+ .Ignore(x => x.ConfirmTime);
+
+ CreateMap()
+ .ForMember(x => x.FromPackingCode, y => y.MapFrom(d => d.HandledPackingCode))
+ .ForMember(x => x.ToPackingCode, y => y.MapFrom(d => d.HandledPackingCode))
+ .ForMember(x => x.SupplierBatch, y => y.MapFrom(d => d.HandledSupplierBatch))
+ .ForMember(x => x.ArriveDate, y => y.MapFrom(d => d.HandledArriveDate))
+ .ForMember(x => x.ProduceDate, y => y.MapFrom(d => d.HandledProduceDate))
+ .ForMember(x => x.ExpireDate, y => y.MapFrom(d => d.HandledExpireDate))
+ .ForMember(x => x.FromLot, y => y.MapFrom(d => d.HandledLot))
+ .ForMember(x => x.ToLot, y => y.MapFrom(d => d.HandledLot))
+ .ForMember(x => x.ToContainerCode, y => y.MapFrom(d => d.HandledContainerCode))
+ .ForMember(x => x.FromContainerCode, y => y.MapFrom(d => d.HandledContainerCode))
+ .ForMember(x => x.FromStatus, y => y.MapFrom(d => d.Status))
+ .ForMember(x => x.ToStatus, y => y.MapFrom(d => d.Status))
+ .ForMember(x => x.Qty, y => y.MapFrom(d => d.HandledQty))
+ .ForMember(x => x.IssueTime, y => y.MapFrom(d => DateTime.Now))
+ .ForMember(x => x.FromLocationCode, y => y.MapFrom(d => d.HandledFromLocationCode))
+ .ForMember(x => x.FromLocationArea, y => y.MapFrom(d => d.HandledFromLocationArea))
+ .ForMember(x => x.FromLocationGroup, y => y.MapFrom(d => d.HandledFromLocationGroup))
+ .ForMember(x => x.FromLocationErpCode, y => y.MapFrom(d => d.HandledFromLocationErpCode))
+ .ForMember(x => x.FromWarehouseCode, y => y.MapFrom(d => d.HandledFromWarehouseCode))
+ .ForMember(x => x.ToLocationCode, y => y.MapFrom(d => d.ToLocationCode))
+ .Ignore(x => x.ToLocationArea)
+ .Ignore(x => x.ToLocationGroup)
+ .Ignore(x => x.ToLocationErpCode)
+ ;
+
+ CreateMap()
+ .MapExpectInOutFrom()
+ .Ignore(x => x.Worker)
+ .Ignore(x => x.SerialNumber)
+ .Ignore(x => x.ExtraProperties)
+ ;
+
+ CreateMap()
+ .MapExpectInOutFrom()
+ .Ignore(x => x.Worker)
+ .Ignore(x => x.SerialNumber)
+ .Ignore(x => x.ExtraProperties);
+
+ CreateMap()
+ .ForMember(x => x.RequestNumber, y => y.MapFrom(d => d.AssembleRequestNumber))
+ .Ignore(x => x.Confirmed)
+ .Ignore(x => x.JobNumber)
+ .Ignore(x => x.ActiveDate)
+ ;
+ CreateMap()
+ .ForMember(x => x.Qty, y => y.MapFrom(d => d.HandledQty))
+ .ForMember(x => x.IssueTime, y => y.MapFrom(d => DateTime.Now))
+ .ForMember(x => x.FromPackingCode, y => y.MapFrom(d => d.HandledPackingCode))
+ .ForMember(x => x.ToPackingCode, y => y.MapFrom(d => d.HandledPackingCode))
+ .ForMember(x => x.FromContainerCode, y => y.MapFrom(d => d.HandledContainerCode))
+ .ForMember(x => x.ToContainerCode, y => y.MapFrom(d => d.HandledContainerCode))
+ .ForMember(x => x.FromLot, y => y.MapFrom(d => d.HandledLot))
+ .ForMember(x => x.ToLot, y => y.MapFrom(d => d.HandledLot))
+ .ForMember(x => x.SupplierBatch, y => y.MapFrom(d => d.HandledSupplierBatch))
+ .ForMember(x => x.ArriveDate, y => y.MapFrom(d => d.HandledArriveDate))
+ .ForMember(x => x.ProduceDate, y => y.MapFrom(d => d.HandledProduceDate))
+ .ForMember(x => x.ExpireDate, y => y.MapFrom(d => d.ExpiredTime))
+ .ForMember(x => x.FromLocationCode, y => y.MapFrom(d => d.HandledFromLocationCode))
+ .ForMember(x => x.FromLocationArea, y => y.MapFrom(d => d.HandledFromLocationArea))
+ .ForMember(x => x.FromLocationGroup, y => y.MapFrom(d => d.HandledFromLocationGroup))
+ .ForMember(x => x.FromLocationErpCode, y => y.MapFrom(d => d.HandledFromLocationErpCode))
+ .ForMember(x => x.FromWarehouseCode, y => y.MapFrom(d => d.HandledFromWarehouseCode))
+ .ForMember(x => x.FromStatus, y => y.MapFrom(d => d.Status))
+ .ForMember(x => x.ToStatus, y => y.MapFrom(d => d.Status))
+ ;
+ }
+}
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
new file mode 100644
index 000000000..15033a58a
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Notes/AssembleNoteAutoMapperProfile.cs
@@ -0,0 +1,22 @@
+using AutoMapper;
+using Volo.Abp.AutoMapper;
+using Win_in.Sfs.Wms.Inventory.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Event;
+
+public partial class StoreEventAutoMapperProfile : Profile
+{
+ private void AssembleNoteAutoMapperProfile()
+ {
+ CreateMap()
+ .Ignore(x => x.DocNumber)
+ .Ignore(x => x.JobNumber)
+ .Ignore(x => x.Worker)
+ .Ignore(x => x.TransType)
+ .Ignore(x => x.ExtraProperties)
+ .Ignore(x => x.TransSubType)
+ ;
+ }
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Notes/InjectionNoteAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Notes/InjectionNoteAutoMapperProfile.cs
new file mode 100644
index 000000000..14299295f
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Notes/InjectionNoteAutoMapperProfile.cs
@@ -0,0 +1,22 @@
+using AutoMapper;
+using Volo.Abp.AutoMapper;
+using Win_in.Sfs.Wms.Inventory.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Event;
+
+public partial class StoreEventAutoMapperProfile : Profile
+{
+ private void InjectionNoteAutoMapperProfile()
+ {
+ CreateMap()
+ .Ignore(x => x.DocNumber)
+ .Ignore(x => x.JobNumber)
+ .Ignore(x => x.Worker)
+ .Ignore(x => x.TransType)
+ .Ignore(x => x.ExtraProperties)
+ .Ignore(x => x.TransSubType)
+ ;
+ }
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/AssembleRequestAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/AssembleRequestAutoMapperProfile.cs
new file mode 100644
index 000000000..dcf76a76b
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/AssembleRequestAutoMapperProfile.cs
@@ -0,0 +1,135 @@
+using AutoMapper;
+using Volo.Abp.AutoMapper;
+using Win_in.Sfs.Shared.Application;
+using Win_in.Sfs.Wms.Inventory.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Event;
+
+public partial class StoreEventAutoMapperProfile : Profile
+{
+ private void AssembleRequestAutoMapperProfile()
+ {
+ CreateMap()
+ .ForMember(x => x.AssembleRequestNumber, y => y.MapFrom(d => d.Number))
+ .ForMember(x => x.RequestType, y => y.MapFrom(d => d.Type))
+ .Ignore(x => x.WarehouseCode)
+ .Ignore(x => x.Workshop)
+ .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)
+ ;
+
+ CreateMap()
+ .ForMember(x => x.RequestLocationCode, y => y.MapFrom(d => d.ToLocationCode))
+ .Ignore(x => x.RecommendFromLocationArea)
+ .Ignore(x => x.RecommendFromLocationGroup)
+ .Ignore(x => x.HandledFromLocationArea)
+ .Ignore(x => x.HandledFromLocationGroup)
+ .Ignore(x => x.RecommendFromWarehouseCode)
+ .Ignore(x => x.HandledFromWarehouseCode)
+ .Ignore(x => x.OnTheWayLocationCode)
+ .Ignore(x => x.DistributionType)
+ .Ignore(x => x.RoundedQty)
+ .Ignore(x => x.Operation)
+ .Ignore(x => x.ExpiredTime)
+ .Ignore(x => x.TruncType)
+ .Ignore(x => x.PlanBeginTime)
+ .Ignore(x => x.PlannedSplitRule)
+ .Ignore(x => x.DeliveryQty)
+ .Ignore(x => x.Status)
+ .Ignore(x => x.RecommendContainerCode)
+ .Ignore(x => x.StdPackQty)
+ .Ignore(x => x.RecommendPackingCode)
+ .Ignore(x => x.HandledContainerCode)
+ .Ignore(x => x.HandledPackingCode)
+ .Ignore(x => x.RecommendSupplierBatch)
+ .Ignore(x => x.RecommendProduceDate)
+ .Ignore(x => x.RecommendArriveDate)
+ .Ignore(x => x.RecommendExpireDate)
+ .Ignore(x => x.HandledFromLocationCode)
+ .Ignore(x => x.HandledFromLocationErpCode)
+ .Ignore(x => x.HandledUom)
+ .Ignore(x => x.RecommendFromLocationErpCode)
+ .Ignore(x => x.HandledExpireDate)
+ .Ignore(x => x.HandledLot)
+ .Ignore(x => x.HandledArriveDate)
+ .Ignore(x => x.HandledProduceDate)
+ .Ignore(x => x.HandledQty)
+ .Ignore(x => x.RecommendQty)
+ .Ignore(x => x.Uom)
+ .Ignore(x => x.HandledSupplierBatch)
+ .Ignore(x => x.RecommendFromLocationCode)
+ .Ignore(x => x.RecommendLot)
+ .IgnoreIHasRecommendAndHandledFrom();
+
+ CreateMap()
+ .ForMember(x => x.RecommendArriveDate, y => y.MapFrom(d => d.ArriveDate))
+ .ForMember(x => x.RecommendContainerCode, y => y.MapFrom(d => d.ContainerCode))
+ .ForMember(x => x.RecommendExpireDate, y => y.MapFrom(d => d.ExpireDate))
+ .ForMember(x => x.RecommendFromLocationCode, y => y.MapFrom(d => d.LocationCode))
+ .ForMember(x => x.RecommendFromLocationErpCode, y => y.MapFrom(d => d.LocationErpCode))
+ .ForMember(x => x.RecommendFromWarehouseCode, y => y.MapFrom(d => d.WarehouseCode))
+ .ForMember(x => x.RecommendFromLocationArea, y => y.MapFrom(d => d.LocationArea))
+ .ForMember(x => x.RecommendFromLocationGroup, y => y.MapFrom(d => d.LocationGroup))
+ .ForMember(x => x.RecommendLot, y => y.MapFrom(d => d.Lot))
+ .ForMember(x => x.RecommendPackingCode, y => y.MapFrom(d => d.PackingCode))
+ .ForMember(x => x.RecommendProduceDate, y => y.MapFrom(d => d.ProduceDate))
+ .ForMember(x => x.RecommendQty, y => y.MapFrom(d => d.Qty))
+ .ForMember(x => x.RecommendSupplierBatch, y => y.MapFrom(d => d.SupplierBatch))
+ .ForMember(x => x.Uom, y => y.MapFrom(d => d.Uom)).Ignore(x => x.HandledArriveDate)
+ .Ignore(x => x.HandledFromLocationArea)
+ .Ignore(x => x.HandledFromLocationGroup)
+ .Ignore(x => x.ToLocationErpCode)
+ .Ignore(x => x.ToWarehouseCode)
+ .Ignore(x => x.ToLocationArea)
+ .Ignore(x => x.ToLocationGroup)
+ .Ignore(x => x.HandledFromWarehouseCode)
+ .Ignore(x => x.RequestLocationCode)
+ .Ignore(x => x.ToLocationCode)
+ .Ignore(x => x.ProdLine)
+ .Ignore(x => x.WorkStation)
+ .Ignore(x => x.HandledContainerCode)
+ .Ignore(x => x.HandledExpireDate)
+ .Ignore(x => x.HandledFromLocationCode)
+ .Ignore(x => x.HandledFromLocationErpCode)
+ .Ignore(x => x.HandledLot)
+ .Ignore(x => x.HandledPackingCode)
+ .Ignore(x => x.HandledProduceDate)
+ .Ignore(x => x.HandledQty)
+ .Ignore(x => x.HandledSupplierBatch)
+ .Ignore(x => x.HandledUom)
+ .Ignore(x => x.Remark)
+ .Ignore(x => x.OnTheWayLocationCode)
+ .Ignore(x => x.DistributionType)
+ .Ignore(x => x.RoundedQty)
+ .Ignore(x => x.Operation)
+ .Ignore(x => x.ExpiredTime)
+ .Ignore(x => x.TruncType)
+ .Ignore(x => x.PlanBeginTime)
+ .Ignore(x => x.PlannedSplitRule)
+ .Ignore(x => x.DeliveryQty)
+ .Ignore(x => x.RequestLocationCode)
+ .Ignore(x => x.ToLocationCode)
+ .Ignore(x => x.ProdLine)
+ .Ignore(x => x.WorkStation)
+ .Ignore(x => x.PositionCode)
+ .Ignore(x => x.RecommendType)
+ .IgnoreIHasRecommendAndHandledFrom();
+
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/InjectionRequestAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/InjectionRequestAutoMapperProfile.cs
index 2d2aef453..b927aa03d 100644
--- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/InjectionRequestAutoMapperProfile.cs
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/InjectionRequestAutoMapperProfile.cs
@@ -15,6 +15,7 @@ public partial class StoreEventAutoMapperProfile : Profile
.ForMember(x => x.InjectionRequestNumber, y => y.MapFrom(d => d.Number))
.ForMember(x => x.RequestType, y => y.MapFrom(d => d.Type))
.Ignore(x => x.WarehouseCode)
+ .Ignore(x => x.Workshop)
.Ignore(x => x.UpStreamJobNumber)
.Ignore(x => x.JobType)
.Ignore(x => x.IsAutoComplete)
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/AssembleJobEventHandler.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/AssembleJobEventHandler.cs
new file mode 100644
index 000000000..8834827b7
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/AssembleJobEventHandler.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Volo.Abp.EventBus;
+using Volo.Abp.Uow;
+using Win_in.Sfs.Basedata.Application.Contracts;
+using Win_in.Sfs.Shared.Domain.Shared;
+using Win_in.Sfs.Shared.Event;
+using Win_in.Sfs.Wms.Store.Application.Contracts;
+using Win_in.Sfs.Wms.Store.Domain;
+using Win_in.Sfs.Wms.Store.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Event.BusinessJob;
+
+public class AssembleJobEventHandler :
+ StoreEventHandlerBase
+ , ILocalEventHandler>
+{
+ private const EnumTransType TransType = EnumTransType.Issue;
+
+ private readonly IAssembleNoteAppService _assembleNoteAppService;
+ private readonly ILocationAppService _locationAppService;
+
+ public AssembleJobEventHandler(IAssembleNoteAppService assembleNoteAppService, ILocationAppService locationAppService)
+ {
+ _assembleNoteAppService = assembleNoteAppService;
+ _locationAppService = locationAppService;
+ }
+
+ ///
+ /// 执行后
+ ///
+ ///
+ ///
+ [UnitOfWork]
+ public virtual async Task HandleEventAsync(SfsCompletedEntityEventData eventData)
+ {
+ var entity = eventData.Entity;
+ var assembleNote = await BuildAssembleNoteAsync(entity).ConfigureAwait(false);
+ await _assembleNoteAppService.CreateAsync(assembleNote).ConfigureAwait(false);
+ }
+
+ #region 私有
+
+ ///
+ /// 创建补料记录实体
+ ///
+ ///
+ ///
+ private async Task BuildAssembleNoteAsync(AssembleJob entity)
+ {
+ var assembleNoteCreateInput = ObjectMapper.Map(entity);
+ assembleNoteCreateInput.JobNumber = entity.Number;
+ var locationCodes = assembleNoteCreateInput.Details.Select(p => p.ToLocationCode).Distinct().ToList();
+ var locations = await _locationAppService.GetByCodesAsync(locationCodes).ConfigureAwait(false);
+
+ assembleNoteCreateInput.Details.RemoveAll(p => p.Qty == 0);
+
+ foreach (var detail in assembleNoteCreateInput.Details)
+ {
+ var location = locations.First(p => p.Code == detail.ToLocationCode);
+ await RemovePackingCodeAndContainerCodeAndLotAsync(detail, location.Type).ConfigureAwait(false); //去箱 去托 去批
+
+ detail.ToLocationArea = location.AreaCode;
+ detail.ToLocationGroup = location.LocationGroupCode;
+ detail.ToLocationErpCode = location.ErpLocationCode;
+ detail.ToWarehouseCode = location.WarehouseCode;
+ }
+
+ return assembleNoteCreateInput;
+ }
+
+ ///
+ /// 去除箱码 托码 批次
+ ///
+ private async Task RemovePackingCodeAndContainerCodeAndLotAsync(AssembleNoteDetailInput assembleNoteDetail,
+ EnumLocationType locationType)
+ {
+ switch (locationType)
+ {
+ case EnumLocationType.WIP:
+ {
+ //用开关控制 发料到线边后去除箱码和托码 ???
+ if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToWip.IsRemovePackingCode)
+ .ConfigureAwait(false))
+ {
+ assembleNoteDetail.ToPackingCode = "";
+ }
+
+ if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToWip.IsRemoveContainerCode)
+ .ConfigureAwait(false))
+ {
+ assembleNoteDetail.ToContainerCode = "";
+ }
+
+ if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToWip.IsRemoveLot).ConfigureAwait(false))
+ {
+ assembleNoteDetail.ToLot = "";
+ }
+
+ break;
+ }
+ case EnumLocationType.SEMI:
+ {
+ //用开关控制 发料到后去除箱码和托码 ???
+ if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToSemi.IsRemovePackingCode)
+ .ConfigureAwait(false))
+ {
+ assembleNoteDetail.ToPackingCode = "";
+ }
+
+ if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToSemi.IsRemoveContainerCode)
+ .ConfigureAwait(false))
+ {
+ assembleNoteDetail.ToContainerCode = "";
+ }
+
+ if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToSemi.IsRemoveLot).ConfigureAwait(false))
+ {
+ assembleNoteDetail.ToLot = "";
+ }
+
+ break;
+ }
+ }
+ }
+
+ #endregion
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/AssembleRequestEventHandler.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/AssembleRequestEventHandler.cs
new file mode 100644
index 000000000..796227276
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/AssembleRequestEventHandler.cs
@@ -0,0 +1,283 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using FluentValidation.Validators;
+using Volo.Abp;
+using Volo.Abp.EventBus;
+using Volo.Abp.SettingManagement;
+using Win_in.Sfs.Basedata.Application.Contracts;
+using Win_in.Sfs.Shared.Domain.Shared;
+using Win_in.Sfs.Shared.Event;
+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;
+
+namespace Win_in.Sfs.Wms.Store.Event.BusinessRequest;
+
+public class AssembleRequestEventHandler
+ : StoreEventHandlerBase
+ , ILocalEventHandler>
+ , ILocalEventHandler>
+ , ILocalEventHandler>
+ , ILocalEventHandler>
+ , ILocalEventHandler>>
+{
+ private readonly IAssembleJobAppService _assembleJobAppService;
+ private readonly IProductionLineAppService _productionLineAppService;
+ private readonly IAssembleRequestManager _assembleRequestManager;
+ private readonly ILocationAppService _locationAppService;
+ private readonly IBalanceAppService _balanceAppService;
+
+ public AssembleRequestEventHandler(
+ IAssembleJobAppService assembleJobAppService
+ , IProductionLineAppService productionLineAppService
+ , IAssembleRequestManager assembleRequestManager
+ , ILocationAppService locationAppService
+ , IBalanceAppService balanceAppService)
+ {
+ _assembleJobAppService = assembleJobAppService;
+ _productionLineAppService = productionLineAppService;
+ _assembleRequestManager = assembleRequestManager;
+ _locationAppService = locationAppService;
+ _balanceAppService = balanceAppService;
+ }
+
+ ///
+ /// 创建后
+ ///
+ /// Event data
+ public virtual async Task HandleEventAsync(SfsCreatedEntityEventData eventData)
+ {
+ var entity = eventData.Entity;
+
+ //if (entity.AutoSubmit)
+ //{
+ // await _assembleRequestManager.SubmitAsync(entity).ConfigureAwait(false);
+ //}
+ }
+
+ ///
+ /// 批量创建后
+ ///
+ /// Event data
+ public virtual async Task HandleEventAsync(SfsCreatedEntityEventData> eventData)
+ {
+ var entitys = eventData.Entity;
+ foreach (var entity in entitys)
+ {
+ if (entity.AutoSubmit)
+ {
+ await _assembleRequestManager.SubmitAsync(entity).ConfigureAwait(false);
+ }
+
+ }
+ }
+
+ ///
+ /// 执行后
+ ///
+ ///
+ ///
+ public virtual async Task HandleEventAsync(SfsHandledEntityEventData eventData)
+ {
+ var entity = eventData.Entity;
+ var assembleJobs = await BuildAssembleJobAsync(entity).ConfigureAwait(false);
+ if (assembleJobs.Any())
+ {
+ await _assembleJobAppService.CreateManyAsync(assembleJobs).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// 驳回后
+ ///
+ ///
+ ///
+ public virtual async Task HandleEventAsync(SfsAbortedEntityEventData eventData)
+ {
+
+ }
+
+ ///
+ /// 完成后
+ ///
+ ///
+ ///
+ public virtual async Task HandleEventAsync(SfsCompletedEntityEventData eventData)
+ {
+ _ = eventData.Entity;
+ // await _assembleJobAppService.CompleteByAssembleRequestAsync(entity.Number);
+
+ await Task.CompletedTask.ConfigureAwait(false);
+ }
+
+ #region 私有
+
+ private async Task> BuildAssembleJobAsync
+ (AssembleRequest assembleRequest)
+ {
+ var jobs = new List();
+
+ var transactionType = await TransactionTypeAclService.GetByTransTypeAsync(EnumTransType.Issue, EnumTransSubType.None).ConfigureAwait(false);//库存事务
+
+ var toLocationCodes = assembleRequest.Details.Select(p => p.ToLocationCode).Distinct().ToList();//所有发送库位的集合
+ var toLocations = await _locationAppService.GetByCodesAsync(toLocationCodes).ConfigureAwait(false);//所有库位的集合
+
+ var assembleRequestDetails = assembleRequest.Details.Where(p => p.ToBeIssuedQty > 0);//所有还没发送物品的集合
+ foreach (var assembleRequestDetail in assembleRequestDetails)//如果有还有剩余未叫料的数量 则创建新的任务
+ {
+ var toLocation = toLocations.FirstOrDefault(p => p.Code == assembleRequestDetail.ToLocationCode);//判断目标库位是否存在
+ Check.NotNull(toLocation, "库位代码", $"库位 {assembleRequestDetail.ToLocationCode} 不存在");
+
+ //创建详情
+ var jobDetails = await BuildAssembleJobDetailInputsAsync(assembleRequest, assembleRequestDetail, transactionType, toLocation.LocationGroupCode).ConfigureAwait(false);
+ if (!jobDetails.Any())
+ {
+ continue;
+ }
+
+ 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.ToLocationCode != assembleRequestDetail.ToLocationCode))
+ {
+ job = BuildAssembleJobCreateInput(assembleRequest, fromLocation);
+ jobs.Add(job);
+ }
+ job.Details.AddRange(jobDetails);
+ if (assembleRequestDetail.ToBeIssuedQty < 0)
+ {
+ assembleRequestDetail.Status = EnumStatus.Close;
+ }
+ }
+
+ jobs = jobs.Where(p => p.Details.Any()).ToList();
+
+ var openRequestDetails =
+ assembleRequest.Details.Where(p => p.Status != EnumStatus.Close).ToList();
+
+ if (!openRequestDetails.Any())
+ {
+ return jobs;
+ }
+
+
+ var enableMultipleCreateAssembleJob = await SettingManager.IsTrueAsync(StoreSettings.MaterialRequest.EnableMultipleCreateIssueJob).ConfigureAwait(false);
+ if (enableMultipleCreateAssembleJob)
+ {
+
+ //assembleRequest.Partial();
+ }
+ else
+ {
+ var sb = new StringBuilder();
+ foreach (var openRequestDetail in openRequestDetails)
+ {
+ sb.AppendLine($"{openRequestDetail.ItemCode}请求数量 {openRequestDetail.Qty},可用库存数量 {openRequestDetail.IssuedQty}");
+ }
+ throw new UserFriendlyException($"{sb} 可用库存数量不足, 无法生成发料任务");
+ }
+ return jobs;
+ }
+
+ private AssembleJobEditInput BuildAssembleJobCreateInput(AssembleRequest assembleRequest, LocationDTO fromLocation)
+ {
+ AssembleJobEditInput job;
+ job = ObjectMapper.Map(assembleRequest);
+ job.JobType = EnumJobType.IssueJob;
+ job.JobStatus = EnumJobStatus.Open;
+ job.WorkGroupCode = fromLocation.WorkGroupCode;
+ job.WarehouseCode = fromLocation.WarehouseCode;
+ job.ProdLine = fromLocation.LocationGroupCode;
+ job.Worker = assembleRequest.Worker;
+ if (string.IsNullOrEmpty(job.Worker))
+ {
+ job.Worker = "admin";
+ }
+ job.AssembleRequestNumber = assembleRequest.Number;
+ return job;
+ }
+
+ private async Task> BuildAssembleJobDetailInputsAsync(AssembleRequest assembleRequest,
+ AssembleRequestDetail assembleRequestDetail, TransactionTypeDTO transactionType, string toLocationGroupCode)
+ {
+ var jobDetails = new List();
+ var input = new RecommendBalanceRequestInput()
+ {
+ ItemCode = assembleRequestDetail.ItemCode,
+ Qty = assembleRequestDetail.ToBeIssuedQty,
+ LocationTypes = transactionType.OutLocationTypes,
+ LocationAreas = new List { assembleRequestDetail.FromLocationArea },
+ Statuses = transactionType.OutInventoryStatuses,
+ };
+ //获取推荐库存
+ var recommendList = await _balanceAppService.GetRecommendBalancesAsync(input).ConfigureAwait(false);
+ //没有推荐库存时 跳过此明细 不生成任务
+ if (recommendList.Count != 0)
+ {
+ foreach (var recommend in recommendList)
+ {
+ //拿走需求量
+ var detail = await BuildAssembleJobDetailAsync(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 BuildAssembleJobDetailAsync(AssembleRequestDetail assembleRequestDetail, BalanceDTO balance, string toLocationGroupCode)
+ {
+
+ //ProductionLineDTO prodLine = await _productionLineAppService.GetByLocationGroupCodeAsync(toLocationGroupCode).ConfigureAwait(false);
+
+ var detail = ObjectMapper.Map(balance);
+ detail.RequestLocationCode = assembleRequestDetail.ToLocationCode;
+ detail.WorkStation = assembleRequestDetail.WorkStation;
+ detail.ExpiredTime = assembleRequestDetail.ExpiredTime;
+ detail.PositionCode = assembleRequestDetail.PositionCode;
+ detail.RecommendType = assembleRequestDetail.RecommendType;
+
+ detail.RecommendPackingCode = balance.PackingCode;
+ detail.RecommendContainerCode = balance.ContainerCode;
+ detail.RecommendSupplierBatch = balance.SupplierBatch;
+ detail.RecommendProduceDate = balance.ProduceDate;
+ detail.RecommendExpireDate = balance.ExpireDate;
+ detail.RecommendLot = balance.Lot;
+ detail.RecommendProduceDate = balance.ProduceDate;
+ detail.RecommendArriveDate = balance.ArriveDate;
+ detail.RecommendFromLocationArea = balance.LocationArea;
+ detail.RecommendFromLocationCode = balance.LocationCode;
+ detail.RecommendFromLocationErpCode = balance.LocationErpCode;
+ detail.RecommendFromLocationGroup = balance.LocationGroup;
+ detail.RecommendFromWarehouseCode = balance.WarehouseCode;
+ detail.RecommendQty = balance.Qty;
+ detail.Uom = balance.Uom;
+
+ detail.ToLocationCode = assembleRequestDetail.ToLocationCode;
+ detail.ToLocationErpCode = assembleRequestDetail.ToLocationErpCode;
+ detail.ToLocationArea = assembleRequestDetail.ToLocationArea;
+ detail.ToWarehouseCode = assembleRequestDetail.ToWarehouseCode;
+
+ //detail.ProdLine = prodLine == null ? toLocationGroupCode : prodLine.Code;
+ detail.ProdLine = toLocationGroupCode;
+ await Task.CompletedTask.ConfigureAwait(false);
+ return detail;
+
+ }
+
+ #endregion
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/StoreEventAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/StoreEventAutoMapperProfile.cs
index 303d94bc3..682288fa9 100644
--- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/StoreEventAutoMapperProfile.cs
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/StoreEventAutoMapperProfile.cs
@@ -36,6 +36,7 @@ public partial class StoreEventAutoMapperProfile : Profile
InspectJobAutoMapperProfile();
IssueJobAutoMapperProfile();
InjectionJobAutoMapperProfile();
+ AssembleJobAutoMapperProfile();
JisDeliverJobAutoMapperProfile();
ProductionReturnJobAutoMapperProfile();
ProductReceiveJobAutoMapperProfile();
@@ -66,11 +67,14 @@ public partial class StoreEventAutoMapperProfile : Profile
InventoryTransferNoteAutoMapperProfile();
IsolationNoteAutoMapperProfile();
IssueNoteAutoMapperProfile();
+ InjectionNoteAutoMapperProfile();
+ AssembleNoteAutoMapperProfile();
ItemTransformNoteAutoMapperProfile();
JisDeliverNoteAutoMapperProfile();
JisProductReceiptNoteAutoMapperProfile();
MaterialRequestAutoMapperProfile();
InjectionRequestAutoMapperProfile();
+ AssembleRequestAutoMapperProfile();
ProductionReturnRequestAutoMapperProfile();
ProductionReturnNoteAutoMapperProfile();
ProductReceiptNoteAutoMapperProfile();