diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/DTOs/InjectionJobDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/DTOs/InjectionJobDTO.cs
new file mode 100644
index 000000000..0a9ec1c80
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/DTOs/InjectionJobDTO.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 InjectionJobDTO : 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 InjectionRequestNumber { 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/InjectionJobs/DTOs/InjectionJobDetailDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/DTOs/InjectionJobDetailDTO.cs
new file mode 100644
index 000000000..363521370
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/DTOs/InjectionJobDetailDTO.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 InjectionJobDetailDTO : 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/InjectionJobs/IInjectionJobAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/IInjectionJobAppService.cs
new file mode 100644
index 000000000..a238cf57b
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/IInjectionJobAppService.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 IInjectionJobAppService
+ : ISfsJobAppServiceBase
+{
+ Task> CheckJobExistByItemCodeAndLocationCode(string itemCode, string locationCode);
+
+ Task CancelByMaterialRequestAsync(string injectionNumber);
+
+ 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/InjectionJobs/InjectionJobPermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/InjectionJobPermissions.cs
new file mode 100644
index 000000000..31b455675
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/InjectionJobPermissions.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 InjectionJobPermissions
+{
+
+ public const string Default = StorePermissions.GroupName + "." + nameof(InjectionJob);
+ public const string Create = Default + "." + StorePermissions.CreateStr;
+ public const string Update = Default + "." + StorePermissions.UpdateStr;
+ public const string Delete = Default + "." + StorePermissions.DeleteStr;
+
+ //自动发料任务
+ public const string AutoInjectionJob = StorePermissions.GroupName + "." + nameof(AutoInjectionJob);
+
+ public static void AddInjectionJobPermission(this PermissionGroupDefinition permissionGroup)
+ {
+ var InjectionJobPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(InjectionJob)));
+ InjectionJobPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
+ InjectionJobPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
+ InjectionJobPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
+
+ permissionGroup.AddPermission(AutoInjectionJob, StorePermissionDefinitionProvider.L(nameof(AutoInjectionJob)));
+
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobCheckInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobCheckInput.cs
new file mode 100644
index 000000000..45aff0d7e
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobCheckInput.cs
@@ -0,0 +1,6 @@
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class InjectionJobCheckInput : SfsJobCheckInputBase
+{
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobDetailInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobDetailInput.cs
new file mode 100644
index 000000000..38890b9a9
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobDetailInput.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 InjectionJobDetailInput : 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/InjectionJobs/Inputs/InjectionJobEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobEditInput.cs
new file mode 100644
index 000000000..ebc95b6c7
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobEditInput.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 InjectionJobEditInput : 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 InjectionRequestNumber { 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/InjectionNotes/DTOs/InjectionNoteDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/DTOs/InjectionNoteDTO.cs
new file mode 100644
index 000000000..96f533b19
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/DTOs/InjectionNoteDTO.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 InjectionNoteDTO : 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/InjectionNotes/DTOs/InjectionNoteDetailDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/DTOs/InjectionNoteDetailDTO.cs
new file mode 100644
index 000000000..e36d271b3
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/DTOs/InjectionNoteDetailDTO.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 InjectionNoteDetailDTO : 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/InjectionNotes/IInjectionNoteAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/IInjectionNoteAppService.cs
new file mode 100644
index 000000000..8d88bd51d
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/IInjectionNoteAppService.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 IInjectionNoteAppService : ISfsStoreMasterReadOnlyAppServiceBase
+{
+ Task CreateAsync(InjectionNoteEditInput 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/InjectionNotes/InjectionNotePermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/InjectionNotePermissions.cs
new file mode 100644
index 000000000..ec202d6be
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/InjectionNotePermissions.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 InjectionNotePermissions
+{
+
+ public const string Default = StorePermissions.GroupName + "." + nameof(InjectionNote);
+ public const string Create = Default + "." + StorePermissions.CreateStr;
+ public const string Update = Default + "." + StorePermissions.UpdateStr;
+ public const string Delete = Default + "." + StorePermissions.DeleteStr;
+
+ //自动发料记录
+ public const string AutoInjectionNote = StorePermissions.GroupName + "." + nameof(AutoInjectionNote);
+
+ //直接发料
+ public const string DirectInjectionNote = StorePermissions.GroupName + "." + nameof(DirectInjectionNote);
+
+ public static void AddInjectionNotePermission(this PermissionGroupDefinition permissionGroup)
+ {
+ var injectionNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(InjectionNote)));
+ injectionNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
+ injectionNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
+ injectionNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
+
+ permissionGroup.AddPermission(AutoInjectionNote, StorePermissionDefinitionProvider.L(nameof(AutoInjectionNote)));
+ permissionGroup.AddPermission(DirectInjectionNote, StorePermissionDefinitionProvider.L(nameof(DirectInjectionNote)));
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteDetailInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteDetailInput.cs
new file mode 100644
index 000000000..48714bb23
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteDetailInput.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 InjectionNoteDetailInput : 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/InjectionNotes/Inputs/InjectionNoteEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteEditInput.cs
new file mode 100644
index 000000000..410903705
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteEditInput.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 InjectionNoteEditInput : 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/InjectionNotes/Inputs/InjectionNoteImportInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteImportInput.cs
new file mode 100644
index 000000000..2876aa4ee
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteImportInput.cs
@@ -0,0 +1,33 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class InjectionNoteImportInput : 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 b45ea84a6..c99e2abe8 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
@@ -26,8 +26,10 @@ public class StorePermissionDefinitionProvider : PermissionDefinitionProvider
storeGroup.AddPurchaseReturnNotePermission();
storeGroup.AddPutawayNotePermission();
storeGroup.AddMaterialRequestPermission();
+ storeGroup.AddInjectionRequestPermission();
storeGroup.AddContainerRequestPermission();
storeGroup.AddIssueNotePermission();
+ storeGroup.AddInjectionNotePermission();
storeGroup.AddContainerNotePermission();
storeGroup.AddUnplannedReceiptNotePermission();
storeGroup.AddUnplannedIssueNotePermission();
@@ -90,6 +92,7 @@ public class StorePermissionDefinitionProvider : PermissionDefinitionProvider
storeGroup.AddInspectJobPermission();
storeGroup.AddPutawayJobPermission();
storeGroup.AddIssueJobPermission();
+ storeGroup.AddInjectionJobPermission();
storeGroup.AddContainerJobPermission();
storeGroup.AddDeliverJobPermission();
storeGroup.AddPurchaseReturnJobPermission();
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/DTOs/InjectionRequestDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/DTOs/InjectionRequestDTO.cs
new file mode 100644
index 000000000..b57dece0c
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/DTOs/InjectionRequestDTO.cs
@@ -0,0 +1,37 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Win_in.Sfs.Wms.Store.Application.Contracts;
+
+public class InjectionRequestDTO : SfsStoreRequestDTOBase, IHasNumber
+{
+ ///
+ /// 叫料类型
+ ///
+ [Display(Name = "叫料类型")]
+ public string Type { get; set; }
+
+ ///
+ /// 备料计划单号
+ ///
+ [Display(Name = "备料计划单号")]
+ public string PreparationPlanNumber { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [Display(Name = "生产线")]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 车间
+ ///
+ [Display(Name = "车间")]
+ 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/Requests/InjectionRequests/DTOs/InjectionRequestDetailDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/DTOs/InjectionRequestDetailDTO.cs
new file mode 100644
index 000000000..6116135fb
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/DTOs/InjectionRequestDetailDTO.cs
@@ -0,0 +1,94 @@
+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 InjectionRequestDetailDTO : SfsStoreDetailWithQtyDTOBase
+
+{
+
+ ///
+ /// 目标库位
+ ///
+ [Display(Name = "目标库位")]
+ public string ToLocationCode { get; set; }
+
+ ///
+ /// 来源库区
+ ///
+ [Display(Name = "来源库区")]
+ [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
+ public string FromLocationArea { get; set; }
+
+ // ///
+ // /// 在途库库位
+ // ///
+ // 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; }
+
+ ///
+ /// 目标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; }
+
+ ///
+ /// 请求未发
+ ///
+ [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/InjectionRequests/IInjectionRequestAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/IInjectionRequestAppService.cs
new file mode 100644
index 000000000..bde30d873
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/IInjectionRequestAppService.cs
@@ -0,0 +1,35 @@
+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 IInjectionRequestAppService
+ : ISfsStoreRequestMasterAppServiceBase
+
+{
+ Task CreateAndHandleAsync(InjectionRequestEditInput input);
+
+ ///
+ /// 根据备料计划生成 叫料请求
+ ///
+ ///
+ Task CreateAndHandleByPreparationPlan(string productionPlanNumber);
+
+ Task CreateAndHandleByAPIAsync(InjectionRequestEditInput input);
+
+ ///
+ /// 根据类型获取叫料请求
+ ///
+ ///
+ /// 叫料请求类型
+ ///
+ ///
+ ///
+ Task> GetListByTypeAsync(SfsStoreRequestInputBase requestInput,
+ string type, bool includeDetails = false, CancellationToken cancellationToken = default);
+
+ Task> GetListByTypeAsync(string type);
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/InjectionRequestPermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/InjectionRequestPermissions.cs
new file mode 100644
index 000000000..1757aaada
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/InjectionRequestPermissions.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 InjectionRequestPermissions
+{
+
+ public const string Default = StorePermissions.GroupName + "." + nameof(InjectionRequest);
+ public const string Create = Default + "." + StorePermissions.CreateStr;
+ public const string Update = Default + "." + StorePermissions.UpdateStr;
+ public const string Delete = Default + "." + StorePermissions.DeleteStr;
+
+ //自动叫料申请
+ public const string AutoInjectionRequest = StorePermissions.GroupName + "." + nameof(AutoInjectionRequest);
+
+ public static void AddInjectionRequestPermission(this PermissionGroupDefinition permissionGroup)
+ {
+ var InjectionRequestPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(InjectionRequest)));
+ InjectionRequestPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
+ InjectionRequestPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
+ InjectionRequestPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
+
+ permissionGroup.AddPermission(AutoInjectionRequest, StorePermissionDefinitionProvider.L(nameof(AutoInjectionRequest)));
+
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestDetailInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestDetailInput.cs
new file mode 100644
index 000000000..f1e0eb41b
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestDetailInput.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 InjectionRequestDetailInput : 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/InjectionRequests/Inputs/InjectionRequestEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestEditInput.cs
new file mode 100644
index 000000000..7277bf50c
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestEditInput.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 InjectionRequestEditInput : 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/InjectionRequests/Inputs/InjectionRequestImportInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestImportInput.cs
new file mode 100644
index 000000000..e661693ef
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestImportInput.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 InjectionRequestImportInput : 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/InjectionJobs/InjectionJobAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/InjectionJobs/InjectionJobAppService.cs
new file mode 100644
index 000000000..a8ff9b2bd
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/InjectionJobs/InjectionJobAppService.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}injection-job")]
+public class InjectionJobAppService
+ : SfsJobAppServiceBase,
+ IInjectionJobAppService
+{
+ private readonly IInjectionJobManager _injectionJobManager;
+
+ public InjectionJobAppService(
+ IInjectionJobRepository repository, IInjectionJobManager injectionJobManager
+ ) : base(repository, injectionJobManager)
+ {
+ _injectionJobManager = injectionJobManager;
+ }
+
+ ///
+ /// 根据物品和库位 检查是否存在发料任务
+ ///
+ ///
+ ///
+ ///
+ ///
+ [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/{injectionNumber}")]
+ public virtual async Task CancelByMaterialRequestAsync(string injectionNumber)
+ {
+ var entities = await _repository.GetListAsync(p => p.InjectionRequestNumber == injectionNumber).ConfigureAwait(false);
+ foreach (var entity in entities)
+ {
+ await _injectionJobManager.CancelAsync(entity).ConfigureAwait(false);
+ }
+ }
+
+ [HttpPost("invalid")]
+ public override async Task CancelAsync(Guid id)
+ {
+ var injectionJob = await _repository.GetAsync(id).ConfigureAwait(false);
+ if (injectionJob == null)
+ {
+ throw new UserFriendlyException($"未找到ID为 {id} 的任务");
+ }
+
+ await _injectionJobManager.CancelAsync(injectionJob).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.InjectionRequestNumber == 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);
+ InjectionJobDetail detail = job.Details.FirstOrDefault(p => p.RecommendPackingCode == input.FromPackingCode ); /*&& p.HandledQty == input.FromQty*/
+ if (detail == null)
+ {
+ //throw new UserFriendlyException($"根据HandledPackingCode={input.FromPackingCode}取InjectionJobDetail表为空!");
+ throw new UserFriendlyException($"根据RecommendPackingCode={input.FromPackingCode}取InjectionJobDetail表为空!");
+ }
+ //插入目标箱
+ 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/InjectionJobs/InjectionJobAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/InjectionJobs/InjectionJobAutoMapperProfile.cs
new file mode 100644
index 000000000..c1b17e043
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/InjectionJobs/InjectionJobAutoMapperProfile.cs
@@ -0,0 +1,30 @@
+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 InjectionJobAutoMapperProfile()
+ {
+ CreateMap();
+
+ CreateMap();
+
+ 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/InjectionNotes/InjectionNoteAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/InjectionNotes/InjectionNoteAppService.cs
new file mode 100644
index 000000000..c4bad1cfb
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/InjectionNotes/InjectionNoteAppService.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}injection-note")]
+public class InjectionNoteAppService :
+ SfsStoreWithDetailsAppServiceBase,
+ IInjectionNoteAppService
+{
+ private readonly IInjectionNoteManager _injectionNoteManager;
+
+ public InjectionNoteAppService(
+ IInjectionNoteRepository repository,
+ IInjectionNoteManager injectionNoteManager
+ ) : base(repository)
+ {
+ _injectionNoteManager = injectionNoteManager;
+ }
+
+ [HttpPost("")]
+ //[Authorize(InjectionNotePermissions.Create)]
+ public override async Task CreateAsync(InjectionNoteEditInput input)
+ {
+ var entity = ObjectMapper.Map(input);
+ await _injectionNoteManager.CreateAsync(entity).ConfigureAwait(false);
+ var dto = ObjectMapper.Map(entity);
+ return dto;
+ }
+
+ ///
+ /// 确认对应的记录单
+ ///
+ ///
+ ///
+ [HttpPost("confirm/{id}")]
+ public virtual async Task ConfirmAsync(Guid id)
+ {
+ var injectionNote= await _repository.GetAsync(id).ConfigureAwait(false);
+ injectionNote.Confirmed = true;
+ injectionNote=await _repository.UpdateAsync(injectionNote).ConfigureAwait(false);
+ await LocalEventBus.PublishAsync(new SfsConfirmedEntityEventData(injectionNote), false).ConfigureAwait(false);
+ return ObjectMapper.Map(injectionNote);
+ }
+
+ [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(InjectionNote));
+ var result = await _injectionNoteManager.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/InjectionNotes/InjectionNoteAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/InjectionNotes/InjectionNoteAutoMapperProfile.cs
new file mode 100644
index 000000000..937b4edcb
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/InjectionNotes/InjectionNoteAutoMapperProfile.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 InjectionNoteAutoMapperProfile()
+ {
+ 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/Notes/ProductRecycleNotes/ProductRecycleNoteAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/ProductRecycleNotes/ProductRecycleNoteAutoMapperProfile.cs
index bed3ee5c7..97e507c24 100644
--- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/ProductRecycleNotes/ProductRecycleNoteAutoMapperProfile.cs
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/ProductRecycleNotes/ProductRecycleNoteAutoMapperProfile.cs
@@ -15,6 +15,8 @@ public partial class StoreApplicationAutoMapperProfile : Profile
CreateMap();
+ CreateMap();
+
CreateMap()
.IgnoreAuditedObjectProperties()
.Ignore(x => x.MasterID)
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/InjectionRequests/InjectionRequestAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/InjectionRequests/InjectionRequestAppService.cs
new file mode 100644
index 000000000..e3d7400db
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/InjectionRequests/InjectionRequestAppService.cs
@@ -0,0 +1,503 @@
+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}injection-request")]
+public class InjectionRequestAppService : SfsStoreRequestAppServiceBase,
+ IInjectionRequestAppService
+{
+ private readonly IInjectionRequestManager _injectionRequestManager;
+
+ private readonly IPreparationPlanManager _preparationPlanManager;
+
+ 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 InjectionRequestAppService(
+ IInjectionRequestRepository repository,
+ IInjectionRequestManager injectionRequestManager,
+ IPreparationPlanManager preparationPlanManager,
+ IItemStoreRelationAppService itemStoreRelationApp,
+ IAreaAppService areaApp,
+ ILocationAppService locationAppService,
+ IItemBasicAppService itemBasicAppService,
+ IProductionLineAppService productionLineAppService,
+ IInjectionJobAppService issueJobAppService)
+ : base(repository, injectionRequestManager)
+ {
+ _injectionRequestManager = injectionRequestManager;
+ _preparationPlanManager = preparationPlanManager;
+ _itemStoreRelationApp = itemStoreRelationApp;
+ _areaApp = areaApp;
+ _locationAppService = locationAppService;
+ _itemBasicAppService = itemBasicAppService;
+ _productionLineAppService = productionLineAppService;
+ _issueJobAppService = issueJobAppService;
+ }
+
+ #region 东阳使用
+
+ ///
+ /// 用来重写 导入数据时可以加工数据
+ ///
+ ///
+ ///
+ protected override async Task> ImportProcessingEntityAsync(
+ Dictionary dictionary)
+ {
+ var addList = dictionary.Where(p => p.Value == EntityState.Added).Select(p => p.Key);
+
+ foreach (var injectionRequest in addList)
+ {
+ injectionRequest.Worker = CurrentUser.GetUserName();
+ injectionRequest.CreatorId = CurrentUser.Id;
+ if (injectionRequest.Type == EnumTransSubType.Issue_Manual.GetDisplayName())
+ {
+ injectionRequest.Type = EnumTransSubType.Issue_Manual.ToString();
+ }
+
+ foreach (var detail in injectionRequest.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;
+ }
+
+ 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);
+ }
+
+ #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
+
+ #endregion
+
+ [HttpPost("")]
+ //[Authorize(InjectionRequestPermissions.Create)]
+ public override async Task CreateAsync(InjectionRequestEditInput input)
+ {
+ foreach (var item in input.Details)
+ {
+ if (item.Qty <= 0)
+ {
+ throw new UserFriendlyException($"{item.ItemCode} 物料的需求量必须大于 0");
+ }
+ }
+
+ //检验备料计划是否存在要料请求
+ if (!string.IsNullOrWhiteSpace(input.PreparationPlanNumber))
+ {
+ var exist = await CheckExistByPreparationPlanAsync(input.PreparationPlanNumber).ConfigureAwait(false);
+ if (exist.Count > 0)
+ {
+ throw new UserFriendlyException($"{input.PreparationPlanNumber} 备料计划已存在要料申请");
+ }
+ }
+
+ foreach (var item in input.Details) //赋值生产线
+ {
+ var location = await LocationAclService.GetByCodeAsync(item.ToLocationCode).ConfigureAwait(false);
+ item.ProdLine = location.LocationGroupCode;
+ input.ProdLine = location.LocationGroupCode;
+ }
+
+ var entity = ObjectMapper.Map(input);
+
+ var result = await _injectionRequestManager.CreateAsync(entity).ConfigureAwait(false);
+
+ var dto = ObjectMapper.Map(result);
+ return dto;
+ }
+
+ ///
+ /// 创建并且执行叫料请求
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("create-and-handle-api")]
+ //[Authorize(InjectionRequestPermissions.Create)]
+ public virtual async Task CreateAndHandleByAPIAsync(InjectionRequestEditInput input)
+ {
+ foreach (var item in input.Details)
+ {
+ if (item.Qty <= 0)
+ {
+ throw new UserFriendlyException($"{item.ItemCode} 物料的需求量必须大于 0");
+ }
+ }
+
+
+ input.AutoSubmit = true;
+ input.AutoAgree = true;
+ input.AutoHandle = true;
+ input.AutoCompleteJob = false;
+ input.DirectCreateNote = false;
+
+ 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.ItemDesc1 = itemBasicDto.Desc1;
+ if(detailInput.PositionCode.Contains('W'))
+ {
+ detailInput.RecommendType = EnumRecommendType.W;
+ }
+ else if(detailInput.PositionCode.Contains('Q'))
+ {
+ detailInput.RecommendType = EnumRecommendType.Q;
+ }
+ else if(detailInput.PositionCode.Contains('K'))
+ {
+ detailInput.RecommendType = EnumRecommendType.K;
+ }
+ else
+ {
+ detailInput.RecommendType = EnumRecommendType.None;
+ }
+
+ var productionLineDto = await _productionLineAppService.GetByLocationGroupCodeAsync(toLocationDto.LocationGroupCode).ConfigureAwait(false);
+
+ detailInput.ToLocationCode = toLocationDto.ErpLocationCode;
+ if (productionLineDto != null)
+ {
+ detailInput.ProdLine = productionLineDto.Code;
+ }
+ }
+
+ var entity = ObjectMapper.Map(input);
+ foreach (var detail in entity.Details)
+ {
+ var toLocationDto = await _locationAppService.GetByCodeAsync(detail.ToLocationCode).ConfigureAwait(false);
+ var productionLineDto = await _productionLineAppService.GetByLocationGroupCodeAsync(toLocationDto.LocationGroupCode).ConfigureAwait(false);
+
+ detail.ToLocationArea= toLocationDto.AreaCode;
+ detail.ToLocationErpCode = toLocationDto.ErpLocationCode;
+ detail.ToLocationGroup = toLocationDto.LocationGroupCode;
+ detail.ToWarehouseCode= toLocationDto.WarehouseCode;
+ }
+
+ entity.UseOnTheWayLocation = false;
+
+ var result = await _injectionRequestManager.CreateBynNumberAsync(entity).ConfigureAwait(false);
+
+ var dto = ObjectMapper.Map(result);
+
+ return dto;
+ }
+
+ ///
+ /// 创建并且执行叫料请求
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("create-and-handle")]
+ //[Authorize(InjectionRequestPermissions.Create)]
+ public virtual async Task CreateAndHandleAsync(InjectionRequestEditInput input)
+ {
+ foreach (var item in input.Details)
+ {
+ if (item.Qty <= 0)
+ {
+ throw new UserFriendlyException($"{item.ItemCode} 物料的需求量必须大于0");
+ }
+ }
+
+ //检验备料计划是否存在要料请求
+ if (!string.IsNullOrWhiteSpace(input.PreparationPlanNumber))
+ {
+ var exist = await CheckExistByPreparationPlanAsync(input.PreparationPlanNumber).ConfigureAwait(false);
+ if (exist.Count > 0)
+ {
+ throw new UserFriendlyException($"{input.PreparationPlanNumber} 备料计划已存在要料申请");
+ }
+ }
+
+ 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);
+
+ var location = await LocationAclService.GetByCodeAsync(detailInput.ToLocationCode).ConfigureAwait(false);
+ detailInput.ProdLine = location.LocationGroupCode;
+ input.ProdLine = location.LocationGroupCode;
+ input.Worker = input.Worker;
+ }
+
+ input.AutoSubmit = true;
+ input.AutoAgree = true;
+ input.AutoHandle = true;
+ input.AutoCompleteJob = false;
+ input.DirectCreateNote = false;
+
+ var entity = ObjectMapper.Map(input);
+
+ var result = await _injectionRequestManager.CreateAsync(entity).ConfigureAwait(false);
+
+ var dto = ObjectMapper.Map(result);
+
+ return dto;
+ }
+
+ ///
+ /// 根据备料计划生成 叫料请求
+ ///
+ ///
+ [HttpPost("create-and-handle-by-preparation-plan/{number}")]
+ public virtual async Task CreateAndHandleByPreparationPlan(string number)
+ {
+ var prodPreparationPlan = await _preparationPlanManager.GetByNumberAsync(number).ConfigureAwait(false);
+
+ var injectionRequestCreateInput = new InjectionRequestEditInput { Worker = CurrentUser.GetUserName() };
+
+ foreach (var preparationPlanDetail in prodPreparationPlan.Details)
+ {
+ var detail = new InjectionRequestDetailInput
+ {
+ ItemCode = preparationPlanDetail.ItemCode,
+ ItemName = preparationPlanDetail.ItemName,
+ ItemDesc1 = preparationPlanDetail.ItemDesc1,
+ ItemDesc2 = preparationPlanDetail.ItemDesc2,
+ Uom = preparationPlanDetail.Uom,
+ Qty = preparationPlanDetail.Qty,
+ StdPackQty = preparationPlanDetail.StdPackQty,
+ ToLocationCode = preparationPlanDetail.ToLocationCode
+ };
+
+ injectionRequestCreateInput.Details.Add(detail);
+ }
+
+ var dto = await CreateAndHandleAsync(injectionRequestCreateInput).ConfigureAwait(false);
+
+ return dto;
+ }
+
+ ///
+ /// 检验备料计划是否存在要料请求
+ ///
+ ///
+ ///
+ private async Task> CheckExistByPreparationPlanAsync(string preparationPlanNumber)
+ {
+ var entities = await _repository.GetListAsync(c => c.PreparationPlanNumber == preparationPlanNumber)
+ .ConfigureAwait(false);
+ return entities;
+ }
+
+ ///
+ /// 根据类型获取叫料请求
+ ///
+ ///
+ ///
+ /// 叫料请求类型:
+ /// 人工拉动:Issue_Manual;
+ /// 线边拉动:Issue_WIP;
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("by-type/{type}")]
+ public virtual async Task> GetListByTypeAsync(
+ SfsStoreRequestInputBase requestInput,
+ string type,
+ bool includeDetails = false,
+ CancellationToken cancellationToken = default)
+ {
+ Expression> expression = p => p.Type == type;
+ 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);
+ }
+
+ #region 导入
+
+
+ ///
+ /// 导入验证
+ ///
+ ///
+ ///
+ ///
+ protected override async Task ValidateImportModelAsync(InjectionRequestImportInput 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(InjectionRequestImportInput 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(InjectionRequestImportInput 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(InjectionRequestImportInput 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(InjectionRequestImportInput 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
+
+ ///
+ /// 根据类型 获取叫料申请
+ ///
+ ///
+ ///
+ [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;
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/InjectionRequests/InjectionRequestAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/InjectionRequests/InjectionRequestAutoMapperProfile.cs
new file mode 100644
index 000000000..de78a07de
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/InjectionRequests/InjectionRequestAutoMapperProfile.cs
@@ -0,0 +1,74 @@
+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 InjectionRequestAutoMapperProfile()
+ {
+ 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.PreparationPlanNumber)
+ .Ignore(x => x.ProdLine)
+ .Ignore(x => x.Workshop)
+ .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 7fa33e59e..1f5b385d9 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
@@ -14,6 +14,7 @@ public partial class StoreApplicationAutoMapperProfile : Profile
InspectRequestAutoMapperProfile();
ItemTransformRequestAutoMapperProfile();
MaterialRequestAutoMapperProfile();
+ InjectionRequestAutoMapperProfile();
ProductionReturnRequestAutoMapperProfile();
ProductReceiptRequestAutoMapperProfile();
UnplannedIssueRequestAutoMapperProfile();
@@ -60,6 +61,7 @@ public partial class StoreApplicationAutoMapperProfile : Profile
InventoryTransferNoteMapperProfile();
IsolationNoteAutoMapperProfile();
IssueNoteAutoMapperProfile();
+ InjectionNoteAutoMapperProfile();
ContainerNoteAutoMapperProfile();
ItemTransformNoteAutoMapperProfile();
JisDeliverNoteAutoMapperProfile();
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain.Shared/Settings/StoreSettings.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain.Shared/Settings/StoreSettings.cs
index bcf1e32b1..729511a4b 100644
--- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain.Shared/Settings/StoreSettings.cs
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain.Shared/Settings/StoreSettings.cs
@@ -112,6 +112,12 @@ public static class StoreSettings
public const string EnableMultipleCreateIssueJob = $"{Default}.{nameof(EnableMultipleCreateIssueJob)}";
}
+ public static class InjectionRequest
+ {
+ private const string Default = $"{GroupName}.{nameof(InjectionRequest)}";
+ public const string EnableMultipleCreateInjectionJob = $"{Default}.{nameof(EnableMultipleCreateInjectionJob)}";
+ }
+
public static class Cache
{
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/IInjectionJobManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/IInjectionJobManager.cs
new file mode 100644
index 000000000..7be96ee4a
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/IInjectionJobManager.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public interface IInjectionJobManager : IJobManager
+{
+ Task GetAsync(Expression> expression);
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/IInjectionJobRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/IInjectionJobRepository.cs
new file mode 100644
index 000000000..aeeac0878
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/IInjectionJobRepository.cs
@@ -0,0 +1,6 @@
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public interface IIssueJobRepository : ISfsJobRepositoryBase
+{
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJob.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJob.cs
new file mode 100644
index 000000000..8f22c73b2
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJob.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 InjectionJob : SfsJobAggregateRootBase
+{
+ ///
+ /// 叫料请求类型
+ ///
+ [IgnoreUpdate]
+ public string RequestType { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [IgnoreUpdate]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 要货单号
+ ///
+ [IgnoreUpdate]
+ public string InjectionRequestNumber { 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/InjectionJobs/InjectionJobDetail.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJobDetail.cs
new file mode 100644
index 000000000..5d37078d1
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJobDetail.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 InjectionJobDetail : 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/InjectionJobs/InjectionJobManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJobManager.cs
new file mode 100644
index 000000000..a88e5c213
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJobManager.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 InjectionJobManager : SfsJobManagerBase, IInjectionJobManager
+{
+
+ public InjectionJobManager(
+ IInjectionJobRepository repository
+ ) : base(repository)
+ {
+ }
+
+ ///
+ /// 执行任务 发料任务
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override async Task CompleteAsync(InjectionJob 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(InjectionJob 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/IIssueJobRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/IIssueJobRepository.cs
index aeeac0878..f507ca852 100644
--- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/IIssueJobRepository.cs
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/IIssueJobRepository.cs
@@ -1,6 +1,6 @@
namespace Win_in.Sfs.Wms.Store.Domain;
-public interface IIssueJobRepository : ISfsJobRepositoryBase
+public interface IInjectionJobRepository : ISfsJobRepositoryBase
{
}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/IInjectionNoteManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/IInjectionNoteManager.cs
new file mode 100644
index 000000000..281cc8cba
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/IInjectionNoteManager.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Threading.Tasks;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public interface IInjectionNoteManager : ISfsStoreManager
+{
+ Task ConfirmAsync(Guid id);
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/IInjectionNoteRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/IInjectionNoteRepository.cs
new file mode 100644
index 000000000..fb894c737
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/IInjectionNoteRepository.cs
@@ -0,0 +1,6 @@
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public interface IInjectionNoteRepository : ISfsStoreRepositoryBase
+{
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNote.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNote.cs
new file mode 100644
index 000000000..582852d31
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNote.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 InjectionNote : 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/InjectionNotes/InjectionNoteDetail.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNoteDetail.cs
new file mode 100644
index 000000000..9e9d44882
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNoteDetail.cs
@@ -0,0 +1,43 @@
+using System;
+using Win_in.Sfs.Shared.Domain.Shared;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public class InjectionNoteDetail : 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/InjectionNotes/InjectionNoteManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNoteManager.cs
new file mode 100644
index 000000000..c75194264
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNoteManager.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 InjectionNoteManager : SfsStoreManagerBase, IInjectionNoteManager
+{
+
+ public InjectionNoteManager(
+ IInjectionNoteRepository 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(InjectionNote entity)
+ {
+ try
+ {
+ await LocalEventBus.PublishAsync(new SfsConfirmedEntityEventData(entity), false).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ Logger.LogDebug($"{nameof(InjectionNote)} Confirmed Event:{ex.Message}", null);
+ Console.WriteLine(ex.Source);
+ throw;
+ }
+ }
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/IInjectionRequestManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/IInjectionRequestManager.cs
new file mode 100644
index 000000000..bf4efb85c
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/IInjectionRequestManager.cs
@@ -0,0 +1,16 @@
+using System.Threading.Tasks;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+using Win_in.Sfs.Shared.Domain;
+
+public interface IInjectionRequestManager : ISfsStoreRequestManager,
+ IBulkImportService
+{
+
+ Task UpdateDetailsAsync(InjectionRequest entity);
+
+ Task CompleteAsync(string number);
+
+ Task CreateBynNumberAsync(InjectionRequest entity);
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/IInjectionRequestRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/IInjectionRequestRepository.cs
new file mode 100644
index 000000000..ce92572ec
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/IInjectionRequestRepository.cs
@@ -0,0 +1,9 @@
+using Win_in.Sfs.Shared.Domain;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+public interface IInjectionRequestRepository : ISfsStoreRepositoryBase,
+ ISfsBulkRepositoryBase
+{
+
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequest.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequest.cs
new file mode 100644
index 000000000..c6058c8ae
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequest.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using Win_in.Sfs.Shared.Domain.Entities;
+
+namespace Win_in.Sfs.Wms.Store.Domain;
+
+///
+/// 注塑申请
+///
+public class InjectionRequest : SfsStoreRequestAggregateRootBase
+{
+ ///
+ /// 叫料类型
+ ///
+ [Display(Name = "叫料类型")]
+ [IgnoreUpdate]
+ public string Type { get; set; }
+
+ ///
+ /// 备料计划单号
+ ///
+ [IgnoreUpdate]
+ public string PreparationPlanNumber { get; set; }
+
+ ///
+ /// 生产线
+ ///
+ [IgnoreUpdate]
+ public string ProdLine { get; set; }
+
+ ///
+ /// 车间
+ ///
+ [IgnoreUpdate]
+ public string Workshop { 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/InjectionRequests/InjectionRequestDetail.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequestDetail.cs
new file mode 100644
index 000000000..7fab50d6e
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequestDetail.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 InjectionRequestDetail : 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/InjectionRequests/InjectionRequestManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequestManager.cs
new file mode 100644
index 000000000..53b2f4cee
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequestManager.cs
@@ -0,0 +1,141 @@
+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 InjectionRequestManager
+ : SfsStoreRequestManagerBase
+ , IInjectionRequestManager
+{
+ private readonly IInjectionRequestRepository _repository;
+ private readonly IIssueJobRepository _issueJobRepository;
+
+ public InjectionRequestManager(
+ IInjectionRequestRepository repository
+ , IIssueJobRepository issueJobRepository
+ ) : base(repository)
+ {
+ _repository = repository;
+ _issueJobRepository = issueJobRepository;
+ }
+
+ ///
+ /// 创建
+ ///
+ ///
+ ///
+ public virtual async Task CreateBynNumberAsync(InjectionRequest entity)
+ {
+ var number = string.IsNullOrEmpty(entity.Number) ? await GenerateNumberAsync(nameof(InjectionRequest), 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(InjectionRequest 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 SetMaterialRequestStatus(oldEntity).ConfigureAwait(false);
+
+ await Repository.UpdateAsync(oldEntity).ConfigureAwait(false);
+ }
+
+ }
+
+ private void SetMaterialRequestDetailStatus(InjectionRequestDetail detail)
+ {
+ if (detail.ReceivedQty >= detail.Qty)//执行的时候 实际收料 多余 要料数
+ {
+ detail.Status = EnumStatus.Close;
+ }
+ else
+ {
+ detail.Status = EnumStatus.Open;
+ }
+ }
+
+ private async Task SetMaterialRequestStatus(InjectionRequest 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.EntityFrameworkCore/IStoreDbContext.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/IStoreDbContext.cs
index 6ce3b9881..3e88393d3 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
@@ -18,6 +18,7 @@ public interface IStoreDbContext : IEfCoreDbContext
public DbSet TransferRequests { get; }
public DbSet ProductReceiptRequests { get; }
public DbSet MaterialRequests { get; }
+ public DbSet InjectionRequests { get; }
public DbSet ContainerRequests { get; }
public DbSet DeliverRequests { get; }
public DbSet InspectRequests { get; }
@@ -69,6 +70,7 @@ public interface IStoreDbContext : IEfCoreDbContext
public DbSet InventoryTransferNotes { get; }
public DbSet WarehouseTransferNotes { get; }
public DbSet IssueNotes { get; }
+ public DbSet InjectionNotes { get; }
public DbSet ContainerNotes { get; }
public DbSet UnplannedReceiptNotes { get; }
public DbSet UnplannedIssueNotes { get; }
@@ -94,6 +96,7 @@ public interface IStoreDbContext : IEfCoreDbContext
public DbSet InspectJobs { get; }
public DbSet PutawayJobs { get; }
public DbSet IssueJobs { get; }
+ public DbSet InjectionJobs { 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/InjectionJobs/InjectionJobDbContextModelCreatingExtensions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/InjectionJobs/InjectionJobDbContextModelCreatingExtensions.cs
new file mode 100644
index 000000000..49690e16a
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/InjectionJobs/InjectionJobDbContextModelCreatingExtensions.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 InjectionJobDbContextModelCreatingExtensions
+{
+ public static void ConfigureInjectionJob(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options)
+ {
+ builder.Entity(b =>
+ {
+ //Configure table & schema name
+ b.ToTable(StoreDbProperties.JobDbTablePrefix + nameof(InjectionJob), 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.InjectionRequestNumber).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(InjectionJobDetail), 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/InjectionJobs/InjectionJobEfCoreRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/InjectionJobs/InjectionJobEfCoreRepository.cs
new file mode 100644
index 000000000..3f08eb44e
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/InjectionJobs/InjectionJobEfCoreRepository.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 InjectionJobEfCoreRepository : SfsJobEfCoreRepositoryBase, IInjectionJobRepository
+{
+ public InjectionJobEfCoreRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider)
+ {
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/InjectionNotes/InjectionNoteDbContextModelCreatingExtensions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/InjectionNotes/InjectionNoteDbContextModelCreatingExtensions.cs
new file mode 100644
index 000000000..debf08f37
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/InjectionNotes/InjectionNoteDbContextModelCreatingExtensions.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 InjectionNoteDbContextModelCreatingExtensions
+{
+ public static void ConfigureInjectionNote(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options)
+ {
+ builder.Entity(b =>
+ {
+ //Configure table & schema name
+ b.ToTable(options.TablePrefix + nameof(InjectionNote), 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(InjectionNoteDetail), 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/InjectionNotes/InjectionNoteEfCoreRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/InjectionNotes/InjectionNoteEfCoreRepository.cs
new file mode 100644
index 000000000..26e8dc61c
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/InjectionNotes/InjectionNoteEfCoreRepository.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 InjectionNoteEfCoreRepository : SfsStoreEfCoreRepositoryBase, IInjectionNoteRepository
+{
+ public InjectionNoteEfCoreRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider)
+ {
+ }
+}
diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/InjectionRequests/InjectionRequestDbContextModelCreatingExtensions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/InjectionRequests/InjectionRequestDbContextModelCreatingExtensions.cs
new file mode 100644
index 000000000..f34683a95
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/InjectionRequests/InjectionRequestDbContextModelCreatingExtensions.cs
@@ -0,0 +1,67 @@
+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 InjectionRequestDbContextModelCreatingExtensions
+{
+ public static void ConfigureInjectionRequest(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options)
+ {
+ builder.Entity(b =>
+ {
+ //Configure table & schema name
+ b.ToTable(options.TablePrefix + nameof(InjectionRequest), 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.PreparationPlanNumber).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength);
+ b.Property(q => q.Workshop).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(InjectionRequestDetail), 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/InjectionRequests/InjectionRequestEfCoreRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/InjectionRequests/InjectionRequestEfCoreRepository.cs
new file mode 100644
index 000000000..7b5e20a16
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/InjectionRequests/InjectionRequestEfCoreRepository.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 InjectionRequestEfCoreRepository : SfsStoreEfCoreRepositoryBase, IInjectionRequestRepository
+{
+ public InjectionRequestEfCoreRepository(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 d33e47fe6..667258241 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
@@ -18,6 +18,7 @@ public class StoreDbContext : AbpDbContext, IStoreDbContext
public DbSet TransferRequests { get; set; }
public DbSet ProductReceiptRequests { get; set; }
public DbSet MaterialRequests { get; set; }
+ public DbSet InjectionRequests { get; set; }
public DbSet ContainerRequests { get; set; }
public DbSet DeliverRequests { get; set; }
public DbSet InspectRequests { get; set; }
@@ -69,6 +70,7 @@ public class StoreDbContext : AbpDbContext, IStoreDbContext
public DbSet InventoryTransferNotes { get; set; }
public DbSet WarehouseTransferNotes { get; set; }
public DbSet IssueNotes { get; set; }
+ public DbSet InjectionNotes { get; set; }
public DbSet ContainerNotes { get; set; }
public DbSet UnplannedReceiptNotes { get; set; }
public DbSet UnplannedIssueNotes { get; set; }
@@ -94,6 +96,7 @@ public class StoreDbContext : AbpDbContext, IStoreDbContext
public DbSet InspectJobs { get; set; }
public DbSet PutawayJobs { get; set; }
public DbSet IssueJobs { get; set; }
+ public DbSet InjectionJobs { 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 a325299a5..54acd711b 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
@@ -54,6 +54,7 @@ public static class StoreDbContextModelCreatingExtensions
builder.ConfigureProductReceiptRequest(options);
builder.ConfigurePurchaseReceiptRequest(options);
builder.ConfigureMaterialRequest(options);
+ builder.ConfigureInjectionRequest(options);
builder.ConfigureDeliverRequest(options);
builder.ConfigureContainerRequest(options);
builder.ConfigureInspectRequest(options);
@@ -87,6 +88,7 @@ public static class StoreDbContextModelCreatingExtensions
builder.ConfigureInventoryTransferNote(options);
builder.ConfigureWarehouseTransferNote(options);
builder.ConfigureIssueNote(options);
+ builder.ConfigureInjectionNote(options);
builder.ConfigureContainerNote(options);
builder.ConfigureUnplannedReceiptNote(options);
builder.ConfigureUnplannedIssueNote(options);
@@ -113,6 +115,7 @@ public static class StoreDbContextModelCreatingExtensions
builder.ConfigureInspectJob(options);
builder.ConfigurePutawayJob(options);
builder.ConfigureIssueJob(options);
+ builder.ConfigureInjectionJob(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 24dc4c2c4..d9d854595 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
@@ -54,6 +54,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();
@@ -88,6 +89,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();
@@ -114,6 +116,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();
@@ -174,6 +177,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 =>
@@ -222,6 +227,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 =>
@@ -293,6 +300,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/InjectionJobAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/InjectionJobAutoMapperProfile.cs
new file mode 100644
index 000000000..4665215e3
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/InjectionJobAutoMapperProfile.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 InjectionJobAutoMapperProfile()
+ {
+
+ CreateMap()
+ .ForMember(x => x.JobNumber, y => y.MapFrom(d => d.Number))
+ .ForMember(x => x.RequestNumber, y => y.MapFrom(d => d.InjectionRequestNumber))
+ .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.InjectionRequestNumber))
+ .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/Requests/InjectionRequestAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/InjectionRequestAutoMapperProfile.cs
new file mode 100644
index 000000000..2d2aef453
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/InjectionRequestAutoMapperProfile.cs
@@ -0,0 +1,134 @@
+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 InjectionRequestAutoMapperProfile()
+ {
+ CreateMap()
+ .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.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/Jobs/InjectionJobEventHandler.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/InjectionJobEventHandler.cs
new file mode 100644
index 000000000..9499c8fa1
--- /dev/null
+++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/InjectionJobEventHandler.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 InjectionJobEventHandler :
+ StoreEventHandlerBase
+ , ILocalEventHandler>
+{
+ private const EnumTransType TransType = EnumTransType.Issue;
+
+ private readonly IInjectionNoteAppService _injectionNoteAppService;
+ private readonly ILocationAppService _locationAppService;
+
+ public InjectionJobEventHandler(IInjectionNoteAppService injectionNoteAppService, ILocationAppService locationAppService)
+ {
+ _injectionNoteAppService = injectionNoteAppService;
+ _locationAppService = locationAppService;
+ }
+
+ ///
+ /// 执行后
+ ///
+ ///
+ ///
+ [UnitOfWork]
+ public virtual async Task HandleEventAsync(SfsCompletedEntityEventData eventData)
+ {
+ var entity = eventData.Entity;
+ var injectionNote = await BuildInjectionNoteAsync(entity).ConfigureAwait(false);
+ await _injectionNoteAppService.CreateAsync(injectionNote).ConfigureAwait(false);
+ }
+
+ #region 私有
+
+ ///
+ /// 创建补料记录实体
+ ///
+ ///
+ ///
+ private async Task BuildInjectionNoteAsync(InjectionJob entity)
+ {
+ var injectionNoteCreateInput = ObjectMapper.Map(entity);
+ injectionNoteCreateInput.JobNumber = entity.Number;
+ var locationCodes = injectionNoteCreateInput.Details.Select(p => p.ToLocationCode).Distinct().ToList();
+ var locations = await _locationAppService.GetByCodesAsync(locationCodes).ConfigureAwait(false);
+
+ injectionNoteCreateInput.Details.RemoveAll(p => p.Qty == 0);
+
+ foreach (var detail in injectionNoteCreateInput.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 injectionNoteCreateInput;
+ }
+
+ ///