diff --git a/.vs/WZC2/v17/.wsuo b/.vs/WZC2/v17/.wsuo new file mode 100644 index 000000000..1bda40505 Binary files /dev/null and b/.vs/WZC2/v17/.wsuo differ diff --git a/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/Equipments/EquipmentLocAppService.cs b/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/Equipments/EquipmentLocAppService.cs index 14ad08e9e..19258aa20 100644 --- a/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/Equipments/EquipmentLocAppService.cs +++ b/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/Equipments/EquipmentLocAppService.cs @@ -106,8 +106,8 @@ public class EquipmentLocAppService protected override async Task ValidateImportModelAsync(EquipmentLocImportInput importInput, List validationRresult) { await base.CheckItemBasicItemCodeAsync(importInput.Code, validationRresult).ConfigureAwait(false); - await base.CheckRawLocationAsync(importInput.LocCode, validationRresult).ConfigureAwait(false); - //await base.CheckComponentAndComponentQtyAsync(importInput.Component, importInput.ComponentQty, validationRresult).ConfigureAwait(false); + await base.CheckProductLocationAsync(importInput.LocCode, validationRresult).ConfigureAwait(false); + } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/CoatingIssueJobPermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/CoatingIssueJobPermissions.cs new file mode 100644 index 000000000..ec3ed439d --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/CoatingIssueJobPermissions.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 CoatingIssueJobPermissions +{ + + public const string Default = StorePermissions.GroupName + "." + nameof(IssueJob); + public const string Create = Default + "." + StorePermissions.CreateStr; + public const string Update = Default + "." + StorePermissions.UpdateStr; + public const string Delete = Default + "." + StorePermissions.DeleteStr; + + //自动发料任务 + public const string AutoIssueJob = StorePermissions.GroupName + "." + nameof(AutoIssueJob); + + public static void AddCoatingIssueJobPermission(this PermissionGroupDefinition permissionGroup) + { + var IssueJobPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(IssueJob))); + IssueJobPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr)); + IssueJobPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr)); + IssueJobPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr)); + + permissionGroup.AddPermission(AutoIssueJob, StorePermissionDefinitionProvider.L(nameof(AutoIssueJob))); + + } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/DTOs/CoatingIssueJobDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/DTOs/CoatingIssueJobDTO.cs new file mode 100644 index 000000000..33145f1f5 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/DTOs/CoatingIssueJobDTO.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 CoatingIssueJobDTO : 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 MaterialRequestNumber { get; set; } + + /// + /// 车间 + /// + [Display(Name = "车间")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string Workshop { get; set; } + + /// + /// 使用在途库 + /// + [Display(Name = "使用在途库")] + public bool UseOnTheWayLocation { get; set; } + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/DTOs/CoatingIssueJobDetailDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/DTOs/CoatingIssueJobDetailDTO.cs new file mode 100644 index 000000000..f47cb7456 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/DTOs/CoatingIssueJobDetailDTO.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 CoatingIssueJobDetailDTO : SfsJobRecommendFromDetailDTOBase, IHasToLocation +{ + + /// + /// 请求库位 + /// + [Display(Name = "请求库位")] + public string RequestLocationCode { get; set; } + + /// + /// 到库位 + /// + [Display(Name = "到库位")] + public string ToLocationCode { get; set; } + + /// + /// 到库区 + /// + [Display(Name = "到库区")] + public string ToLocationArea { get; set; } + + /// + /// 到库位组 + /// + [Display(Name = "到库位组")] + public string ToLocationGroup { get; set; } + + /// + /// 到ERP库位 + /// + [Display(Name = "到ERP库位")] + public string ToLocationErpCode { get; set; } + + /// + /// 到仓库 + /// + [Display(Name = "到仓库")] + public string ToWarehouseCode { get; set; } + + /// + /// 在途库库位 + /// + [Display(Name = "在途库库位")] + public string OnTheWayLocationCode { get; set; } + + /// + /// 生产线 + /// + [Display(Name = "生产线")] + public string ProdLine { get; set; } + + /// + /// 工作中心 + /// + [Display(Name = "工作中心")] + public string WorkStation { get; set; } + + /// + /// 过期时间 + /// + [Display(Name = "过期时间")] + public DateTime ExpiredTime { get; set; } + + /// + /// 工序 + /// + [Display(Name = "工序")] + public string Operation { get; set; } + + /// + /// 配送方式 + /// + [Display(Name = "配送方式")] + public EnumDistributionType DistributionType { get; set; } + + /// + /// 取整方式 + /// + [Display(Name = "取整方式")] + public EnumTruncType TruncType { get; set; } + + /// + /// 取整后数量 + /// + [Display(Name = "取整后数量")] + public decimal RoundedQty { get; set; } + + /// + /// 计划拆分规则 + /// + [Display(Name = "计划拆分规则")] + public EnumPlannedSplitRule PlannedSplitRule { get; set; } + + /// + /// 计划开始时间 + /// + [Display(Name = "计划开始时间")] + public DateTime PlanBeginTime { get; set; } + + /// + /// 每次配送数量 + /// + [Display(Name = "每次配送数量")] + public decimal DeliveryQty { get; set; } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/ICoatingIssueJobAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/ICoatingIssueJobAppService.cs new file mode 100644 index 000000000..40458cb1d --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/ICoatingIssueJobAppService.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 ICoatingIssueJobAppService + : ISfsJobAppServiceBase +{ + Task> CheckJobExistByItemCodeAndLocationCode(string itemCode, string locationCode); + + Task CancelByMaterialRequestAsync(string materialNumber); + + Task> GetListByTypeAsync(SfsJobRequestInputBase requestInput, string requestType, + bool includeDetails = false, CancellationToken cancellationToken = default); + + Task> GetByRequestNumberAsync(string requestNumber); + + /// + /// 保存拆箱时涉及的明细修改 + /// + /// + Task SaveDetail_SplitPackingAsync(SplitPacking_UpdateJobDetailInput input); + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/Inputs/CoatingIssueJobCheckInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/Inputs/CoatingIssueJobCheckInput.cs new file mode 100644 index 000000000..1cb969449 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/Inputs/CoatingIssueJobCheckInput.cs @@ -0,0 +1,6 @@ +namespace Win_in.Sfs.Wms.Store.Application.Contracts; + +public class CoatingIssueJobCheckInput : SfsJobCheckInputBase +{ + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/Inputs/CoatingIssueJobDetailInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/Inputs/CoatingIssueJobDetailInput.cs new file mode 100644 index 000000000..009e67d4a --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/Inputs/CoatingIssueJobDetailInput.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 CoatingIssueJobDetailInput : SfsJobRecommendFromDetailInputBase, IHasToLocation +{ + + /// + /// 请求库位 + /// + [Display(Name = "请求库位")] + [Required(ErrorMessage = "{0}是必填项")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string RequestLocationCode { get; set; } + + /// + /// 到库位 + /// + [Display(Name = "到库位")] + [Required(ErrorMessage = "{0}是必填项")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string ToLocationCode { get; set; } + + /// + /// 到库区 + /// + [Display(Name = "到库区")] + public string ToLocationArea { get; set; } + + /// + /// 到库位组 + /// + [Display(Name = "到库位组")] + public string ToLocationGroup { get; set; } + + /// + /// 到ERP库位 + /// + [Display(Name = "到ERP库位")] + [Required(ErrorMessage = "{0}是必填项")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string ToLocationErpCode { get; set; } + + /// + /// 到仓库 + /// + [Display(Name = "到仓库")] + [Required(ErrorMessage = "{0}是必填项")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string ToWarehouseCode { get; set; } + + /// + /// 在途库库位 + /// + [Display(Name = "在途库库位")] + public string OnTheWayLocationCode { get; set; } + + /// + /// 生产线 + /// + [Display(Name = "生产线")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string ProdLine { get; set; } + + /// + /// 工作中心 + /// + [Display(Name = "工作中心")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string WorkStation { get; set; } + + /// + /// 过期时间 + /// + [Display(Name = "过期时间")] + [Required(ErrorMessage = "{0}是必填项")] + public DateTime ExpiredTime { get; set; } + + /// + /// 工序 + /// + [Display(Name = "工序")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string Operation { get; set; } + + /// + /// 配送方式 + /// + [Display(Name = "配送方式")] + public EnumDistributionType DistributionType { get; set; } + + /// + /// 取整方式 + /// + [Display(Name = "取整方式")] + public EnumTruncType TruncType { get; set; } + + /// + /// 取整后数量 + /// + [Display(Name = "取整后数量")] + public decimal RoundedQty { get; set; } + + /// + /// 计划拆分规则 + /// + [Display(Name = "计划拆分规则")] + public EnumPlannedSplitRule PlannedSplitRule { get; set; } + + /// + /// 计划开始时间 + /// + [Display(Name = "计划开始时间")] + public DateTime PlanBeginTime { get; set; } + + /// + /// 每次配送数量 + /// + [Display(Name = "每次配送数量")] + public decimal DeliveryQty { get; set; } + + /// + /// 位置码 + /// + public string PositionCode { get; set; } + + /// + /// 推荐类型 + /// + public EnumRecommendType RecommendType { get; set; } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/Inputs/CoatingIssueJobEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/Inputs/CoatingIssueJobEditInput.cs new file mode 100644 index 000000000..c1d1eb848 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/Inputs/CoatingIssueJobEditInput.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 CoatingIssueJobEditInput : 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 MaterialRequestNumber { get; set; } + + /// + /// 叫料请求类型 + /// + [Display(Name = "叫料请求类型")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string RequestType { get; set; } + + /// + /// 任务类型 + /// + [Display(Name = "任务类型")] + [Required(ErrorMessage = "{0}是必填项")] + public EnumJobType JobType { get; set; } + + /// + /// 是否自动完成 + /// + [Display(Name = "是否自动完成")] + [Required(ErrorMessage = "{0}是必填项")] + public bool IsAutoComplete { get; set; } + + /// + /// 过期时间 + /// + [Display(Name = "过期时间")] + [Required(ErrorMessage = "{0}是必填项")] + public DateTime ExpiredTime { get; set; } + + /// + /// 任务明细 + /// + [Display(Name = "任务明细")] + [Required(ErrorMessage = "{0}是必填项")] + public List Details { get; set; } = new(); + + /// + /// 车间 + /// + [Display(Name = "车间")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string Workshop { get; set; } + + /// + /// 生产线 + /// + [Display(Name = "生产线")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string ProdLine { get; set; } + + /// + /// 使用在途库 + /// + [Display(Name = "使用在途库")] + public bool UseOnTheWayLocation { get; set; } + #endregion +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/CoatingIssueNotePermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/CoatingIssueNotePermissions.cs new file mode 100644 index 000000000..351086e58 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/CoatingIssueNotePermissions.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 CoatingIssueNotePermissions +{ + + public const string Default = StorePermissions.GroupName + "." + nameof(IssueNote); + public const string Create = Default + "." + StorePermissions.CreateStr; + public const string Update = Default + "." + StorePermissions.UpdateStr; + public const string Delete = Default + "." + StorePermissions.DeleteStr; + + //自动发料记录 + public const string AutoIssueNote = StorePermissions.GroupName + "." + nameof(AutoIssueNote); + + //直接发料 + public const string DirectIssueNote = StorePermissions.GroupName + "." + nameof(DirectIssueNote); + + public static void AddCoatingIssueNotePermission(this PermissionGroupDefinition permissionGroup) + { + var issueNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(IssueNote))); + issueNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr)); + issueNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr)); + issueNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr)); + + permissionGroup.AddPermission(AutoIssueNote, StorePermissionDefinitionProvider.L(nameof(AutoIssueNote))); + permissionGroup.AddPermission(DirectIssueNote, StorePermissionDefinitionProvider.L(nameof(DirectIssueNote))); + } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/DTOs/CoatingIssueNoteDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/DTOs/CoatingIssueNoteDTO.cs new file mode 100644 index 000000000..0480fc7d4 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/DTOs/CoatingIssueNoteDTO.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 CoatingIssueNoteDTO : SfsStoreDTOBase, IHasJobNumber, IHasRequestNumber +{ + + /// + /// 任务ID + /// + [Display(Name = "任务ID")] + public string JobNumber { get; set; } + + /// + /// 车间 + /// + [Display(Name = "车间")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string Workshop { get; set; } + + /// + /// 请求代码 + /// + [Display(Name = "请求代码")] + public string RequestNumber { get; set; } + + /// + /// 叫料请求类型 + /// + [Display(Name = "叫料请求类型")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string RequestType { get; set; } + + /// + /// 使用在途库 + /// + [Display(Name = "使用在途库")] + public bool UseOnTheWayLocation { get; set; } + + /// + /// 已确认 + /// + [Display(Name = "已确认")] + public bool Confirmed { get; set; } + + /// + /// 确认时间 + /// + [Display(Name = "确认时间")] + public DateTime? ConfirmTime { get; set; } + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/DTOs/CoatingIssueNoteDetailDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/DTOs/CoatingIssueNoteDetailDTO.cs new file mode 100644 index 000000000..045b5997a --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/DTOs/CoatingIssueNoteDetailDTO.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 CoatingIssueNoteDetailDTO : SfsStoreRecommendFromDetailWithFromToDTOBase +{ + + /// + /// 发料时间 + /// + [Display(Name = "发料时间")] + public DateTime IssueTime { get; set; } + + /// + /// 过期时间 + /// + [Display(Name = "过期时间")] + public DateTime ExpiredTime { get; set; } + + /// + /// 生产线 + /// + [Display(Name = "生产线")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string ProdLine { get; set; } + + /// + /// 工作中心 + /// + [Display(Name = "工作中心")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string WorkStation { get; set; } + + /// + /// 在途库库位 + /// + [Display(Name = "在途库库位")] + public string OnTheWayLocationCode { get; set; } + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/ICoatingIssueNoteAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/ICoatingIssueNoteAppService.cs new file mode 100644 index 000000000..56cbe9ea4 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/ICoatingIssueNoteAppService.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 ICoatingIssueNoteAppService : ISfsStoreMasterReadOnlyAppServiceBase +{ + Task CreateAsync(CoatingIssueNoteEditInput input); + + Task ConfirmAsync(Guid id); + + Task ConfirmAsync(string number); + + Task> GetListByTypeAsync(SfsStoreRequestInputBase requestInput, + string requestType, bool includeDetails = false, CancellationToken cancellationToken = default); + + Task> GetListUnConfirmedByTypeAsync(string requestType); +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/Inputs/CoatingIssueNoteDetailInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/Inputs/CoatingIssueNoteDetailInput.cs new file mode 100644 index 000000000..a3da25c2b --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/Inputs/CoatingIssueNoteDetailInput.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 CoatingIssueNoteDetailInput : SfsStoreRecommendFromDetailWithFromToInputBase +{ + + /// + /// 发料时间 + /// + [Display(Name = "发料时间")] + public DateTime IssueTime { get; set; } + + /// + /// 过期时间 + /// + [Display(Name = "过期时间")] + public DateTime ExpiredTime { get; set; } + + /// + /// 生产线 + /// + [Display(Name = "生产线")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string ProdLine { get; set; } + + /// + /// 工作中心 + /// + [Display(Name = "工作中心")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string WorkStation { get; set; } + + /// + /// 在途库库位 + /// + [Display(Name = "在途库库位")] + public string OnTheWayLocationCode { get; set; } + + /// + /// 位置码 + /// + public string PositionCode { get; set; } + + /// + /// 推荐类型 + /// + public EnumRecommendType RecommendType { get; set; } + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/Inputs/CoatingIssueNoteEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/Inputs/CoatingIssueNoteEditInput.cs new file mode 100644 index 000000000..989e7071e --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/Inputs/CoatingIssueNoteEditInput.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 CoatingIssueNoteEditInput : SfsStoreCreateOrUpdateInputBase +{ + #region Base + /// + /// 已确认 + /// + [Display(Name = "已确认")] + public bool Confirmed { get; set; } + #endregion + + #region Create + /// + /// 发料记录号 + /// + [Display(Name = "发料记录号")] + public string Number { get; set; } + + /// + /// 任务ID + /// + [Display(Name = "任务ID")] + [Required(ErrorMessage = "{0}是必填项")] + public string JobNumber { get; set; } + + /// + /// 车间 + /// + [Display(Name = "车间")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string Workshop { get; set; } + + /// + /// 明细列表 + /// + [Display(Name = "明细列表")] + public List Details { get; set; } + + /// + /// 请求号码 + /// + [Display(Name = "请求号码")] + public string RequestNumber { get; set; } + + /// + /// 叫料请求类型 + /// + [Display(Name = "叫料请求类型")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string RequestType { get; set; } + + /// + /// 使用在途库 + /// + [Display(Name = "使用在途库")] + public bool UseOnTheWayLocation { get; set; } + #endregion +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/Inputs/CoatingIssueNoteImportInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/Inputs/CoatingIssueNoteImportInput.cs new file mode 100644 index 000000000..3b53d09fd --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/Inputs/CoatingIssueNoteImportInput.cs @@ -0,0 +1,33 @@ +using System.ComponentModel.DataAnnotations; + +namespace Win_in.Sfs.Wms.Store.Application.Contracts; + +public class CoatingIssueNoteImportInput : 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/Requests/MaterialRequests/CoatingMaterialRequestPermissions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/CoatingMaterialRequestPermissions.cs new file mode 100644 index 000000000..7a7636aea --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/CoatingMaterialRequestPermissions.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 CoatingMaterialRequestPermissions +{ + + public const string Default = StorePermissions.GroupName + "." + nameof(CoatingMaterialRequest); + public const string Create = Default + "." + StorePermissions.CreateStr; + public const string Update = Default + "." + StorePermissions.UpdateStr; + public const string Delete = Default + "." + StorePermissions.DeleteStr; + + //自动叫料申请 + public const string AutoMaterialRequest = StorePermissions.GroupName + "." + nameof(AutoMaterialRequest); + + public static void AddCoatingMaterialRequestPermission(this PermissionGroupDefinition permissionGroup) + { + var MaterialRequestPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(CoatingMaterialRequest))); + MaterialRequestPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr)); + MaterialRequestPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr)); + MaterialRequestPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr)); + + permissionGroup.AddPermission(AutoMaterialRequest, StorePermissionDefinitionProvider.L(nameof(AutoMaterialRequest))); + + } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/DTOs/CoatingMaterialRequestDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/DTOs/CoatingMaterialRequestDTO.cs new file mode 100644 index 000000000..3b67a8df8 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/DTOs/CoatingMaterialRequestDTO.cs @@ -0,0 +1,37 @@ +using System.ComponentModel.DataAnnotations; + +namespace Win_in.Sfs.Wms.Store.Application.Contracts; + +public class CoatingMaterialRequestDTO : 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/MaterialRequests/DTOs/CoatingMaterialRequestDetailDTO.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/DTOs/CoatingMaterialRequestDetailDTO.cs new file mode 100644 index 000000000..bb3b5575c --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/DTOs/CoatingMaterialRequestDetailDTO.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 CoatingMaterialRequestDetailDTO : 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/MaterialRequests/ICoatingMaterialRequestAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/ICoatingMaterialRequestAppService.cs new file mode 100644 index 000000000..3f93ff247 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/ICoatingMaterialRequestAppService.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 ICoatingMaterialRequestAppService + : ISfsStoreRequestMasterAppServiceBase + +{ + Task CreateAndHandleAsync(CoatingMaterialRequestEditInput input); + + /// + /// 根据备料计划生成 叫料请求 + /// + /// + Task CreateAndHandleByPreparationPlan(string productionPlanNumber); + + Task CreateAndHandleByAPIAsync(CoatingMaterialRequestEditInput 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/MaterialRequests/Inputs/CoatingMaterialRequestDetailInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/Inputs/CoatingMaterialRequestDetailInput.cs new file mode 100644 index 000000000..5ce294045 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/Inputs/CoatingMaterialRequestDetailInput.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 CoatingMaterialRequestDetailInput : SfsStoreDetailWithQtyInputBase +{ + /// + /// 目标库位 + /// + [Display(Name = "目标库位")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string ToLocationCode { get; set; } + + /// + /// 来源库区 + /// + [Display(Name = "来源库区")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string FromLocationArea { get; set; } + + /// + /// 生产线 + /// + [Display(Name = "生产线")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string ProdLine { get; set; } + + /// + /// 工作中心 + /// + [Display(Name = "工作中心")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string WorkStation { get; set; } + + /// + /// 过期时间 + /// + [Display(Name = "过期时间")] + public DateTime ExpiredTime { get; set; } + + /// + /// 状态 + /// + [Display(Name = "状态")] + public EnumRequestStatus RequestStatus { get; set; } = EnumRequestStatus.New; + + /// + /// ERP储位 + /// + [Display(Name = "ERP储位")] + public string ToLocationErpCode { get; set; } + + /// + /// 已发数量 + /// + [Display(Name = "已发数量")] + public decimal IssuedQty { get; set; } + + /// + /// 已收数量 + /// + [Display(Name = "已收数量")] + public decimal ReceivedQty { get; set; } + + /// + /// 明细状态 + /// + [Display(Name = "明细状态")] + public EnumStatus Status { get; set; } + + /// + /// 位置码 + /// + public string PositionCode { get; set; } + + /// + /// 推荐类型 + /// + public EnumRecommendType RecommendType { get; set; } + + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/Inputs/CoatingMaterialRequestEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/Inputs/CoatingMaterialRequestEditInput.cs new file mode 100644 index 000000000..381e205a0 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/Inputs/CoatingMaterialRequestEditInput.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 CoatingMaterialRequestEditInput : SfsStoreRequestCreateOrUpdateInputBase +{ + #region Base + /// + /// 车间 + /// + [Display(Name = "车间")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string Workshop { get; set; } + + /// + /// 生产线 + /// + [Display(Name = "生产线")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string ProdLine { get; set; } + + /// + /// 使用在途库 + /// + [Display(Name = "使用在途库")] + public bool UseOnTheWayLocation { get; set; } + #endregion + + #region Create + /// + /// 要货单号 + /// + [Display(Name = "要货单号")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string Number { get; set; } + + /// + /// 叫料类型 + /// + [Display(Name = "叫料类型")] + public string Type { get; set; } + + /// + /// 备料计划单号 + /// + [Display(Name = "备料计划单号")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string PreparationPlanNumber { get; set; } + + /// + /// 明细列表 + /// + [Display(Name = "明细列表")] + public List Details { get; set; } = new List(); + #endregion +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/Inputs/CoatingMaterialRequestImportInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/Inputs/CoatingMaterialRequestImportInput.cs new file mode 100644 index 000000000..2aef0516c --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/MaterialRequests/Inputs/CoatingMaterialRequestImportInput.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 CoatingMaterialRequestImportInput : SfsStoreImportInputBase +{ + /// + /// 叫料类型 + /// + [Display(Name = "叫料类型")] + [Required(ErrorMessage = "{0}是必填项")] + [ImporterHeader(Name = "叫料类型")] + [ExporterHeader(DisplayName = "叫料类型")] + [ValueMapping("人工拉动", EnumMaterialRequestType.Issue_Manual)] + public string Type { get; set; } + + /// + /// 物品代码 + /// + [Display(Name = "物品代码")] + [Required] + public string ItemCode { get; set; } + + /// + /// 目标库位 + /// + [Display(Name = "目标库位")] + [Required] + public string ToLocationCode { get; set; } + + /// + /// 来源库区 + /// + [Display(Name = "调出库区")] + [Required] + public string FromLocationArea { get; set; } + + /// + /// 数量 + /// + [Display(Name = "数量")] + [Required(ErrorMessage = "{0}是必填项")] + public decimal Qty { get; set; } + + /// + /// 备注 + /// + [Display(Name = "备注")] + public string Remark { get; set; } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/CoatingIssueJobAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/CoatingIssueJobAppService.cs new file mode 100644 index 000000000..46d9f488e --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/CoatingIssueJobAppService.cs @@ -0,0 +1,280 @@ +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}coatingissue-job")] + +public class CoatingIssueJobAppService + : SfsJobAppServiceBase, + ICoatingIssueJobAppService +{ + private readonly ICoatingIssueJobManager _CoatingIssueJobManager; + + public CoatingIssueJobAppService( + ICoatingIssueJobRepository repository, ICoatingIssueJobManager CoatingIssueJobManager + ) : base(repository, CoatingIssueJobManager) + { + _CoatingIssueJobManager = CoatingIssueJobManager; + } + + /// + /// 根据物品和库位 检查是否存在发料任务 + /// + /// + /// + /// + /// + [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/{materialNumber}")] + public virtual async Task CancelByMaterialRequestAsync(string materialNumber) + { + var entities = await _repository.GetListAsync(p => p.MaterialRequestNumber == materialNumber).ConfigureAwait(false); + foreach (var entity in entities) + { + await _CoatingIssueJobManager.CancelAsync(entity).ConfigureAwait(false); + } + } + + //[Authorize(CoatingIssueJobPermissions.Delete)] + //[HttpDelete("details/{id}")] + //public virtual async Task DeleteDetailAsync(Guid id, Guid detailId) + //{ + // var entity = await _repository.GetAsync(id); + // Check.NotNull(entity, EntityClassName); + + // var input = new CoatingIssueJobCheckInput + // { + // JobStatuses = new List() { EnumJobStatus.Pending, EnumJobStatus.Open }, + // }; + // var result = new AbpValidationResult(); + + // var detail = entity.GetDetail(detailId); + + // _CoatingIssueJobManager.CheckJobStatus(entity, input.JobStatuses, result); + // if (result.Errors.Any()) + // { + // throw new AbpValidationException("任务状态错误,不能进行删除明细操作"); + // } + // entity.RemoveDetail(detailId); + //} + + //[Authorize(CoatingIssueJobPermissions.Delete)] + [HttpPost("invalid")] + public override async Task CancelAsync(Guid id) + { + var CoatingIssueJob = await _repository.GetAsync(id).ConfigureAwait(false); + if (CoatingIssueJob == null) + { + throw new UserFriendlyException($"未找到ID为 {id} 的任务"); + } + + /* + var listLocationCode = new List();//取出所有当前job 影响的库位code + foreach (var detail in CoatingIssueJob.Details) + { + if (detail.HandledLocationCode != null) + { + listLocationCode.Add(detail.HandledLocationCode); + } + if (detail.HandledLocationCode != null) + { + listLocationCode.Add(detail.RecommendLocationCode); + } + if (detail.HandledLocationCode != null) + { + listLocationCode.Add(detail.RequestLocationCode); + } + if (detail.HandledLocationCode != null) + { + listLocationCode.Add(detail.ToLocationCode); + } + } + listLocationCode = listLocationCode.Distinct().ToList(); + */ + + await _CoatingIssueJobManager.CancelAsync(CoatingIssueJob).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.MaterialRequestNumber == 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); + CoatingIssueJobDetail detail = job.Details.FirstOrDefault(p => p.RecommendPackingCode == input.FromPackingCode ); /*&& p.HandledQty == input.FromQty*/ + if (detail == null) + { + //throw new UserFriendlyException($"根据HandledPackingCode={input.FromPackingCode}取CoatingIssueJobDetail表为空!"); + throw new UserFriendlyException($"根据RecommendPackingCode={input.FromPackingCode}取CoatingIssueJobDetail表为空!"); + } + //插入目标箱 + 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; + } + + + /* + /// + /// + /// + /// + /// + [HttpPost("accept")] + public override async Task AcceptAsync(string jobNumber) + { + var input = new IssueJobCheckInput + { + JobStatuses = new List() { EnumJobStatus.New }, + }; + var dto = await CheckAsync(jobNumber, input); + await _issueJobManager.AcceptAsync(dto.Id, CurrentUser.Id ?? Guid.Empty); + + } + + /// + /// 执行任务时,修改实际数量 + /// + /// + /// + + [HttpPost("handle")] + public override async Task HandleAsync(IssueJobDTO dto) + { + var input = new IssueJobCheckInput + { + JobStatuses = new List() { EnumJobStatus.Pending }, + }; + + await CheckAsync(dto.Number, input); + + var entity = ObjectMapper.Map(dto); + await _issueJobManager.HandleAsync(entity, CurrentUser.Id ?? Guid.Empty); + } + + [HttpPost("check")] + public override async Task CheckAsync(string jobNumber, IssueJobCheckInput input) + { + var result = new AbpValidationResult(); + _issueJobManager.CheckFormat(jobNumber); + var dto = await GetByNumberAsync(jobNumber); + var entity = ObjectMapper.Map(dto); + _issueJobManager.CheckJobStatus(entity, input.JobStatuses, result); + _issueJobManager.CheckDetails(entity, result); + //TODO 添加其它校验 + if (result.Errors.Any()) + { + throw new AbpValidationException(result.Errors); + } + + return dto; + } + */ + + ///// + ///// 临时解决方案 解决创建补料的订阅事件无法返回错误信息的问题 + ///// + ///// + ///// + //[Authorize(IssueJobPermissions.Create)] + //[HttpPost("create-by-eto")] + //public virtual async Task CreateByEtoAsync(MaterialRequestHandledETO materialRequestHandledETO) + //{ + // await _issueJobManager.AddByEtoAsync(materialRequestHandledETO); + + // return new MaterialRequestHandledETO(); + //} + + ///// + ///// 临时解决方案 解决创建补料的订阅事件无法返回错误信息的问题 + ///// + ///// + ///// + //[Authorize(IssueJobPermissions.Create)] + //[HttpPost("create-by-eto2")] + //public virtual async Task CreateByEtoAsync2(MaterialRequestHandledETO materialRequestHandledETO) + //{ + // await _issueJobManager.TestError(); + + // return new IssueJobDTO(); + //} list-by + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/CoatingIssueJobAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/CoatingIssueJobAutoMapperProfile.cs new file mode 100644 index 000000000..6fa0ec7b9 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/CoatingIssueJobAutoMapperProfile.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 CoatingIssueJobAutoMapperProfile() + { + 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/IssueNotes/CoatingIssueNoteAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/CoatingIssueNoteAppService.cs new file mode 100644 index 000000000..ca915b7a6 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/CoatingIssueNoteAppService.cs @@ -0,0 +1,132 @@ +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}coatingissue-note")] + + +public class CoatingIssueNoteAppService : + SfsStoreWithDetailsAppServiceBase, + ICoatingIssueNoteAppService +{ + private readonly ICoatingIssueNoteManager _CoatingIssueNoteManager; + + public CoatingIssueNoteAppService( + ICoatingIssueNoteRepository repository, + ICoatingIssueNoteManager CoatingIssueNoteManager + ) : base(repository) + { + _CoatingIssueNoteManager = CoatingIssueNoteManager; + } + + [HttpPost("")] + //[Authorize(CoatingIssueNotePermissions.Create)] + public override async Task CreateAsync(CoatingIssueNoteEditInput input) + { + var entity = ObjectMapper.Map(input); + await _CoatingIssueNoteManager.CreateAsync(entity).ConfigureAwait(false); + var dto = ObjectMapper.Map(entity); + return dto; + } + + /// + /// 确认对应的记录单 + /// + /// + /// + [HttpPost("confirm/{id}")] + public virtual async Task ConfirmAsync(Guid id) + { + var issueNote= await _repository.GetAsync(id).ConfigureAwait(false); + issueNote.Confirmed = true; + issueNote=await _repository.UpdateAsync(issueNote).ConfigureAwait(false); + await LocalEventBus.PublishAsync(new SfsConfirmedEntityEventData(issueNote), false).ConfigureAwait(false); + return ObjectMapper.Map(issueNote); + } + + [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(CoatingIssueNote)); + var result = await _CoatingIssueNoteManager.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; + } + + //[HttpPost("")] + //[Authorize(IssueNotePermissions.Create)] + //public override Task CreateAsync(IssueNoteCreateInput input) + //{ + // return base.CreateAsync(input); + //} + + //[HttpPut] + //[Route($"{StoreConsts.RootPath}{id}")] + //[Authorize(IssueNotePermissions.Update)] + //public override Task UpdateAsync(Guid id, IssueNoteUpdateInput input) + //{ + // return base.UpdateAsync(id, input); + //} + + //[HttpDelete] + //[Route($"{StoreConsts.RootPath}{id}")] + //[Authorize(IssueNotePermissions.Delete)] + //public override Task DeleteAsync(Guid id) + //{ + // return base.DeleteAsync(id); + //} +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/CoatingIssueNoteAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/CoatingIssueNoteAutoMapperProfile.cs new file mode 100644 index 000000000..83451121d --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/CoatingIssueNoteAutoMapperProfile.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 CoatingIssueNoteAutoMapperProfile() + { + CreateMap() + .ReverseMap(); + + CreateMap(); + + CreateMap() + .IgnoreAuditedObjectProperties() + .Ignore(x => x.MasterID) + .Ignore(x => x.TenantId) + .Ignore(x => x.Number) + .Ignore(x => x.Id); + + CreateMap() + .IgnoreAuditedObjectProperties() + .Ignore(x => x.TenantId) + .Ignore(x => x.Number) + .Ignore(x => x.Id); + ; + } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/MaterialRequests/CoatingMaterialRequestAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/MaterialRequests/CoatingMaterialRequestAppService.cs new file mode 100644 index 000000000..5cdb243b3 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/MaterialRequests/CoatingMaterialRequestAppService.cs @@ -0,0 +1,519 @@ +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}coatingmaterial-request")] +public class CoatingMaterialRequestAppService : SfsStoreRequestAppServiceBase, + ICoatingMaterialRequestAppService +{ + private readonly ICoatingMaterialRequestManager _materialRequestManager; + + 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 IIssueJobAppService _issueJobAppService; + public CoatingMaterialRequestAppService( + ICoatingMaterialRequestRepository repository, + ICoatingMaterialRequestManager CoatingMaterialRequestManager, + IPreparationPlanManager preparationPlanManager, + IItemStoreRelationAppService itemStoreRelationApp, + IAreaAppService areaApp, + ILocationAppService locationAppService, + IItemBasicAppService itemBasicAppService, + IProductionLineAppService productionLineAppService, + IIssueJobAppService issueJobAppService) + : base(repository, CoatingMaterialRequestManager) + { + _materialRequestManager = CoatingMaterialRequestManager; + _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 materialRequest in addList) + { + materialRequest.Worker = CurrentUser.GetUserName(); + materialRequest.CreatorId = CurrentUser.Id; + if (materialRequest.Type == EnumTransSubType.Issue_Manual.GetDisplayName()) + { + materialRequest.Type = EnumTransSubType.Issue_Manual.ToString(); + } + + foreach (var detail in materialRequest.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(CoatingMaterialRequestPermissions.Create)] + public override async Task CreateAsync(CoatingMaterialRequestEditInput 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 _materialRequestManager.CreateAsync(entity).ConfigureAwait(false); + + var dto = ObjectMapper.Map(result); + return dto; + } + + /// + /// 创建并且执行叫料请求 + /// + /// + /// + /// + [HttpPost("create-and-handle-api")] + //[Authorize(CoatingMaterialRequestPermissions.Create)] + public virtual async Task CreateAndHandleByAPIAsync(CoatingMaterialRequestEditInput 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 _materialRequestManager.CreateBynNumberAsync(entity).ConfigureAwait(false); + + var dto = ObjectMapper.Map(result); + + return dto; + } + + /// + /// 创建并且执行叫料请求 + /// + /// + /// + /// + [HttpPost("create-and-handle")] + //[Authorize(CoatingMaterialRequestPermissions.Create)] + public virtual async Task CreateAndHandleAsync(CoatingMaterialRequestEditInput 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 _materialRequestManager.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 materialRequestCreateInput = new CoatingMaterialRequestEditInput { Worker = CurrentUser.GetUserName() }; + + foreach (var preparationPlanDetail in prodPreparationPlan.Details) + { + var detail = new CoatingMaterialRequestDetailInput + { + ItemCode = preparationPlanDetail.ItemCode, + ItemName = preparationPlanDetail.ItemName, + ItemDesc1 = preparationPlanDetail.ItemDesc1, + ItemDesc2 = preparationPlanDetail.ItemDesc2, + Uom = preparationPlanDetail.Uom, + Qty = preparationPlanDetail.Qty, + StdPackQty = preparationPlanDetail.StdPackQty, + ToLocationCode = preparationPlanDetail.ToLocationCode + }; + + materialRequestCreateInput.Details.Add(detail); + } + + var dto = await CreateAndHandleAsync(materialRequestCreateInput).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 CheckImportInputBusinessAsync(CoatingMaterialRequestImportInput importInput, EnumImportMethod importMethod) + //{ + // //await base.CheckImportInputBusinessAsync(importInput, importMethod); + + // var item = await CheckItemBasicAsync(importInput); + // await CheckItemPackAsync(importInput); + // var location = await CheckLocationAsync(importInput); + // await CheckAreaAsync(importInput); + // await CheckStoreRelationAsync(importInput); + // var transactionType = await CheckTransactionTypeAsync(); + + // CheckTransactionType(EnumTransInOut.In, EnumInventoryStatus.OK, transactionType, item, location); + //} + + /// + /// 导入验证 + /// + /// + /// + /// + protected override async Task ValidateImportModelAsync(CoatingMaterialRequestImportInput 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(CoatingMaterialRequestImportInput 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(CoatingMaterialRequestImportInput 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(CoatingMaterialRequestImportInput 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(CoatingMaterialRequestImportInput 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/MaterialRequests/CoatingMaterialRequestAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/MaterialRequests/CoatingMaterialRequestAutoMapperProfile.cs new file mode 100644 index 000000000..c9490e41f --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/MaterialRequests/CoatingMaterialRequestAutoMapperProfile.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 CoatingMaterialRequestAutoMapperProfile() + { + 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..687298210 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 @@ -25,6 +25,9 @@ public partial class StoreApplicationAutoMapperProfile : Profile CountAdjustRequestAutoMapperProfile(); ScrapRequestAutoMapperProfile(); WipWarehouseAdjustRequestMapperProfile(); + CoatingIssueJobAutoMapperProfile(); + CoatingIssueNoteAutoMapperProfile(); + CoatingMaterialRequestAutoMapperProfile(); #endregion diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/CoatingIssueJob.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/CoatingIssueJob.cs new file mode 100644 index 000000000..23e681f45 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/CoatingIssueJob.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 CoatingIssueJob : SfsJobAggregateRootBase +{ + /// + /// 叫料请求类型 + /// + [IgnoreUpdate] + public string RequestType { get; set; } + + /// + /// 生产线 + /// + [IgnoreUpdate] + public string ProdLine { get; set; } + + /// + /// 要货单号 + /// + [IgnoreUpdate] + public string MaterialRequestNumber { get; set; } + + /// + /// 车间 + /// + [IgnoreUpdate] + public string Workshop { get; set; } + + /// + /// 使用在途库 + /// + [Display(Name = "使用在途库")] + [IgnoreUpdate] + public bool UseOnTheWayLocation { get; set; } + + /// + /// 任务明细 + /// + [IgnoreUpdate] + public override List Details { get; set; } = new List(); + + /// + /// 设置任务明细的实际库位和实际数量 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public virtual async Task BuildDetail(Guid id, string handledLocationCode, string handledLocationErpCode, + string handledWarehouseCode, decimal handledQty, string handledSupplierBatch, DateTime handledArriveDate, DateTime handledProduceDate, DateTime handledExpireDate, + string handledContainerCode, string handledLot, string handledPackingCode) + { + var detail = GetDetail(id); + detail.HandledFromLocationCode = handledLocationCode; + detail.HandledFromLocationErpCode = handledLocationErpCode; + detail.HandledFromWarehouseCode = handledWarehouseCode; + detail.HandledQty = handledQty; + detail.HandledSupplierBatch = handledSupplierBatch; + detail.HandledArriveDate = handledArriveDate; + detail.HandledProduceDate = handledProduceDate; + detail.HandledExpireDate = handledExpireDate; + detail.HandledContainerCode = handledContainerCode; + detail.HandledLot = handledLot; + detail.HandledPackingCode = handledPackingCode; + await Task.CompletedTask.ConfigureAwait(false); + } + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/CoatingIssueJobDetail.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/CoatingIssueJobDetail.cs new file mode 100644 index 000000000..e0996947e --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/CoatingIssueJobDetail.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 CoatingIssueJobDetail : SfsJobRecommendFromDetailEntityBase, IHasToLocation +{ + /// + /// 请求库位 + /// + public string RequestLocationCode { get; set; } + + /// + /// 到库位 + /// + public string ToLocationCode { get; set; } + + /// + /// 到库区 + /// + public string ToLocationArea { get; set; } + + /// + /// 到库位组 + /// + public string ToLocationGroup { get; set; } + + /// + /// 到ERP库位 + /// + public string ToLocationErpCode { get; set; } + + /// + /// 到仓库 + /// + public string ToWarehouseCode { get; set; } + + /// + /// 在途库库位 + /// + public string OnTheWayLocationCode { get; set; } + + /// + /// 生产线 + /// + public string ProdLine { get; set; } + + /// + /// 工作中心 + /// + public string WorkStation { get; set; } + + /// + /// 过期时间 + /// + public DateTime ExpiredTime { get; set; } + + /// + /// 工序 + /// + public string Operation { get; set; } + + /// + /// 配送方式 + /// + public EnumDistributionType DistributionType { get; set; } + + /// + /// 取整方式 + /// + public EnumTruncType TruncType { get; set; } + + /// + /// 取整后数量 + /// + public decimal RoundedQty { get; set; } + + /// + /// 计划拆分规则 + /// + public EnumPlannedSplitRule PlannedSplitRule { get; set; } + + /// + /// 计划开始时间 + /// + public DateTime PlanBeginTime { get; set; } + + /// + /// 每次配送数量 + /// + public decimal DeliveryQty { get; set; } + + /// + /// 位置码 + /// + public string PositionCode { get; set; } + + /// + /// 推荐类型 + /// + public EnumRecommendType RecommendType { get; set; } + + public void SetId(Guid id) + { + this.Id = id; + } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/CoatingIssueJobManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/CoatingIssueJobManager.cs new file mode 100644 index 000000000..53215344e --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/CoatingIssueJobManager.cs @@ -0,0 +1,103 @@ +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 CoatingIssueJobManager : SfsJobManagerBase, ICoatingIssueJobManager +{ + + public CoatingIssueJobManager( + ICoatingIssueJobRepository repository + ) : base(repository) + { + } + + /// + /// 执行任务 发料任务 + /// + /// + /// + /// + /// + public override async Task CompleteAsync(CoatingIssueJob 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(CoatingIssueJob 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 virtual async Task> AddByEtoAsync(MaterialRequestHandledETO eventData) + //{ + // var CoatingIssueJobs = await BuildCoatingIssueJobByMaterialRequestAsync(eventData); + + // await Repository.InsertManyAsync(CoatingIssueJobs); + + // var expectIns = await BuildExpectInAsync(CoatingIssueJobs); + // await _expectInAppService.AddManyAndCalculationAvailableCapacityAsync(expectIns); + + // return CoatingIssueJobs; + //} + + //public virtual async Task TestError() + //{ + // throw new UserFriendlyException("我是测试的异常"); + //} + 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/ICoatingIssueJobManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/ICoatingIssueJobManager.cs new file mode 100644 index 000000000..ed9a1d723 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/ICoatingIssueJobManager.cs @@ -0,0 +1,10 @@ +using System; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace Win_in.Sfs.Wms.Store.Domain; + +public interface ICoatingIssueJobManager : IJobManager +{ + Task GetAsync(Expression> expression); +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/ICoatingIssueJobRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/ICoatingIssueJobRepository.cs new file mode 100644 index 000000000..67e324295 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/ICoatingIssueJobRepository.cs @@ -0,0 +1,6 @@ +namespace Win_in.Sfs.Wms.Store.Domain; + +public interface ICoatingIssueJobRepository : ISfsJobRepositoryBase +{ + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/ICoatingssueExtension.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/ICoatingssueExtension.cs new file mode 100644 index 000000000..2bb262cb6 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/ICoatingssueExtension.cs @@ -0,0 +1,54 @@ +using Volo.Abp.Timing; +using Win_in.Sfs.Shared.Domain.Shared; + +namespace Win_in.Sfs.Wms.Store.Domain; + +public static class CoatingIssueExtension +{ + // public static IssueJob SetDetails(this IssueJob job,IGuidGenerator guidGenerator, LocationDTO location) + // { + // foreach (var detail in job.Details) + // { + // detail.SetIdAndNumber(guidGenerator,job.Id,job.Number); + // detail.RecommendLocationCode = location.Code; + // detail.SetBatch(detail.RecommendBatch); + // } + // return job; + // } + + public static IssueJob Init(this IssueJob job) + { + job.JobType = EnumJobType.IssueJob; + job.JobStatus = EnumJobStatus.Open; + return job; + } + + public static IssueJob SetWorkGroup(this IssueJob job, string warehouseCode, string workGroupCode, string groupCode) + { + job.WorkGroupCode = workGroupCode; + job.WarehouseCode = warehouseCode; + job.ProdLine = groupCode; + return job; + } + + public static IssueJob SetWorker(this IssueJob job, string worker) + { + job.Worker = worker; + return job; + } + + public static IssueJob SetPriority(this IssueJob job, IClock clock) + { + job.Priority = PriorityHelper.GetPriority(clock); + job.PriorityIncrement = 1; + return job; + } + + // public static IssueJob SetIdAndNumber(this IssueJob job,IGuidGenerator guidGenerator, ISnowflakeIdGenerator numberGenerator) + // { + // var number = (numberGenerator.CreateAsync().GetAwaiter().GetResult()).ToString(); + // job.SetIdAndNumber(guidGenerator, number); + // return job; + // } + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNote.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNote.cs new file mode 100644 index 000000000..879e34cc5 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNote.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 CoatingIssueNote : SfsStoreAggregateRootBase, IHasJobNumber, IHasRequestNumber +{ + /// + /// 任务ID + /// + [IgnoreUpdate] + public string JobNumber { get; set; } + + /// + /// 车间 + /// + [IgnoreUpdate] + public string Workshop { get; set; } + + /// + /// 明细列表 + /// + [IgnoreUpdate] + public override List Details { get; set; } = new List(); + + [IgnoreUpdate] + public string RequestNumber { get; set; } + + /// + /// 叫料请求类型 + /// + [IgnoreUpdate] + public string RequestType { get; set; } + + /// + /// 使用在途库 + /// + [IgnoreUpdate] + public bool UseOnTheWayLocation { get; set; } + + /// + /// 确认时间 + /// + [Display(Name = "确认时间")] + [IgnoreUpdate] + public DateTime? ConfirmTime { get; set; } + + /// + /// 已确认 + /// + [Display(Name = "已确认")] + public bool Confirmed { get; set; } + + public void Confirm(DateTime confirmTime) + { + + CheckStatus(Confirmed); + Confirmed = true; + ConfirmTime = confirmTime; + } + + private static void CheckStatus(bool confirmed) + { + if (confirmed) + { + throw new UserFriendlyException($"当前状态为 【已确认】 ,无法再次确认!"); + } + + } + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNoteDetail.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNoteDetail.cs new file mode 100644 index 000000000..e60a194a9 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNoteDetail.cs @@ -0,0 +1,43 @@ +using System; +using Win_in.Sfs.Shared.Domain.Shared; + +namespace Win_in.Sfs.Wms.Store.Domain; + +public class CoatingIssueNoteDetail : SfsStoreRecommendFromDetailWithFromToEntityBase +{ + + /// + /// 发料时间 + /// + public DateTime IssueTime { get; set; } + + /// + /// 过期时间 + /// + public DateTime ExpiredTime { get; set; } + + /// + /// 生产线 + /// + public string ProdLine { get; set; } + + /// + /// 工作中心 + /// + public string WorkStation { get; set; } + + /// + /// 在途库库位 + /// + public string OnTheWayLocationCode { get; set; } + + /// + /// 位置码 + /// + public string PositionCode { get; set; } + + /// + /// 推荐类型 + /// + public EnumRecommendType RecommendType { get; set; } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNoteManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNoteManager.cs new file mode 100644 index 000000000..75106c548 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNoteManager.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 CoatingIssueNoteManager : SfsStoreManagerBase, ICoatingIssueNoteManager +{ + + public CoatingIssueNoteManager( + ICoatingIssueNoteRepository 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(CoatingIssueNote entity) + { + try + { + await LocalEventBus.PublishAsync(new SfsConfirmedEntityEventData(entity), false).ConfigureAwait(false); + } + catch (Exception ex) + { + Logger.LogDebug($"{nameof(CoatingIssueNote)} Confirmed Event:{ex.Message}", null); + Console.WriteLine(ex.Source); + throw; + } + } + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNoteRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNoteRepository.cs new file mode 100644 index 000000000..ec4d9f2a5 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/CoatingIssueNoteRepository.cs @@ -0,0 +1,6 @@ +namespace Win_in.Sfs.Wms.Store.Domain; + +public interface ICoatingIssueNoteRepository : ISfsStoreRepositoryBase +{ + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/ICoatingIssueNoteManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/ICoatingIssueNoteManager.cs new file mode 100644 index 000000000..af4d43f9d --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/ICoatingIssueNoteManager.cs @@ -0,0 +1,10 @@ +using System; +using System.Threading.Tasks; + +namespace Win_in.Sfs.Wms.Store.Domain; + +public interface ICoatingIssueNoteManager : ISfsStoreManager +{ + Task ConfirmAsync(Guid id); + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/CoatingMaterialRequest.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/CoatingMaterialRequest.cs new file mode 100644 index 000000000..66d4cd99a --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/CoatingMaterialRequest.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using Win_in.Sfs.Shared.Domain.Entities; + +namespace Win_in.Sfs.Wms.Store.Domain; + +/// +/// 要料申请 +/// +public class CoatingMaterialRequest : 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/MaterialRequests/CoatingMaterialRequestDetail.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/CoatingMaterialRequestDetail.cs new file mode 100644 index 000000000..c4640d1d4 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/CoatingMaterialRequestDetail.cs @@ -0,0 +1,104 @@ +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 CoatingMaterialRequestDetail : SfsStoreDetailWithQtyEntityBase, IHasToLocation +{ + + /// + /// 到库位 + /// + public string ToLocationCode { get; set; } + + /// + /// 到库区 + /// + public string ToLocationArea { get; set; } + + /// + /// 到库位组 + /// + public string ToLocationGroup { get; set; } + + /// + /// 到ERP库位 + /// + public string ToLocationErpCode { get; set; } + + /// + /// 到仓库 + /// + public string ToWarehouseCode { get; set; } + + /// + /// 来源库区 + /// + public string FromLocationArea { get; set; } + + // /// + // /// 在途库库位 + // /// + // public string OnTheWayLocationCode { get; set; } + + /// + /// 生产线 + /// + public string ProdLine { get; set; } + + /// + /// 工作中心 + /// + public string WorkStation { get; set; } + + /// + /// 过期时间 + /// + public DateTime ExpiredTime { get; set; } + + /// + /// 已发数量 + /// + public decimal IssuedQty { get; set; } + + /// + /// 已收数量 + /// + public decimal ReceivedQty { get; set; } + + /// + /// 明细状态 + /// + public EnumStatus Status { get; set; } + + /// + /// 请求未发 还未发送的数量 + /// + [NotMapped] + public decimal ToBeIssuedQty => Qty - IssuedQty; + + /// + /// 已发未收 + /// + [NotMapped] + public decimal ToBeReceivedQty => IssuedQty - ReceivedQty; + + /// + /// 请求未收 + /// + [NotMapped] + public decimal NotFinishQty => Qty - ReceivedQty; + + /// + /// 位置码 + /// + public string PositionCode { get; set; } + + /// + /// 推荐类型 + /// + public EnumRecommendType RecommendType { get; set; } + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/CoatingMaterialRequestManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/CoatingMaterialRequestManager.cs new file mode 100644 index 000000000..8698838cf --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/CoatingMaterialRequestManager.cs @@ -0,0 +1,307 @@ +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 CoatingMaterialRequestManager + : SfsStoreRequestManagerBase + , ICoatingMaterialRequestManager +{ + private readonly ICoatingMaterialRequestRepository _repository; + private readonly ICoatingIssueJobRepository _issueJobRepository; + + public CoatingMaterialRequestManager( + ICoatingMaterialRequestRepository repository + , ICoatingIssueJobRepository issueJobRepository + ) : base(repository) + { + _repository = repository; + _issueJobRepository = issueJobRepository; + } + + /// + /// 创建 + /// + /// + /// + public virtual async Task CreateBynNumberAsync(CoatingMaterialRequest entity) + { + var number = string.IsNullOrEmpty(entity.Number) ? await GenerateNumberAsync(nameof(CoatingMaterialRequest), 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(CoatingMaterialRequest 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(CoatingMaterialRequestDetail detail) + { + if (detail.ReceivedQty >= detail.Qty)//执行的时候 实际收料 多余 要料数 + { + detail.Status = EnumStatus.Close; + } + else + { + detail.Status = EnumStatus.Open; + } + } + + private async Task SetMaterialRequestStatus(CoatingMaterialRequest 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 Handle(Guid id) + // { + // var entity =await Repository.GetAsync(id); + // if (entity == null) + // { + // return false; + // } + // entity.Handle(); + // await Repository.UpdateAsync(entity); + // + // await HandledPublishAsync(entity); + // return true; + // } + // + // private async Task HandledPublishAsync(MaterialRequest entity) + // { + // //发布,以生成发料任务 + // var eto = BuildMaterialRequestHandledETO(entity); + // await DistributedEventBus.PublishAsync(eto); + // } + // + // /// + // /// 关闭 + // /// + // /// + // public virtual async Task Close(Guid id) + // { + // var entity = await Repository.GetAsync(id); + // if (entity == null) + // { + // return false; + // } + // entity.Close(); + // await Repository.UpdateAsync(entity); + // + // //发布,以关闭发料任务 + // var eto = BuildMaterialRequestClosedETO(entity); + // await DistributedEventBus.PublishAsync(eto); + // return true; + // } + // + // /// + // /// 打开 + // /// + // /// + // public virtual async Task Open(Guid id) + // { + // var entity = await Repository.GetAsync(id); + // if (entity == null) + // { + // return false; + // } + // entity.Open(); + // + // await Repository.UpdateAsync(entity); + // + // //发布,以打开发料任务 + // var eto = BuildMaterialRequestOpenedETO(entity); + // await DistributedEventBus.PublishAsync(eto); + // return true; + // } + + public virtual async Task CreateAndHandleAsync(MaterialRequest entity) + { + + await base.CreateAsync(entity); + + await base.HandleAsync(entity.Id); + + return entity; + } + */ + + + #endregion + + #region Import + + /// + /// 执行导入 + /// + 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 + + /* + #region 私有 + + private MaterialRequestOpenedETO BuildMaterialRequestOpenedETO(MaterialRequest materialRequest) + { + var materialRequestETO = new MaterialRequestOpenedETO() + { + Number = materialRequest.Number, + Workshop = materialRequest.Workshop, + Status = materialRequest.Status, + Details = BuildMaterialRequestDetailETO(materialRequest.Details) + }; + return materialRequestETO; + } + + private MaterialRequestClosedETO BuildMaterialRequestClosedETO(MaterialRequest materialRequest) + { + var materialRequestETO = new MaterialRequestClosedETO() + { + Company = materialRequest.Company, + Number = materialRequest.Number + }; + return materialRequestETO; + } + + private MaterialRequestHandledETO BuildMaterialRequestHandledETO(MaterialRequest materialRequest) + { + var materialRequestETO = new MaterialRequestHandledETO() + { + Company = materialRequest.Company, + Number = materialRequest.Number, + Workshop = materialRequest.Workshop, + Status = materialRequest.Status, + Details = BuildMaterialRequestDetailETO(materialRequest.Details) + }; + return materialRequestETO; + } + + private List BuildMaterialRequestDetailETO(List materialRequestDetail) + { + var list = new List(); + foreach (var detail in materialRequestDetail) + { + var materialRequestDetailETO = new MaterialRequestDetailETO() + { + Number = detail.Number, + Item = detail.Item, + ItemCode = detail.ItemCode, + Qty = detail.Qty, + ToLocationCode = detail.ToLocationCode, + ProdLine = detail.ProdLine, + WorkStation = detail.WorkStation, + ExpiredTime = detail.ExpiredTime, + Status = detail.Status + }; + list.Add(materialRequestDetailETO); + } + return list; + } + + #endregion + */ +} + +///// +///// 为了解决补料时 无法拿到订阅错误信息 +///// +///// +///// +///// +//public virtual async Task CreateAndHandleAsync(MaterialRequest entity, bool flag) +//{ +// await entity.Handle(); +// foreach (var detail in entity.Details) +// { +// detail.Status = EnumStoreStatus.Handle; +// } +// await base.CreateAsync(entity); + +// //发布,以打开发料任务?? +// //var eto = BuildMaterialRequestHandledETO(entity); +// //await DistributedEventBus.PublishAsync(eto); + +// return entity; +//} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/ICoatingMaterialRequestManager.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/ICoatingMaterialRequestManager.cs new file mode 100644 index 000000000..816bd12b5 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/ICoatingMaterialRequestManager.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; + +namespace Win_in.Sfs.Wms.Store.Domain; + +using Win_in.Sfs.Shared.Domain; + +public interface ICoatingMaterialRequestManager : ISfsStoreRequestManager, + IBulkImportService +{ + // Task CreateAndHandleAsync(MaterialRequest entity); + Task UpdateDetailsAsync(CoatingMaterialRequest entity); + + Task CompleteAsync(string number); + + Task CreateBynNumberAsync(CoatingMaterialRequest entity); +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/ICoatingMaterialRequestRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/ICoatingMaterialRequestRepository.cs new file mode 100644 index 000000000..da8f1d030 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/MaterialRequests/ICoatingMaterialRequestRepository.cs @@ -0,0 +1,9 @@ +using Win_in.Sfs.Shared.Domain; + +namespace Win_in.Sfs.Wms.Store.Domain; + +public interface ICoatingMaterialRequestRepository : ISfsStoreRepositoryBase, + ISfsBulkRepositoryBase +{ + +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/CoatingIssueJobDbContextModelCreatingExtensions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/CoatingIssueJobDbContextModelCreatingExtensions.cs new file mode 100644 index 000000000..b4f9d6f1c --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/CoatingIssueJobDbContextModelCreatingExtensions.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 CoatingIssueJobDbContextModelCreatingExtensions +{ + public static void ConfigureCoatingIssueJob(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options) + { + builder.Entity(b => + { + //Configure table & schema name + b.ToTable(StoreDbProperties.JobDbTablePrefix + nameof(CoatingIssueJob), 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.MaterialRequestNumber).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(CoatingIssueJobDetail), 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).IsRequired(false); + b.Property(q => q.RecommendType).HasMaxLength(SfsPropertyConst.CodeLength).HasConversion(); + + //Relations + //None + + //Indexes + //b.HasIndex(q => new { q.PackingCode }).IsUnique(); + }); + } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/CoatingIssueJobEfCoreRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/CoatingIssueJobEfCoreRepository.cs new file mode 100644 index 000000000..ef96924b9 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/IssueJobs/CoatingIssueJobEfCoreRepository.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 CoatingIssueJobEfCoreRepository : SfsJobEfCoreRepositoryBase, ICoatingIssueJobRepository +{ + public CoatingIssueJobEfCoreRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/CoatingIssueNoteDbContextModelCreatingExtensions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/CoatingIssueNoteDbContextModelCreatingExtensions.cs new file mode 100644 index 000000000..f1f16696b --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/CoatingIssueNoteDbContextModelCreatingExtensions.cs @@ -0,0 +1,62 @@ +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 CoatingIssueNoteDbContextModelCreatingExtensions +{ + public static void ConfigureCoatingIssueNote(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options) + { + builder.Entity(b => + { + //Configure table & schema name + b.ToTable(options.TablePrefix + nameof(CoatingIssueNote), 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(CoatingIssueNoteDetail), 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.RecommendType).HasMaxLength(SfsPropertyConst.NameLength).HasConversion(); + + //Relations + + //Indexes + b.HasIndex(q => new { q.Number, q.FromPackingCode, q.FromLocationCode, q.ToLocationCode }).IsUnique(); + b.HasIndex(q => new { q.FromPackingCode }); + }); + } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/CoatingIssueNoteEfCoreRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/CoatingIssueNoteEfCoreRepository.cs new file mode 100644 index 000000000..6ca2ca978 --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/IssueNotes/CoatingIssueNoteEfCoreRepository.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 CoatingIssueNoteEfCoreRepository : SfsStoreEfCoreRepositoryBase, ICoatingIssueNoteRepository +{ + public CoatingIssueNoteEfCoreRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/CoatingMaterialRequestDbContextModelCreatingExtensions.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/CoatingMaterialRequestDbContextModelCreatingExtensions.cs new file mode 100644 index 000000000..74d9d006e --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/CoatingMaterialRequestDbContextModelCreatingExtensions.cs @@ -0,0 +1,64 @@ +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 CoatingMaterialRequestDbContextModelCreatingExtensions +{ + public static void ConfigureCoatingMaterialRequest(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options) + { + builder.Entity(b => + { + //Configure table & schema name + b.ToTable(options.TablePrefix + nameof(CoatingMaterialRequest), 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(CoatingMaterialRequestDetail), 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.RecommendType).HasMaxLength(SfsPropertyConst.NameLength).HasConversion(); + //Relations + //Indexes + b.HasIndex(q => new { q.Number, q.ItemCode, q.ToLocationCode }).IsUnique(); + b.HasIndex(q => new { q.ItemCode }); + }); + } +} diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/CoatingMaterialRequestEfCoreRepository.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/CoatingMaterialRequestEfCoreRepository.cs new file mode 100644 index 000000000..2eab403be --- /dev/null +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/MaterialRequests/CoatingMaterialRequestEfCoreRepository.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 CoatingMaterialRequestEfCoreRepository : SfsStoreEfCoreRepositoryBase, ICoatingMaterialRequestRepository +{ + public CoatingMaterialRequestEfCoreRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } +} 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..e76616062 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 @@ -66,6 +66,9 @@ public static class StoreDbContextModelCreatingExtensions builder.ConfigureScrapRequest(options); builder.ConfigureCountAdjustRequest(options); builder.ConfigureWipWarehouseAdjustRequest(options); + builder.ConfigureCoatingIssueNote(options); + builder.ConfigureCoatingMaterialRequest(options); + builder.ConfigureCoatingIssueJob(options); #endregion