| | |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_ITaskInfoService; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Model.Models.Basic; |
| | | using WIDESEA_Model.Models.Outbound; |
| | |
| | | private readonly IDailySequenceService _dailySequenceService; |
| | | private readonly IAllocateService _allocateService; |
| | | private readonly IRepository<Dt_OutboundBatch> _outboundBatchRepository; |
| | | private readonly ITask_HtyService _task_HtyService; |
| | | private readonly ILogger<OutboundPickingService> _logger; |
| | | |
| | | private Dictionary<string, string> stations = new Dictionary<string, string> |
| | |
| | | public OutboundBatchPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService, |
| | | IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService, |
| | | IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService, IOutboundOrderService outboundOrderService, |
| | | IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository) : base(BaseDal) |
| | | IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository, ITask_HtyService task_HtyService) : base(BaseDal) |
| | | { |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | | _stockInfoService = stockInfoService; |
| | |
| | | _dailySequenceService = dailySequenceService; |
| | | _allocateService = allocateService; |
| | | _outboundBatchRepository = outboundBatchRepository; |
| | | _task_HtyService = task_HtyService; |
| | | } |
| | | |
| | | // <summary> |
| | |
| | | $"æçè¿æ{unfinishedCount}æ¡æªå®æè®°å½ï¼å©ä½æ°é{unfinishedQty}ï¼ä¸è½å走空箱"); |
| | | } |
| | | |
| | | // æ£æ¥æç䏿¯å¦è¿æåºåè´§ç© |
| | | var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>() |
| | | .FirstAsync(x => x.PalletCode == palletCode); |
| | | |
| | | if (stockInfo != null) |
| | | { |
| | | var remainingStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.StockId == stockInfo.Id && |
| | | x.Status == (int)StockStatusEmun.åºåºéå® && |
| | | x.StockQuantity > 0) |
| | | .ToListAsync(); |
| | | |
| | | if (remainingStock.Any()) |
| | | { |
| | | var remainingQty = remainingStock.Sum(x => x.StockQuantity); |
| | | return ValidationResult<List<Dt_OutStockLockInfo>>.Error( |
| | | $"æçä¸è¿æåºåè´§ç©ï¼æ°é{remainingQty}ï¼ä¸è½å走空箱"); |
| | | } |
| | | } |
| | | |
| | | // è·å已宿çéå®è®°å½ |
| | | var completedLocks = lockInfos.Where(x => |
| | | x.Status == (int)OutLockStockStatusEnum.æ£é宿).ToList(); |
| | |
| | | } |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | #region æå¨æå
|
| | | |
| | |
| | | |
| | | _logger.LogInformation($"æ¾å°åºåä¿¡æ¯ - åºåæ°é: {stockDetail.StockQuantity}, åºåºæ°é: {stockDetail.OutboundQuantity}"); |
| | | |
| | | // éè¦ä¿®å¤ï¼éªè¯æå
æ°éä¸è½å¤§äºåºåæ°é |
| | | // éªè¯æå
æ°éä¸è½å¤§äºåºåæ°é |
| | | if (stockDetail.StockQuantity < splitQuantity) |
| | | { |
| | | _logger.LogWarning($"æå
æ°é大äºåºåæ°é - æå
æ°é: {splitQuantity}, åºåæ°é: {stockDetail.StockQuantity}"); |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error($"æå
æ°éä¸è½å¤§äºåºåæ°éï¼å½ååºåï¼{stockDetail.StockQuantity}"); |
| | | } |
| | | |
| | | // éè¦ä¿®å¤ï¼éªè¯æå
æ°éä¸è½å¤§äºéå®ä¿¡æ¯çåé
æ°é |
| | | // éªè¯æå
æ°éä¸è½å¤§äºéå®ä¿¡æ¯çåé
æ°é |
| | | if (lockInfo.AssignQuantity < splitQuantity) |
| | | { |
| | | _logger.LogWarning($"æå
æ°é大äºåé
æ°é - æå
æ°é: {splitQuantity}, åé
æ°é: {lockInfo.AssignQuantity}"); |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error($"æå
æ°éä¸è½å¤§äºåé
æ°éï¼å½ååé
æ°éï¼{lockInfo.AssignQuantity}"); |
| | | } |
| | | |
| | | // éè¦ä¿®å¤ï¼éªè¯æå
æ°éä¸è½å¤§äºéå®ä¿¡æ¯çæªæ£éæ°é |
| | | // éªè¯æå
æ°éä¸è½å¤§äºéå®ä¿¡æ¯çæªæ£éæ°é |
| | | decimal remainingToPick = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | if (remainingToPick < splitQuantity) |
| | | { |
| | |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error($"æå
æ°éä¸è½å¤§äºæªæ£éæ°éï¼å½åæªæ£éï¼{remainingToPick}"); |
| | | } |
| | | |
| | | // éè¦ä¿®å¤ï¼éªè¯æå
ååéå®ä¿¡æ¯çåé
æ°éä¸ä¼ä¸ºè´æ° |
| | | // éªè¯æå
ååéå®ä¿¡æ¯çåé
æ°éä¸ä¼ä¸ºè´æ° |
| | | if (lockInfo.AssignQuantity - splitQuantity < 0) |
| | | { |
| | | _logger.LogWarning($"æå
ååé
æ°éä¸ºè´æ° - å½ååé
æ°é: {lockInfo.AssignQuantity}, æå
æ°é: {splitQuantity}"); |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error($"æå
ååé
æ°éä¸è½ä¸ºè´æ°"); |
| | | } |
| | | |
| | | // éè¦ä¿®å¤ï¼éªè¯è®¢åæç»çåé
æ°éæ¯å¦è¶³å¤ |
| | | // éªè¯è®¢åæç»çåé
æ°éæ¯å¦è¶³å¤ |
| | | // 注æï¼æå¨æå
ä¸ä¼æ¹å订åæç»çåé
æ°éï¼å 为æ»åé
æ°éä¸å |
| | | // åªæ¯ä»ä¸ä¸ªéå®ä¿¡æ¯è½¬ç§»å°å¦ä¸ä¸ªéå®ä¿¡æ¯ |
| | | decimal totalLockAssignQuantity = await GetTotalLockAssignQuantity(orderDetail.Id); |
| | |
| | | { |
| | | _logger.LogInformation($"å¼å§æ§è¡æå¨æå
é»è¾ - åæ¡ç : {stockDetail.Barcode}, æå
æ°é: {splitQuantity}"); |
| | | |
| | | // éè¦ä¿®å¤ï¼è·å订åæç»å¹¶éªè¯åé
æ°é |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == lockInfo.OrderDetailId); |
| | | |
| | | if (orderDetail == null) |
| | | throw new InvalidOperationException("æªæ¾å°è®¢åæç»"); |
| | | |
| | | // éªè¯æå
æ°éä¸ä¼å¯¼è´åé
æ°éä¸ºè´æ° |
| | | // éªè¯æå
æ°é |
| | | if (lockInfo.AssignQuantity < splitQuantity) |
| | | { |
| | | throw new InvalidOperationException($"æå
æ°éè¶
è¿éå®ä¿¡æ¯åé
æ°éï¼æå
æ°é: {splitQuantity}, åé
æ°é: {lockInfo.AssignQuantity}"); |
| | |
| | | // çææ°æ¡ç |
| | | string newBarcode = await GenerateNewBarcode(); |
| | | |
| | | // è®°å½æå
åçåé
æ°é |
| | | decimal originalAssignQtyBefore = lockInfo.AssignQuantity; |
| | | decimal originalOrderQtyBefore = lockInfo.OrderQuantity; |
| | | decimal remainQty = originalAssignQtyBefore - splitQuantity; |
| | | if (remainQty < 0) |
| | | { |
| | | throw new InvalidOperationException($"æå
åå©ä½æ°éä¸ºè´æ°ï¼ååé
æ°é: {originalAssignQtyBefore}, æå
æ°é: {splitQuantity}"); |
| | | } |
| | | // å建æ°åºåæç» |
| | | // 计ç®å©ä½æ°é |
| | | decimal remainQty = lockInfo.AssignQuantity - splitQuantity; |
| | | |
| | | // å建æ°åºåæç» |
| | | var newStockDetail = new Dt_StockInfoDetail |
| | | { |
| | | StockId = stockDetail.StockId, |
| | |
| | | InboundOrderRowNo = stockDetail.InboundOrderRowNo, |
| | | }; |
| | | await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync(); |
| | | _logger.LogInformation($"å建æ°åºåæç» - æ¡ç : {newBarcode}, åºåæ°é: {splitQuantity}"); |
| | | |
| | | // æ´æ°ååºåæç» |
| | | decimal originalStockQtyBefore = stockDetail.StockQuantity; |
| | | // æ´æ°ååºåæç» |
| | | stockDetail.StockQuantity -= splitQuantity; |
| | | if (stockDetail.StockQuantity < 0) |
| | | { |
| | | stockDetail.StockQuantity = 0; |
| | | _logger.LogWarning($"ååºåæ°éåºç°è´æ°ï¼é置为0"); |
| | | } |
| | | if (stockDetail.StockQuantity < 0) stockDetail.StockQuantity = 0; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | _logger.LogInformation($"æ´æ°ååºåæç» - åºåæ°éä» {originalStockQtyBefore} åå°å° {stockDetail.StockQuantity}"); |
| | | |
| | | // å建æ°éå®ä¿¡æ¯ |
| | | // å建æ°éå®ä¿¡æ¯ |
| | | var newLockInfo = new Dt_OutStockLockInfo |
| | | { |
| | | OrderNo = lockInfo.OrderNo, |
| | | OrderDetailId = lockInfo.OrderDetailId, |
| | | OrderDetailId = lockInfo.OrderDetailId, // ç»å®å°åä¸ä¸ªè®¢åæç» |
| | | OutboundBatchNo = lockInfo.OutboundBatchNo, |
| | | MaterielCode = lockInfo.MaterielCode, |
| | | MaterielName = lockInfo.MaterielName, |
| | |
| | | }; |
| | | |
| | | await _outStockLockInfoService.Db.Insertable(newLockInfo).ExecuteCommandAsync(); |
| | | _logger.LogInformation($"å建æ°éå®ä¿¡æ¯ - æ¡ç : {newBarcode}, åé
æ°é: {splitQuantity}"); |
| | | |
| | | // æ´æ°åéå®ä¿¡æ¯ |
| | | // æ´æ°åéå®ä¿¡æ¯ |
| | | lockInfo.AssignQuantity = remainQty; |
| | | lockInfo.OrderQuantity = remainQty; |
| | | |
| | | _logger.LogInformation($"æ´æ°åéå®ä¿¡æ¯ - åé
æ°éä» {originalAssignQtyBefore} åå°å° {lockInfo.AssignQuantity}"); |
| | | _logger.LogInformation($"æ´æ°åéå®ä¿¡æ¯ - è®¢åæ°éä» {originalOrderQtyBefore} åå°å° {lockInfo.OrderQuantity}"); |
| | | |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | |
| | | _logger.LogInformation($"订åæç»åé
æ°éä¿æä¸å - å·²åé
æ°é: {orderDetail.AllocatedQuantity}"); |
| | | // éè¦ï¼æå¨æå
䏿¹å订åæç»çæ»åé
æ°é |
| | | // å 为åé
æ°éåªæ¯ä»ä¸ä¸ªéå®ä¿¡æ¯è½¬ç§»å°å¦ä¸ä¸ªéå®ä¿¡æ¯ |
| | | _logger.LogInformation($"æå¨æå
- 订åæç»æ»åé
æ°éä¿æä¸å"); |
| | | |
| | | // è®°å½æå
åå² |
| | | // è®°å½æå
åå² |
| | | await RecordSplitHistory(lockInfo, stockDetail, splitQuantity, newBarcode, false); |
| | | |
| | | // å建æå
ç»æå表 |
| | | // å建æå
ç»æå表 |
| | | var splitResults = CreateSplitResults(lockInfo, splitQuantity, remainQty, newBarcode, stockDetail.Barcode); |
| | | |
| | | _logger.LogInformation($"æå¨æå
é»è¾æ§è¡å®æ"); |
| | | |
| | | return splitResults; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éªè¯æå
åæ°æ®ä¸è´æ§ |
| | | /// </summary> |
| | | private async Task ValidateDataConsistencyAfterSplit(long orderDetailId, decimal expectedAllocatedQty, decimal expectedLockQty) |
| | | { |
| | | // éæ°è·å订åæç»æ°æ® |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == orderDetailId); |
| | | |
| | | if (orderDetail == null) |
| | | return; |
| | | |
| | | // è®¡ç®ææéå®ä¿¡æ¯çæ»åé
æ°é |
| | | var allLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderDetailId == orderDetailId) |
| | | .ToListAsync(); |
| | | |
| | | decimal totalLockAssignQty = allLocks.Sum(x => x.AssignQuantity); |
| | | |
| | | _logger.LogInformation($"æ°æ®ä¸è´æ§éªè¯ - 订åæç»åé
æ°é: {orderDetail.AllocatedQuantity}, éå®ä¿¡æ¯æ»åé
æ°é: {totalLockAssignQty}"); |
| | | |
| | | // å¦ææ°æ®ä¸ä¸è´ï¼è®°å½è¦å |
| | | if (Math.Abs(orderDetail.AllocatedQuantity - totalLockAssignQty) > 0.01m) |
| | | { |
| | | _logger.LogWarning($"æ°æ®ä¸ä¸è´ - 订åæç»åé
æ°é: {orderDetail.AllocatedQuantity}, éå®ä¿¡æ¯æ»åé
æ°é: {totalLockAssignQty}"); |
| | | } |
| | | |
| | | // éªè¯åé
æ°é没æå¼å¸¸åå |
| | | if (Math.Abs(orderDetail.AllocatedQuantity - expectedAllocatedQty) > 0.01m) |
| | | { |
| | | _logger.LogWarning($"åé
æ°éå¼å¸¸åå - ææ: {expectedAllocatedQty}, å®é
: {orderDetail.AllocatedQuantity}"); |
| | | } |
| | | |
| | | if (Math.Abs(orderDetail.LockQuantity - expectedLockQty) > 0.01m) |
| | | { |
| | | _logger.LogWarning($"é宿°éå¼å¸¸åå - ææ: {expectedLockQty}, å®é
: {orderDetail.LockQuantity}"); |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | |
| | |
| | | { |
| | | _logger.LogInformation($"å¼å§æ§è¡åæ¶æå
é»è¾ - åæ¡ç : {splitRecord.OriginalBarcode}, æ°æ¡ç : {splitRecord.NewBarcode}, æå
æ°é: {splitRecord.SplitQty}"); |
| | | |
| | | // è·å订åæç» |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == originalLockInfo.OrderDetailId); |
| | | |
| | | if (orderDetail == null) |
| | | throw new InvalidOperationException("æªæ¾å°è®¢åæç»"); |
| | | |
| | | // è®°å½åæ¶æå
åçå
³é®æ°æ® |
| | | decimal originalOrderDetailAllocatedQty = orderDetail.AllocatedQuantity; |
| | | decimal originalOrderDetailLockQty = orderDetail.LockQuantity; |
| | | |
| | | _logger.LogInformation($"åæ¶æå
åæ°æ® - 订åæç»åé
æ°é: {originalOrderDetailAllocatedQty}, é宿°é: {originalOrderDetailLockQty}"); |
| | | |
| | | // æ¢å¤åéå®ä¿¡æ¯ |
| | | decimal originalAssignQtyBefore = originalLockInfo.AssignQuantity; |
| | | decimal originalOrderQtyBefore = originalLockInfo.OrderQuantity; |
| | | |
| | | |
| | | originalLockInfo.AssignQuantity += splitRecord.SplitQty; |
| | | originalLockInfo.OrderQuantity += splitRecord.SplitQty; |
| | | // æ ¹æ®æå
ç±»åå³å®å¦ä½æ¢å¤ |
| | | if (splitRecord.IsAutoSplit) |
| | | { |
| | | // èªå¨æå
ï¼åéå®ä¿¡æ¯ä¿æä¸åï¼åªéè¦å 餿°éå®ä¿¡æ¯ |
| | | _logger.LogInformation($"åæ¶èªå¨æå
- åéå®ä¿¡æ¯ä¿æä¸å"); |
| | | } |
| | | else |
| | | { |
| | | // æå¨æå
ï¼æ¢å¤åéå®ä¿¡æ¯çåé
æ°é |
| | | originalLockInfo.AssignQuantity += splitRecord.SplitQty; |
| | | originalLockInfo.OrderQuantity += splitRecord.SplitQty; |
| | | |
| | | _logger.LogInformation($"æ¢å¤åéå®ä¿¡æ¯ - åé
æ°éä» {originalAssignQtyBefore} å¢å å° {originalLockInfo.AssignQuantity}"); |
| | | _logger.LogInformation($"æ¢å¤åéå®ä¿¡æ¯ - è®¢åæ°éä» {originalOrderQtyBefore} å¢å å° {originalLockInfo.OrderQuantity}"); |
| | | _logger.LogInformation($"åæ¶æå¨æå
- æ¢å¤åéå®ä¿¡æ¯åé
æ°éä» {originalAssignQtyBefore} å¢å å° {originalLockInfo.AssignQuantity}"); |
| | | } |
| | | |
| | | // 妿åéå®ä¿¡æ¯çç¶ææ¯æ£é宿ï¼éè¦éæ°è®¾ç½®ä¸ºåºåºä¸ |
| | | if (originalLockInfo.Status == (int)OutLockStockStatusEnum.æ£é宿) |
| | |
| | | |
| | | if (originalStock != null) |
| | | { |
| | | decimal originalStockQtyBefore = originalStock.StockQuantity; |
| | | originalStock.StockQuantity += splitRecord.SplitQty; |
| | | |
| | | _logger.LogInformation($"æ¢å¤ååºåæç» - åºåæ°éä» {originalStockQtyBefore} å¢å å° {originalStock.StockQuantity}"); |
| | | |
| | | // 妿ååºåç¶ææ¯åºåºå®æï¼éè¦éæ°è®¾ç½®ä¸ºåºåºéå® |
| | | if (originalStock.Status == (int)StockStatusEmun.åºåºå®æ) |
| | | if (splitRecord.IsAutoSplit) |
| | | { |
| | | originalStock.Status = (int)StockStatusEmun.åºåºéå®; |
| | | _logger.LogInformation($"ååºåç¶æä»åºåºå®ææ¢å¤ä¸ºåºåºéå®"); |
| | | // èªå¨æå
ï¼ååºåæç»ä¿æä¸å |
| | | _logger.LogInformation($"åæ¶èªå¨æå
- ååºåæç»ä¿æä¸å"); |
| | | } |
| | | else |
| | | { |
| | | // æå¨æå
ï¼æ¢å¤ååºåæ°é |
| | | decimal originalStockQtyBefore = originalStock.StockQuantity; |
| | | originalStock.StockQuantity += splitRecord.SplitQty; |
| | | |
| | | await _stockInfoDetailService.Db.Updateable(originalStock).ExecuteCommandAsync(); |
| | | _logger.LogInformation($"åæ¶æå¨æå
- æ¢å¤ååºåæç»æ°éä» {originalStockQtyBefore} å¢å å° {originalStock.StockQuantity}"); |
| | | |
| | | // 妿ååºåç¶ææ¯åºåºå®æï¼éè¦éæ°è®¾ç½®ä¸ºåºåºéå® |
| | | if (originalStock.Status == (int)StockStatusEmun.åºåºå®æ) |
| | | { |
| | | originalStock.Status = (int)StockStatusEmun.åºåºéå®; |
| | | _logger.LogInformation($"ååºåç¶æä»åºåºå®ææ¢å¤ä¸ºåºåºéå®"); |
| | | } |
| | | |
| | | await _stockInfoDetailService.Db.Updateable(originalStock).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | |
| | | if (newLockInfo != null) |
| | | { |
| | | // å 餿°éå®ä¿¡æ¯ |
| | | _logger.LogInformation($"å 餿°éå®ä¿¡æ¯ - æ¡ç : {newLockInfo?.CurrentBarcode}, åé
æ°é: {newLockInfo?.AssignQuantity}"); |
| | | await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.Id == newLockInfo.Id) |
| | | .ExecuteCommandAsync(); |
| | | // å 餿°éå®ä¿¡æ¯ |
| | | _logger.LogInformation($"å 餿°éå®ä¿¡æ¯ - æ¡ç : {newLockInfo.CurrentBarcode}, åé
æ°é: {newLockInfo.AssignQuantity}"); |
| | | await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.Id == newLockInfo.Id) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // å 餿°åºåæç» |
| | | _logger.LogInformation($"å 餿°åºåæç» - æ¡ç : {newStockDetail.Barcode}, åºåæ°é: {newStockDetail.StockQuantity}"); |
| | | await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == newLockInfo.CurrentBarcode) |
| | | .ExecuteCommandAsync(); |
| | | // å 餿°åºåæç» |
| | | _logger.LogInformation($"å 餿°åºåæç» - æ¡ç : {newStockDetail.Barcode}, åºåæ°é: {newStockDetail.StockQuantity}"); |
| | | await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == newLockInfo.CurrentBarcode) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // 妿æ¯èªå¨æå
ï¼éè¦åå°è®¢åæç»çåé
æ°éåé宿°é |
| | | if (splitRecord.IsAutoSplit) |
| | | { |
| | | decimal originalAllocatedBefore = orderDetail.AllocatedQuantity; |
| | | decimal originalLockBefore = orderDetail.LockQuantity; |
| | | |
| | | orderDetail.AllocatedQuantity -= splitRecord.SplitQty; |
| | | orderDetail.LockQuantity -= splitRecord.SplitQty; |
| | | |
| | | // è¾¹çæ£æ¥ï¼ç¡®ä¿æ°éä¸ä¼ä¸ºè´æ° |
| | | if (orderDetail.AllocatedQuantity < 0) |
| | | { |
| | | _logger.LogWarning($"åé
æ°éåºç°è´æ°ï¼é置为0ãåå¼: {orderDetail.AllocatedQuantity + splitRecord.SplitQty}, åå°: {splitRecord.SplitQty}"); |
| | | orderDetail.AllocatedQuantity = 0; |
| | | } |
| | | if (orderDetail.LockQuantity < 0) |
| | | { |
| | | _logger.LogWarning($"é宿°éåºç°è´æ°ï¼é置为0ãåå¼: {orderDetail.LockQuantity + splitRecord.SplitQty}, åå°: {splitRecord.SplitQty}"); |
| | | orderDetail.LockQuantity = 0; |
| | | } |
| | | |
| | | await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"åæ¶èªå¨æå
åå°è®¢åæç»æ°é - åé
æ°éä» {originalAllocatedBefore} åå°å° {orderDetail.AllocatedQuantity}"); |
| | | _logger.LogInformation($"åæ¶èªå¨æå
åå°è®¢åæç»æ°é - é宿°éä» {originalLockBefore} åå°å° {orderDetail.LockQuantity}"); |
| | | } |
| | | |
| | | // æ è®°æå
è®°å½ä¸ºå·²æ¤é |
| | |
| | | await _splitPackageService.Db.Updateable(splitRecord).ExecuteCommandAsync(); |
| | | _logger.LogInformation($"æ è®°æå
è®°å½ä¸ºå·²æ¤é"); |
| | | |
| | | // éªè¯åæ¶æå
åæ°æ®ä¸è´æ§ |
| | | await ValidateDataConsistencyAfterCancelSplit(orderDetail.Id, originalOrderDetailAllocatedQty, originalOrderDetailLockQty, splitRecord.IsAutoSplit, splitRecord.SplitQty); |
| | | |
| | | // æ£æ¥å¹¶æ´æ°æ¹æ¬¡å订åç¶æ |
| | | await CheckAndUpdateBatchStatus(originalLockInfo.BatchNo); |
| | | await CheckAndUpdateOrderStatus(originalLockInfo.OrderNo); |
| | | |
| | | _logger.LogInformation($"åæ¶æå
é»è¾æ§è¡å®æ"); |
| | | } |
| | | /// <summary> |
| | | /// éªè¯åæ¶æå
åæ°æ®ä¸è´æ§ - ææ°çæ¬ |
| | | /// </summary> |
| | | private async Task ValidateDataConsistencyAfterCancelSplit(long orderDetailId, decimal originalAllocatedQty, decimal originalLockQty, bool isAutoSplit, decimal splitQuantity) |
| | | { |
| | | // éæ°è·å订åæç»æ°æ® |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == orderDetailId); |
| | | |
| | | if (orderDetail == null) |
| | | return; |
| | | |
| | | // è®¡ç®ææéå®ä¿¡æ¯çæ»åé
æ°é |
| | | var allLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderDetailId == orderDetailId) |
| | | .ToListAsync(); |
| | | |
| | | decimal totalLockAssignQty = allLocks.Sum(x => x.AssignQuantity); |
| | | |
| | | _logger.LogInformation($"åæ¶æå
åæ°æ®ä¸è´æ§éªè¯ - 订åæç»åé
æ°é: {orderDetail.AllocatedQuantity}, éå®ä¿¡æ¯æ»åé
æ°é: {totalLockAssignQty}"); |
| | | |
| | | // æ ¹æ®æå
ç±»åè®¡ç®ææå¼ |
| | | decimal expectedAllocatedQty; |
| | | decimal expectedLockQty; |
| | | |
| | | if (isAutoSplit) |
| | | { |
| | | // èªå¨æå
åæ¶ï¼åé
æ°éåºè¯¥åå°æå
æ°é |
| | | expectedAllocatedQty = originalAllocatedQty - splitQuantity; |
| | | expectedLockQty = originalLockQty - splitQuantity; |
| | | |
| | | _logger.LogInformation($"åæ¶èªå¨æå
ææå¼ - åé
æ°é: {expectedAllocatedQty}, é宿°é: {expectedLockQty}"); |
| | | } |
| | | else |
| | | { |
| | | // æå¨æå
åæ¶ï¼åé
æ°éåºè¯¥ä¿æä¸å |
| | | expectedAllocatedQty = originalAllocatedQty; |
| | | expectedLockQty = originalLockQty; |
| | | |
| | | _logger.LogInformation($"åæ¶æå¨æå
ææå¼ - åé
æ°é: {expectedAllocatedQty}, é宿°é: {expectedLockQty}"); |
| | | } |
| | | |
| | | // è¾¹çæ£æ¥ï¼ç¡®ä¿ææå¼ä¸ä¸ºè´æ° |
| | | if (expectedAllocatedQty < 0) |
| | | { |
| | | _logger.LogWarning($"ææåé
æ°éä¸ºè´æ°ï¼é置为0ã计ç®å¼: {expectedAllocatedQty}"); |
| | | expectedAllocatedQty = 0; |
| | | } |
| | | |
| | | if (expectedLockQty < 0) |
| | | { |
| | | _logger.LogWarning($"ææé宿°éä¸ºè´æ°ï¼é置为0ã计ç®å¼: {expectedLockQty}"); |
| | | expectedLockQty = 0; |
| | | } |
| | | |
| | | // éªè¯åé
æ°é |
| | | if (Math.Abs(orderDetail.AllocatedQuantity - expectedAllocatedQty) > 0.01m) |
| | | { |
| | | _logger.LogWarning($"åæ¶æå
ååé
æ°éå¼å¸¸ - ææ: {expectedAllocatedQty}, å®é
: {orderDetail.AllocatedQuantity}"); |
| | | } |
| | | |
| | | // éªè¯é宿°é |
| | | if (Math.Abs(orderDetail.LockQuantity - expectedLockQty) > 0.01m) |
| | | { |
| | | _logger.LogWarning($"åæ¶æå
åé宿°éå¼å¸¸ - ææ: {expectedLockQty}, å®é
: {orderDetail.LockQuantity}"); |
| | | } |
| | | |
| | | // éªè¯è®¢åæç»åé
æ°éä¸éå®ä¿¡æ¯æ»åé
æ°éçä¸è´æ§ |
| | | if (Math.Abs(orderDetail.AllocatedQuantity - totalLockAssignQty) > 0.01m) |
| | | { |
| | | _logger.LogWarning($"åæ¶æå
åæ°æ®ä¸ä¸è´ - 订åæç»åé
æ°é: {orderDetail.AllocatedQuantity}, éå®ä¿¡æ¯æ»åé
æ°é: {totalLockAssignQty}"); |
| | | } |
| | | |
| | | // è®°å½è¯¦ç»çä¸è´æ§æ¥å |
| | | _logger.LogInformation($"åæ¶æå
æ°æ®ä¸è´æ§æ¥å - " + |
| | | $"订åæç»åé
æ°é: {orderDetail.AllocatedQuantity}, " + |
| | | $"订åæç»é宿°é: {orderDetail.LockQuantity}, " + |
| | | $"éå®ä¿¡æ¯æ»åé
æ°é: {totalLockAssignQty}, " + |
| | | $"æå
ç±»å: {(isAutoSplit ? "èªå¨" : "æå¨")}, " + |
| | | $"æå
æ°é: {splitQuantity}"); |
| | | } |
| | | /// <summary> |
| | | /// éªè¯åæ¶æå
è¯·æ± |
| | | /// </summary> |
| | |
| | | |
| | | _logger.LogInformation($"æ¾å°æ°éå®ä¿¡æ¯ - ç¶æ: {newLockInfo.Status}, å·²æ£é: {newLockInfo.PickedQty}, åé
æ°é: {newLockInfo.AssignQuantity}"); |
| | | |
| | | // éè¦ä¿®å¤ï¼æ£æ¥æ°æ¡ç æ¯å¦å·²è¢«åæ£ |
| | | // æ£æ¥æ°æ¡ç æ¯å¦å·²è¢«åæ£ |
| | | var newBarcodePickingRecords = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(x => x.Barcode == newBarcode && x.OrderNo == orderNo && !x.IsCancelled) |
| | | .ToListAsync(); |
| | |
| | | $"æ°æ¡ç å·²è¢«åæ£ï¼å·²æ£éæ°éï¼{totalPickedQty}ï¼ï¼è¯·å
忶忣ï¼ç¶åååæ¶æå
"); |
| | | } |
| | | |
| | | // éè¦ä¿®å¤ï¼æ£æ¥åæ¡ç æ¯å¦å·²è¢«åæ£ |
| | | // æ£æ¥åæ¡ç æ¯å¦å·²è¢«åæ£ |
| | | var originalBarcodePickingRecords = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(x => x.Barcode == splitRecord.OriginalBarcode && x.OrderNo == orderNo && !x.IsCancelled) |
| | | .ToListAsync(); |
| | |
| | | |
| | | #endregion |
| | | |
| | | #region ç»ä¸ååºé»è¾ |
| | | #region ç»ä¸ååºé»è¾ |
| | | private async Task<Dt_Task> GetCurrentTask(string orderNo, string palletCode) |
| | | { |
| | | // å
å°è¯éè¿è®¢åå·åæçå·æ¥æ¾ä»»å¡ |
| | |
| | | return WebResponseContent.Instance.Error("订åå·åæçç ä¸è½ä¸ºç©º"); |
| | | |
| | | // è·ååºåä¿¡æ¯ |
| | | var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>().FirstAsync(x => x.PalletCode == palletCode); |
| | | var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>() |
| | | .FirstAsync(x => x.PalletCode == palletCode); |
| | | if (stockInfo == null) |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°æç {palletCode} 对åºçåºåä¿¡æ¯"); |
| | | |
| | | var task = await GetCurrentTask(orderNo, palletCode); |
| | | if (task == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçä»»å¡ä¿¡æ¯"); |
| | | |
| | | // åææçç¶æ |
| | | var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id); |
| | | var statusAnalysis = await AnalyzePalletStatusForReturn(orderNo, palletCode, stockInfo.Id); |
| | | |
| | | if (!statusAnalysis.HasItemsToReturn) |
| | | return await HandleNoReturnItems(orderNo, palletCode, task, stockInfo.Id); |
| | | return await HandleEmptyPalletReturn(orderNo, palletCode, stockInfo); |
| | | |
| | | // æ£æ¥æ¯å¦æè¿è¡ä¸çä»»å¡ |
| | | if (statusAnalysis.HasActiveTasks) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æç {palletCode} æè¿è¡ä¸çä»»å¡ï¼ä¸è½æ§è¡ååºæä½"); |
| | | } |
| | | _logger.LogInformation($"å¼å§ååºæä½ - 订å: {orderNo}, æç: {palletCode}, ååºæ°é: {statusAnalysis.TotalReturnQty}"); |
| | | |
| | | // æ§è¡ååºæä½ |
| | | await ExecuteReturnDataOperations(orderNo, palletCode, stockInfo, task, statusAnalysis); |
| | | // æ§è¡ååºæ°æ®æä½ |
| | | await ExecuteReturnDataOperations(statusAnalysis); |
| | | |
| | | // éæ¾ææéå®ä»¥ä¾¿éæ°åé
|
| | | await ReleaseAllLocksForReallocation(orderNo, palletCode, statusAnalysis); |
| | | // æ´æ°è®¢åç¶æ |
| | | await UpdateOrderStatusAfterReturn(orderNo); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | // æ¶éææéè¦ååºçæ¡ç |
| | | var returnBarcodes = await CollectReturnBarcodes(statusAnalysis); |
| | | |
| | | // å建ESSååºä»»å¡ |
| | | if (returnBarcodes.Any()) |
| | | { |
| | | _logger.LogInformation($"å建ååºAGVä»»å¡ - 订å: {orderNo}, æç: {palletCode}, æ¡ç æ°é: {returnBarcodes.Count}, åå : {returnReason}"); |
| | | await CreateReturnTaskAndHandleESS(orderNo, palletCode, task, TaskTypeEnum.InPick, stockInfo.PalletType); |
| | | } |
| | | |
| | | // æ´æ°è®¢åç¶æï¼ä¸è§¦åMESåä¼ ï¼ |
| | | await UpdateOrderStatusForReturn(orderNo); |
| | | // å建ååºä»»å¡ï¼AGVï¼ |
| | | await CreateReturnTask(orderNo, palletCode, stockInfo); |
| | | |
| | | return WebResponseContent.Instance.OK($"ååºæä½æåï¼å
±ååºæ°éï¼{statusAnalysis.TotalReturnQty}", new |
| | | { |
| | | ReturnQuantity = statusAnalysis.TotalReturnQty, |
| | | ReturnBarcodes = returnBarcodes, |
| | | ReturnBarcodes = statusAnalysis.AllBarcodes, |
| | | Reason = returnReason, |
| | | PalletCode = palletCode, |
| | | OrderNo = orderNo |
| | |
| | | return WebResponseContent.Instance.Error($"ååºæä½å¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | private async Task ExecuteReturnDataOperations(string orderNo, string palletCode, Dt_StockInfo stockInfo,Dt_Task task, PalletStatusAnalysis statusAnalysis) |
| | | /// <summary> |
| | | /// æ§è¡ååºæ°æ®æä½ |
| | | /// ç¡®ä¿ä¸ä¼å°çæçæ¡ç æ°éé误ç»å®å°é宿°é |
| | | /// </summary> |
| | | private async Task ExecuteReturnDataOperations(PalletStatusAnalysis statusAnalysis) |
| | | { |
| | | _logger.LogInformation($"å¼å§æ§è¡ååºæ°æ®æä½ - 订å: {orderNo}, æç: {palletCode}"); |
| | | _logger.LogInformation($"å¼å§æ§è¡ååºæ°æ®æä½ - 订å: {statusAnalysis.OrderNo}, æç: {statusAnalysis.PalletCode}"); |
| | | |
| | | // 1. å¤çæªåæ£çéå®è®°å½ |
| | | if (statusAnalysis.HasRemainingLocks) |
| | | try |
| | | { |
| | | _logger.LogInformation($"å¤ç {statusAnalysis.RemainingLocks.Count} æ¡æªåæ£éå®è®°å½"); |
| | | await HandleRemainingLocksReturn(statusAnalysis.RemainingLocks); |
| | | // 1. å¤çå·²åé
çæªåæ£éå®è®°å½ |
| | | if (statusAnalysis.HasRemainingLocks) |
| | | { |
| | | _logger.LogInformation($"å¤ç {statusAnalysis.RemainingLocks.Count} æ¡å·²åé
æªåæ£éå®è®°å½"); |
| | | await HandleAllocatedLocksReturn(statusAnalysis.RemainingLocks); |
| | | } |
| | | |
| | | // 2. å¤çæªåé
çéå®è®°å½ï¼å¦èªå¨æå
产ççï¼ |
| | | if (statusAnalysis.HasUnallocatedLocks) |
| | | { |
| | | _logger.LogInformation($"å¤ç {statusAnalysis.UnallocatedLocks.Count} æ¡æªåé
éå®è®°å½"); |
| | | await HandleUnallocatedLocksReturn(statusAnalysis.UnallocatedLocks); |
| | | } |
| | | |
| | | // 3. å¤çæªåé
çåºåè´§ç© |
| | | if (statusAnalysis.HasPalletStockGoods) |
| | | { |
| | | _logger.LogInformation($"å¤ç {statusAnalysis.PalletStockGoods.Count} 个æªåé
åºåè´§ç©"); |
| | | await HandleUnallocatedStockReturn(statusAnalysis.PalletStockGoods); |
| | | } |
| | | |
| | | _logger.LogInformation($"ååºæ°æ®æä½å®æ - æ»ååºæ°é: {statusAnalysis.TotalReturnQty}"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError($"ååºæ°æ®æä½å¤±è´¥ - 订å: {statusAnalysis.OrderNo}, æç: {statusAnalysis.PalletCode}, Error: {ex.Message}"); |
| | | throw; |
| | | } |
| | | } |
| | | // <summary> |
| | | /// å¤çæªåé
çéå®è®°å½ååº |
| | | /// ä¸éè¦åå°è®¢åæç»çåé
æ°é |
| | | /// </summary> |
| | | private async Task HandleUnallocatedLocksReturn(List<Dt_OutStockLockInfo> unallocatedLocks) |
| | | { |
| | | _logger.LogInformation($"å¼å§å¤çæªåé
éå®è®°å½ååº - å
± {unallocatedLocks.Count} æ¡è®°å½"); |
| | | |
| | | foreach (var lockInfo in unallocatedLocks) |
| | | { |
| | | // 计ç®ååºæ°éï¼æªæ£éçé¨åï¼ |
| | | decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | |
| | | if (returnQty <= 0) |
| | | { |
| | | _logger.LogInformation($"è·³è¿æªåé
éå®è®°å½ - éå®ID: {lockInfo.Id}, å·²æ£éå®æææ éååº"); |
| | | continue; |
| | | } |
| | | |
| | | _logger.LogInformation($"å¤çæªåé
éå®è®°å½ååº - éå®ID: {lockInfo.Id}, æ¡ç : {lockInfo.CurrentBarcode}, ååºæ°é: {returnQty}"); |
| | | |
| | | // æ¢å¤åºåç¶æ |
| | | await RestoreStockForLockInfo(lockInfo, returnQty); |
| | | |
| | | // æ´æ°éå®è®°å½ç¶æä¸ºå·²ååº |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | lockInfo.Operator = App.User.UserName; |
| | | |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ´æ°æªåé
éå®ç¶æ - éå®ID: {lockInfo.Id}, ç¶æ: åºåºä¸ -> å·²ååº"); |
| | | |
| | | // éè¦ï¼æªåé
éå®è®°å½ä¸éè¦åå°è®¢åæç»çåé
æ°é |
| | | _logger.LogInformation($"æªåé
éå®è®°å½ååºå®æ - éå®ID: {lockInfo.Id}, ååºæ°é: {returnQty}, æ éæ´æ°è®¢åæç»"); |
| | | } |
| | | |
| | | // 2. å¤çæçä¸çåºåè´§ç© |
| | | if (statusAnalysis.HasPalletStockGoods) |
| | | _logger.LogInformation($"æªåé
éå®è®°å½ååºå¤ç宿 - å
±å¤ç {unallocatedLocks.Count} æ¡è®°å½"); |
| | | } |
| | | private async Task HandleAllocatedLocksReturn(List<Dt_OutStockLockInfo> allocatedLocks) |
| | | { |
| | | _logger.LogInformation($"å¼å§å¤çå·²åé
éå®è®°å½ååº - å
± {allocatedLocks.Count} æ¡è®°å½"); |
| | | |
| | | // æè®¢åæç»åç»å¤ç |
| | | var orderDetailGroups = allocatedLocks.GroupBy(x => x.OrderDetailId); |
| | | |
| | | foreach (var group in orderDetailGroups) |
| | | { |
| | | _logger.LogInformation($"å¤ç {statusAnalysis.PalletStockGoods.Count} 个åºåè´§ç©"); |
| | | await HandlePalletStockGoodsReturn(statusAnalysis.PalletStockGoods, stockInfo.Id); |
| | | var orderDetailId = group.Key; |
| | | var groupLocks = group.ToList(); |
| | | |
| | | _logger.LogInformation($"å¤ç订åæç» {orderDetailId} ç {groupLocks.Count} æ¡éå®è®°å½"); |
| | | |
| | | // è·å订åæç» |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == orderDetailId); |
| | | |
| | | if (orderDetail == null) |
| | | { |
| | | _logger.LogWarning($"æªæ¾å°è®¢åæç» - OrderDetailId: {orderDetailId}"); |
| | | continue; |
| | | } |
| | | |
| | | decimal totalReturnQtyForDetail = 0; |
| | | |
| | | foreach (var lockInfo in groupLocks) |
| | | { |
| | | // 计ç®ååºæ°éï¼æªæ£éçé¨åï¼ |
| | | decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | |
| | | if (returnQty <= 0) |
| | | { |
| | | _logger.LogInformation($"è·³è¿éå®è®°å½ - éå®ID: {lockInfo.Id}, å·²æ£éå®æææ éååº"); |
| | | continue; |
| | | } |
| | | |
| | | _logger.LogInformation($"å¤çå·²åé
éå®è®°å½ååº - éå®ID: {lockInfo.Id}, æ¡ç : {lockInfo.CurrentBarcode}, ååºæ°é: {returnQty}"); |
| | | |
| | | // æ¢å¤åºåç¶æ |
| | | await RestoreStockForLockInfo(lockInfo, returnQty); |
| | | |
| | | // æ´æ°éå®è®°å½ç¶æä¸ºå·²ååº |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | lockInfo.Operator = App.User.UserName; |
| | | |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ´æ°å·²åé
éå®ç¶æ - éå®ID: {lockInfo.Id}, ç¶æ: åºåºä¸ -> å·²ååº"); |
| | | |
| | | totalReturnQtyForDetail += returnQty; |
| | | } |
| | | |
| | | // åå°è®¢åæç»çåé
æ°é |
| | | if (totalReturnQtyForDetail > 0) |
| | | { |
| | | await ReduceOrderDetailAllocation(orderDetail, totalReturnQtyForDetail); |
| | | } |
| | | } |
| | | |
| | | // 3. å¤çæå
è®°å½ |
| | | if (statusAnalysis.HasSplitRecords) |
| | | _logger.LogInformation($"å·²åé
éå®è®°å½ååºå¤ç宿 - å
±å¤ç {allocatedLocks.Count} æ¡è®°å½"); |
| | | } |
| | | /// <summary> |
| | | /// æ¢å¤éå®è®°å½å¯¹åºçåºå |
| | | /// </summary> |
| | | private async Task RestoreStockForLockInfo(Dt_OutStockLockInfo lockInfo, decimal returnQty) |
| | | { |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId); |
| | | |
| | | if (stockDetail != null) |
| | | { |
| | | _logger.LogInformation($"å¤ç {statusAnalysis.SplitRecords.Count} æ¡æå
è®°å½"); |
| | | await HandleSplitRecordsReturn(statusAnalysis.SplitRecords, stockInfo.Id); |
| | | // è®°å½æ¢å¤åçåºåç¶æ |
| | | decimal originalStockQty = stockDetail.StockQuantity; |
| | | decimal originalOutboundQty = stockDetail.OutboundQuantity; |
| | | |
| | | // æ¢å¤åºåæ°éï¼åºåºæ°éåå°ï¼åºåæ°éå¢å |
| | | stockDetail.OutboundQuantity -= returnQty; |
| | | stockDetail.StockQuantity += returnQty; |
| | | |
| | | // ç¡®ä¿æ°éä¸ä¼ä¸ºè´æ° |
| | | if (stockDetail.OutboundQuantity < 0) |
| | | { |
| | | _logger.LogWarning($"åºåºæ°éåºç°è´æ°ï¼é置为0ãåå¼: {stockDetail.OutboundQuantity + returnQty}"); |
| | | stockDetail.OutboundQuantity = 0; |
| | | } |
| | | |
| | | // æ¢å¤åºåç¶æä¸ºå¯ç¨ç¶æ |
| | | if (stockDetail.Status == (int)StockStatusEmun.åºåºéå®) |
| | | { |
| | | stockDetail.Status = (int)StockStatusEmun.å
¥åºå®æ; |
| | | _logger.LogInformation($"åºåç¶ææ´æ°ä¸ºå
¥åºå®æ - æ¡ç : {stockDetail.Barcode}"); |
| | | } |
| | | |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ¢å¤åºåç¶æ - æ¡ç : {stockDetail.Barcode}, " + |
| | | $"åºåæ°é: {originalStockQty} -> {stockDetail.StockQuantity}, " + |
| | | $"åºåºæ°é: {originalOutboundQty} -> {stockDetail.OutboundQuantity}"); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogWarning($"æªæ¾å°å¯¹åºçåºåä¿¡æ¯ - æ¡ç : {lockInfo.CurrentBarcode}, StockId: {lockInfo.StockId}"); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// å建ååºä»»å¡ |
| | | /// </summary> |
| | | private async Task CreateReturnTask(string orderNo, string palletCode, Dt_StockInfo stockInfo) |
| | | { |
| | | // è·åå½åä»»å¡ä¿¡æ¯ |
| | | var currentTask = await _taskRepository.Db.Queryable<Dt_Task>() |
| | | .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode) |
| | | .FirstAsync(); |
| | | |
| | | if (currentTask != null) |
| | | { |
| | | // åé
æ°è´§ä½ |
| | | var newLocation = _locationInfoService.AssignLocation(stockInfo.LocationType); |
| | | |
| | | var returnTask = new Dt_Task() |
| | | { |
| | | CurrentAddress = stations[currentTask.TargetAddress], |
| | | Grade = 0, |
| | | PalletCode = palletCode, |
| | | NextAddress = "", |
| | | OrderNo = orderNo, |
| | | Roadway = newLocation.RoadwayNo, |
| | | SourceAddress = stations[currentTask.TargetAddress], |
| | | TargetAddress = newLocation.LocationCode, |
| | | TaskStatus = TaskStatusEnum.New.ObjToInt(), |
| | | TaskType = TaskTypeEnum.InPick.ObjToInt(), |
| | | PalletType = stockInfo.PalletType, |
| | | WarehouseId = currentTask.WarehouseId |
| | | }; |
| | | try |
| | | { |
| | | await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync(); |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogInformation($"å建ååºä»»å¡å¤±è´¥ - 订å: {orderNo}, æç: {palletCode}"); |
| | | throw new Exception($"å建ååºä»»å¡å¤±è´¥ - 订å: {orderNo}, æç: {palletCode}"); |
| | | |
| | | } |
| | | // åéESSå½ä»¤ |
| | | await SendESSCommands(palletCode, currentTask.TargetAddress, returnTask); |
| | | |
| | | _logger.LogInformation($"å建ååºä»»å¡æå - 订å: {orderNo}, æç: {palletCode}"); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// æ´æ°ååºåç订åç¶æ |
| | | /// </summary> |
| | | private async Task UpdateOrderStatusAfterReturn(string orderNo) |
| | | { |
| | | // æ£æ¥è®¢åæ¯å¦è¿ææªå®æçéå®è®°å½ |
| | | var activeLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | (x.Status == (int)OutLockStockStatusEnum.åºåºä¸ || |
| | | x.Status == (int)OutLockStockStatusEnum.ååºä¸)) |
| | | .ToListAsync(); |
| | | |
| | | if (!activeLocks.Any()) |
| | | { |
| | | // ææéå®è®°å½é½å·²å®ææå·²ååºï¼æ´æ°è®¢åç¶æ |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => new Dt_OutboundOrder |
| | | { |
| | | OrderStatus = (int)OutOrderStatusEnum.åºåºå®æ, |
| | | }) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ´æ°è®¢åç¶æä¸ºåºåºå®æ - 订å: {orderNo}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤ç空æçååº |
| | | /// </summary> |
| | | private async Task<WebResponseContent> HandleEmptyPalletReturn(string orderNo, string palletCode, Dt_StockInfo stockInfo) |
| | | { |
| | | _logger.LogInformation($"å¤ç空æçååº - 订å: {orderNo}, æç: {palletCode}"); |
| | | |
| | | try |
| | | { |
| | | // æ¸
çé¶åºåæ°æ® |
| | | await CleanupZeroStockData(stockInfo.Id); |
| | | |
| | | // å建空æçåºåè®°å½ |
| | | var emptyStockInfo = new Dt_StockInfo() |
| | | { |
| | | PalletType = PalletTypeEnum.Empty.ObjToInt(), |
| | | StockStatus = StockStatusEmun.ç»çæå.ObjToInt(), |
| | | PalletCode = palletCode, |
| | | LocationType = stockInfo.LocationType |
| | | }; |
| | | emptyStockInfo.Details = new List<Dt_StockInfoDetail>(); |
| | | _stockInfoService.AddMaterielGroup(emptyStockInfo); |
| | | |
| | | // å建空æçååºä»»å¡ |
| | | await CreateReturnTask(orderNo, palletCode, emptyStockInfo); |
| | | |
| | | return WebResponseContent.Instance.OK("空æçååºæå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError($"空æçååºå¤±è´¥: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"空æçååºå¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// åææçç¶æç¨äºååº |
| | | /// ç¡®ä¿ä¸ä¼é误è¯å«éè¦ååºçç©å |
| | | /// </summary> |
| | | private async Task<PalletStatusAnalysis> AnalyzePalletStatusForReturn(string orderNo, string palletCode, int stockId) |
| | | { |
| | | var result = new PalletStatusAnalysis |
| | | { |
| | | OrderNo = orderNo, |
| | | PalletCode = palletCode, |
| | | StockId = stockId |
| | | }; |
| | | |
| | | // 1. åææªåæ£çéå®è®°å½ï¼ç¶æä¸ºåºåºä¸ï¼ |
| | | var unfinishedLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode == palletCode && |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .ToListAsync(); |
| | | |
| | | if (unfinishedLocks.Any()) |
| | | { |
| | | // åºåå·²åé
åæªåé
çéå®è®°å½ |
| | | var allocatedLocks = unfinishedLocks.Where(x => x.IsUnallocated != 1 && x.OrderDetailId > 0).ToList(); |
| | | var unallocatedLocks = unfinishedLocks.Where(x => x.IsUnallocated == 1 || x.OrderDetailId == 0).ToList(); |
| | | |
| | | // å¤çå·²åé
çéå®è®°å½ |
| | | if (allocatedLocks.Any()) |
| | | { |
| | | result.HasRemainingLocks = true; |
| | | result.RemainingLocks = allocatedLocks; |
| | | result.RemainingLocksReturnQty = allocatedLocks.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | |
| | | foreach (var lockInfo in allocatedLocks) |
| | | { |
| | | if (!string.IsNullOrEmpty(lockInfo.CurrentBarcode)) |
| | | { |
| | | result.AllBarcodes.Add(lockInfo.CurrentBarcode); |
| | | } |
| | | } |
| | | |
| | | _logger.LogInformation($"åç°{allocatedLocks.Count}æ¡å·²åé
æªåæ£éå®è®°å½ï¼æ»æ°é: {result.RemainingLocksReturnQty}"); |
| | | } |
| | | |
| | | // å¤çæªåé
çéå®è®°å½ï¼å¦èªå¨æå
产ççï¼ |
| | | if (unallocatedLocks.Any()) |
| | | { |
| | | result.HasUnallocatedLocks = true; |
| | | result.UnallocatedLocks = unallocatedLocks; |
| | | result.UnallocatedLocksReturnQty = unallocatedLocks.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | |
| | | foreach (var lockInfo in unallocatedLocks) |
| | | { |
| | | if (!string.IsNullOrEmpty(lockInfo.CurrentBarcode)) |
| | | { |
| | | result.AllBarcodes.Add(lockInfo.CurrentBarcode); |
| | | } |
| | | } |
| | | |
| | | _logger.LogInformation($"åç°{unallocatedLocks.Count}æ¡æªåé
éå®è®°å½ï¼æ»æ°é: {result.UnallocatedLocksReturnQty}"); |
| | | } |
| | | } |
| | | |
| | | _logger.LogInformation($"ååºæ°æ®æä½å®æ - æ»ååºæ°é: {statusAnalysis.TotalReturnQty}"); |
| | | // 2. åææçä¸çå©ä½åºåè´§ç©ï¼ç¶æä¸ºåºåºéå®ä½æªåé
ï¼ |
| | | var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.StockId == stockId && |
| | | x.Status == (int)StockStatusEmun.åºåºéå® && |
| | | x.StockQuantity > 0) |
| | | .ToListAsync(); |
| | | |
| | | // è¿æ»¤æå·²ç»è¢«éå®è®°å½å ç¨çåºå |
| | | var lockedBarcodes = unfinishedLocks.Select(x => x.CurrentBarcode).ToList(); |
| | | var unlockedStockGoods = palletStockGoods.Where(x => !lockedBarcodes.Contains(x.Barcode)).ToList(); |
| | | |
| | | // è¿ä¸æ¥è¿æ»¤ï¼æ£æ¥è¿äºåºåæ¯å¦æå
³èçéå®è®°å½ |
| | | var trulyUnallocatedGoods = new List<Dt_StockInfoDetail>(); |
| | | foreach (var stock in unlockedStockGoods) |
| | | { |
| | | var hasLock = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.CurrentBarcode == stock.Barcode && |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .AnyAsync(); |
| | | |
| | | if (!hasLock) |
| | | { |
| | | trulyUnallocatedGoods.Add(stock); |
| | | } |
| | | } |
| | | |
| | | if (trulyUnallocatedGoods.Any()) |
| | | { |
| | | result.HasPalletStockGoods = true; |
| | | result.PalletStockGoods = trulyUnallocatedGoods; |
| | | result.PalletStockReturnQty = trulyUnallocatedGoods.Sum(x => x.StockQuantity); |
| | | |
| | | foreach (var stock in trulyUnallocatedGoods) |
| | | { |
| | | result.AllBarcodes.Add(stock.Barcode); |
| | | } |
| | | |
| | | _logger.LogInformation($"åç°{trulyUnallocatedGoods.Count}ä¸ªçæ£æªåé
åºåè´§ç©ï¼æ»æ°é: {result.PalletStockReturnQty}"); |
| | | } |
| | | |
| | | // 3. è®¡ç®æ»ååºæ°é |
| | | result.TotalReturnQty = result.RemainingLocksReturnQty + result.UnallocatedLocksReturnQty + result.PalletStockReturnQty; |
| | | result.HasItemsToReturn = result.TotalReturnQty > 0; |
| | | result.IsEmptyPallet = !result.HasItemsToReturn; |
| | | |
| | | _logger.LogInformation($"æçç¶æåæå®æ - 订å: {orderNo}, æç: {palletCode}, æ»ååºæ°é: {result.TotalReturnQty}"); |
| | | |
| | | return result; |
| | | } |
| | | /// <summary> |
| | | /// å¤çæªåæ£çéå®è®°å½ååº |
| | | /// ç¡®ä¿ä¸ä¼é误ç»å®æ¡ç æ°éå°é宿°é |
| | | /// </summary> |
| | | private async Task HandleRemainingLocksReturn(List<Dt_OutStockLockInfo> remainingLocks) |
| | | { |
| | | _logger.LogInformation($"å¼å§å¤çæªåæ£éå®è®°å½ååº - å
± {remainingLocks.Count} æ¡è®°å½"); |
| | | |
| | | // æè®¢åæç»åç»å¤çï¼ç¡®ä¿è®¢åæç»æ°æ®çä¸è´æ§ |
| | | var orderDetailGroups = remainingLocks.GroupBy(x => x.OrderDetailId); |
| | | |
| | | foreach (var group in orderDetailGroups) |
| | | { |
| | | var orderDetailId = group.Key; |
| | | var groupLocks = group.ToList(); |
| | | |
| | | _logger.LogInformation($"å¤ç订åæç» {orderDetailId} ç {groupLocks.Count} æ¡éå®è®°å½"); |
| | | |
| | | // è·å订åæç» |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == orderDetailId); |
| | | |
| | | if (orderDetail == null) |
| | | { |
| | | _logger.LogWarning($"æªæ¾å°è®¢åæç» - OrderDetailId: {orderDetailId}"); |
| | | continue; |
| | | } |
| | | |
| | | decimal totalReturnQtyForDetail = 0; |
| | | |
| | | foreach (var lockInfo in groupLocks) |
| | | { |
| | | // åªå¤çç¶æä¸ºåºåºä¸çéå®è®°å½ |
| | | if (lockInfo.Status != (int)OutLockStockStatusEnum.åºåºä¸) |
| | | { |
| | | _logger.LogInformation($"è·³è¿éåºåºä¸ç¶æçéå®è®°å½ - éå®ID: {lockInfo.Id}, ç¶æ: {lockInfo.Status}"); |
| | | continue; |
| | | } |
| | | |
| | | // 计ç®ååºæ°éï¼æªæ£éçé¨åï¼ |
| | | decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | |
| | | if (returnQty <= 0) |
| | | { |
| | | _logger.LogInformation($"è·³è¿éå®è®°å½ - éå®ID: {lockInfo.Id}, å·²æ£éå®æææ éååº"); |
| | | continue; |
| | | } |
| | | |
| | | _logger.LogInformation($"å¤çéå®è®°å½ååº - éå®ID: {lockInfo.Id}, æ¡ç : {lockInfo.CurrentBarcode}, ååºæ°é: {returnQty}"); |
| | | |
| | | // æ¢å¤åºåç¶æ |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId); |
| | | |
| | | if (stockDetail != null) |
| | | { |
| | | // è®°å½æ¢å¤åçåºåç¶æ |
| | | decimal originalStockQty = stockDetail.StockQuantity; |
| | | decimal originalOutboundQty = stockDetail.OutboundQuantity; |
| | | |
| | | // åªæ¢å¤å®é
çåºåæ°éï¼ä¸å建æ°çæ¡ç æç»å® |
| | | // æ¢å¤åºåæ°éï¼åºåºæ°éåå°ï¼åºåæ°éå¢å |
| | | stockDetail.OutboundQuantity -= returnQty; |
| | | stockDetail.StockQuantity += returnQty; |
| | | |
| | | // ç¡®ä¿æ°éä¸ä¼ä¸ºè´æ° |
| | | if (stockDetail.OutboundQuantity < 0) |
| | | { |
| | | _logger.LogWarning($"åºåºæ°éåºç°è´æ°ï¼é置为0ãåå¼: {stockDetail.OutboundQuantity + returnQty}"); |
| | | stockDetail.OutboundQuantity = 0; |
| | | } |
| | | |
| | | // æ¢å¤åºåç¶æä¸ºå¯ç¨ç¶æ |
| | | if (stockDetail.Status == (int)StockStatusEmun.åºåºéå®) |
| | | { |
| | | stockDetail.Status = (int)StockStatusEmun.å
¥åºå®æ; |
| | | _logger.LogInformation($"åºåç¶ææ´æ°ä¸ºå
¥åºå®æ - æ¡ç : {stockDetail.Barcode}"); |
| | | } |
| | | |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ¢å¤åºåç¶æ - æ¡ç : {stockDetail.Barcode}, " + |
| | | $"åºåæ°é: {originalStockQty} -> {stockDetail.StockQuantity}, " + |
| | | $"åºåºæ°é: {originalOutboundQty} -> {stockDetail.OutboundQuantity}"); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogWarning($"æªæ¾å°å¯¹åºçåºåä¿¡æ¯ - æ¡ç : {lockInfo.CurrentBarcode}, StockId: {lockInfo.StockId}"); |
| | | // éè¦ï¼å¦ææ¾ä¸å°åºåä¿¡æ¯ï¼è·³è¿æ¤éå®è®°å½ï¼é¿å
æ°æ®ä¸ä¸è´ |
| | | continue; |
| | | } |
| | | |
| | | // æ´æ°éå®è®°å½ç¶æä¸ºå·²ååºï¼ä½ä¸ä¿®æ¹åé
æ°é |
| | | // åé
æ°éå¨è®¢åæç»å±é¢ç»ä¸å¤ç |
| | | var originalStatus = lockInfo.Status; |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | lockInfo.Operator = App.User.UserName; |
| | | |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ´æ°éå®ç¶æ - éå®ID: {lockInfo.Id}, ç¶æ: {originalStatus} -> {lockInfo.Status}"); |
| | | |
| | | totalReturnQtyForDetail += returnQty; |
| | | |
| | | _logger.LogInformation($"éå®è®°å½ååºå®æ - éå®ID: {lockInfo.Id}, ååºæ°é: {returnQty}"); |
| | | } |
| | | |
| | | // åå°è®¢åæç»çåé
æ°é |
| | | if (totalReturnQtyForDetail > 0) |
| | | { |
| | | await ReduceOrderDetailAllocation(orderDetail, totalReturnQtyForDetail); |
| | | } |
| | | } |
| | | |
| | | _logger.LogInformation($"æªåæ£éå®è®°å½ååºå¤ç宿 - å
±å¤ç {remainingLocks.Count} æ¡è®°å½"); |
| | | } |
| | | /// <summary> |
| | | /// å¤çæªåé
çåºåè´§ç©ååº |
| | | /// ç¡®ä¿ä¸ä¼å建æ°çéå®è®°å½ |
| | | /// </summary> |
| | | private async Task HandleUnallocatedStockReturn(List<Dt_StockInfoDetail> stockGoods) |
| | | { |
| | | _logger.LogInformation($"å¼å§å¤çæªåé
åºåååº - å
± {stockGoods.Count} 个货ç©"); |
| | | |
| | | foreach (var stockDetail in stockGoods) |
| | | { |
| | | if (stockDetail.StockQuantity <= 0) |
| | | { |
| | | _logger.LogInformation($"è·³è¿é¶åºåè´§ç© - æ¡ç : {stockDetail.Barcode}"); |
| | | continue; |
| | | } |
| | | |
| | | _logger.LogInformation($"å¤çæªåé
åºåååº - æ¡ç : {stockDetail.Barcode}, æ°é: {stockDetail.StockQuantity}"); |
| | | |
| | | // æ£æ¥æ¯å¦å·²ç»æå¯¹åºçéå®è®°å½ |
| | | var existingLock = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.CurrentBarcode == stockDetail.Barcode && |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .FirstAsync(); |
| | | |
| | | if (existingLock != null) |
| | | { |
| | | _logger.LogWarning($"åºåæ¡ç {stockDetail.Barcode} å·²æéå®è®°å½ï¼è·³è¿ç´æ¥ååºå¤ç"); |
| | | continue; |
| | | } |
| | | |
| | | // è®°å½æ¢å¤åçç¶æ |
| | | var originalStatus = stockDetail.Status; |
| | | |
| | | // ç´æ¥æ¢å¤åºåç¶æä¸ºå¯ç¨ç¶æï¼ä¸å建任ä½éå®è®°å½ |
| | | stockDetail.Status = (int)StockStatusEmun.å
¥åºå®æ; |
| | | |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æªåé
åºåååºå®æ - æ¡ç : {stockDetail.Barcode}, ç¶æ: {originalStatus} -> {stockDetail.Status}"); |
| | | } |
| | | |
| | | _logger.LogInformation($"æªåé
åºåååºå¤ç宿 - å
±å¤ç {stockGoods.Count} 个货ç©"); |
| | | } |
| | | /// <summary> |
| | | /// åå°è®¢åæç»çåé
æ°é |
| | | /// ç¡®ä¿åé
æ°éçåå°æ¯åç¡®ç |
| | | /// </summary> |
| | | private async Task ReduceOrderDetailAllocation(Dt_OutboundOrderDetail orderDetail, decimal reduceQty) |
| | | { |
| | | if (orderDetail == null) |
| | | return; |
| | | |
| | | decimal originalAllocated = orderDetail.AllocatedQuantity; |
| | | decimal originalLock = orderDetail.LockQuantity; |
| | | |
| | | // éªè¯åå°æ°éä¸ä¼å¯¼è´è´æ° |
| | | if (orderDetail.AllocatedQuantity < reduceQty) |
| | | { |
| | | _logger.LogWarning($"åé
æ°éä¸è¶³ï¼è°æ´åå°æ°é - å计ååå°: {reduceQty}, å®é
å¯ç¨: {orderDetail.AllocatedQuantity}"); |
| | | reduceQty = orderDetail.AllocatedQuantity; |
| | | } |
| | | |
| | | // åå°åé
æ°éåé宿°é |
| | | orderDetail.AllocatedQuantity -= reduceQty; |
| | | orderDetail.LockQuantity -= reduceQty; |
| | | |
| | | // ç¡®ä¿æ°éä¸ä¼ä¸ºè´æ° |
| | | if (orderDetail.AllocatedQuantity < 0) |
| | | { |
| | | _logger.LogWarning($"åé
æ°éåºç°è´æ°ï¼é置为0ãåå¼: {orderDetail.AllocatedQuantity + reduceQty}, åå°: {reduceQty}"); |
| | | orderDetail.AllocatedQuantity = 0; |
| | | } |
| | | |
| | | if (orderDetail.LockQuantity < 0) |
| | | { |
| | | _logger.LogWarning($"é宿°éåºç°è´æ°ï¼é置为0ãåå¼: {orderDetail.LockQuantity + reduceQty}, åå°: {reduceQty}"); |
| | | orderDetail.LockQuantity = 0; |
| | | } |
| | | |
| | | // æ´æ°æ¹æ¬¡åé
ç¶æ |
| | | await UpdateBatchAllocateStatus(orderDetail); |
| | | |
| | | await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"åå°è®¢åæç»åé
- OrderDetailId: {orderDetail.Id}, " + |
| | | $"åé
æ°é: {originalAllocated} -> {orderDetail.AllocatedQuantity}, " + |
| | | $"é宿°é: {originalLock} -> {orderDetail.LockQuantity}, " + |
| | | $"åå°æ°é: {reduceQty}"); |
| | | |
| | | // éªè¯æ°æ®ä¸è´æ§ |
| | | await ValidateOrderDetailConsistency(orderDetail.Id); |
| | | } |
| | | /// <summary> |
| | | /// éªè¯è®¢åæç»æ°æ®ä¸è´æ§ |
| | | /// </summary> |
| | | private async Task ValidateOrderDetailConsistency(long orderDetailId) |
| | | { |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == orderDetailId); |
| | | |
| | | if (orderDetail == null) |
| | | return; |
| | | |
| | | // è®¡ç®ææç¸å
³éå®è®°å½çæ»åé
æ°é |
| | | var relatedLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderDetailId == orderDetailId && |
| | | x.Status != (int)OutLockStockStatusEnum.å·²ååº) |
| | | .ToListAsync(); |
| | | |
| | | decimal totalLockAssignQty = relatedLocks.Sum(x => x.AssignQuantity); |
| | | |
| | | // éªè¯è®¢åæç»åé
æ°éä¸éå®è®°å½æ»åé
æ°éçä¸è´æ§ |
| | | if (Math.Abs(orderDetail.AllocatedQuantity - totalLockAssignQty) > 0.01m) |
| | | { |
| | | _logger.LogWarning($"æ°æ®ä¸ä¸è´è¦å - OrderDetailId: {orderDetailId}, " + |
| | | $"订åæç»åé
æ°é: {orderDetail.AllocatedQuantity}, " + |
| | | $"éå®è®°å½æ»åé
æ°é: {totalLockAssignQty}"); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogInformation($"æ°æ®ä¸è´æ§éªè¯éè¿ - OrderDetailId: {orderDetailId}"); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// åæ¹ååº - è°ç¨ç»ä¸ååºæ¹æ³ |
| | |
| | | } |
| | | |
| | | _logger.LogInformation($"ååºæä½å®æ - æ»ååºæ°é: {statusAnalysis.TotalReturnQty}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çæªåæ£çéå®è®°å½ååº |
| | | /// </summary> |
| | | private async Task HandleRemainingLocksReturn(List<Dt_OutStockLockInfo> remainingLocks) |
| | | { |
| | | foreach (var lockInfo in remainingLocks) |
| | | { |
| | | // 计ç®ååºæ°éï¼æªæ£éçé¨åï¼ |
| | | decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | |
| | | if (returnQty > 0) |
| | | { |
| | | // æ¢å¤åºåç¶æ |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId); |
| | | |
| | | if (stockDetail != null) |
| | | { |
| | | stockDetail.StockQuantity += returnQty; |
| | | stockDetail.OutboundQuantity -= returnQty; |
| | | |
| | | // ç¡®ä¿åºåºæ°éä¸ä¼ä¸ºè´æ° |
| | | if (stockDetail.OutboundQuantity < 0) |
| | | { |
| | | stockDetail.OutboundQuantity = 0; |
| | | } |
| | | |
| | | // ååºååºåç¶ææ¢å¤ä¸ºå
¥åºå®æï¼å¯ç¨ç¶æï¼ |
| | | stockDetail.Status = (int)StockStatusEmun.å
¥åºå®æ; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ¢å¤åºå - æ¡ç : {stockDetail.Barcode}, æ°é: {returnQty}, æ°åºå: {stockDetail.StockQuantity}"); |
| | | } |
| | | |
| | | // æ´æ°éå®è®°å½ç¶æä¸ºå·²ååº |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | lockInfo.Operator = App.User.UserName; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"æ´æ°éå®ç¶æ - éå®ID: {lockInfo.Id}, ååºæ°é: {returnQty}"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çæçä¸çåºåè´§ç©ååº |
| | |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çå个éå®è®°å½ååº |
| | | /// </summary> |
| | | private async Task HandleSingleLockReturn(Dt_OutStockLockInfo lockInfo) |
| | | { |
| | | decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | |
| | | if (returnQty > 0) |
| | | if (returnQty <= 0) |
| | | { |
| | | // æ¢å¤åºå |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId); |
| | | _logger.LogInformation($"è·³è¿éå®è®°å½ - éå®ID: {lockInfo.Id}, å·²æ£éå®æææ éååº"); |
| | | return; |
| | | } |
| | | |
| | | if (stockDetail != null) |
| | | _logger.LogInformation($"å¤çæå
ç¸å
³éå®è®°å½ - éå®ID: {lockInfo.Id}, æ¡ç : {lockInfo.CurrentBarcode}, ååºæ°é: {returnQty}"); |
| | | |
| | | // æ¢å¤åºå |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId); |
| | | |
| | | if (stockDetail != null) |
| | | { |
| | | decimal originalStockQty = stockDetail.StockQuantity; |
| | | decimal originalOutboundQty = stockDetail.OutboundQuantity; |
| | | |
| | | stockDetail.StockQuantity += returnQty; |
| | | stockDetail.OutboundQuantity -= returnQty; |
| | | |
| | | if (stockDetail.OutboundQuantity < 0) |
| | | { |
| | | stockDetail.StockQuantity += returnQty; |
| | | stockDetail.OutboundQuantity -= returnQty; |
| | | |
| | | if (stockDetail.OutboundQuantity < 0) |
| | | { |
| | | stockDetail.OutboundQuantity = 0; |
| | | } |
| | | |
| | | stockDetail.Status = (int)StockStatusEmun.å
¥åºå®æ; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | stockDetail.OutboundQuantity = 0; |
| | | } |
| | | |
| | | // æ´æ°éå®ç¶æ |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | lockInfo.Operator = App.User.UserName; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | stockDetail.Status = (int)StockStatusEmun.å
¥åºå®æ; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | _logger.LogInformation($"å¤çæå
ç¸å
³éå® - æ¡ç : {lockInfo.CurrentBarcode}, ååºæ°é: {returnQty}"); |
| | | _logger.LogInformation($"æ¢å¤æå
ç¸å
³åºå - æ¡ç : {stockDetail.Barcode}, " + |
| | | $"åºåæ°é: {originalStockQty} -> {stockDetail.StockQuantity}"); |
| | | } |
| | | } |
| | | |
| | | // æ´æ°éå®ç¶æ |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | lockInfo.Operator = App.User.UserName; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // åå°è®¢åæç»çåé
æ°é |
| | | if (lockInfo.OrderDetailId > 0) |
| | | { |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == lockInfo.OrderDetailId); |
| | | |
| | | if (orderDetail != null) |
| | | { |
| | | await ReduceOrderDetailAllocation(orderDetail, returnQty); |
| | | } |
| | | } |
| | | |
| | | _logger.LogInformation($"æå
ç¸å
³éå®è®°å½ååºå®æ - éå®ID: {lockInfo.Id}, ååºæ°é: {returnQty}"); |
| | | } |
| | | /// <summary> |
| | | /// éæ¾ææéå®ä»¥ä¾¿éæ°åé
|
| | | /// </summary> |
| | |
| | | { |
| | | // 1. å é¤åºåæ°é为0çæç»è®°å½ |
| | | var deleteDetailCount = await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>() |
| | | .Where(x => x.StockId == stockId && x.StockQuantity == 0 && (x.Status == StockStatusEmun.åºåºå®æ.ObjToInt() || x.Status == |
| | | StockStatusEmun.å
¥åºå®æ.ObjToInt())) |
| | | .ExecuteCommandAsync(); |
| | | .Where(x => x.StockId == stockId && x.StockQuantity == 0) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | await _stockInfoService.Db.Deleteable<Dt_StockInfo>() |
| | | .Where(x => x.Id == stockId).ExecuteCommandAsync(); |
| | |
| | | if (lockInfo == null) |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Error("æªæ¾å°ææçéå®ä¿¡æ¯"); |
| | | |
| | | if (lockInfo.IsUnallocated == 1 || lockInfo.OrderDetailId == 0) |
| | | { |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Error("该æ¡ç æ¯æªåé
éå®è®°å½ï¼ä¸è½ç´æ¥åæ£"); |
| | | } |
| | | |
| | | _logger.LogInformation($"æ¾å°éå®ä¿¡æ¯ - åé
æ°é: {lockInfo.AssignQuantity}, å·²æ£é: {lockInfo.PickedQty}"); |
| | | |
| | | // æ£æ¥æ¯å¦å·²ç»åæ£å®æ |
| | |
| | | |
| | | _logger.LogInformation($"æ¾å°è®¢åæç» - å·²åé
æ°é: {orderDetail.AllocatedQuantity}, é宿°é: {orderDetail.LockQuantity}"); |
| | | |
| | | // éè¦ä¿®å¤ï¼æ£æ¥è®¢åæç»çå·²åé
æ°éæ¯å¦è¶³å¤ |
| | | // æ£æ¥è®¢åæç»çå·²åé
æ°éæ¯å¦è¶³å¤ |
| | | decimal remainingToPick = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | if (orderDetail.AllocatedQuantity < remainingToPick) |
| | | |
| | | // è¿éåºè¯¥æ£æ¥éå®ä¿¡æ¯çåé
æ°éï¼è䏿¯è®¢åæç»çåé
æ°é |
| | | // å 为æå
åï¼éå®ä¿¡æ¯çåé
æ°éå¯è½å°äºè®¢åæç»çåé
æ°é |
| | | if (lockInfo.AssignQuantity < remainingToPick) |
| | | { |
| | | _logger.LogWarning($"订åæç»å·²åé
æ°éä¸è¶³ - éè¦æ£é: {remainingToPick}, å¯ç¨åé
æ°é: {orderDetail.AllocatedQuantity}"); |
| | | _logger.LogWarning($"éå®ä¿¡æ¯åé
æ°éä¸è¶³ - éè¦æ£é: {remainingToPick}, éå®ä¿¡æ¯åé
æ°é: {lockInfo.AssignQuantity}"); |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Error( |
| | | $"订åæç»åé
æ°éä¸è¶³ï¼éè¦æ£éï¼{remainingToPick}ï¼å¯ç¨åé
æ°éï¼{orderDetail.AllocatedQuantity}"); |
| | | $"éå®ä¿¡æ¯åé
æ°éä¸è¶³ï¼éè¦æ£éï¼{remainingToPick}ï¼éå®ä¿¡æ¯åé
æ°éï¼{lockInfo.AssignQuantity}"); |
| | | } |
| | | |
| | | // éè¦ä¿®å¤ï¼æ£æ¥é宿°éæ¯å¦è¶³å¤ |
| | | // æ£æ¥é宿°éæ¯å¦è¶³å¤ |
| | | if (orderDetail.LockQuantity < remainingToPick) |
| | | { |
| | | _logger.LogWarning($"订åæç»é宿°éä¸è¶³ - éè¦æ£é: {remainingToPick}, å¯ç¨é宿°é: {orderDetail.LockQuantity}"); |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Error( |
| | | $"订åæç»é宿°éä¸è¶³ï¼éè¦æ£éï¼{remainingToPick}ï¼å¯ç¨é宿°éï¼{orderDetail.LockQuantity}"); |
| | | } |
| | | |
| | | // æ£æ¥è®¢åæç»åé
æ°éæ¯å¦ä¸ºè´æ° |
| | | if (orderDetail.AllocatedQuantity < 0) |
| | | { |
| | | _logger.LogError($"订åæç»åé
æ°éä¸ºè´æ° - å½åå¼: {orderDetail.AllocatedQuantity}"); |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Error( |
| | | $"订åæç»åé
æ°éå¼å¸¸ï¼è´æ°ï¼ï¼è¯·è系管çåå¤ç"); |
| | | } |
| | | |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | |
| | | $"åºåæ°éä¸è¶³ï¼éè¦æ£éï¼{remainingToPick}ï¼å®é
åºåï¼{stockDetail.StockQuantity}"); |
| | | |
| | | // éªè¯åºåç¶æ |
| | | if (stockDetail.Status != (int)StockStatusEmun.åºåºéå®) |
| | | { |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Error( |
| | | $"åºåç¶æå¼å¸¸ï¼å½åç¶æï¼{stockDetail.Status}ï¼ææç¶æï¼åºåºéå®"); |
| | | } |
| | | //if (stockDetail.Status != (int)StockStatusEmun.åºåºéå®) |
| | | //{ |
| | | // return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Error( |
| | | // $"åºåç¶æå¼å¸¸ï¼å½åç¶æï¼{stockDetail.Status}ï¼ææç¶æï¼åºåºéå®"); |
| | | //} |
| | | |
| | | // ä½¿ç¨ OutboundBatchNo æ¥æ¾æ¹æ¬¡ |
| | | var batch = await _outboundBatchRepository.Db.Queryable<Dt_OutboundBatch>() |
| | |
| | | /// </summary> |
| | | private async Task<List<SplitResult>> CheckAndAutoSplitIfNeeded(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail, string palletCode) |
| | | { |
| | | if (lockInfo.IsUnallocated == 1 || lockInfo.OrderDetailId == 0) |
| | | { |
| | | _logger.LogInformation($"è·³è¿æªåé
éå®è®°å½çèªå¨æå
æ£æ¥ - éå®ID: {lockInfo.Id}"); |
| | | return null; |
| | | } |
| | | // æ£æ¥æ¯å¦éè¦èªå¨æå
çæ¡ä»¶ï¼ |
| | | // 1. åºåæ°é大äºåé
æ°é |
| | | // 2. éå®ä¿¡æ¯ç¶æä¸ºåºåºä¸ |
| | |
| | | } |
| | | /// <summary> |
| | | /// æ§è¡èªå¨æå
é»è¾ |
| | | /// ç¡®ä¿èªå¨æå
ä¸ä¼å½±åååºé»è¾ |
| | | /// </summary> |
| | | private async Task<List<SplitResult>> ExecuteAutoSplitLogic(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail, |
| | | decimal splitQuantity, string palletCode) |
| | | decimal splitQuantity, string palletCode) |
| | | { |
| | | _logger.LogInformation($"å¼å§æ§è¡èªå¨æå
é»è¾ - åæ¡ç : {stockDetail.Barcode}, æå
æ°é: {splitQuantity}"); |
| | | |
| | | // éªè¯æå
æ°éåçæ§ |
| | | if (splitQuantity <= 0) |
| | | { |
| | | throw new InvalidOperationException($"æå
æ°éå¿
须大äº0ï¼å½åå¼: {splitQuantity}"); |
| | | } |
| | | |
| | | if (stockDetail.StockQuantity < lockInfo.AssignQuantity + splitQuantity) |
| | | { |
| | | throw new InvalidOperationException($"åºåæ°éä¸è¶³ä»¥è¿è¡èªå¨æå
"); |
| | | } |
| | | |
| | | // çææ°æ¡ç |
| | | string newBarcode = await GenerateNewBarcode(); |
| | | |
| | | // éè¦ä¿®å¤ï¼è®°å½æå
åçåé
æ°é |
| | | decimal originalAssignQtyBefore = lockInfo.AssignQuantity; |
| | | decimal originalOrderQtyBefore = lockInfo.OrderQuantity; |
| | | decimal remainQty = originalAssignQtyBefore; // èªå¨æå
ååæ¡ç åé
æ°éä¿æä¸å |
| | | // è®°å½æå
åçåé
æ°é |
| | | decimal originalAssignQty = lockInfo.AssignQuantity; |
| | | decimal remainQty = originalAssignQty; // åéå®ä¿¡æ¯åé
æ°éä¿æä¸å |
| | | |
| | | // å建æ°åºåæç»ï¼å©ä½é¨åï¼ |
| | | // å建æ°åºåæç»ï¼å¤ä½é¨åï¼ |
| | | var newStockDetail = new Dt_StockInfoDetail |
| | | { |
| | | StockId = stockDetail.StockId, |
| | |
| | | await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync(); |
| | | _logger.LogInformation($"å建æ°åºåæç» - æ¡ç : {newBarcode}, åºåæ°é: {splitQuantity}"); |
| | | |
| | | // æ´æ°ååºåæç» |
| | | // éè¦ä¿®å¤ï¼èªå¨æå
æ¶ï¼ååºåæ°éä¿æä¸åï¼å 为æä»¬è¦åæ£çå°±æ¯åé
æ°é |
| | | // stockDetail.StockQuantity ä¿æä¸å |
| | | |
| | | _logger.LogInformation($"ååºåæç»ä¿æä¸å - åºåæ°é: {stockDetail.StockQuantity}"); |
| | | |
| | | // å建æ°éå®ä¿¡æ¯ï¼å©ä½é¨åï¼ |
| | | // å建æ°éå®ä¿¡æ¯ï¼å¤ä½é¨åï¼- æ 记为æªåé
|
| | | var newLockInfo = new Dt_OutStockLockInfo |
| | | { |
| | | OrderNo = lockInfo.OrderNo, |
| | | OrderDetailId = lockInfo.OrderDetailId, |
| | | OrderDetailId = 0, // éè¦ï¼ä¸ç»å®å°å
·ä½è®¢åæç» |
| | | OutboundBatchNo = lockInfo.OutboundBatchNo, |
| | | MaterielCode = lockInfo.MaterielCode, |
| | | MaterielName = lockInfo.MaterielName, |
| | |
| | | WarehouseCode = lockInfo.WarehouseCode, |
| | | BarcodeQty = lockInfo.BarcodeQty, |
| | | BarcodeUnit = lockInfo.BarcodeUnit, |
| | | IsUnallocated = 1 // æ 记为æªåé
|
| | | }; |
| | | |
| | | await _outStockLockInfoService.Db.Insertable(newLockInfo).ExecuteCommandAsync(); |
| | | _logger.LogInformation($"å建æ°éå®ä¿¡æ¯ - æ¡ç : {newBarcode}, åé
æ°é: {splitQuantity}"); |
| | | _logger.LogInformation($"å建æ°éå®ä¿¡æ¯ - æ¡ç : {newBarcode}, åé
æ°é: {splitQuantity}, æ 记为æªåé
"); |
| | | |
| | | // èªå¨æå
æ¶ï¼åéå®ä¿¡æ¯çåé
æ°éä¿æä¸å |
| | | // å 为èªå¨æå
åï¼åæ¡ç ä»ç¶éè¦è¢«åæ£ï¼åé
æ°éä¸åºè¯¥æ¹å |
| | | _logger.LogInformation($"åéå®ä¿¡æ¯ä¿æä¸å - åé
æ°é: {lockInfo.AssignQuantity}, è®¢åæ°é: {lockInfo.OrderQuantity}"); |
| | | // èªå¨æå
䏿¹å订åæç»çåé
æ°é |
| | | _logger.LogInformation($"èªå¨æå
- 订åæç»åé
æ°éä¿æä¸å"); |
| | | |
| | | // è®°å½æå
åå² |
| | | await RecordSplitHistory(lockInfo, stockDetail, splitQuantity, newBarcode, true, stockDetail.StockQuantity); |
| | | |
| | | // å建æå
ç»æå表 |
| | | // å建æå
ç»æå表 |
| | | var splitResults = CreateSplitResults(lockInfo, splitQuantity, remainQty, newBarcode, stockDetail.Barcode); |
| | | |
| | | _logger.LogInformation($"èªå¨æå
é»è¾æ§è¡å®æ"); |
| | |
| | | return splitResults; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éªè¯èªå¨æå
åæ°æ®ä¸è´æ§ |
| | | /// </summary> |
| | | private async Task ValidateDataConsistencyAfterAutoSplit(long orderDetailId, decimal originalAllocatedQty, decimal originalLockQty, decimal splitQuantity) |
| | | { |
| | | // éæ°è·å订åæç»æ°æ® |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == orderDetailId); |
| | | |
| | | if (orderDetail == null) |
| | | return; |
| | | |
| | | // è®¡ç®ææéå®ä¿¡æ¯çæ»åé
æ°é |
| | | var allLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderDetailId == orderDetailId) |
| | | .ToListAsync(); |
| | | |
| | | decimal totalLockAssignQty = allLocks.Sum(x => x.AssignQuantity); |
| | | |
| | | _logger.LogInformation($"èªå¨æå
åæ°æ®ä¸è´æ§éªè¯ - 订åæç»åé
æ°é: {orderDetail.AllocatedQuantity}, éå®ä¿¡æ¯æ»åé
æ°é: {totalLockAssignQty}"); |
| | | |
| | | // éªè¯èªå¨æå
åçæ°æ®ä¸è´æ§ |
| | | decimal expectedAllocatedQty = originalAllocatedQty + splitQuantity; |
| | | decimal expectedLockQty = originalLockQty + splitQuantity; |
| | | |
| | | if (Math.Abs(orderDetail.AllocatedQuantity - expectedAllocatedQty) > 0.01m) |
| | | { |
| | | _logger.LogWarning($"èªå¨æå
ååé
æ°éå¼å¸¸ - ææ: {expectedAllocatedQty}, å®é
: {orderDetail.AllocatedQuantity}"); |
| | | } |
| | | |
| | | if (Math.Abs(orderDetail.LockQuantity - expectedLockQty) > 0.01m) |
| | | { |
| | | _logger.LogWarning($"èªå¨æå
åé宿°éå¼å¸¸ - ææ: {expectedLockQty}, å®é
: {orderDetail.LockQuantity}"); |
| | | } |
| | | |
| | | if (Math.Abs(orderDetail.AllocatedQuantity - totalLockAssignQty) > 0.01m) |
| | | { |
| | | _logger.LogWarning($"èªå¨æå
åæ°æ®ä¸ä¸è´ - 订åæç»åé
æ°é: {orderDetail.AllocatedQuantity}, éå®ä¿¡æ¯æ»åé
æ°é: {totalLockAssignQty}"); |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | #region æ ¸å¿é»è¾æ¹æ³ |
| | |
| | | decimal originalPickedQty = lockInfo.PickedQty; |
| | | decimal originalAssignQty = lockInfo.AssignQuantity; // è®°å½åå§åé
æ°é |
| | | |
| | | // éè¦ä¿®å¤ï¼åªæ¢å¤å·²æ£éæ°éï¼ä¸ä¿®æ¹åé
æ°é |
| | | // åªæ¢å¤å·²æ£éæ°éï¼ä¸ä¿®æ¹åé
æ°é |
| | | lockInfo.PickedQty -= pickingRecord.PickQuantity; |
| | | |
| | | // ç¡®ä¿å·²æ£éæ°éä¸ä¼ä¸ºè´æ° |
| | |
| | | throw new InvalidOperationException("æªæ¾å°è®¢åæç»"); |
| | | |
| | | orderDetail = latestOrderDetail; |
| | | // éè¦ä¿®å¤ï¼éªè¯åé
æ°éä¸ä¼åæè´æ° |
| | | // éªè¯åé
æ°éä¸ä¼åæè´æ° |
| | | if (orderDetail.AllocatedQuantity < pickedQty) |
| | | { |
| | | decimal actualPickedQty = orderDetail.AllocatedQuantity; |
| | |
| | | decimal originalAllocatedQty = orderDetail.AllocatedQuantity; |
| | | decimal originalLockQty = orderDetail.LockQuantity; |
| | | |
| | | // éè¦ä¿®å¤ï¼åªæ¢å¤ç¸å
³æ°éï¼åé
æ°éä¿æä¸å |
| | | // åªæ¢å¤ç¸å
³æ°éï¼åé
æ°éä¿æä¸å |
| | | orderDetail.OverOutQuantity -= pickingRecord.PickQuantity; |
| | | orderDetail.AllocatedQuantity += pickingRecord.PickQuantity; |
| | | orderDetail.AllocatedQuantity += pickingRecord.PickQuantity; |
| | | orderDetail.LockQuantity += pickingRecord.PickQuantity; |
| | | if (orderDetail.OverOutQuantity < 0) orderDetail.OverOutQuantity = 0; |
| | | if (orderDetail.AllocatedQuantity < 0) orderDetail.AllocatedQuantity = 0; |
| | |
| | | |
| | | }; |
| | | // ä¿åååºä»»å¡ |
| | | await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync(); |
| | | var insertcount = await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync(); |
| | | if (insertcount <= 0) |
| | | { |
| | | throw new Exception("å建任å¡å¤±è´¥ï¼"); |
| | | } |
| | | var targetAddress = originalTask.TargetAddress; |
| | | |
| | | // å é¤åå§åºåºä»»å¡ |
| | | _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.èªå¨å®æ); |
| | | // await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync(); |
| | | //_taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.èªå¨å®æ); |
| | | _task_HtyService.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.人工å é¤); |
| | | await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync(); |
| | | |
| | | |
| | | |