From 24d0b060842426436a438d7471dd4e4b80775df5 Mon Sep 17 00:00:00 2001 From: liuyunfeng Date: Tue, 12 Mar 2024 13:48:52 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=8B=86=E7=AE=B1=E6=B6=89=E5=8F=8AexpectO?= =?UTF-8?q?ut=E7=9B=B8=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Commons/SplitPacking_UpdateDetailInput.cs | 40 +++++++++++++++++++ .../ExpectOuts/IExpectOutAppService.cs | 8 ++++ .../ExpectOuts/ExpectOutAppService.cs | 34 ++++++++++++++++ .../TransferNotes/TransferNoteAppService.cs | 23 ++++++++++- 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/SplitPackings/Commons/SplitPacking_UpdateDetailInput.cs diff --git a/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/SplitPackings/Commons/SplitPacking_UpdateDetailInput.cs b/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/SplitPackings/Commons/SplitPacking_UpdateDetailInput.cs new file mode 100644 index 000000000..9b47d3434 --- /dev/null +++ b/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/SplitPackings/Commons/SplitPacking_UpdateDetailInput.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Win_in.Sfs.Basedata.SplitPackings.Commons; +public class SplitPacking_UpdateDetailInput +{ + /// + /// 主表number + /// + [Required(ErrorMessage = "{0}是必填项")] + public string Number { get; set; } + /// + /// 子表from标签 + /// + [Required(ErrorMessage = "{0}是必填项")] + public string FromPackingCode { get; set; } + /// + /// from数量 + /// + [Required(ErrorMessage = "{0}是必填项")] + [Range(1, 99999, ErrorMessage = "{0}值范围在1至99999之间")] + public decimal FromQty { get; set; } + /// + /// 子表的to标签 + /// + [Required(ErrorMessage = "{0}是必填项")] + public string ToPackingCode { get; set; } + /// + /// to数量 + /// + [Required(ErrorMessage = "{0}是必填项")] + [Range(1, 99999, ErrorMessage = "{0}值范围在1至99999之间")] + public decimal ToQty { get; set; } + + +} diff --git a/be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application.Contracts/ExpectOuts/IExpectOutAppService.cs b/be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application.Contracts/ExpectOuts/IExpectOutAppService.cs index 6ce12eb30..1b293473d 100644 --- a/be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application.Contracts/ExpectOuts/IExpectOutAppService.cs +++ b/be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application.Contracts/ExpectOuts/IExpectOutAppService.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Win_in.Sfs.Basedata.SplitPackings.Commons; using Win_in.Sfs.Shared.Domain.Shared; namespace Win_in.Sfs.Wms.Inventory.Application.Contracts; @@ -29,4 +30,11 @@ public interface IExpectOutAppService string packingCode, EnumInventoryStatus enumInventoryStatus, string lot); + + /// + /// 保存拆箱时涉及的明细修改 + /// + /// + Task> SaveDetail_SplitPackingAsync(SplitPacking_UpdateDetailInput input); + } diff --git a/be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application/ExpectOuts/ExpectOutAppService.cs b/be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application/ExpectOuts/ExpectOutAppService.cs index 5125a0034..c1700e45d 100644 --- a/be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application/ExpectOuts/ExpectOutAppService.cs +++ b/be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application/ExpectOuts/ExpectOutAppService.cs @@ -6,6 +6,8 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.ObjectMapping; +using Win_in.Sfs.Basedata.Domain.Shared; +using Win_in.Sfs.Basedata.SplitPackings.Commons; using Win_in.Sfs.Shared.Application.Contracts; using Win_in.Sfs.Shared.Domain.Shared; using Win_in.Sfs.Wms.Inventory.Application.Contracts; @@ -179,4 +181,36 @@ public class ExpectOutAppService return ObjectMapper.Map, List>(entitys); } + + /// + /// 保存拆箱时涉及的明细修改 + /// + /// + [HttpPost("save-detail-split-packing")] + public virtual async Task> SaveDetail_SplitPackingAsync(SplitPacking_UpdateDetailInput input) + { + var obj = await _repository.FindAsync(p => p.JobNumber == input.Number && p.PackingCode == input.FromPackingCode && p.Qty == input.FromQty).ConfigureAwait(false); + if (obj == null) + { + return null; + } + + //插入目标箱 + var newObj = CommonHelper.CloneObj(obj); + newObj.SetId(GuidGenerator.Create()); + newObj.PackingCode = input.ToPackingCode; + newObj.Qty = input.ToQty; + var insRet = await _repository.InsertAsync(newObj).ConfigureAwait(false); + //修改源箱 + obj.Qty = input.FromQty - input.ToQty; + var updRet = await _repository.UpdateAsync(obj).ConfigureAwait(false); + List lst = new List(); + lst.Add(insRet); + lst.Add(updRet); + var ret = ObjectMapper.Map, List>(lst); + return ret; + } + + + } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/TransferNotes/TransferNoteAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/TransferNotes/TransferNoteAppService.cs index f2ee44369..3ee3eb757 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/TransferNotes/TransferNoteAppService.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/TransferNotes/TransferNoteAppService.cs @@ -10,6 +10,7 @@ using Volo.Abp; using Volo.Abp.Application.Dtos; using Win_in.Sfs.Basedata.Application.Contracts; using Win_in.Sfs.Basedata.Domain.Shared; +using Win_in.Sfs.Basedata.SplitPackings.Commons; using Win_in.Sfs.Shared.Domain; using Win_in.Sfs.Shared.Domain.Shared; using Win_in.Sfs.Wms.Inventory.Application.Contracts; @@ -38,6 +39,10 @@ public class TransferNoteAppService : SfsStoreWithDetailsAppServiceBase private readonly IInspectJobAppService _inspectJobAppService; //质检 private readonly IIssueJobAppService _issueJobAppService; //发料 + private readonly IExpectOutAppService _expectOutAppService; // + + + public TransferNoteAppService( @@ -49,7 +54,8 @@ public class TransferNoteAppService : SfsStoreWithDetailsAppServiceBase IPurchaseReceiptJobAppService purchaseReceiptJobAppService, IPurchaseReceiptRequestAppService purchaseReceiptRequestAppService, IInspectJobAppService inspectJobAppService, - IIssueJobAppService issueJobAppService) : base(repository) + IIssueJobAppService issueJobAppService, + IExpectOutAppService expectOutAppService) : base(repository) { _transferNoteManager = transferNoteManager; _balanceAppService = balanceAppService; @@ -59,6 +65,7 @@ public class TransferNoteAppService : SfsStoreWithDetailsAppServiceBase _purchaseReceiptRequestAppService = purchaseReceiptRequestAppService; _inspectJobAppService = inspectJobAppService; _issueJobAppService = issueJobAppService; + _expectOutAppService = expectOutAppService; } #region 东阳使用 @@ -438,6 +445,13 @@ public class TransferNoteAppService : SfsStoreWithDetailsAppServiceBase [HttpPost("split-packing-inspect")] public async Task SplitPacking_InspectAsync(TransferNoteEditInput transferNoteEditInput, [FromQuery] SplitPacking_UpdateJobDetailInput updateJobDetailInput) { + SplitPacking_UpdateDetailInput newInput = new SplitPacking_UpdateDetailInput(); + newInput.Number = updateJobDetailInput.Number; + newInput.FromPackingCode = updateJobDetailInput.FromPackingCode; + newInput.FromQty = updateJobDetailInput.FromQty; + newInput.ToPackingCode = updateJobDetailInput.ToPackingCode; + newInput.ToQty = updateJobDetailInput.ToQty; + var expectOutRet = await _expectOutAppService.SaveDetail_SplitPackingAsync(newInput).ConfigureAwait(false); var jobRet = await _inspectJobAppService.SaveDetail_SplitPackingAsync(updateJobDetailInput).ConfigureAwait(false); var ret = await SplitPackingAsync(transferNoteEditInput).ConfigureAwait(false); //库存操作 return ret; @@ -452,6 +466,13 @@ public class TransferNoteAppService : SfsStoreWithDetailsAppServiceBase [HttpPost("split-packing-issue")] public async Task SplitPacking_IssueAsync(TransferNoteEditInput transferNoteEditInput, [FromQuery] SplitPacking_UpdateJobDetailInput updateJobDetailInput) { + SplitPacking_UpdateDetailInput newInput = new SplitPacking_UpdateDetailInput(); + newInput.Number = updateJobDetailInput.Number; + newInput.FromPackingCode = updateJobDetailInput.FromPackingCode; + newInput.FromQty = updateJobDetailInput.FromQty; + newInput.ToPackingCode = updateJobDetailInput.ToPackingCode; + newInput.ToQty = updateJobDetailInput.ToQty; + var expectOutRet = await _expectOutAppService.SaveDetail_SplitPackingAsync(newInput).ConfigureAwait(false); var jobRet = await _issueJobAppService.SaveDetail_SplitPackingAsync(updateJobDetailInput).ConfigureAwait(false); var ret = await SplitPackingAsync(transferNoteEditInput).ConfigureAwait(false); //库存操作 return ret; From a3af15d36170bddcad80f03a7dbb595b5230aa9f Mon Sep 17 00:00:00 2001 From: zhouhongjun <565221961@qq.com> Date: Tue, 12 Mar 2024 16:09:52 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BD=8D=E7=BD=AE=E7=A0=81=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Inputs/PositionCodeEditInput.cs | 3 + .../Inputs/PositionCodeImportInput.cs | 9 +- .../PositionCode/PositionCodeAppService.cs | 126 ++++++++++++++-- .../Enums/Store/EnumRecommendType.cs | 12 +- .../Inputs/ProductRecycleJobEditInput.cs | 7 + .../ProductRecycleJobAutoMapperProfile.cs | 2 +- .../ProductRecycleRequestAppService.cs | 34 +++-- .../ProductRecycleRequestAutoMapperProfile.cs | 14 +- .../StoreApplicationAutoMapperProfile.cs | 1 + .../ProductRecycleRequestEventHandler.cs | 138 +++++++++++++++++- 10 files changed, 299 insertions(+), 47 deletions(-) diff --git a/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/PositionCode/Inputs/PositionCodeEditInput.cs b/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/PositionCode/Inputs/PositionCodeEditInput.cs index e629da700..6db7b8d01 100644 --- a/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/PositionCode/Inputs/PositionCodeEditInput.cs +++ b/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/PositionCode/Inputs/PositionCodeEditInput.cs @@ -13,6 +13,7 @@ public class PositionCodeEditInput : SfsBaseDataCreateOrUpdateInputBase /// 物料号 /// [Display(Name = "物料号")] + [Required(ErrorMessage = "{0}是必填项")] public string PartCode { get; set; } /// /// 物料名称 @@ -33,6 +34,7 @@ public class PositionCodeEditInput : SfsBaseDataCreateOrUpdateInputBase /// 库位 /// [Display(Name = "库位")] + [Required(ErrorMessage = "{0}是必填项")] public string LocationCode { get; set; } /// /// 库位名称 @@ -48,6 +50,7 @@ public class PositionCodeEditInput : SfsBaseDataCreateOrUpdateInputBase /// 类型 /// [Display(Name = "类型")] + [Required(ErrorMessage = "{0}是必填项")] public EnumRecommendType Type { get; set; } #endregion diff --git a/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/PositionCode/Inputs/PositionCodeImportInput.cs b/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/PositionCode/Inputs/PositionCodeImportInput.cs index 53432b077..825994c1d 100644 --- a/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/PositionCode/Inputs/PositionCodeImportInput.cs +++ b/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/PositionCode/Inputs/PositionCodeImportInput.cs @@ -8,10 +8,10 @@ namespace Win_in.Sfs.Basedata.Application.Contracts; public class PositionCodeImportInput : SfsBaseDataImportInputBase { /// - /// 代码 + /// 位置码 /// [Key] - [Display(Name = "代码")] + [Display(Name = "位置码")] [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] [Required(ErrorMessage = "{0}是必填项")] public string Code { get; set; } @@ -20,6 +20,7 @@ public class PositionCodeImportInput : SfsBaseDataImportInputBase /// [Display(Name = "物料号")] [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + [Required(ErrorMessage = "{0}是必填项")] public string PartCode { get; set; } /// /// 物料名称 @@ -44,6 +45,7 @@ public class PositionCodeImportInput : SfsBaseDataImportInputBase /// [Display(Name = "库位")] [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + [Required(ErrorMessage = "{0}是必填项")] public string LocationCode { get; set; } /// /// 库位名称 @@ -54,8 +56,7 @@ public class PositionCodeImportInput : SfsBaseDataImportInputBase /// /// 标包数量 /// - [Display(Name = "标包数量")] - [Required(ErrorMessage = "{0}是必填项")] + [Display(Name = "标包数量")] public decimal StdPackQty { get; set; } /// /// 类型 diff --git a/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/PositionCode/PositionCodeAppService.cs b/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/PositionCode/PositionCodeAppService.cs index 29bd0b204..043d22231 100644 --- a/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/PositionCode/PositionCodeAppService.cs +++ b/be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/PositionCode/PositionCodeAppService.cs @@ -1,12 +1,17 @@ +using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; +using DocumentFormat.OpenXml.Vml.Office; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Volo.Abp; using Volo.Abp.Caching; +using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; +using Volo.Abp.ObjectMapping; using Volo.Abp.Uow; using Win_in.Sfs.Basedata.Application.Contracts; using Win_in.Sfs.Basedata.Domain; @@ -23,18 +28,27 @@ public class PositionCodeAppService , IPositionCodeAppService { private readonly IPositionCodeManager _manager; - private new readonly IPositionCodeRepository _repository; + + private new readonly IPositionCodeRepository _repository; + - public PositionCodeAppService(IPositionCodeRepository repository, IDistributedCache cache, IPositionCodeManager manager) : base(repository, cache) + public PositionCodeAppService(IPositionCodeRepository repository, + IDistributedCache cache, IPositionCodeManager manager) : base(repository, cache) { base.CreatePolicyName = CategoryPermissions.Create; base.UpdatePolicyName = CategoryPermissions.Update; base.DeletePolicyName = CategoryPermissions.Delete; _manager = manager; _repository = repository; + } - + /// + /// 用来重写 新增实体 + /// + /// + /// + /// [HttpPost("")] [UnitOfWork] public override async Task CreateAsync(PositionCodeEditInput input) @@ -53,33 +67,82 @@ public class PositionCodeAppService var itemBasic = await ItemBasicAppService.GetByCodeAsync(input.PartCode).ConfigureAwait(false); Check.NotNull(itemBasic, "物品代码", $"物品 {input.PartCode} 不存在"); + //如果类型选择为原料,校验物料号类型必须为原料,器具、KItting 的不用加校验 + if (input.Type == EnumRecommendType.W && itemBasic.Type != "10C02") + { + throw new UserFriendlyException($"{input.PartCode} 物料号类型必须为原料"); + } input.PartName = itemBasic.Name; input.PartDesc = itemBasic.Desc1; input.BasicUom = itemBasic.BasicUom; + input.StdPackQty = itemBasic.StdPackQty; var location = await LocationAppService.GetByCodeAsync(input.LocationCode).ConfigureAwait(false); Check.NotNull(location, "库位代码", $"库位 {input.LocationCode} 不存在"); + //如果类型选择为原料,库位的类型必须为原料库位 + if (input.Type == EnumRecommendType.W && location.Type != EnumLocationType.RAW) + { + throw new UserFriendlyException($"{input.LocationCode} 库位的类型必须为原料库位"); + } input.LocationName = location.Name; - if(input.Code.Contains('W')) + if(input.Type== EnumRecommendType.None) { - input.Type = EnumRecommendType.W; + throw new UserFriendlyException($"{input.Type} 位置码类型不正确"); + } + + return await base.CreateAsync(input).ConfigureAwait(false); + } + + /// + /// 用来重写 更新实体 + /// + /// + /// + /// + /// + [HttpPut] + [Route("{id}")] + public override async Task UpdateAsync(Guid id, PositionCodeEditInput input) + { + var entity = await _repository.GetAsync(id).ConfigureAwait(false); + if (entity == null) + { + throw new UserFriendlyException($"{id} 未找到位置码信息"); } - else if (input.Code.Contains('Q')) + var itemEntity = await _repository.FirstOrDefaultAsync(p => p.PartCode == input.PartCode && p.Code!=input.Code).ConfigureAwait(false); + if (itemEntity != null) { - input.Type = EnumRecommendType.Q; + throw new UserFriendlyException($"{input.PartCode} 物品已存在"); } - else if(input.Code.Contains('K')) + + + var itemBasic = await ItemBasicAppService.GetByCodeAsync(input.PartCode).ConfigureAwait(false); + Check.NotNull(itemBasic, "物品代码", $"物品 {input.PartCode} 不存在"); + //如果类型选择为原料,校验物料号类型必须为原料,器具、KItting 的不用加校验 + if (input.Type == EnumRecommendType.W && itemBasic.Type != "10C02") { - input.Type = EnumRecommendType.K; + throw new UserFriendlyException($"{input.PartCode} 物料号类型必须为原料"); } - else + entity.PartName = itemBasic.Name; + entity.PartDesc = itemBasic.Desc1; + entity.BasicUom = itemBasic.BasicUom; + entity.StdPackQty = itemBasic.StdPackQty; + + var location = await LocationAppService.GetByCodeAsync(input.LocationCode).ConfigureAwait(false); + Check.NotNull(location, "库位代码", $"库位 {input.LocationCode} 不存在"); + //如果类型选择为原料,库位的类型必须为原料库位 + if (input.Type == EnumRecommendType.W && location.Type!= EnumLocationType.RAW) { - input.Type = EnumRecommendType.None; + throw new UserFriendlyException($"{input.LocationCode} 库位的类型必须为原料库位"); } + entity.LocationName = location.Name; - - return await base.CreateAsync(input).ConfigureAwait(false); + await _repository.UpdateAsync(entity).ConfigureAwait(false); + var dto = ObjectMapper.Map(entity); + + return dto; + } /// @@ -94,11 +157,48 @@ public class PositionCodeAppService foreach (var positionCode in addList) { + var itemBasic = await ItemBasicAppService.GetByCodeAsync(positionCode.PartCode).ConfigureAwait(false); + positionCode.PartName = itemBasic.Name; + positionCode.PartDesc = itemBasic.Desc1; + positionCode.BasicUom = itemBasic.BasicUom; + positionCode.StdPackQty = itemBasic.StdPackQty; positionCode.Code = positionCode.Type + positionCode.Code; positionCode.CreatorId= CurrentUser.Id; + var location = await LocationAppService.GetByCodeAsync(positionCode.LocationCode).ConfigureAwait(false); + positionCode.LocationName = location.Name; } return dictionary; } + private async Task CheckPositionCodeInputAsync(PositionCodeImportInput input, List validationRresult) + { + var itemEntity = await _repository.FirstOrDefaultAsync(p => p.PartCode == input.PartCode && p.Code != input.Code).ConfigureAwait(false); + if (itemEntity != null) + { + validationRresult.Add(new ValidationResult($"物品代码{input.PartCode}已存在", new string[] { "物品代码" })); + } + var itemBasic = await ItemBasicAppService.GetByCodeAsync(input.PartCode).ConfigureAwait(false); + //如果类型选择为原料,校验物料号类型必须为原料,器具、KItting 的不用加校验 + if (input.Type == EnumRecommendType.W && itemBasic.Type != "10C02") + { + validationRresult.Add(new ValidationResult($"物品代码{input.PartCode} 物料号类型必须为原料", new string[] { "物料号类型" })); + } + var location = await LocationAppService.GetByCodeAsync(input.LocationCode).ConfigureAwait(false); + //如果类型选择为原料,库位的类型必须为原料库位 + if (input.Type==EnumRecommendType.W && location.Type != EnumLocationType.RAW) + { + validationRresult.Add(new ValidationResult($"库位代码{input.LocationCode} 库位的类型必须为原料库位", new string[] { "库位类型" })); + } + } + + protected override async Task ValidateImportModelAsync(PositionCodeImportInput importInput, List validationRresult) + { + await base.ValidateImportModelAsync(importInput, validationRresult).ConfigureAwait(false); + await CheckPositionCodeInputAsync(importInput, validationRresult).ConfigureAwait(false); + await base.CheckItemBasicItemCodeAsync(importInput.PartCode, validationRresult).ConfigureAwait(false); + await base.CheckRawLocationAsync(importInput.LocationCode, validationRresult).ConfigureAwait(false); + + } + } diff --git a/be/Modules/Shared/src/Win_in.Sfs.Shared.Domain.Shared/Enums/Store/EnumRecommendType.cs b/be/Modules/Shared/src/Win_in.Sfs.Shared.Domain.Shared/Enums/Store/EnumRecommendType.cs index ea81e7e09..4b64c050b 100644 --- a/be/Modules/Shared/src/Win_in.Sfs.Shared.Domain.Shared/Enums/Store/EnumRecommendType.cs +++ b/be/Modules/Shared/src/Win_in.Sfs.Shared.Domain.Shared/Enums/Store/EnumRecommendType.cs @@ -13,20 +13,20 @@ public enum EnumRecommendType None = 0, /// - /// 位置码 + /// 原料 /// - [Display(Name = "位置码")] + [Display(Name = "原料")] W = 1, /// - /// 器具码 + /// 器具 /// - [Display(Name = "器具码")] + [Display(Name = "器具")] Q = 2, /// - /// Kitting箱码 + /// kitting区 /// - [Display(Name = "Kitting箱码")] + [Display(Name = "Kitting区")] K = 3 } diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/ProductRecycleJobs/Inputs/ProductRecycleJobEditInput.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/ProductRecycleJobs/Inputs/ProductRecycleJobEditInput.cs index 3fc12e68e..759bd3f2b 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/ProductRecycleJobs/Inputs/ProductRecycleJobEditInput.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/ProductRecycleJobs/Inputs/ProductRecycleJobEditInput.cs @@ -10,6 +10,13 @@ public class ProductRecycleJobEditInput : SfsJobCreateUpdateInputBase, ISfsJobCr { #region Create + /// + /// 车间 + /// + [Display(Name = "车间")] + [StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")] + public string Workshop { get; set; } + /// /// 上游任务编号 /// diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/ProductRecycleJobs/ProductRecycleJobAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/ProductRecycleJobs/ProductRecycleJobAutoMapperProfile.cs index 87069a2b4..a58f3029c 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/ProductRecycleJobs/ProductRecycleJobAutoMapperProfile.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/ProductRecycleJobs/ProductRecycleJobAutoMapperProfile.cs @@ -13,7 +13,7 @@ public partial class StoreApplicationAutoMapperProfile : Profile .ReverseMap(); CreateMap() - ; + ; CreateMap(); diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/ProductRecycleRequests/ProductRecycleRequestAppService.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/ProductRecycleRequests/ProductRecycleRequestAppService.cs index fa3bcbfa7..b008dcd02 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/ProductRecycleRequests/ProductRecycleRequestAppService.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/ProductRecycleRequests/ProductRecycleRequestAppService.cs @@ -21,6 +21,7 @@ using Volo.Abp.Data; using Volo.Abp.Domain.Entities; using Win_in.Sfs.Shared.Application.Contracts; using Win_in.Sfs.Wms.Inventory.Application.Contracts; +using Win_in.Sfs.Wms.Inventory.Domain; /// /// 产品退拆申请 @@ -102,15 +103,16 @@ public class ProductRecycleRequestAppService : foreach (var detail in productRecycleRequest.Details) { - var balance = await _balanceAppService.GetByItemLocationAndPackingAsync( - string.Empty, - detail.ItemCode, - detail.LocationCode).ConfigureAwait(false); + //var balance = await _balanceAppService.GetByItemLocationAndPackingAsync( + // string.Empty, + // detail.ItemCode, + // detail.LocationCode).ConfigureAwait(false); - if (balance != null) - { - detail.Status = balance.Status; - } + //if (balance != null) + //{ + // detail.Status = balance.Status; + //} + detail.Status = EnumInventoryStatus.OK; var locationDto = await _locationAppService.GetByCodeAsync(detail.LocationCode) .ConfigureAwait(false); @@ -188,15 +190,15 @@ public class ProductRecycleRequestAppService : detail.RawLocationGroup = rawLocation.LocationGroupCode; } - var balance = await BalanceAclService.GetByItemLocationAndPackingAsync( - string.Empty, - detail.ItemCode, - detail.LocationCode).ConfigureAwait(false); + //var balance = await BalanceAclService.GetByItemLocationAndPackingAsync( + // string.Empty, + // detail.ItemCode, + // detail.LocationCode).ConfigureAwait(false); - if (balance != null) - { - detail.Status = balance.Status; - } + //if (balance != null) + //{ + // detail.Status = balance.Status; + //} } #endregion diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/ProductRecycleRequests/ProductRecycleRequestAutoMapperProfile.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/ProductRecycleRequests/ProductRecycleRequestAutoMapperProfile.cs index 5f5d91fbe..fc94e67c3 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/ProductRecycleRequests/ProductRecycleRequestAutoMapperProfile.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/ProductRecycleRequests/ProductRecycleRequestAutoMapperProfile.cs @@ -1,5 +1,6 @@ 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; @@ -25,8 +26,11 @@ public partial class StoreApplicationAutoMapperProfile : Profile CreateMap(); + CreateMap() + .ReverseMap(); + - CreateMap(); + CreateMap() .IgnoreAuditedObjectProperties() @@ -56,5 +60,13 @@ public partial class StoreApplicationAutoMapperProfile : Profile .Ignore(x => x.Number) .Ignore(x => x.Id) .Ignore(x => x.Remark); + + CreateMap() + .ReverseMap(); + + CreateMap() + .ReverseMap(); + + } } 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 465605d0d..64fa4bdb4 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 @@ -92,6 +92,7 @@ public partial class StoreApplicationAutoMapperProfile : Profile IssueJobAutoMapperProfile(); JisDeliverJobAutoMapperProfile(); ProductReceiveJobAutoMapperProfile(); + ProductRecycleJobAutoMapperProfile(); PurchaseReceiptJobAutoMapperProfile(); PurchaseReturnJobAutoMapperProfile(); PutawayJobAutoMapperProfile(); diff --git a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/ProductRecycleRequestEventHandler.cs b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/ProductRecycleRequestEventHandler.cs index 2e0b3a9f8..d2c3ca821 100644 --- a/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/ProductRecycleRequestEventHandler.cs +++ b/be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/ProductRecycleRequestEventHandler.cs @@ -12,6 +12,9 @@ using Win_in.Sfs.Wms.Store.Event.BusinessRequest; namespace Win_in.Sfs.Wms.Store.Event.Stores; using Application.Contracts; +using Volo.Abp.ObjectMapping; +using Win_in.Sfs.Wms.Inventory.Application.Contracts; +using static Win_in.Sfs.Wms.Store.Domain.Shared.StoreSettings; public class ProductRecycleRequestEventHandler : StoreEventHandlerBase @@ -19,21 +22,32 @@ public class ProductRecycleRequestEventHandler , ILocalEventHandler> , ILocalEventHandler>> { + private readonly IProductRecycleJobAppService _productRecycleJobAppService; private readonly IProductRecycleNoteAppService _productRecycleNoteApp; private readonly IBackFlushNoteAppService _backFlushNoteApp; private readonly IBomAppService _bomApp; private readonly IProductRecycleRequestManager _productRecycleRequestManager; + private readonly IBalanceAppService _balanceAppService; + private readonly ILocationAppService _locationAppService; public ProductRecycleRequestEventHandler( IProductRecycleNoteAppService productRecycleNoteApp, + IBalanceAppService balanceAppService, + ILocationAppService locationAppService, IBackFlushNoteAppService backFlushNoteApp, - IBomAppService bomApp, IProductRecycleRequestManager - productRecycleRequestManager) + IBomAppService bomApp, + IProductRecycleRequestManager productRecycleRequestManager, + IProductRecycleJobAppService productRecycleJobAppService + ) { _productRecycleNoteApp = productRecycleNoteApp; _backFlushNoteApp = backFlushNoteApp; _bomApp = bomApp; _productRecycleRequestManager = productRecycleRequestManager; + _balanceAppService = balanceAppService; + _locationAppService = locationAppService; + _productRecycleJobAppService = productRecycleJobAppService; + } /// @@ -60,6 +74,8 @@ public class ProductRecycleRequestEventHandler var entitys = eventData.Entity; foreach (var entity in entitys) { + entity.AutoAgree = true; + entity.DirectCreateNote = false; if (entity.AutoSubmit) { await _productRecycleRequestManager.SubmitAsync(entity).ConfigureAwait(false); @@ -77,15 +93,125 @@ public class ProductRecycleRequestEventHandler var productRecycle = await BuildProductRecycleNoteAsync(entity).ConfigureAwait(false); await _productRecycleNoteApp.CreateAsync(productRecycle).ConfigureAwait(false); - - // var backFlushs = await BuildFlushNotesAsync(entity); - // - // await _backFlushNoteApp.CreateManyAsync(backFlushs); + + } + else + { + var productRecycleJobs = await BuildProductRecycleJobsAsync(entity).ConfigureAwait(false); + await _productRecycleJobAppService.CreateManyAsync(productRecycleJobs).ConfigureAwait(false); } } #region 私有 + private async Task> BuildProductRecycleJobsAsync(ProductRecycleRequest request) + { + var jobs = new List(); + + var transactionType = await TransactionTypeAclService.GetByTransTypeAsync(EnumTransType.ProductRecycle, EnumTransSubType.None).ConfigureAwait(false);//库存事务 + + var job = ObjectMapper.Map(request); + + //job.Details = new List(); + + foreach (var detail in request.Details) + { + + //创建详情 + var jobDetails = await BuildProductRecycleInputsAsync(request, detail, transactionType).ConfigureAwait(false); + if (!jobDetails.Any()) + { + continue; + } + + var fromLocationCode = jobDetails[0].LocationCode; + var fromLocation = await _locationAppService.GetByCodeAsync(fromLocationCode).ConfigureAwait(false); + job = BuildProductRecycleJobCreateInput(request, fromLocation); + job.Details.Clear(); + jobs.Add(job); + job.Details.AddRange(jobDetails); + + } + + return jobs; + } + + private ProductRecycleJobEditInput BuildProductRecycleJobCreateInput(ProductRecycleRequest productRecycleRequest, LocationDTO fromLocation) + { + ProductRecycleJobEditInput job; + job = ObjectMapper.Map(productRecycleRequest); + job.JobType = EnumJobType.ProductionReturnJob; + job.JobStatus = EnumJobStatus.Open; + job.WorkGroupCode = fromLocation.WorkGroupCode; + job.WarehouseCode = fromLocation.WarehouseCode; + job.Worker = productRecycleRequest.Worker; + job.Workshop= fromLocation.AreaCode; + if (job.Worker==null) + { + job.Worker = "admin"; + } + //job.MaterialRequestNumber = productRecycleRequest.Number; + return job; + } + + private async Task> BuildProductRecycleInputsAsync(ProductRecycleRequest productRecycleRequest, + ProductRecycleRequestDetail productRecycleRequestDetail, TransactionTypeDTO transactionType) + { + var jobDetails = new List(); + //var input = new RecommendBalanceRequestInput() + //{ + // ItemCode = productRecycleRequestDetail.ItemCode, + // Qty = productRecycleRequestDetail.Qty, + // LocationTypes = transactionType.OutLocationTypes, + // LocationAreas = new List { productRecycleRequestDetail.LocationArea }, + // Statuses = transactionType.OutInventoryStatuses, + //}; + //获取推荐库存 + var recommendList = await _balanceAppService.GetListByItemCodeAsync(productRecycleRequestDetail.ItemCode).ConfigureAwait(false); + //没有推荐库存时 跳过此明细 不生成任务 + if (recommendList.Count != 0) + { + foreach (var recommend in recommendList) + { + if(recommend.LocationCode== productRecycleRequestDetail.LocationCode) + { + var detail = await BuildProductRecycleJobDetailAsync(productRecycleRequestDetail, recommend).ConfigureAwait(false); + + jobDetails.Add(detail); + } + + + } + } + return jobDetails; + } + + private async Task BuildProductRecycleJobDetailAsync(ProductRecycleRequestDetail productRecycleRequestDetail, BalanceDTO balance) + { + + var detail = ObjectMapper.Map(productRecycleRequestDetail); + + detail.RecommendToLocationErpCode = balance.LocationErpCode; + detail.RecommendToLocationCode = balance.LocationCode; + detail.RecommendPackingCode = balance.PackingCode; + detail.RecommendContainerCode = balance.ContainerCode; + detail.RecommendSupplierBatch = balance.SupplierBatch; + detail.RecommendProduceDate = balance.ProduceDate; + detail.RecommendExpireDate = balance.ExpireDate; + detail.RecommendLot = balance.Lot; + detail.RecommendProduceDate = balance.ProduceDate; + detail.RecommendArriveDate = balance.ArriveDate; + detail.RecommendQty = balance.Qty; + detail.Uom = balance.Uom; + + + await Task.CompletedTask.ConfigureAwait(false); + return detail; + + } + + + private async Task BuildProductRecycleNoteAsync(ProductRecycleRequest request) { var createInput = ObjectMapper.Map(request);