| | |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>(); |
| | | List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>(); |
| | | |
| | | // æç©æåæ¹æ¬¡åç»å¤ç |
| | | // æç©æãæ¹æ¬¡ãä¾åºååç» |
| | | var groupDetails = outboundOrderDetails |
| | | .GroupBy(x => new { x.MaterielCode, x.BatchNo ,x.SupplyCode}) |
| | | .Select(x => new |
| | | { |
| | | MaterielCode = x.Key.MaterielCode, |
| | | BatchNo = x.Key.BatchNo, |
| | | SupplyCode = x.Key.SupplyCode, |
| | | x.Key.MaterielCode, |
| | | x.Key.BatchNo, |
| | | x.Key.SupplyCode, |
| | | Details = x.ToList(), |
| | | TotalNeedQuantity = x.Sum(v => v.OrderQuantity - v.OverOutQuantity - v.LockQuantity-v.MoveQty) |
| | | }) |
| | |
| | | { |
| | | var needQuantity = item.TotalNeedQuantity; |
| | | |
| | | // è·åå¯ç¨åºåï¼æå
è¿å
åºæåºï¼ |
| | | List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(item.MaterielCode, item.BatchNo,item.SupplyCode); |
| | | // è·åå¯ç¨åºåï¼å·²æå
è¿å
åºæåºï¼ |
| | | List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks( |
| | | item.MaterielCode, item.BatchNo, item.SupplyCode); |
| | | |
| | | if (!stockInfos.Any()) |
| | | { |
| | | throw new Exception($"ç©æ[{item.MaterielCode}]æ¹æ¬¡[{item.BatchNo}]æªæ¾å°å¯åé
åºå"); |
| | | } |
| | | |
| | | // åé
åºåï¼æå
è¿å
åºï¼ |
| | | // åé
åºå |
| | | var (autoAssignStocks, stockAllocations) = _stockService.StockInfoService.GetOutboundStocks( |
| | | stockInfos, item.MaterielCode, needQuantity, out decimal residueQuantity); |
| | | |
| | | if (residueQuantity > 0 && residueQuantity == needQuantity) |
| | | // æ£æ¥åé
ç»æ |
| | | if (residueQuantity > 0) |
| | | { |
| | | throw new Exception($"ç©æ[{item.MaterielCode}]åºåä¸è¶³ï¼éè¦{needQuantity}ï¼å¯ç¨{needQuantity - residueQuantity}"); |
| | | var allocatedQuantity = needQuantity - residueQuantity; |
| | | throw new Exception($"ç©æ[{item.MaterielCode}]åºåä¸è¶³ï¼éè¦{needQuantity}ï¼å®é
åé
{allocatedQuantity}"); |
| | | } |
| | | |
| | | outStocks.AddRange(autoAssignStocks); |
| | | |
| | | // æå
è¿å
åºåååé
é宿°éå°å个æç» |
| | | DistributeLockQuantityByFIFO(item.Details, autoAssignStocks, stockAllocations, outStockLockInfos, outboundOrder); |
| | | // æå
è¿å
åºåé
é宿°é |
| | | DistributeLockQuantityByFIFO(item.Details, autoAssignStocks, stockAllocations, |
| | | outStockLockInfos, outboundOrder); |
| | | } |
| | | |
| | | locationInfos.AddRange(_locationInfoService.GetLocationInfos(outStocks.Select(x => x.LocationCode).Distinct().ToList())); |
| | | locationInfos.AddRange(_locationInfoService.GetLocationInfos( |
| | | outStocks.Select(x => x.LocationCode).Distinct().ToList())); |
| | | |
| | | return (outStocks, outboundOrderDetails, outStockLockInfos, locationInfos); |
| | | } |
| | |
| | | /// <summary> |
| | | /// æå
è¿å
åºåååé
é宿°éå°å个æç» |
| | | /// </summary> |
| | | private void DistributeLockQuantityByFIFO( |
| | | List<Dt_OutboundOrderDetail> details, |
| | | List<Dt_StockInfo> assignStocks, |
| | | Dictionary<int, decimal> stockAllocations, |
| | | List<Dt_OutStockLockInfo> outStockLockInfos, |
| | | private void DistributeLockQuantityByFIFO(List<Dt_OutboundOrderDetail> details,List<Dt_StockInfo> assignStocks,Dictionary<int, decimal> stockAllocations,List<Dt_OutStockLockInfo> outStockLockInfos, |
| | | Dt_OutboundOrder outboundOrder) |
| | | { |
| | | // æå
è¿å
åºæåºåºåºåæç»ï¼å设å
å建çæç»éè¦ä¼å
æ»¡è¶³ï¼ |
| | | var sortedStocks = assignStocks.OrderBy(x => x.CreateDate).ToList(); |
| | | |
| | | var totalNeedQuantity = details.Sum(d => d.OrderQuantity - d.OverOutQuantity - d.LockQuantity - d.MoveQty); |
| | | decimal allocatedQuantity = 0; |
| | | |
| | | foreach (var stock in sortedStocks) |
| | | { |
| | | if (allocatedQuantity >= totalNeedQuantity) break; |
| | | |
| | | if (!stockAllocations.TryGetValue(stock.Id, out decimal stockAllocation) || stockAllocation <= 0) |
| | | continue; |
| | | |
| | | var sortedDetails = details |
| | | .Where(d => d.OrderQuantity - d.OverOutQuantity - d.LockQuantity -d.MoveQty> 0) // åªå¤çè¿éè¦åé
çæ°é |
| | | .Where(d => d.OrderQuantity - d.OverOutQuantity - d.LockQuantity - d.MoveQty > 0) |
| | | .OrderBy(x => x.Id) |
| | | .ToList(); |
| | | |
| | | if (!sortedDetails.Any()) return; |
| | | |
| | | // è·åææåé
äºåºåçæç»ï¼æå
è¿å
åºæåº |
| | | var allocatedStockDetails = assignStocks |
| | | .SelectMany(x => x.Details) |
| | | .Where(x => stockAllocations.ContainsKey(x.Id)) |
| | | .OrderBy(x => x.CreateDate) |
| | | .ThenBy(x => x.StockId) |
| | | .ToList(); |
| | | |
| | | // 为æ¯ä¸ªåºåæç»å建åé
è®°å½ |
| | | foreach (var stockDetail in allocatedStockDetails) |
| | | { |
| | | if (!stockAllocations.TryGetValue(stockDetail.Id, out decimal allocatedQuantity)) |
| | | continue; |
| | | |
| | | if (allocatedQuantity <= 0) continue; |
| | | |
| | | var stockInfo = assignStocks.First(x => x.Id == stockDetail.StockId); |
| | | decimal remainingAllocate = allocatedQuantity; |
| | | |
| | | // æé¡ºåºåé
ç»å个åºåºåæç» |
| | | foreach (var detail in sortedDetails) |
| | | { |
| | | if (remainingAllocate <= 0) break; |
| | | if (stockAllocation <= 0) break; |
| | | |
| | | // 计ç®è¿ä¸ªæç»è¿éè¦åé
çæ°é |
| | | var detailNeed = detail.OrderQuantity - detail.OverOutQuantity - detail.LockQuantity-detail.MoveQty; |
| | | if (detailNeed <= 0) continue; |
| | | |
| | | // åé
æ°é |
| | | var assignQuantity = Math.Min(remainingAllocate, detailNeed); |
| | | var assignQuantity = Math.Min(stockAllocation, detailNeed); |
| | | |
| | | // éªè¯æ¡ç æ¯å¦åå¨ |
| | | if (string.IsNullOrEmpty(stockDetail.Barcode)) |
| | | // 使ç¨åºåä¸çæææ¡ç |
| | | var barcode = stock.Details |
| | | .Where(d => !string.IsNullOrEmpty(d.Barcode)) |
| | | .Select(d => d.Barcode) |
| | | .FirstOrDefault(); |
| | | |
| | | if (string.IsNullOrEmpty(barcode)) |
| | | { |
| | | throw new Exception($"åºåæç»ID[{stockDetail.Id}]çæ¡ç 为空"); |
| | | throw new Exception($"åºåID[{stock.Id}]çæ¡ç 为空"); |
| | | } |
| | | |
| | | // å建åºåºéå®ä¿¡æ¯ |
| | | var lockInfo = _outStockLockInfoService.GetOutStockLockInfo( |
| | | outboundOrder, detail, stockInfo, assignQuantity, stockDetail.Barcode); |
| | | outStockLockInfos.Add(lockInfo); |
| | | |
| | | // æ´æ°æç»çé宿°é |
| | | detail.LockQuantity += assignQuantity; |
| | | remainingAllocate -= assignQuantity; |
| | | } |
| | | |
| | | // å¦æè¿æå©ä½åé
æ°éï¼éæ°åé
æè®°å½è¦å |
| | | if (remainingAllocate > 0) |
| | | { |
| | | // éæ°åé
ç»å
¶ä»éè¦åé
çæç» |
| | | foreach (var detail in sortedDetails) |
| | | { |
| | | if (remainingAllocate <= 0) break; |
| | | |
| | | var detailNeed = detail.OrderQuantity - detail.OverOutQuantity - detail.LockQuantity; |
| | | if (detailNeed <= 0) continue; |
| | | |
| | | var assignQuantity = Math.Min(remainingAllocate, detailNeed); |
| | | |
| | | var lockInfo = _outStockLockInfoService.GetOutStockLockInfo( |
| | | outboundOrder, detail, stockInfo, assignQuantity, stockDetail.Barcode); |
| | | outboundOrder, detail, stock, assignQuantity, barcode); |
| | | outStockLockInfos.Add(lockInfo); |
| | | |
| | | detail.LockQuantity += assignQuantity; |
| | | remainingAllocate -= assignQuantity; |
| | | stockAllocation -= assignQuantity; |
| | | allocatedQuantity += assignQuantity; |
| | | |
| | | if (allocatedQuantity >= totalNeedQuantity) break; |
| | | } |
| | | } |
| | | |
| | | // å¦æè¿æå©ä½ï¼è®°å½è¦åä½ä¸æåºå¼å¸¸ |
| | | if (remainingAllocate > 0) |
| | | // éªè¯æ¯å¦å®å
¨åé
|
| | | if (allocatedQuantity < totalNeedQuantity) |
| | | { |
| | | _logger.LogWarning($"åºååé
å仿å©ä½æ°éæªåé
: {remainingAllocate}, æ¡ç : {stockDetail.Barcode}"); |
| | | } |
| | | } |
| | | _logger.LogWarning($"åºååé
ä¸å®å
¨ï¼éè¦{totalNeedQuantity}ï¼å®é
åé
{allocatedQuantity}"); |
| | | } |
| | | } |
| | | |