|
|
@ -1,19 +1,17 @@ |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Linq; |
|
|
|
using System.Text; |
|
|
|
using System.Text.Json; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using AutoMapper.Internal; |
|
|
|
using Castle.Components.DictionaryAdapter; |
|
|
|
using Volo.Abp; |
|
|
|
using Volo.Abp.EventBus; |
|
|
|
using Win_in.Sfs.Basedata.Application.Contracts; |
|
|
|
using Win_in.Sfs.Shared.Domain.Shared; |
|
|
|
using Win_in.Sfs.Shared.Domain.Shared.Enums.Store; |
|
|
|
using Win_in.Sfs.Shared.Event; |
|
|
|
using Win_in.Sfs.Wms.Inventory.Application.Contracts; |
|
|
|
using Win_in.Sfs.Wms.Store.Application.Contracts; |
|
|
|
using Win_in.Sfs.Wms.Store.Domain; |
|
|
|
using Win_in.Sfs.Wms.Store.Domain.Shared; |
|
|
|
|
|
|
|
namespace Win_in.Sfs.Wms.Store.Event.BusinessRequest; |
|
|
|
|
|
|
@ -30,17 +28,21 @@ public class KittingIssueRequestEventHandler |
|
|
|
private readonly IProductionLineItemAppService _productionLineItemAppService; |
|
|
|
private readonly ILocationAppService _locationAppService; |
|
|
|
private readonly IBalanceAppService _balanceAppService; |
|
|
|
//private readonly IKittingIssueRequestManager _kittingIssueRequestManager;
|
|
|
|
|
|
|
|
public KittingIssueRequestEventHandler( |
|
|
|
IKittingIssueJobAppService kittingIssueJobAppService, IProductionLineAppService productionLineAppService, |
|
|
|
ILocationAppService locationAppService, |
|
|
|
IBalanceAppService balanceAppService, IProductionLineItemAppService productionLineItemAppService) |
|
|
|
IBalanceAppService balanceAppService, IProductionLineItemAppService productionLineItemAppService |
|
|
|
//, IKittingIssueRequestManager kittingIssueRequestManager
|
|
|
|
) |
|
|
|
{ |
|
|
|
_kittingIssueJobAppService = kittingIssueJobAppService; |
|
|
|
_productionLineAppService = productionLineAppService; |
|
|
|
_locationAppService = locationAppService; |
|
|
|
_balanceAppService = balanceAppService; |
|
|
|
_productionLineItemAppService = productionLineItemAppService; |
|
|
|
//_kittingIssueRequestManager = kittingIssueRequestManager;
|
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
@ -49,7 +51,9 @@ public class KittingIssueRequestEventHandler |
|
|
|
/// <param name="eventData">Event data</param>
|
|
|
|
public virtual async Task HandleEventAsync(SfsCreatedEntityEventData<KittingIssueRequest> eventData) |
|
|
|
{ |
|
|
|
await Task.CompletedTask.ConfigureAwait(false); |
|
|
|
var entity = eventData.Entity; |
|
|
|
|
|
|
|
await CreateAllKittingIssueJobAsync(entity).ConfigureAwait(false); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
@ -58,6 +62,8 @@ public class KittingIssueRequestEventHandler |
|
|
|
/// <param name="eventData">Event data</param>
|
|
|
|
public virtual async Task HandleEventAsync(SfsCreatedEntityEventData<List<KittingIssueRequest>> eventData) |
|
|
|
{ |
|
|
|
var entity = eventData.Entity; |
|
|
|
|
|
|
|
await Task.CompletedTask.ConfigureAwait(false); |
|
|
|
} |
|
|
|
|
|
|
@ -70,22 +76,7 @@ public class KittingIssueRequestEventHandler |
|
|
|
{ |
|
|
|
var entity = eventData.Entity; |
|
|
|
|
|
|
|
List<KittingIssueJobEditInput> kittingIssueJobs = new EditableList<KittingIssueJobEditInput>(); |
|
|
|
|
|
|
|
//switch (entity.Type)
|
|
|
|
//{
|
|
|
|
// case nameof(EnumIssueType.BoxQty):
|
|
|
|
// kittingIssueJobs = await CreateKittingIssueJobWithBoxQtyTypeAsync(entity).ConfigureAwait(false);
|
|
|
|
// break;
|
|
|
|
// case nameof(EnumIssueType.Qty):
|
|
|
|
// kittingIssueJobs = await CreateKittingIssueJobWithQtyTypeAsync(entity).ConfigureAwait(false);
|
|
|
|
// break;
|
|
|
|
//}
|
|
|
|
|
|
|
|
if (kittingIssueJobs.Any()) |
|
|
|
{ |
|
|
|
await _kittingIssueJobAppService.CreateManyAsync(kittingIssueJobs).ConfigureAwait(false); |
|
|
|
} |
|
|
|
await CreateAllKittingIssueJobAsync(entity).ConfigureAwait(false); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
@ -116,106 +107,98 @@ public class KittingIssueRequestEventHandler |
|
|
|
#region 按数量叫料
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 创建注塑任务
|
|
|
|
/// 创建注塑任务-按数量
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="kittingIssueRequest"></param>
|
|
|
|
/// <param name="kittingIssueRequestDetails"></param>
|
|
|
|
/// <param name="recommendbalanceDtos"></param>
|
|
|
|
/// <param name="useBalanceList"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <exception cref="UserFriendlyException"></exception>
|
|
|
|
private async Task<List<KittingIssueJobEditInput>> CreateKittingIssueJobWithQtyTypeAsync |
|
|
|
(KittingIssueRequest kittingIssueRequest) |
|
|
|
(KittingIssueRequest kittingIssueRequest, List<KittingIssueRequestDetail> kittingIssueRequestDetails, |
|
|
|
List<BalanceDTO> recommendbalanceDtos, |
|
|
|
List<BalanceDTO> useBalanceList) |
|
|
|
{ |
|
|
|
var jobs = new List<KittingIssueJobEditInput>(); |
|
|
|
//用来临时存放所有未生成任务的发料集合 如果生成完了再这里去掉
|
|
|
|
var tempDetailDtos = |
|
|
|
ObjectMapper.Map<List<KittingIssueRequestDetail>, List<KittingIssueRequestDetailDTO>>( |
|
|
|
kittingIssueRequestDetails); |
|
|
|
|
|
|
|
var toLocationCodes = kittingIssueRequest.Details.Select(p => p.ToLocationCode).Distinct().ToList(); //所有发送库位的集合
|
|
|
|
var toLocations = await _locationAppService.GetByCodesAsync(toLocationCodes).ConfigureAwait(false); //所有库位的集合
|
|
|
|
var kittingIssueJobDetailInputs = new List<KittingIssueJobDetailInput>(); |
|
|
|
|
|
|
|
var kittingIssueRequestDetails = kittingIssueRequest.Details.Where(p => p.ToBeIssuedQty > 0); //所有还没发送物品的集合
|
|
|
|
foreach (var kittingIssueRequestDetail in kittingIssueRequestDetails) //如果有还有剩余未叫料的数量 则创建新的任务
|
|
|
|
if (recommendbalanceDtos != null && recommendbalanceDtos.Count > 0) |
|
|
|
{ |
|
|
|
var toLocation = |
|
|
|
toLocations.FirstOrDefault(p => p.Code == kittingIssueRequestDetail.ToLocationCode); //判断目标库位是否存在
|
|
|
|
Check.NotNull(toLocation, "库位代码", $"库位 {kittingIssueRequestDetail.ToLocationCode} 不存在"); |
|
|
|
|
|
|
|
//创建详情
|
|
|
|
var jobDetails = |
|
|
|
await CreateKittingIssueJobDetailInputsWithQtyTypeAsync(kittingIssueRequest, kittingIssueRequestDetail, |
|
|
|
toLocation.LocationGroupCode).ConfigureAwait(false); |
|
|
|
if (!jobDetails.Any()) |
|
|
|
var queue = new Queue<BalanceDTO>(recommendbalanceDtos); |
|
|
|
while (queue.TryDequeue(out var balanceDto)) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
var fromLocationCode = jobDetails[0].RecommendFromLocationCode; |
|
|
|
var fromLocation = await _locationAppService.GetByCodeAsync(fromLocationCode).ConfigureAwait(false); |
|
|
|
var job = jobs.FirstOrDefault(p => p.WorkGroupCode == fromLocation?.WorkGroupCode); |
|
|
|
if (job == null || job.Details.Any(p => p.RecommendToLocationCode != kittingIssueRequestDetail.ToLocationCode)) |
|
|
|
{ |
|
|
|
job = await BuildKittingIssueJobCreateInputWithQtyTypeAsync(kittingIssueRequest, fromLocation) |
|
|
|
.ConfigureAwait(false); |
|
|
|
jobs.Add(job); |
|
|
|
} |
|
|
|
var next = false; |
|
|
|
|
|
|
|
job.Details.AddRange(jobDetails); |
|
|
|
if (kittingIssueRequestDetail.ToBeIssuedQty < 0) |
|
|
|
{ |
|
|
|
kittingIssueRequestDetail.Status = EnumStatus.Close; |
|
|
|
} |
|
|
|
} |
|
|
|
var temp = tempDetailDtos.ToList(); |
|
|
|
|
|
|
|
jobs = jobs.Where(p => p.Details.Any()).ToList(); |
|
|
|
foreach (var tempDetailDto in tempDetailDtos) |
|
|
|
{ |
|
|
|
//未发送的数量
|
|
|
|
tempDetailDto.Qty = tempDetailDto.Qty - tempDetailDto.IssuedQty; |
|
|
|
|
|
|
|
if (tempDetailDto.Qty > balanceDto.Qty) //需求量大于 这条推荐库存的余额
|
|
|
|
{ |
|
|
|
tempDetailDto.Qty -= balanceDto.Qty; |
|
|
|
} |
|
|
|
else if (tempDetailDto.Qty <= balanceDto.Qty) |
|
|
|
{ |
|
|
|
temp.Remove(tempDetailDto); |
|
|
|
balanceDto.Qty = tempDetailDto.Qty; |
|
|
|
} |
|
|
|
|
|
|
|
kittingIssueJobDetailInputs.Add( |
|
|
|
await BuildKittingIssueJobDetailWithQtyTypeAsync(tempDetailDto, balanceDto) |
|
|
|
.ConfigureAwait(false)); |
|
|
|
useBalanceList.Add(balanceDto); |
|
|
|
|
|
|
|
if (balanceDto.Qty <= 0) |
|
|
|
{ |
|
|
|
next = true; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var openRequestDetails = |
|
|
|
kittingIssueRequest.Details.Where(p => p.Status != EnumStatus.Close).ToList(); |
|
|
|
tempDetailDtos = temp; |
|
|
|
|
|
|
|
if (!openRequestDetails.Any()) |
|
|
|
{ |
|
|
|
return jobs; |
|
|
|
if (next) |
|
|
|
{ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var enableMultipleCreateKittingIssueJob = await SettingManager |
|
|
|
.IsTrueAsync(StoreSettings.MaterialRequest.EnableMultipleCreateIssueJob).ConfigureAwait(false); |
|
|
|
if (enableMultipleCreateKittingIssueJob) |
|
|
|
if (kittingIssueJobDetailInputs.Any()) |
|
|
|
{ |
|
|
|
//kittingIssueRequest.Partial();
|
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
var sb = new StringBuilder(); |
|
|
|
foreach (var openRequestDetail in openRequestDetails) |
|
|
|
{ |
|
|
|
sb.AppendLine( |
|
|
|
$"{openRequestDetail.ItemCode}请求数量 {openRequestDetail.Qty},可用库存数量 {openRequestDetail.IssuedQty}"); |
|
|
|
} |
|
|
|
|
|
|
|
throw new UserFriendlyException($"{sb} 可用库存数量不足, 无法生成发料任务"); |
|
|
|
var kittingIssueJobEditInput = new KittingIssueJobEditInput(); |
|
|
|
kittingIssueJobEditInput = await BuildKittingIssueJobCreateInputWithQtyTypeAsync(kittingIssueRequest, |
|
|
|
kittingIssueRequestDetails.First()).ConfigureAwait(false); |
|
|
|
kittingIssueJobEditInput.Details = kittingIssueJobDetailInputs; |
|
|
|
jobs.Add(kittingIssueJobEditInput); |
|
|
|
} |
|
|
|
|
|
|
|
return jobs; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 构造注塑任务
|
|
|
|
/// 构造注塑任务-按数量
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="kittingIssueRequest"></param>
|
|
|
|
/// <param name="fromLocation"></param>
|
|
|
|
/// <param name="requestDetailInput"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
private async Task<KittingIssueJobEditInput> BuildKittingIssueJobCreateInputWithQtyTypeAsync( |
|
|
|
KittingIssueRequest kittingIssueRequest, |
|
|
|
LocationDTO fromLocation) |
|
|
|
KittingIssueRequest kittingIssueRequest, KittingIssueRequestDetail requestDetailInput) |
|
|
|
{ |
|
|
|
KittingIssueJobEditInput job; |
|
|
|
job = ObjectMapper.Map<KittingIssueRequest, KittingIssueJobEditInput>(kittingIssueRequest); |
|
|
|
var job = ObjectMapper.Map<KittingIssueRequest, KittingIssueJobEditInput>(kittingIssueRequest); |
|
|
|
job.JobType = EnumJobType.IssueJob; |
|
|
|
job.JobStatus = EnumJobStatus.Open; |
|
|
|
job.WorkGroupCode = fromLocation.WorkGroupCode; |
|
|
|
job.WarehouseCode = fromLocation.WarehouseCode; |
|
|
|
job.WorkGroupCode = requestDetailInput.ToLocationGroup; |
|
|
|
job.WarehouseCode = requestDetailInput.ToWarehouseCode; |
|
|
|
job.Worker = kittingIssueRequest.Worker; |
|
|
|
if (string.IsNullOrEmpty(job.Worker)) |
|
|
|
{ |
|
|
|
job.Worker = "admin"; |
|
|
|
} |
|
|
|
|
|
|
|
job.KittingRequestNumber = kittingIssueRequest.Number; |
|
|
|
|
|
|
|
await Task.CompletedTask.ConfigureAwait(false); |
|
|
@ -223,87 +206,35 @@ public class KittingIssueRequestEventHandler |
|
|
|
return job; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 创建注塑任务明细
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="kittingIssueRequest"></param>
|
|
|
|
/// <param name="kittingIssueRequestDetail"></param>
|
|
|
|
/// <param name="toLocationGroupCode"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <exception cref="UserFriendlyException"></exception>
|
|
|
|
private async Task<List<KittingIssueJobDetailInput>> CreateKittingIssueJobDetailInputsWithQtyTypeAsync( |
|
|
|
KittingIssueRequest kittingIssueRequest, |
|
|
|
KittingIssueRequestDetail kittingIssueRequestDetail, string toLocationGroupCode) |
|
|
|
{ |
|
|
|
var jobDetails = new List<KittingIssueJobDetailInput>(); |
|
|
|
|
|
|
|
//获取推荐库存
|
|
|
|
var productionLineDto = await _productionLineAppService |
|
|
|
.GetByLocationCodeAsync(kittingIssueRequestDetail.ToLocationCode).ConfigureAwait(false); |
|
|
|
var productionLineItemDtos = await _productionLineItemAppService |
|
|
|
.GetByProductLineCodeAsync(productionLineDto.Code).ConfigureAwait(false); |
|
|
|
if (productionLineItemDtos == null) |
|
|
|
{ |
|
|
|
throw new UserFriendlyException($"物品代码【{kittingIssueRequestDetail.ItemCode}】没有对应的【生产线物品关系】"); |
|
|
|
} |
|
|
|
|
|
|
|
var productionLineItemDto = |
|
|
|
productionLineItemDtos.FirstOrDefault(p => p.ItemCode == kittingIssueRequestDetail.ItemCode); |
|
|
|
var input = new RecommendBalanceRequestInput |
|
|
|
{ |
|
|
|
ItemCode = kittingIssueRequestDetail.ItemCode, |
|
|
|
Qty = kittingIssueRequestDetail.ToBeIssuedQty, |
|
|
|
//LocationTypes = transactionType.OutLocationTypes, productionLineItemDto.RawLocationCodeListJson
|
|
|
|
Statuses = new EditableList<EnumInventoryStatus> { EnumInventoryStatus.OK }, |
|
|
|
Locations = JsonSerializer.Deserialize<List<string>>(productionLineItemDto.RawLocationCodeListJson) |
|
|
|
}; |
|
|
|
|
|
|
|
var recommendList = await _balanceAppService.GetRecommendBalancesByLocationsAsync(input).ConfigureAwait(false); |
|
|
|
//没有推荐库存时 跳过此明细 不生成任务
|
|
|
|
if (recommendList.Count != 0) |
|
|
|
{ |
|
|
|
foreach (var recommend in recommendList) |
|
|
|
{ |
|
|
|
//拿走需求量
|
|
|
|
var detail = |
|
|
|
await BuildKittingIssueJobDetailWithQtyTypeAsync(kittingIssueRequestDetail, recommend, |
|
|
|
toLocationGroupCode) |
|
|
|
.ConfigureAwait(false); |
|
|
|
if (kittingIssueRequest.UseOnTheWayLocation) |
|
|
|
{ |
|
|
|
//获取在途库
|
|
|
|
var locationDto = await _locationAppService.GetFirstByTypeAsync(EnumLocationType.TRANSPORT) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
detail.OnTheWayLocationCode = locationDto.Code; |
|
|
|
} |
|
|
|
|
|
|
|
jobDetails.Add(detail); |
|
|
|
kittingIssueRequestDetail.IssuedQty += recommend.Qty; |
|
|
|
|
|
|
|
//await _kittingIssueRequestManager.UpdateDetailsAsync(kittingIssueRequest).ConfigureAwait(false);
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return jobDetails; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 构造注塑任务明细
|
|
|
|
/// 构造注塑任务明细-按数量
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="kittingIssueRequestDetail"></param>
|
|
|
|
/// <param name="balance"></param>
|
|
|
|
/// <param name="toLocationGroupCode"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
private async Task<KittingIssueJobDetailInput> BuildKittingIssueJobDetailWithQtyTypeAsync( |
|
|
|
KittingIssueRequestDetail kittingIssueRequestDetail, BalanceDTO balance, string toLocationGroupCode) |
|
|
|
KittingIssueRequestDetailDTO kittingIssueRequestDetail, BalanceDTO balance) |
|
|
|
{ |
|
|
|
//ProductionLineDTO prodLine = await _productionLineAppService.GetByLocationGroupCodeAsync(toLocationGroupCode).ConfigureAwait(false);
|
|
|
|
|
|
|
|
var detail = ObjectMapper.Map<BalanceDTO, KittingIssueJobDetailInput>(balance); |
|
|
|
var detail = new KittingIssueJobDetailInput(); |
|
|
|
detail.RequestLocationCode = kittingIssueRequestDetail.ToLocationCode; |
|
|
|
detail.PositionCode = kittingIssueRequestDetail.PositionCode; |
|
|
|
detail.RecommendType = kittingIssueRequestDetail.RecommendType; |
|
|
|
detail.Uom = balance.Uom; |
|
|
|
detail.ItemCode= balance.ItemCode; |
|
|
|
detail.ItemDesc2= balance.ItemDesc2; |
|
|
|
detail.ItemDesc1= balance.ItemDesc1; |
|
|
|
detail.ItemName= balance.ItemName; |
|
|
|
detail.ProdLine= kittingIssueRequestDetail.ProdLine; |
|
|
|
detail.RequestQty = balance.Qty; |
|
|
|
detail.StdPackQty = kittingIssueRequestDetail.StdPackQty; |
|
|
|
detail.Status = balance.Status; |
|
|
|
|
|
|
|
detail.RequestLocationErpCode = kittingIssueRequestDetail.ToLocationErpCode; |
|
|
|
detail.RequestLocationArea = kittingIssueRequestDetail.ToLocationArea; |
|
|
|
detail.RequestWarehouseCode = kittingIssueRequestDetail.ToWarehouseCode; |
|
|
|
detail.RequestLocationGroup = kittingIssueRequestDetail.ToLocationGroup; |
|
|
|
detail.RequestLocationCode = kittingIssueRequestDetail.ToLocationCode; |
|
|
|
|
|
|
|
detail.RecommendFromPackingCode = balance.PackingCode; |
|
|
|
detail.RecommendFromContainerCode = balance.ContainerCode; |
|
|
@ -313,21 +244,69 @@ public class KittingIssueRequestEventHandler |
|
|
|
detail.RecommendFromLot = balance.Lot; |
|
|
|
detail.RecommendFromProduceDate = balance.ProduceDate; |
|
|
|
detail.RecommendFromArriveDate = balance.ArriveDate; |
|
|
|
detail.RecommendFromQty = balance.Qty; |
|
|
|
detail.RecommendFromContainerCode= balance.ContainerCode; |
|
|
|
detail.RecommendFromPackingCode= balance.PackingCode; |
|
|
|
|
|
|
|
detail.RecommendToPackingCode = balance.PackingCode; |
|
|
|
detail.RecommendToContainerCode = balance.ContainerCode; |
|
|
|
detail.RecommendToSupplierBatch = balance.SupplierBatch; |
|
|
|
detail.RecommendToProduceDate = balance.ProduceDate; |
|
|
|
detail.RecommendToExpireDate = balance.ExpireDate; |
|
|
|
detail.RecommendToLot = balance.Lot; |
|
|
|
detail.RecommendToProduceDate = balance.ProduceDate; |
|
|
|
detail.RecommendToArriveDate = balance.ArriveDate; |
|
|
|
detail.RecommendToQty = balance.Qty; |
|
|
|
detail.RecommendToContainerCode = balance.ContainerCode; |
|
|
|
detail.RecommendToPackingCode = balance.PackingCode; |
|
|
|
|
|
|
|
detail.RecommendFromLocationArea = balance.LocationArea; |
|
|
|
detail.RecommendFromLocationCode = balance.LocationCode; |
|
|
|
detail.RecommendFromLocationErpCode = balance.LocationErpCode; |
|
|
|
detail.RecommendFromLocationGroup = balance.LocationGroup; |
|
|
|
detail.RecommendFromWarehouseCode = balance.WarehouseCode; |
|
|
|
detail.RecommendFromQty = balance.Qty; |
|
|
|
detail.Uom = balance.Uom; |
|
|
|
|
|
|
|
detail.RecommendToLocationCode = kittingIssueRequestDetail.ToLocationCode; |
|
|
|
detail.RecommendToLocationErpCode = kittingIssueRequestDetail.ToLocationErpCode; |
|
|
|
detail.RecommendToLocationArea = kittingIssueRequestDetail.ToLocationArea; |
|
|
|
detail.RecommendToWarehouseCode = kittingIssueRequestDetail.ToWarehouseCode; |
|
|
|
detail.RecommendToLocationGroup = kittingIssueRequestDetail.ToLocationGroup; |
|
|
|
|
|
|
|
detail.TransferLibFromPackingCode = balance.PackingCode; |
|
|
|
detail.TransferLibFromContainerCode = balance.ContainerCode; |
|
|
|
detail.TransferLibFromSupplierBatch = balance.SupplierBatch; |
|
|
|
detail.TransferLibFromProduceDate = balance.ProduceDate; |
|
|
|
detail.TransferLibFromExpireDate = balance.ExpireDate; |
|
|
|
detail.TransferLibFromLot = balance.Lot; |
|
|
|
detail.TransferLibFromProduceDate = balance.ProduceDate; |
|
|
|
detail.TransferLibFromArriveDate = balance.ArriveDate; |
|
|
|
detail.TransferLibFromQty = balance.Qty; |
|
|
|
detail.TransferLibFromContainerCode= balance.ContainerCode; |
|
|
|
detail.TransferLibFromPackingCode = balance.PackingCode; |
|
|
|
|
|
|
|
detail.TransferLibToPackingCode = balance.PackingCode; |
|
|
|
detail.TransferLibToContainerCode = balance.ContainerCode; |
|
|
|
detail.TransferLibToSupplierBatch = balance.SupplierBatch; |
|
|
|
detail.TransferLibToProduceDate = balance.ProduceDate; |
|
|
|
detail.TransferLibToExpireDate = balance.ExpireDate; |
|
|
|
detail.TransferLibToLot = balance.Lot; |
|
|
|
detail.TransferLibToProduceDate = balance.ProduceDate; |
|
|
|
detail.TransferLibToArriveDate = balance.ArriveDate; |
|
|
|
detail.TransferLibToQty = balance.Qty; |
|
|
|
detail.TransferLibToPackingCode = balance.PackingCode; |
|
|
|
|
|
|
|
detail.TransferLibFromLocationArea = balance.LocationArea; |
|
|
|
detail.TransferLibFromLocationCode = balance.LocationCode; |
|
|
|
detail.TransferLibFromLocationErpCode = balance.LocationErpCode; |
|
|
|
detail.TransferLibFromLocationGroup = balance.LocationGroup; |
|
|
|
detail.TransferLibFromWarehouseCode = balance.WarehouseCode; |
|
|
|
|
|
|
|
detail.TransferLibToLocationCode = kittingIssueRequestDetail.ToLocationCode; |
|
|
|
detail.TransferLibToLocationErpCode = kittingIssueRequestDetail.ToLocationErpCode; |
|
|
|
detail.TransferLibToLocationArea = kittingIssueRequestDetail.ToLocationArea; |
|
|
|
detail.TransferLibToWarehouseCode = kittingIssueRequestDetail.ToWarehouseCode; |
|
|
|
detail.TransferLibToLocationGroup = kittingIssueRequestDetail.ToLocationGroup; |
|
|
|
|
|
|
|
//detail.ProdLine = prodLine == null ? toLocationGroupCode : prodLine.Code;
|
|
|
|
detail.ProdLine = toLocationGroupCode; |
|
|
|
await Task.CompletedTask.ConfigureAwait(false); |
|
|
|
return detail; |
|
|
|
} |
|
|
@ -337,72 +316,71 @@ public class KittingIssueRequestEventHandler |
|
|
|
#region 按箱叫料
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 创建注塑任务
|
|
|
|
/// 创建注塑任务 按箱叫料-按箱
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="kittingIssueRequest"></param>
|
|
|
|
/// <param name="kittingIssueRequestDetailList"></param>
|
|
|
|
/// <param name="recommendbalanceDtos"></param>
|
|
|
|
/// <param name="useBalanceList"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <exception cref="UserFriendlyException"></exception>
|
|
|
|
private async Task<List<KittingIssueJobEditInput>> CreateKittingIssueJobWithBoxQtyTypeAsync |
|
|
|
(KittingIssueRequest kittingIssueRequest) |
|
|
|
( |
|
|
|
KittingIssueRequest kittingIssueRequest, |
|
|
|
List<KittingIssueRequestDetail> kittingIssueRequestDetailList, |
|
|
|
List<BalanceDTO> recommendbalanceDtos, |
|
|
|
List<BalanceDTO> useBalanceList) |
|
|
|
{ |
|
|
|
var inputJobs = new List<KittingIssueJobEditInput>(); |
|
|
|
var inputExpectOutEditInput = new ExpectOutEditInput(); |
|
|
|
//已用的库存的箱码集合
|
|
|
|
var useBalanceList = new List<string>(); |
|
|
|
|
|
|
|
var groupByItemCodeAndLocationCode = |
|
|
|
kittingIssueRequest.Details.GroupBy(p => new { p.ItemCode, p.ToLocationCode }); |
|
|
|
|
|
|
|
//已用的库存的集合
|
|
|
|
useBalanceList = useBalanceList; |
|
|
|
|
|
|
|
foreach (var locationCodeItemCodeGroup in groupByItemCodeAndLocationCode) |
|
|
|
foreach (var detail in kittingIssueRequestDetailList) |
|
|
|
{ |
|
|
|
var inputDetails = kittingIssueRequest.Details.Where(p => |
|
|
|
p.ItemCode == locationCodeItemCodeGroup.Key.ItemCode && |
|
|
|
p.ToLocationCode == locationCodeItemCodeGroup.Key.ToLocationCode); |
|
|
|
var inputDetailTemplate = inputDetails.First(); |
|
|
|
//当前零件的集合
|
|
|
|
var inputDetails = kittingIssueRequestDetailList; |
|
|
|
//获取请求下 这个零件和这个库位一个需要多少箱
|
|
|
|
var sumBoxQty = inputDetails.Sum(p => p.BoxQty); |
|
|
|
var sumBoxQty = inputDetails.Sum(p => p.BoxQty-p.IssuedQty); |
|
|
|
//获取生产线
|
|
|
|
var productionLineDto = await _productionLineAppService |
|
|
|
.GetByLocationCodeAsync(inputDetails.First().ToLocationCode).ConfigureAwait(false); |
|
|
|
if (productionLineDto == null) |
|
|
|
{ |
|
|
|
throw new UserFriendlyException($"库位【{inputDetailTemplate.ToLocationCode}】没有对应的【生产线】"); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var productLineCodeAndItemCode = await _productionLineItemAppService |
|
|
|
.GetByProductLineCodeAndItemCodeAsync(productionLineDto.Code, inputDetailTemplate.ItemCode) |
|
|
|
.GetByProductLineCodeAndItemCodeAsync(productionLineDto.Code, detail.ItemCode) |
|
|
|
.ConfigureAwait(false); |
|
|
|
if (productLineCodeAndItemCode == null) |
|
|
|
{ |
|
|
|
throw new UserFriendlyException( |
|
|
|
$"物品代码【{inputDetailTemplate.ItemCode}】在生产线【{productionLineDto.Code}】中没有对应的【生产线物品关系】"); |
|
|
|
$"物品代码【{detail.ItemCode}】在生产线【{productionLineDto.Code}】中没有对应的【生产线物品关系】"); |
|
|
|
} |
|
|
|
|
|
|
|
//获取可用库存
|
|
|
|
var input = new RecommendBalanceRequestInput |
|
|
|
{ |
|
|
|
ItemCode = locationCodeItemCodeGroup.Key.ItemCode, |
|
|
|
Qty = decimal.MaxValue, |
|
|
|
Statuses = new EditableList<EnumInventoryStatus> { EnumInventoryStatus.OK }, |
|
|
|
Locations = JsonSerializer.Deserialize<List<string>>(productLineCodeAndItemCode |
|
|
|
.RawLocationCodeListJson) |
|
|
|
}; |
|
|
|
var usableList = await _balanceAppService.GetUsableListAsync(input).ConfigureAwait(false); |
|
|
|
usableList = usableList.Where(p => !useBalanceList.Contains(p.PackingCode)).ToList(); |
|
|
|
//可用库存
|
|
|
|
var usableList = recommendbalanceDtos; |
|
|
|
usableList = usableList.Where(p => !useBalanceList.Select(p => p.PackingCode).Contains(p.PackingCode)) |
|
|
|
.ToList(); |
|
|
|
if (usableList.Any()) |
|
|
|
{ |
|
|
|
for (var i = 0; i < sumBoxQty; i++) |
|
|
|
{ |
|
|
|
var firstUsable = usableList.First(); |
|
|
|
useBalanceList.Add(firstUsable.PackingCode); |
|
|
|
usableList.Remove(firstUsable); |
|
|
|
|
|
|
|
var kittingIssueJobEditInput = |
|
|
|
await BuildKittingIssueJobCreateInputWithBoxQtyTypeAsync(kittingIssueRequest, inputDetailTemplate, |
|
|
|
firstUsable) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
inputJobs.Add(kittingIssueJobEditInput); |
|
|
|
if (usableList.Any()) |
|
|
|
{ |
|
|
|
var firstUsable = usableList.First(); |
|
|
|
useBalanceList.Add(firstUsable); |
|
|
|
usableList.Remove(firstUsable); |
|
|
|
|
|
|
|
var kittingIssueJobEditInput = |
|
|
|
await BuildKittingIssueJobCreateInputWithBoxQtyTypeAsync(kittingIssueRequest, |
|
|
|
detail, firstUsable) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
inputJobs.Add(kittingIssueJobEditInput); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -411,7 +389,7 @@ public class KittingIssueRequestEventHandler |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 构造注塑任务
|
|
|
|
/// 构造注塑任务-按箱
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="kittingIssueRequest"></param>
|
|
|
|
/// <param name="kittingIssueRequestDetail"></param>
|
|
|
@ -438,7 +416,7 @@ public class KittingIssueRequestEventHandler |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 构造注塑任务明细
|
|
|
|
/// 构造注塑任务明细-按箱
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="kittingIssueRequestDetail"></param>
|
|
|
|
/// <param name="balance"></param>
|
|
|
@ -453,6 +431,7 @@ public class KittingIssueRequestEventHandler |
|
|
|
detail.RequestLocationArea = kittingIssueRequestDetail.ToLocationArea; |
|
|
|
detail.RequestLocationErpCode = kittingIssueRequestDetail.ToLocationErpCode; |
|
|
|
detail.RequestWarehouseCode = kittingIssueRequestDetail.ToWarehouseCode; |
|
|
|
detail.RequestQty = 1; |
|
|
|
|
|
|
|
detail.PositionCode = kittingIssueRequestDetail.PositionCode; |
|
|
|
detail.RecommendType = kittingIssueRequestDetail.RecommendType; |
|
|
@ -509,4 +488,172 @@ public class KittingIssueRequestEventHandler |
|
|
|
#endregion
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
//创建任务
|
|
|
|
private async Task<List<KittingIssueJobDTO>> CreateAllKittingIssueJobAsync( |
|
|
|
KittingIssueRequest kittingIssueRequest) |
|
|
|
{ |
|
|
|
var kittingIssueJobEditInputs = new List<KittingIssueJobEditInput>(); |
|
|
|
|
|
|
|
//已用的库存的集合
|
|
|
|
var useBalanceList = new List<BalanceDTO>(); |
|
|
|
|
|
|
|
foreach (var groupbyItemCodeAndProdLine in kittingIssueRequest.Details.GroupBy(p => |
|
|
|
new { p.ItemCode })) |
|
|
|
{ |
|
|
|
foreach (var kittingIssueRequestDetail in groupbyItemCodeAndProdLine) |
|
|
|
{ |
|
|
|
var productionLineItemDto = await _productionLineItemAppService.GetByProductLineCodeAndItemCodeAsync( |
|
|
|
kittingIssueRequestDetail.ProdLine, |
|
|
|
groupbyItemCodeAndProdLine.Key.ItemCode).ConfigureAwait(false); |
|
|
|
|
|
|
|
if (productionLineItemDto == null) |
|
|
|
{ |
|
|
|
throw new UserFriendlyException( |
|
|
|
$"未在生产线【{kittingIssueRequestDetail.ProdLine}】物品【{groupbyItemCodeAndProdLine.Key.ItemCode}】的关系,请查看【生产线物品关系】"); |
|
|
|
} |
|
|
|
|
|
|
|
//原料
|
|
|
|
if (!string.IsNullOrEmpty(productionLineItemDto.RawLocationCodeListJson)) //因为一个零件 要不是原料 要不是半成品
|
|
|
|
{ |
|
|
|
var usableLocationCode = |
|
|
|
JsonSerializer.Deserialize<List<string>>(productionLineItemDto.RawLocationCodeListJson); |
|
|
|
if (!usableLocationCode.Any()) |
|
|
|
{ |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
//获取可用库存
|
|
|
|
var input = new RecommendBalanceRequestInput |
|
|
|
{ |
|
|
|
ItemCode = kittingIssueRequestDetail.ItemCode, |
|
|
|
Qty = decimal.MaxValue, |
|
|
|
Statuses = new EditableList<EnumInventoryStatus> { EnumInventoryStatus.OK }, |
|
|
|
Locations = |
|
|
|
JsonSerializer.Deserialize<List<string>>(productionLineItemDto.RawLocationCodeListJson), |
|
|
|
IsPackingCode = true |
|
|
|
}; |
|
|
|
var usableList = await _balanceAppService.GetUsableListAsync(input).ConfigureAwait(false); |
|
|
|
|
|
|
|
//因为是按箱叫料 先把值赋值给箱数量上
|
|
|
|
kittingIssueRequestDetail.BoxQty = kittingIssueRequestDetail.Qty; |
|
|
|
|
|
|
|
if (usableList.Any()) |
|
|
|
{ |
|
|
|
//因为是原料所以按箱叫料
|
|
|
|
kittingIssueJobEditInputs.AddRange( |
|
|
|
await CreateKittingIssueJobWithBoxQtyTypeAsync(kittingIssueRequest, |
|
|
|
new EditableList<KittingIssueRequestDetail> { kittingIssueRequestDetail }, usableList, |
|
|
|
useBalanceList).ConfigureAwait(false)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//半成品
|
|
|
|
if (!string.IsNullOrEmpty(productionLineItemDto.ProductLocationCodeListJson)) //因为一个零件 要不是原料 要不是半成品
|
|
|
|
{ |
|
|
|
var usableLocationCode = |
|
|
|
JsonSerializer.Deserialize<List<string>>(productionLineItemDto.ProductLocationCodeListJson); |
|
|
|
if (!usableLocationCode.Any()) |
|
|
|
{ |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
//获取可用库存
|
|
|
|
var input = new RecommendBalanceRequestInput |
|
|
|
{ |
|
|
|
ItemCode = groupbyItemCodeAndProdLine.Key.ItemCode, |
|
|
|
Qty = kittingIssueRequestDetail.Qty, |
|
|
|
Statuses = new EditableList<EnumInventoryStatus> { EnumInventoryStatus.OK }, |
|
|
|
Locations = |
|
|
|
JsonSerializer.Deserialize<List<string>>(productionLineItemDto.ProductLocationCodeListJson), |
|
|
|
IsPackingCode = false |
|
|
|
}; |
|
|
|
var usableList = await _balanceAppService.GetUsableListAsync(input).ConfigureAwait(false); |
|
|
|
var temp = usableList.ToList(); |
|
|
|
|
|
|
|
foreach (var balanceDto in usableList) //计算已经用过的库存
|
|
|
|
{ |
|
|
|
var useBalanceDto = useBalanceList.Where(p => |
|
|
|
p.ItemCode == balanceDto.ItemCode && p.LocationCode == balanceDto.LocationCode && |
|
|
|
p.Lot == balanceDto.Lot && p.Status == balanceDto.Status && |
|
|
|
p.PackingCode == balanceDto.PackingCode); |
|
|
|
if (useBalanceDto.Any()) //如果不为NULL,就是用过了的库存 需要减去使用量
|
|
|
|
{ |
|
|
|
balanceDto.Qty -= useBalanceDto.Sum(p => p.Qty); |
|
|
|
if (balanceDto.Qty <= 0) |
|
|
|
{ |
|
|
|
temp.Remove(balanceDto); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
usableList = temp; |
|
|
|
|
|
|
|
kittingIssueJobEditInputs.AddRange( |
|
|
|
await CreateKittingIssueJobWithQtyTypeAsync(kittingIssueRequest, |
|
|
|
new List<KittingIssueRequestDetail> { kittingIssueRequestDetail }, temp, |
|
|
|
useBalanceList).ConfigureAwait(false)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (kittingIssueJobEditInputs.Count > 0)//有库存 可以创建任务
|
|
|
|
{ |
|
|
|
//新增任务
|
|
|
|
var addKittingIssueJobDtos= await _kittingIssueJobAppService.CreateManyAsync(kittingIssueJobEditInputs).ConfigureAwait(false); |
|
|
|
|
|
|
|
await UpdateKittingIssueRequestDetailQtyAsync(kittingIssueRequest, addKittingIssueJobDtos).ConfigureAwait(false); |
|
|
|
|
|
|
|
return addKittingIssueJobDtos; |
|
|
|
} |
|
|
|
|
|
|
|
return new List<KittingIssueJobDTO>(); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 修改请求的 已发 已收数量
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="kittingIssueRequest"></param>
|
|
|
|
/// <param name="addKittingIssueJobDtos"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
private async Task UpdateKittingIssueRequestDetailQtyAsync(KittingIssueRequest kittingIssueRequest, List<KittingIssueJobDTO> addKittingIssueJobDtos) |
|
|
|
{ |
|
|
|
//原有任务
|
|
|
|
var existKittingIssueJobDtos = await _kittingIssueJobAppService.GetByRequestNumberAsync(kittingIssueRequest.Number) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
//新增的任务和已有的任务总和
|
|
|
|
var allKittingIssueJobDtos = new List<KittingIssueJobDTO>(); |
|
|
|
allKittingIssueJobDtos.AddRange(addKittingIssueJobDtos); |
|
|
|
allKittingIssueJobDtos.AddRange(existKittingIssueJobDtos); |
|
|
|
|
|
|
|
var groupByItemCodeLocationCode = kittingIssueRequest.Details.GroupBy(p => |
|
|
|
new { p.ItemCode, p.ToLocationCode }); |
|
|
|
foreach (var group in groupByItemCodeLocationCode) |
|
|
|
{ |
|
|
|
foreach (var requestDetail in group) |
|
|
|
{ |
|
|
|
//所有已发数量
|
|
|
|
decimal allIssuedQty = 0; |
|
|
|
|
|
|
|
//所有已发数量
|
|
|
|
decimal allReceivedQty = 0; |
|
|
|
|
|
|
|
foreach (var allKittingIssueJobDto in allKittingIssueJobDtos) |
|
|
|
{ |
|
|
|
var jobDetailDtos = allKittingIssueJobDto.Details.Where(p => |
|
|
|
p.ItemCode == group.Key.ItemCode && p.RequestLocationCode == group.Key.ToLocationCode); |
|
|
|
//所有已发数量
|
|
|
|
allIssuedQty += jobDetailDtos.Sum(p => p.RequestQty); |
|
|
|
//所有已发数量
|
|
|
|
allReceivedQty += jobDetailDtos.Sum(p => p.HandledToQty); |
|
|
|
} |
|
|
|
|
|
|
|
requestDetail.IssuedQty += allIssuedQty; |
|
|
|
requestDetail.ReceivedQty += allReceivedQty; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//await _kittingIssueRequestManager.UpdateAsync(kittingIssueRequest).ConfigureAwait(false);
|
|
|
|
} |
|
|
|
} |
|
|
|