| | |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_DTO.Stock; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_IRecordService; |
| | |
| | | MaterielCode = x.Key.MaterielCode, |
| | | BatchNo = x.Key.BatchNo, |
| | | Details = x.ToList(), |
| | | TotalNeedQuantity = x.Sum(v => v.OrderQuantity - v.OverOutQuantity - v.LockQuantity) |
| | | TotalNeedQuantity = x.Sum(v => v.OrderQuantity - v.OverOutQuantity - v.LockQuantity-v.MoveQty) |
| | | }) |
| | | .Where(x => x.TotalNeedQuantity > 0) |
| | | .ToList(); |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå
è¿å
åºåååé
é宿°éå°å个æç» - ä¿®å¤çæ¬ |
| | | /// æå
è¿å
åºåååé
é宿°éå°å个æç» |
| | | /// </summary> |
| | | private void DistributeLockQuantityByFIFO( |
| | | List<Dt_OutboundOrderDetail> details, |
| | |
| | | { |
| | | // æå
è¿å
åºæåºåºåºåæç»ï¼å设å
å建çæç»éè¦ä¼å
æ»¡è¶³ï¼ |
| | | var sortedDetails = details |
| | | .Where(d => d.OrderQuantity - d.OverOutQuantity - d.LockQuantity > 0) // åªå¤çè¿éè¦åé
çæ°é |
| | | .Where(d => d.OrderQuantity - d.OverOutQuantity - d.LockQuantity -d.MoveQty> 0) // åªå¤çè¿éè¦åé
çæ°é |
| | | .OrderBy(x => x.Id) |
| | | .ToList(); |
| | | |
| | |
| | | var allocatedStockDetails = assignStocks |
| | | .SelectMany(x => x.Details) |
| | | .Where(x => stockAllocations.ContainsKey(x.Id)) |
| | | .OrderBy(x => x.ProductionDate) |
| | | .OrderBy(x => x.CreateDate) |
| | | .ThenBy(x => x.StockId) |
| | | .ToList(); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// å建åºåºéå®ä¿¡æ¯ |
| | | /// </summary> |
| | | private void CreateOutStockLockInfos(Dt_OutboundOrder outboundOrder,List<Dt_OutboundOrderDetail> details, |
| | | List<Dt_StockInfo> assignStocks,List<Dt_OutStockLockInfo> outStockLockInfos) |
| | | { |
| | | foreach (var stock in assignStocks) |
| | | { |
| | | // è·å该åºåä¸ç¸å
³ç©æçå¯ç¨æ¡ç ä¿¡æ¯ |
| | | var stockDetails = stock.Details |
| | | .Where(x => details.Any(d => d.MaterielCode == x.MaterielCode) && |
| | | x.StockQuantity > x.OutboundQuantity) |
| | | .OrderBy(x => x.ProductionDate) // å
è¿å
åº |
| | | .ToList(); |
| | | if (!stockDetails.Any()) continue; |
| | | |
| | | var stockAssignQuantity = stockDetails.Sum(x => x.OutboundQuantity); |
| | | |
| | | |
| | | // æ¥æ¾è¿ä¸ªåºåå·²ç»åé
çæ°é |
| | | var existingAssign = outStockLockInfos |
| | | .Where(x => x.StockId == stock.Id && |
| | | details.Any(d => d.Id == x.OrderDetailId)) |
| | | .Sum(x => x.AssignQuantity); |
| | | |
| | | var availableAssign = stockAssignQuantity - existingAssign; |
| | | |
| | | if (availableAssign <= 0) continue; |
| | | |
| | | // æå
è¿å
åºåååé
æ¡ç |
| | | var barcodeAllocation = AllocateBarcodes(stockDetails, availableAssign); |
| | | |
| | | |
| | | // åé
ç»å个æç» |
| | | foreach (var detail in details.Where(d => d.LockQuantity > 0)) |
| | | { |
| | | var alreadyAssigned = outStockLockInfos |
| | | .Where(x => x.OrderDetailId == detail.Id && x.StockId == stock.Id) |
| | | .Sum(x => x.AssignQuantity); |
| | | |
| | | var canAssign = Math.Min(detail.LockQuantity - alreadyAssigned, availableAssign); |
| | | |
| | | if (canAssign > 0) |
| | | { |
| | | // 为è¿ä¸ªåé
ç¡®å®æ¡ç |
| | | var (barcode, barcodeQuantity) = GetBarcodeForAllocation(barcodeAllocation, canAssign); |
| | | |
| | | var lockInfo = _outStockLockInfoService.GetOutStockLockInfo( |
| | | outboundOrder, detail, stock, canAssign, barcode); |
| | | outStockLockInfos.Add(lockInfo); |
| | | |
| | | availableAssign -= canAssign; |
| | | |
| | | // æ´æ°æ¡ç åé
è®°å½ |
| | | UpdateBarcodeAllocation(barcodeAllocation, barcode, barcodeQuantity); |
| | | } |
| | | |
| | | if (availableAssign <= 0) break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå
è¿å
åºåååé
æ¡ç |
| | | /// </summary> |
| | | private Dictionary<string, decimal> AllocateBarcodes(List<Dt_StockInfoDetail> stockDetails, decimal totalQuantity) |
| | | { |
| | | var allocation = new Dictionary<string, decimal>(); |
| | | decimal remainingQuantity = totalQuantity; |
| | | |
| | | foreach (var detail in stockDetails.OrderBy(x => x.ProductionDate)) |
| | | { |
| | | if (remainingQuantity <= 0) break; |
| | | |
| | | decimal available = detail.StockQuantity - detail.OutboundQuantity; |
| | | decimal allocate = Math.Min(available, remainingQuantity); |
| | | |
| | | allocation[detail.Barcode] = allocate; |
| | | remainingQuantity -= allocate; |
| | | } |
| | | |
| | | return allocation; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 为åé
è·ååéçæ¡ç |
| | | /// </summary> |
| | | private (string barcode, decimal quantity) GetBarcodeForAllocation(Dictionary<string, decimal> barcodeAllocation, decimal requiredQuantity) |
| | | { |
| | | foreach (var (barcode, quantity) in barcodeAllocation) |
| | | { |
| | | if (quantity >= requiredQuantity) |
| | | { |
| | | return (barcode, requiredQuantity); |
| | | } |
| | | } |
| | | |
| | | // 妿å个æ¡ç æ°éä¸è¶³ï¼ä½¿ç¨ç¬¬ä¸ä¸ªæ¡ç |
| | | var first = barcodeAllocation.First(); |
| | | return (first.Key, Math.Min(first.Value, requiredQuantity)); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ´æ°æ¡ç åé
è®°å½ |
| | | /// </summary> |
| | | private void UpdateBarcodeAllocation(Dictionary<string, decimal> barcodeAllocation, string barcode, decimal usedQuantity) |
| | | { |
| | | if (barcodeAllocation.ContainsKey(barcode)) |
| | | { |
| | | barcodeAllocation[barcode] -= usedQuantity; |
| | | if (barcodeAllocation[barcode] <= 0) |
| | | { |
| | | barcodeAllocation.Remove(barcode); |
| | | } |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// åºåºåºååé
åï¼æ´æ°æ°æ®åºæ°æ® |
| | | /// </summary> |