|
|
@ -3,8 +3,10 @@ using System.Linq; |
|
|
|
using System.Text; |
|
|
|
using System.Text.Json; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using AutoMapper; |
|
|
|
using Castle.Components.DictionaryAdapter; |
|
|
|
using Volo.Abp; |
|
|
|
using Volo.Abp.AutoMapper; |
|
|
|
using Volo.Abp.EventBus; |
|
|
|
using Win_in.Sfs.Basedata.Application.Contracts; |
|
|
|
using Win_in.Sfs.Shared.Domain.Shared; |
|
|
@ -25,22 +27,27 @@ public class AssembleIssueRequestEventHandler |
|
|
|
, ILocalEventHandler<SfsCreatedEntityEventData<AssembleIssueRequest>> |
|
|
|
, ILocalEventHandler<SfsCreatedEntityEventData<List<AssembleIssueRequest>>> |
|
|
|
{ |
|
|
|
private readonly IAssembleIssueJobAppService _assembleJobAppService; |
|
|
|
private readonly IAssembleIssueJobAppService _assembleIssueJobAppService; |
|
|
|
private readonly IProductionLineAppService _productionLineAppService; |
|
|
|
private readonly IProductionLineItemAppService _productionLineItemAppService; |
|
|
|
private readonly ILocationAppService _locationAppService; |
|
|
|
private readonly IBalanceAppService _balanceAppService; |
|
|
|
private IMapper _mapper; |
|
|
|
//private readonly IAssembleIssueRequestManager _assembleIssueRequestManager;
|
|
|
|
|
|
|
|
public AssembleIssueRequestEventHandler( |
|
|
|
IAssembleIssueJobAppService assembleJobAppService, IProductionLineAppService productionLineAppService, |
|
|
|
IAssembleIssueJobAppService assembleIssueJobAppService, IProductionLineAppService productionLineAppService, |
|
|
|
ILocationAppService locationAppService, |
|
|
|
IBalanceAppService balanceAppService, IProductionLineItemAppService productionLineItemAppService) |
|
|
|
IBalanceAppService balanceAppService, IProductionLineItemAppService productionLineItemAppService |
|
|
|
//, IAssembleIssueRequestManager assembleIssueRequestManager
|
|
|
|
) |
|
|
|
{ |
|
|
|
_assembleJobAppService = assembleJobAppService; |
|
|
|
_assembleIssueJobAppService = assembleIssueJobAppService; |
|
|
|
_productionLineAppService = productionLineAppService; |
|
|
|
_locationAppService = locationAppService; |
|
|
|
_balanceAppService = balanceAppService; |
|
|
|
_productionLineItemAppService = productionLineItemAppService; |
|
|
|
//_assembleIssueRequestManager = assembleIssueRequestManager;
|
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
@ -49,7 +56,9 @@ public class AssembleIssueRequestEventHandler |
|
|
|
/// <param name="eventData">Event data</param>
|
|
|
|
public virtual async Task HandleEventAsync(SfsCreatedEntityEventData<AssembleIssueRequest> eventData) |
|
|
|
{ |
|
|
|
await Task.CompletedTask.ConfigureAwait(false); |
|
|
|
var entity = eventData.Entity; |
|
|
|
|
|
|
|
await CreateAllAssembleIssueJobAsync(entity).ConfigureAwait(false); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
@ -58,6 +67,8 @@ public class AssembleIssueRequestEventHandler |
|
|
|
/// <param name="eventData">Event data</param>
|
|
|
|
public virtual async Task HandleEventAsync(SfsCreatedEntityEventData<List<AssembleIssueRequest>> eventData) |
|
|
|
{ |
|
|
|
var entity = eventData.Entity; |
|
|
|
|
|
|
|
await Task.CompletedTask.ConfigureAwait(false); |
|
|
|
} |
|
|
|
|
|
|
@ -70,22 +81,7 @@ public class AssembleIssueRequestEventHandler |
|
|
|
{ |
|
|
|
var entity = eventData.Entity; |
|
|
|
|
|
|
|
List<AssembleIssueJobEditInput> assembleJobs = new EditableList<AssembleIssueJobEditInput>(); |
|
|
|
|
|
|
|
//switch (entity.Type)
|
|
|
|
//{
|
|
|
|
// case nameof(EnumIssueType.BoxQty):
|
|
|
|
// assembleJobs = await CreateAssembleIssueJobWithBoxQtyTypeAsync(entity).ConfigureAwait(false);
|
|
|
|
// break;
|
|
|
|
// case nameof(EnumIssueType.Qty):
|
|
|
|
// assembleJobs = await CreateAssembleIssueJobWithQtyTypeAsync(entity).ConfigureAwait(false);
|
|
|
|
// break;
|
|
|
|
//}
|
|
|
|
|
|
|
|
if (assembleJobs.Any()) |
|
|
|
{ |
|
|
|
await _assembleJobAppService.CreateManyAsync(assembleJobs).ConfigureAwait(false); |
|
|
|
} |
|
|
|
await CreateAllAssembleIssueJobAsync(entity).ConfigureAwait(false); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
@ -106,7 +102,7 @@ public class AssembleIssueRequestEventHandler |
|
|
|
public virtual async Task HandleEventAsync(SfsCompletedEntityEventData<AssembleIssueRequest> eventData) |
|
|
|
{ |
|
|
|
_ = eventData.Entity; |
|
|
|
// await _assembleJobAppService.CompleteByAssembleIssueRequestAsync(entity.Number);
|
|
|
|
// await _assembleIssueJobAppService.CompleteByAssembleIssueRequestAsync(entity.Number);
|
|
|
|
|
|
|
|
await Task.CompletedTask.ConfigureAwait(false); |
|
|
|
} |
|
|
@ -116,194 +112,135 @@ public class AssembleIssueRequestEventHandler |
|
|
|
#region 按数量叫料
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 创建注塑任务
|
|
|
|
/// 创建注塑任务-按数量
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="assembleRequest"></param>
|
|
|
|
/// <param name="assembleIssueRequest"></param>
|
|
|
|
/// <param name="assembleIssueRequestDetails"></param>
|
|
|
|
/// <param name="recommendbalanceDtos"></param>
|
|
|
|
/// <param name="useBalanceList"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <exception cref="UserFriendlyException"></exception>
|
|
|
|
private async Task<List<AssembleIssueJobEditInput>> CreateAssembleIssueJobWithQtyTypeAsync |
|
|
|
(AssembleIssueRequest assembleRequest) |
|
|
|
(AssembleIssueRequest assembleIssueRequest, List<AssembleIssueRequestDetail> assembleIssueRequestDetails, |
|
|
|
List<BalanceDTO> recommendbalanceDtos, |
|
|
|
List<BalanceDTO> useBalanceList) |
|
|
|
{ |
|
|
|
var jobs = new List<AssembleIssueJobEditInput>(); |
|
|
|
//用来临时存放所有未生成任务的发料集合 如果生成完了再这里去掉
|
|
|
|
var tempDetailDtos = |
|
|
|
ObjectMapper.Map<List<AssembleIssueRequestDetail>, List<AssembleIssueRequestDetailDTO>>( |
|
|
|
assembleIssueRequestDetails); |
|
|
|
|
|
|
|
var toLocationCodes = assembleRequest.Details.Select(p => p.ToLocationCode).Distinct().ToList(); //所有发送库位的集合
|
|
|
|
var toLocations = await _locationAppService.GetByCodesAsync(toLocationCodes).ConfigureAwait(false); //所有库位的集合
|
|
|
|
var assembleIssueJobDetailInputs = new List<AssembleIssueJobDetailInput>(); |
|
|
|
|
|
|
|
var assembleRequestDetails = assembleRequest.Details.Where(p => p.ToBeIssuedQty > 0); //所有还没发送物品的集合
|
|
|
|
foreach (var assembleRequestDetail in assembleRequestDetails) //如果有还有剩余未叫料的数量 则创建新的任务
|
|
|
|
if (recommendbalanceDtos != null && recommendbalanceDtos.Count > 0) |
|
|
|
{ |
|
|
|
var toLocation = |
|
|
|
toLocations.FirstOrDefault(p => p.Code == assembleRequestDetail.ToLocationCode); //判断目标库位是否存在
|
|
|
|
Check.NotNull(toLocation, "库位代码", $"库位 {assembleRequestDetail.ToLocationCode} 不存在"); |
|
|
|
|
|
|
|
//创建详情
|
|
|
|
var jobDetails = |
|
|
|
await CreateAssembleIssueJobDetailInputsWithQtyTypeAsync(assembleRequest, assembleRequestDetail, |
|
|
|
toLocation.LocationGroupCode).ConfigureAwait(false); |
|
|
|
if (!jobDetails.Any()) |
|
|
|
var queue = new Queue<BalanceDTO>(recommendbalanceDtos); |
|
|
|
while (queue.TryDequeue(out var balanceDto)) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
} |
|
|
|
var next = false; |
|
|
|
|
|
|
|
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 != assembleRequestDetail.ToLocationCode)) |
|
|
|
{ |
|
|
|
job = await BuildAssembleIssueJobCreateInputWithQtyTypeAsync(assembleRequest, fromLocation) |
|
|
|
.ConfigureAwait(false); |
|
|
|
jobs.Add(job); |
|
|
|
} |
|
|
|
var temp = tempDetailDtos.ToList(); |
|
|
|
|
|
|
|
job.Details.AddRange(jobDetails); |
|
|
|
if (assembleRequestDetail.ToBeIssuedQty < 0) |
|
|
|
{ |
|
|
|
assembleRequestDetail.Status = EnumStatus.Close; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
assembleIssueJobDetailInputs.Add( |
|
|
|
await BuildAssembleIssueJobDetailWithQtyTypeAsync(tempDetailDto, balanceDto) |
|
|
|
.ConfigureAwait(false)); |
|
|
|
useBalanceList.Add(balanceDto); |
|
|
|
|
|
|
|
if (balanceDto.Qty <= 0) |
|
|
|
{ |
|
|
|
next = true; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var openRequestDetails = |
|
|
|
assembleRequest.Details.Where(p => p.Status != EnumStatus.Close).ToList(); |
|
|
|
tempDetailDtos = temp; |
|
|
|
|
|
|
|
if (!openRequestDetails.Any()) |
|
|
|
{ |
|
|
|
return jobs; |
|
|
|
if (next) |
|
|
|
{ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var enableMultipleCreateAssembleIssueJob = await SettingManager |
|
|
|
.IsTrueAsync(StoreSettings.MaterialRequest.EnableMultipleCreateIssueJob).ConfigureAwait(false); |
|
|
|
if (enableMultipleCreateAssembleIssueJob) |
|
|
|
if (assembleIssueJobDetailInputs.Any()) |
|
|
|
{ |
|
|
|
//assembleRequest.Partial();
|
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
var sb = new StringBuilder(); |
|
|
|
foreach (var openRequestDetail in openRequestDetails) |
|
|
|
{ |
|
|
|
sb.AppendLine( |
|
|
|
$"{openRequestDetail.ItemCode}请求数量 {openRequestDetail.Qty},可用库存数量 {openRequestDetail.IssuedQty}"); |
|
|
|
} |
|
|
|
|
|
|
|
throw new UserFriendlyException($"{sb} 可用库存数量不足, 无法生成发料任务"); |
|
|
|
var assembleIssueJobEditInput = new AssembleIssueJobEditInput(); |
|
|
|
assembleIssueJobEditInput = await BuildAssembleIssueJobCreateInputWithQtyTypeAsync(assembleIssueRequest, |
|
|
|
assembleIssueRequestDetails.First()).ConfigureAwait(false); |
|
|
|
assembleIssueJobEditInput.Details = assembleIssueJobDetailInputs; |
|
|
|
jobs.Add(assembleIssueJobEditInput); |
|
|
|
} |
|
|
|
|
|
|
|
return jobs; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 构造注塑任务
|
|
|
|
/// 构造注塑任务-按数量
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="assembleRequest"></param>
|
|
|
|
/// <param name="fromLocation"></param>
|
|
|
|
/// <param name="assembleIssueRequest"></param>
|
|
|
|
/// <param name="requestDetailInput"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
private async Task<AssembleIssueJobEditInput> BuildAssembleIssueJobCreateInputWithQtyTypeAsync( |
|
|
|
AssembleIssueRequest assembleRequest, |
|
|
|
LocationDTO fromLocation) |
|
|
|
AssembleIssueRequest assembleIssueRequest, AssembleIssueRequestDetail requestDetailInput) |
|
|
|
{ |
|
|
|
AssembleIssueJobEditInput job; |
|
|
|
job = ObjectMapper.Map<AssembleIssueRequest, AssembleIssueJobEditInput>(assembleRequest); |
|
|
|
var job = ObjectMapper.Map<AssembleIssueRequest, AssembleIssueJobEditInput>(assembleIssueRequest); |
|
|
|
job.JobType = EnumJobType.IssueJob; |
|
|
|
job.JobStatus = EnumJobStatus.Open; |
|
|
|
job.WorkGroupCode = fromLocation.WorkGroupCode; |
|
|
|
job.WarehouseCode = fromLocation.WarehouseCode; |
|
|
|
job.Worker = assembleRequest.Worker; |
|
|
|
if (string.IsNullOrEmpty(job.Worker)) |
|
|
|
{ |
|
|
|
job.Worker = "admin"; |
|
|
|
} |
|
|
|
|
|
|
|
job.AssembleRequestNumber = assembleRequest.Number; |
|
|
|
job.WorkGroupCode = requestDetailInput.ToLocationGroup; |
|
|
|
job.WarehouseCode = requestDetailInput.ToWarehouseCode; |
|
|
|
job.Worker = assembleIssueRequest.Worker; |
|
|
|
job.AssembleRequestNumber = assembleIssueRequest.Number; |
|
|
|
job.EnumIssueSendType = EnumIssueSendType.QtyType; |
|
|
|
|
|
|
|
await Task.CompletedTask.ConfigureAwait(false); |
|
|
|
|
|
|
|
return job; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 创建注塑任务明细
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="assembleRequest"></param>
|
|
|
|
/// <param name="assembleRequestDetail"></param>
|
|
|
|
/// <param name="toLocationGroupCode"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <exception cref="UserFriendlyException"></exception>
|
|
|
|
private async Task<List<AssembleIssueJobDetailInput>> CreateAssembleIssueJobDetailInputsWithQtyTypeAsync( |
|
|
|
AssembleIssueRequest assembleRequest, |
|
|
|
AssembleIssueRequestDetail assembleRequestDetail, string toLocationGroupCode) |
|
|
|
{ |
|
|
|
var jobDetails = new List<AssembleIssueJobDetailInput>(); |
|
|
|
|
|
|
|
//获取推荐库存
|
|
|
|
var productionLineDto = await _productionLineAppService |
|
|
|
.GetByLocationCodeAsync(assembleRequestDetail.ToLocationCode).ConfigureAwait(false); |
|
|
|
var productionLineItemDtos = await _productionLineItemAppService |
|
|
|
.GetByProductLineCodeAsync(productionLineDto.Code).ConfigureAwait(false); |
|
|
|
if (productionLineItemDtos == null) |
|
|
|
{ |
|
|
|
throw new UserFriendlyException($"物品代码【{assembleRequestDetail.ItemCode}】没有对应的【生产线物品关系】"); |
|
|
|
} |
|
|
|
|
|
|
|
var productionLineItemDto = |
|
|
|
productionLineItemDtos.FirstOrDefault(p => p.ItemCode == assembleRequestDetail.ItemCode); |
|
|
|
var input = new RecommendBalanceRequestInput |
|
|
|
{ |
|
|
|
ItemCode = assembleRequestDetail.ItemCode, |
|
|
|
Qty = assembleRequestDetail.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 BuildAssembleIssueJobDetailWithQtyTypeAsync(assembleRequestDetail, recommend, |
|
|
|
toLocationGroupCode) |
|
|
|
.ConfigureAwait(false); |
|
|
|
if (assembleRequest.UseOnTheWayLocation) |
|
|
|
{ |
|
|
|
//获取在途库
|
|
|
|
var locationDto = await _locationAppService.GetFirstByTypeAsync(EnumLocationType.TRANSPORT) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
detail.OnTheWayLocationCode = locationDto.Code; |
|
|
|
} |
|
|
|
|
|
|
|
jobDetails.Add(detail); |
|
|
|
assembleRequestDetail.IssuedQty += recommend.Qty; |
|
|
|
|
|
|
|
//await _assembleRequestManager.UpdateDetailsAsync(assembleRequest).ConfigureAwait(false);
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return jobDetails; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 构造注塑任务明细
|
|
|
|
/// 构造注塑任务明细-按数量
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="assembleRequestDetail"></param>
|
|
|
|
/// <param name="assembleIssueRequestDetail"></param>
|
|
|
|
/// <param name="balance"></param>
|
|
|
|
/// <param name="toLocationGroupCode"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
private async Task<AssembleIssueJobDetailInput> BuildAssembleIssueJobDetailWithQtyTypeAsync( |
|
|
|
AssembleIssueRequestDetail assembleRequestDetail, BalanceDTO balance, string toLocationGroupCode) |
|
|
|
AssembleIssueRequestDetailDTO assembleIssueRequestDetail, BalanceDTO balance) |
|
|
|
{ |
|
|
|
//ProductionLineDTO prodLine = await _productionLineAppService.GetByLocationGroupCodeAsync(toLocationGroupCode).ConfigureAwait(false);
|
|
|
|
|
|
|
|
var detail = ObjectMapper.Map<BalanceDTO, AssembleIssueJobDetailInput>(balance); |
|
|
|
detail.RequestLocationCode = assembleRequestDetail.ToLocationCode; |
|
|
|
detail.PositionCode = assembleRequestDetail.PositionCode; |
|
|
|
detail.RecommendType = assembleRequestDetail.RecommendType; |
|
|
|
var detail = new AssembleIssueJobDetailInput(); |
|
|
|
detail.RequestLocationCode = assembleIssueRequestDetail.ToLocationCode; |
|
|
|
detail.PositionCode = assembleIssueRequestDetail.PositionCode; |
|
|
|
detail.RecommendType = assembleIssueRequestDetail.RecommendType; |
|
|
|
detail.Uom = balance.Uom; |
|
|
|
detail.ItemCode = balance.ItemCode; |
|
|
|
detail.ItemDesc2 = balance.ItemDesc2; |
|
|
|
detail.ItemDesc1 = balance.ItemDesc1; |
|
|
|
detail.ItemName = balance.ItemName; |
|
|
|
detail.ProdLine = assembleIssueRequestDetail.ProdLine; |
|
|
|
detail.RequestQty = balance.Qty; |
|
|
|
detail.StdPackQty = assembleIssueRequestDetail.StdPackQty; |
|
|
|
detail.Status = balance.Status; |
|
|
|
|
|
|
|
detail.RequestLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode; |
|
|
|
detail.RequestLocationArea = assembleIssueRequestDetail.ToLocationArea; |
|
|
|
detail.RequestWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; |
|
|
|
detail.RequestLocationGroup = assembleIssueRequestDetail.ToLocationGroup; |
|
|
|
detail.RequestLocationCode = assembleIssueRequestDetail.ToLocationCode; |
|
|
|
|
|
|
|
detail.RecommendFromPackingCode = balance.PackingCode; |
|
|
|
detail.RecommendFromContainerCode = balance.ContainerCode; |
|
|
@ -313,21 +250,69 @@ public class AssembleIssueRequestEventHandler |
|
|
|
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 = assembleRequestDetail.ToLocationCode; |
|
|
|
detail.RecommendToLocationErpCode = assembleRequestDetail.ToLocationErpCode; |
|
|
|
detail.RecommendToLocationArea = assembleRequestDetail.ToLocationArea; |
|
|
|
detail.RecommendToWarehouseCode = assembleRequestDetail.ToWarehouseCode; |
|
|
|
detail.RecommendToLocationCode = assembleIssueRequestDetail.ToLocationCode; |
|
|
|
detail.RecommendToLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode; |
|
|
|
detail.RecommendToLocationArea = assembleIssueRequestDetail.ToLocationArea; |
|
|
|
detail.RecommendToWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; |
|
|
|
detail.RecommendToLocationGroup = assembleIssueRequestDetail.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 = assembleIssueRequestDetail.ToLocationCode; |
|
|
|
detail.TransferLibToLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode; |
|
|
|
detail.TransferLibToLocationArea = assembleIssueRequestDetail.ToLocationArea; |
|
|
|
detail.TransferLibToWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; |
|
|
|
detail.TransferLibToLocationGroup = assembleIssueRequestDetail.ToLocationGroup; |
|
|
|
|
|
|
|
//detail.ProdLine = prodLine == null ? toLocationGroupCode : prodLine.Code;
|
|
|
|
detail.ProdLine = toLocationGroupCode; |
|
|
|
await Task.CompletedTask.ConfigureAwait(false); |
|
|
|
return detail; |
|
|
|
} |
|
|
@ -337,72 +322,71 @@ public class AssembleIssueRequestEventHandler |
|
|
|
#region 按箱叫料
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 创建注塑任务
|
|
|
|
/// 创建注塑任务 按箱叫料-按箱
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="assembleRequest"></param>
|
|
|
|
/// <param name="assembleIssueRequest"></param>
|
|
|
|
/// <param name="assembleIssueRequestDetailList"></param>
|
|
|
|
/// <param name="recommendbalanceDtos"></param>
|
|
|
|
/// <param name="useBalanceList"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <exception cref="UserFriendlyException"></exception>
|
|
|
|
private async Task<List<AssembleIssueJobEditInput>> CreateAssembleIssueJobWithBoxQtyTypeAsync |
|
|
|
(AssembleIssueRequest assembleRequest) |
|
|
|
( |
|
|
|
AssembleIssueRequest assembleIssueRequest, |
|
|
|
List<AssembleIssueRequestDetail> assembleIssueRequestDetailList, |
|
|
|
List<SortBalance> recommendbalanceDtos, |
|
|
|
List<BalanceDTO> useBalanceList) |
|
|
|
{ |
|
|
|
var inputJobs = new List<AssembleIssueJobEditInput>(); |
|
|
|
var inputExpectOutEditInput = new ExpectOutEditInput(); |
|
|
|
//已用的库存的箱码集合
|
|
|
|
var useBalanceList = new List<string>(); |
|
|
|
|
|
|
|
var groupByItemCodeAndLocationCode = |
|
|
|
assembleRequest.Details.GroupBy(p => new { p.ItemCode, p.ToLocationCode }); |
|
|
|
//已用的库存的集合
|
|
|
|
useBalanceList = useBalanceList; |
|
|
|
|
|
|
|
foreach (var locationCodeItemCodeGroup in groupByItemCodeAndLocationCode) |
|
|
|
foreach (var detail in assembleIssueRequestDetailList) |
|
|
|
{ |
|
|
|
var inputDetails = assembleRequest.Details.Where(p => |
|
|
|
p.ItemCode == locationCodeItemCodeGroup.Key.ItemCode && |
|
|
|
p.ToLocationCode == locationCodeItemCodeGroup.Key.ToLocationCode); |
|
|
|
var inputDetailTemplate = inputDetails.First(); |
|
|
|
//当前零件的集合
|
|
|
|
var inputDetails = assembleIssueRequestDetailList; |
|
|
|
//获取请求下 这个零件和这个库位一个需要多少箱
|
|
|
|
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 assembleJobEditInput = |
|
|
|
await BuildAssembleIssueJobCreateInputWithBoxQtyTypeAsync(assembleRequest, inputDetailTemplate, |
|
|
|
firstUsable) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
inputJobs.Add(assembleJobEditInput); |
|
|
|
if (usableList.Any()) |
|
|
|
{ |
|
|
|
var firstUsable = usableList.First(); |
|
|
|
useBalanceList.Add((BalanceDTO)firstUsable); |
|
|
|
usableList.Remove(firstUsable); |
|
|
|
|
|
|
|
var assembleIssueJobEditInput = |
|
|
|
await BuildAssembleIssueJobCreateInputWithBoxQtyTypeAsync(assembleIssueRequest, |
|
|
|
detail, firstUsable) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
inputJobs.Add(assembleIssueJobEditInput); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -411,25 +395,26 @@ public class AssembleIssueRequestEventHandler |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 构造注塑任务
|
|
|
|
/// 构造注塑任务-按箱
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="assembleRequest"></param>
|
|
|
|
/// <param name="assembleRequestDetail"></param>
|
|
|
|
/// <param name="assembleIssueRequest"></param>
|
|
|
|
/// <param name="assembleIssueRequestDetail"></param>
|
|
|
|
/// <param name="balanceDtos"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
private async Task<AssembleIssueJobEditInput> BuildAssembleIssueJobCreateInputWithBoxQtyTypeAsync( |
|
|
|
AssembleIssueRequest assembleRequest, |
|
|
|
AssembleIssueRequestDetail assembleRequestDetail, BalanceDTO balanceDtos) |
|
|
|
AssembleIssueRequest assembleIssueRequest, |
|
|
|
AssembleIssueRequestDetail assembleIssueRequestDetail, BalanceDTO balanceDtos) |
|
|
|
{ |
|
|
|
var job = ObjectMapper.Map<AssembleIssueRequest, AssembleIssueJobEditInput>(assembleRequest); |
|
|
|
var job = ObjectMapper.Map<AssembleIssueRequest, AssembleIssueJobEditInput>(assembleIssueRequest); |
|
|
|
job.JobType = EnumJobType.IssueJob; |
|
|
|
job.JobStatus = EnumJobStatus.Open; |
|
|
|
job.WorkGroupCode = assembleRequestDetail.ToLocationGroup; |
|
|
|
job.WarehouseCode = assembleRequestDetail.ToWarehouseCode; |
|
|
|
job.Worker = assembleRequest.Worker; |
|
|
|
job.AssembleRequestNumber = assembleRequest.Number; |
|
|
|
job.WorkGroupCode = assembleIssueRequestDetail.ToLocationGroup; |
|
|
|
job.WarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; |
|
|
|
job.Worker = assembleIssueRequest.Worker; |
|
|
|
job.AssembleRequestNumber = assembleIssueRequest.Number; |
|
|
|
job.EnumIssueSendType = EnumIssueSendType.BoxQtyType; |
|
|
|
|
|
|
|
job.Details.Add(await BuildAssembleIssueJobDetailWithBoxQtyTypeAsync(assembleRequestDetail, balanceDtos) |
|
|
|
job.Details.Add(await BuildAssembleIssueJobDetailWithBoxQtyTypeAsync(assembleIssueRequestDetail, balanceDtos) |
|
|
|
.ConfigureAwait(false)); |
|
|
|
|
|
|
|
await Task.CompletedTask.ConfigureAwait(false); |
|
|
@ -438,30 +423,31 @@ public class AssembleIssueRequestEventHandler |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 构造注塑任务明细
|
|
|
|
/// 构造注塑任务明细-按箱
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="assembleRequestDetail"></param>
|
|
|
|
/// <param name="assembleIssueRequestDetail"></param>
|
|
|
|
/// <param name="balance"></param>
|
|
|
|
/// <param name="toLocationGroupCode"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
private async Task<AssembleIssueJobDetailInput> BuildAssembleIssueJobDetailWithBoxQtyTypeAsync( |
|
|
|
AssembleIssueRequestDetail assembleRequestDetail, BalanceDTO balance) |
|
|
|
AssembleIssueRequestDetail assembleIssueRequestDetail, BalanceDTO balance) |
|
|
|
{ |
|
|
|
var detail = new AssembleIssueJobDetailInput(); |
|
|
|
detail.RequestLocationCode = assembleRequestDetail.ToLocationCode; |
|
|
|
detail.RequestLocationGroup = assembleRequestDetail.ToLocationGroup; |
|
|
|
detail.RequestLocationArea = assembleRequestDetail.ToLocationArea; |
|
|
|
detail.RequestLocationErpCode = assembleRequestDetail.ToLocationErpCode; |
|
|
|
detail.RequestWarehouseCode = assembleRequestDetail.ToWarehouseCode; |
|
|
|
|
|
|
|
detail.PositionCode = assembleRequestDetail.PositionCode; |
|
|
|
detail.RecommendType = assembleRequestDetail.RecommendType; |
|
|
|
detail.ProdLine = assembleRequestDetail.ToLocationCode; |
|
|
|
|
|
|
|
detail.ItemCode = assembleRequestDetail.ItemCode; |
|
|
|
detail.ItemName = assembleRequestDetail.ItemName; |
|
|
|
detail.ItemDesc1 = assembleRequestDetail.ItemDesc1; |
|
|
|
detail.ItemDesc2 = assembleRequestDetail.ItemDesc2; |
|
|
|
detail.RequestLocationCode = assembleIssueRequestDetail.ToLocationCode; |
|
|
|
detail.RequestLocationGroup = assembleIssueRequestDetail.ToLocationGroup; |
|
|
|
detail.RequestLocationArea = assembleIssueRequestDetail.ToLocationArea; |
|
|
|
detail.RequestLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode; |
|
|
|
detail.RequestWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; |
|
|
|
detail.RequestQty = 1; |
|
|
|
|
|
|
|
detail.PositionCode = assembleIssueRequestDetail.PositionCode; |
|
|
|
detail.RecommendType = assembleIssueRequestDetail.RecommendType; |
|
|
|
detail.ProdLine = assembleIssueRequestDetail.ToLocationCode; |
|
|
|
|
|
|
|
detail.ItemCode = assembleIssueRequestDetail.ItemCode; |
|
|
|
detail.ItemName = assembleIssueRequestDetail.ItemName; |
|
|
|
detail.ItemDesc1 = assembleIssueRequestDetail.ItemDesc1; |
|
|
|
detail.ItemDesc2 = assembleIssueRequestDetail.ItemDesc2; |
|
|
|
|
|
|
|
detail.Status = EnumInventoryStatus.OK; |
|
|
|
detail.Uom = balance.Uom; |
|
|
@ -496,11 +482,11 @@ public class AssembleIssueRequestEventHandler |
|
|
|
detail.RecommendToProduceDate = balance.ProduceDate; |
|
|
|
detail.RecommendToArriveDate = balance.ArriveDate; |
|
|
|
|
|
|
|
detail.RecommendToLocationCode = assembleRequestDetail.ToLocationCode; |
|
|
|
detail.RecommendToLocationErpCode = assembleRequestDetail.ToLocationErpCode; |
|
|
|
detail.RecommendToLocationArea = assembleRequestDetail.ToLocationArea; |
|
|
|
detail.RecommendToWarehouseCode = assembleRequestDetail.ToWarehouseCode; |
|
|
|
detail.RecommendToLocationGroup = assembleRequestDetail.ToLocationGroup; |
|
|
|
detail.RecommendToLocationCode = assembleIssueRequestDetail.ToLocationCode; |
|
|
|
detail.RecommendToLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode; |
|
|
|
detail.RecommendToLocationArea = assembleIssueRequestDetail.ToLocationArea; |
|
|
|
detail.RecommendToWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode; |
|
|
|
detail.RecommendToLocationGroup = assembleIssueRequestDetail.ToLocationGroup; |
|
|
|
|
|
|
|
await Task.CompletedTask.ConfigureAwait(false); |
|
|
|
return detail; |
|
|
@ -509,4 +495,210 @@ public class AssembleIssueRequestEventHandler |
|
|
|
#endregion
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
//创建任务
|
|
|
|
private async Task<List<AssembleIssueJobDTO>> CreateAllAssembleIssueJobAsync( |
|
|
|
AssembleIssueRequest assembleIssueRequest) |
|
|
|
{ |
|
|
|
var assembleIssueJobEditInputs = new List<AssembleIssueJobEditInput>(); |
|
|
|
|
|
|
|
//已用的库存的集合
|
|
|
|
var useBalanceList = new List<BalanceDTO>(); |
|
|
|
|
|
|
|
foreach (var groupbyItemCodeAndProdLine in assembleIssueRequest.Details.GroupBy(p => |
|
|
|
new { p.ItemCode })) |
|
|
|
{ |
|
|
|
foreach (var assembleIssueRequestDetail in groupbyItemCodeAndProdLine) |
|
|
|
{ |
|
|
|
var productionLineItemDto = await _productionLineItemAppService.GetByProductLineCodeAndItemCodeAsync( |
|
|
|
assembleIssueRequestDetail.ProdLine, |
|
|
|
groupbyItemCodeAndProdLine.Key.ItemCode).ConfigureAwait(false); |
|
|
|
|
|
|
|
if (productionLineItemDto == null) |
|
|
|
{ |
|
|
|
throw new UserFriendlyException( |
|
|
|
$"未在生产线【{assembleIssueRequestDetail.ProdLine}】物品【{groupbyItemCodeAndProdLine.Key.ItemCode}】的关系,请查看【生产线物品关系】"); |
|
|
|
} |
|
|
|
|
|
|
|
//原料
|
|
|
|
if (!string.IsNullOrEmpty(productionLineItemDto.RawLocationCodeListJson)) //因为一个零件 要不是原料 要不是半成品
|
|
|
|
{ |
|
|
|
var usableLocationCode = |
|
|
|
JsonSerializer.Deserialize<List<string>>(productionLineItemDto.RawLocationCodeListJson); |
|
|
|
if (usableLocationCode.Any()) |
|
|
|
{ |
|
|
|
//获取可用库存
|
|
|
|
var input = new RecommendBalanceRequestInput |
|
|
|
{ |
|
|
|
ItemCode = assembleIssueRequestDetail.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); |
|
|
|
var sortByFifoAsync = await SortByFifoAsync(usableList).ConfigureAwait(false); |
|
|
|
|
|
|
|
//因为是按箱叫料 先把值赋值给箱数量上
|
|
|
|
assembleIssueRequestDetail.BoxQty = assembleIssueRequestDetail.Qty; |
|
|
|
|
|
|
|
if (usableList.Any()) |
|
|
|
{ |
|
|
|
//因为是原料所以按箱叫料
|
|
|
|
assembleIssueJobEditInputs.AddRange( |
|
|
|
await CreateAssembleIssueJobWithBoxQtyTypeAsync(assembleIssueRequest, |
|
|
|
new EditableList<AssembleIssueRequestDetail> { assembleIssueRequestDetail }, |
|
|
|
sortByFifoAsync, |
|
|
|
useBalanceList).ConfigureAwait(false)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//半成品
|
|
|
|
if (!string.IsNullOrEmpty(productionLineItemDto.ProductLocationCodeListJson)) //因为一个零件 要不是原料 要不是半成品
|
|
|
|
{ |
|
|
|
var usableLocationCode = |
|
|
|
JsonSerializer.Deserialize<List<string>>(productionLineItemDto.ProductLocationCodeListJson); |
|
|
|
if (usableLocationCode.Any()) |
|
|
|
{ |
|
|
|
//获取可用库存
|
|
|
|
var input = new RecommendBalanceRequestInput |
|
|
|
{ |
|
|
|
ItemCode = groupbyItemCodeAndProdLine.Key.ItemCode, |
|
|
|
Qty = assembleIssueRequestDetail.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; |
|
|
|
|
|
|
|
assembleIssueJobEditInputs.AddRange( |
|
|
|
await CreateAssembleIssueJobWithQtyTypeAsync(assembleIssueRequest, |
|
|
|
new List<AssembleIssueRequestDetail> { assembleIssueRequestDetail }, temp, |
|
|
|
useBalanceList).ConfigureAwait(false)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (assembleIssueJobEditInputs.Count > 0) //有库存 可以创建任务
|
|
|
|
{ |
|
|
|
//新增任务
|
|
|
|
var addAssembleIssueJobDtos = await _assembleIssueJobAppService.CreateManyAsync(assembleIssueJobEditInputs) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
await UpdateAssembleIssueRequestDetailQtyAsync(assembleIssueRequest, addAssembleIssueJobDtos) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
return addAssembleIssueJobDtos; |
|
|
|
} |
|
|
|
|
|
|
|
return new List<AssembleIssueJobDTO>(); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 修改请求的 已发 已收数量
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="assembleIssueRequest"></param>
|
|
|
|
/// <param name="addAssembleIssueJobDtos"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
private async Task UpdateAssembleIssueRequestDetailQtyAsync(AssembleIssueRequest assembleIssueRequest, |
|
|
|
List<AssembleIssueJobDTO> addAssembleIssueJobDtos) |
|
|
|
{ |
|
|
|
//原有任务
|
|
|
|
var existAssembleIssueJobDtos = await _assembleIssueJobAppService |
|
|
|
.GetByRequestNumberAsync(assembleIssueRequest.Number) |
|
|
|
.ConfigureAwait(false); |
|
|
|
|
|
|
|
//新增的任务和已有的任务总和
|
|
|
|
var allAssembleIssueJobDtos = new List<AssembleIssueJobDTO>(); |
|
|
|
allAssembleIssueJobDtos.AddRange(addAssembleIssueJobDtos); |
|
|
|
allAssembleIssueJobDtos.AddRange(existAssembleIssueJobDtos); |
|
|
|
|
|
|
|
var groupByItemCodeLocationCode = assembleIssueRequest.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 allAssembleIssueJobDto in allAssembleIssueJobDtos) |
|
|
|
{ |
|
|
|
var jobDetailDtos = allAssembleIssueJobDto.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 _assembleIssueRequestManager.UpdateAsync(assembleIssueRequest).ConfigureAwait(false);
|
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 排序规则 1.批次正序 2.底层 3.到货日期正序 4.数量倒序(整箱优先) 5.库位正序 6.箱码正序
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="balances"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
public async Task<List<SortBalance>> SortByFifoAsync(List<BalanceDTO> balances) |
|
|
|
{ |
|
|
|
var sortBalances = new List<SortBalance>(); |
|
|
|
var config = new MapperConfiguration(cfg => |
|
|
|
{ |
|
|
|
cfg.CreateMap<BalanceDTO, SortBalance>() |
|
|
|
.Ignore(x => x.LocationRow); |
|
|
|
}); |
|
|
|
_mapper = new Mapper(config); |
|
|
|
|
|
|
|
var resultBalances = _mapper.Map<List<BalanceDTO>, List<SortBalance>>(balances); |
|
|
|
foreach (var resultBalance in resultBalances) |
|
|
|
{ |
|
|
|
var locationDto = await _locationAppService.GetByCodeAsync(resultBalance.LocationCode).ConfigureAwait(false); |
|
|
|
resultBalance.LocationRow = locationDto.RowCode; |
|
|
|
} |
|
|
|
|
|
|
|
resultBalances |
|
|
|
.OrderBy(p => p.Lot) |
|
|
|
.ThenBy(p => p.LocationRow) |
|
|
|
.ThenBy(p => p.PutInTime) |
|
|
|
.ThenBy(p => p.Qty)//2023-9-14 苑静雯 从小数开始发料
|
|
|
|
.ThenBy(p => p.LocationCode) |
|
|
|
.ThenBy(p => p.PackingCode) |
|
|
|
.ToList(); |
|
|
|
|
|
|
|
return resultBalances; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|