| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | public async Task<WebResponseContent> ConfirmPicking(string orderNo, string palletCode, string barcode) |
| | | { |
| | | #region "æµè¯æå°" |
| | | // var splitResults=new List<SplitResult>(); |
| | | // splitResults.Add(new SplitResult |
| | | //{ |
| | | // materialCode = "AAAAbbb", |
| | | // supplierCode = "CVBG", |
| | | // quantityTotal = "1234", |
| | | // batchNumber = "WMLOT25111900032", |
| | | // batch = "A234re", |
| | | // factory = "01", |
| | | // date = DateTime.Now.ToString("yyyy-MM-dd"), |
| | | //}); |
| | | |
| | | //splitResults.Add(new SplitResult |
| | | //{ |
| | | // materialCode = "CCDF", |
| | | // supplierCode = "QWCVBG", |
| | | // quantityTotal = "1234", |
| | | // batchNumber = "WMLOT25111900032", |
| | | // batch = "A234re", |
| | | // factory = "01", |
| | | // date = DateTime.Now.ToString("yyyy-MM-dd"), |
| | | //}); |
| | | |
| | | // return WebResponseContent.Instance.OK("æ£é确认æåï¼å·²èªå¨æå
", new { SplitResults = splitResults }); |
| | | #endregion |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // 1. æ¥æ¾åºåºéå®ä¿¡æ¯ |
| | | // 1. éªè¯è¾å
¥åæ° |
| | | if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode) || string.IsNullOrEmpty(barcode)) |
| | | { |
| | | throw new Exception("订åå·ãæçç åæ¡ç ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 2. æ¥æ¾åºåºéå®ä¿¡æ¯ |
| | | var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(it => it.OrderNo == orderNo && |
| | | it.Status == (int)OutLockStockStatusEnum.åºåºä¸ && |
| | |
| | | throw new Exception($"æ¡ç {barcode}å·²ç»åæ£è¿ï¼ä¸è½éå¤åæ£"); |
| | | } |
| | | |
| | | var outorderdetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | // è·å订åæç»å¹¶æ£æ¥æ°ééå¶ |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == lockInfo.OrderDetailId); |
| | | |
| | | if (outorderdetail != null && (lockInfo.AssignQuantity + outorderdetail.OverOutQuantity) > outorderdetail.NeedOutQuantity) |
| | | if (orderDetail == null) |
| | | throw new Exception($"æªæ¾å°è®¢åæç»ï¼ID: {lockInfo.OrderDetailId}"); |
| | | |
| | | // å
³é®ä¿®å¤ï¼æ£æ¥ç´¯è®¡æ£éæ°éæ¯å¦ä¼è¶
è¿è®¢åæ°é |
| | | decimal actualQty = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | decimal remainingOrderQty = orderDetail.NeedOutQuantity - orderDetail.OverOutQuantity; |
| | | |
| | | if (actualQty > remainingOrderQty) |
| | | { |
| | | throw new Exception($"æ¡ç {barcode}çåºåºæ°éå°å¯¼è´è®¢åæç»å·²åºåºæ°éè¶
è¿éæ±æ°é"); |
| | | // 妿åé
æ°é大äºå©ä½è®¢åæ°éï¼è°æ´å®é
æ£éæ°é |
| | | actualQty = remainingOrderQty; |
| | | |
| | | if (actualQty <= 0) |
| | | { |
| | | throw new Exception($"订å{orderNo}çéæ±æ°éå·²æ»¡è¶³ï¼æ æ³ç»§ç»åæ£"); |
| | | } |
| | | |
| | | _logger.LogWarning($"è°æ´åæ£æ°éï¼ååé
{lockInfo.AssignQuantity - lockInfo.PickedQty}ï¼è°æ´ä¸º{actualQty}ï¼è®¢åéæ±{orderDetail.NeedOutQuantity}ï¼å·²åºåº{orderDetail.OverOutQuantity}"); |
| | | } |
| | | |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | |
| | | if (stockDetail == null) |
| | | return WebResponseContent.Instance.Error("æ æçæ¡ç æç©æç¼ç "); |
| | | |
| | | decimal actualQty = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | decimal stockQuantity = stockDetail.StockQuantity; |
| | | |
| | | List<SplitResult> splitResults = new List<SplitResult>(); |
| | | Dt_OutStockLockInfo finalLockInfo = lockInfo; |
| | | var finalBarcode = barcode; |
| | | var finalStockId = stockDetail.Id; |
| | | decimal actualPickedQty = actualQty; // å®é
æ£éæ°é |
| | | decimal actualPickedQty = actualQty; |
| | | |
| | | if (actualQty < stockQuantity) |
| | | { |
| | | // æ
åµ1: åé
æ°éå°äºåºåæ°éï¼éè¦èªå¨æå
|
| | | decimal remainingStockQty = stockQuantity - actualQty; |
| | | |
| | | // æ´æ°åæ¡ç åºå为å©ä½æ°é |
| | | stockDetail.StockQuantity = remainingStockQty; |
| | | stockDetail.OutboundQuantity = remainingStockQty; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | // çææ°æ¡ç ç¨äºè®°å½æ£éæ°é |
| | | var seq = await _dailySequenceService.GetNextSequenceAsync(); |
| | | string newBarcode = "WSLOT" + DateTime.Now.ToString("yyyyMMdd") + seq.ToString()?.PadLeft(5, '0'); |
| | | |
| | | // ä¸ºæ°æ¡ç å建åºåºéå®ä¿¡æ¯ |
| | | var newLockInfo = new Dt_OutStockLockInfo |
| | | { |
| | | OrderNo = lockInfo.OrderNo, |
| | |
| | | var newLockId = await _outStockLockInfoService.Db.Insertable(newLockInfo).ExecuteReturnIdentityAsync(); |
| | | newLockInfo.Id = newLockId; |
| | | |
| | | // è®°å½æå
åå² |
| | | var splitHistory = new Dt_SplitPackageRecord |
| | | { |
| | | FactoryArea = lockInfo.FactoryArea, |
| | |
| | | }; |
| | | await _splitPackageService.Db.Insertable(splitHistory).ExecuteCommandAsync(); |
| | | |
| | | // æ´æ°åéå®ä¿¡æ¯ä¸ºå©ä½åºåæ°é |
| | | lockInfo.AssignQuantity = remainingStockQty; |
| | | lockInfo.PickedQty = 0; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | |
| | | date = DateTime.Now.ToString("yyyy-MM-dd"), |
| | | }); |
| | | |
| | | barcode = newBarcode; |
| | | lockInfo = newLockInfo; |
| | | finalLockInfo = newLockInfo; |
| | | finalBarcode = newBarcode; |
| | | finalStockId = stockDetail.Id; |
| | | } |
| | | else if (actualQty == stockQuantity) |
| | | { |
| | |
| | | lockInfo.PickedQty += actualQty; |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.æ£é宿; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | finalLockInfo = lockInfo; |
| | | finalBarcode = barcode; |
| | | finalStockId = stockDetail.Id; |
| | | } |
| | | else |
| | | { |
| | |
| | | lockInfo.AssignQuantity = remainingAssignQty; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | var _relatedSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | var relatedSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(it => it.OriginalBarcode == barcode || it.NewBarcode == barcode) |
| | | .Where(it => !it.IsReverted) |
| | | .ToListAsync(); |
| | | |
| | | foreach (var record in _relatedSplitRecords) |
| | | foreach (var record in relatedSplitRecords) |
| | | { |
| | | record.Status = (int)SplitPackageStatusEnum.å·²æ£é; |
| | | await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | finalLockInfo = lockInfo; |
| | | finalBarcode = barcode; |
| | | finalStockId = stockDetail.Id; |
| | | actualPickedQty = stockOutQty; // å®é
æ£éæ°éè°æ´ä¸ºåºåæ°é |
| | | actualPickedQty = stockOutQty; |
| | | } |
| | | |
| | | // æ´æ°è®¢åæç»çæ£éæ°éåå·²åºåºæ°é |
| | | // å
³é®ä¿®å¤ï¼åæ¬¡æ£æ¥è®¢åæ°ééå¶ |
| | | decimal newOverOutQuantity = orderDetail.OverOutQuantity + actualPickedQty; |
| | | decimal newPickedQty = orderDetail.PickedQty + actualPickedQty; |
| | | |
| | | if (newOverOutQuantity > orderDetail.NeedOutQuantity) |
| | | { |
| | | throw new Exception($"忣åå°å¯¼è´å·²åºåºæ°é({newOverOutQuantity})è¶
è¿è®¢åéæ±æ°é({orderDetail.NeedOutQuantity})"); |
| | | } |
| | | |
| | | // æ´æ°è®¢åæç» |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(it => new Dt_OutboundOrderDetail |
| | | { |
| | | PickedQty = it.PickedQty + actualPickedQty, |
| | | OverOutQuantity = it.OverOutQuantity + actualPickedQty |
| | | PickedQty = newPickedQty, |
| | | OverOutQuantity = newOverOutQuantity |
| | | }) |
| | | .Where(it => it.Id == lockInfo.OrderDetailId) |
| | | .ExecuteCommandAsync(); |
| | |
| | | return WebResponseContent.Instance.OK("æ£é确认æåï¼å·²èªå¨æå
", new { SplitResults = splitResults }); |
| | | } |
| | | |
| | | return WebResponseContent.Instance.OK("æ£é确认æå"); |
| | | return WebResponseContent.Instance.OK("æ£é确认æå", new { SplitResults = new List<SplitResult>() }); |
| | | |
| | | } |
| | | catch (Exception ex) |
| | |
| | | return WebResponseContent.Instance.Error($"æ£é确认失败ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | public async Task<WebResponseContent> CancelPicking(string orderNo, string palletCode, string barcode) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // æ¥æ¾æ£éè®°å½ |
| | | var pickingRecord = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(it => it.OrderNo == orderNo && |
| | | it.PalletCode == palletCode && |
| | | it.Barcode == barcode) |
| | | .OrderByDescending(it => it.PickTime) |
| | | .FirstAsync(); |
| | | |
| | | if (pickingRecord == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçæ£éè®°å½"); |
| | | |
| | | // æ¥æ¾åºåºéå®ä¿¡æ¯ |
| | | var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(it => it.Id == pickingRecord.OutStockLockId) |
| | | .FirstAsync(); |
| | | |
| | | if (lockInfo == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçåºåºéå®ä¿¡æ¯"); |
| | | |
| | | // æ£æ¥æ¯å¦å¯ä»¥åæ¶ |
| | | if (lockInfo.Status != (int)OutLockStockStatusEnum.æ£é宿) |
| | | return WebResponseContent.Instance.Error("å½åç¶æä¸å
è®¸åæ¶åæ£"); |
| | | |
| | | decimal cancelQty = pickingRecord.PickQuantity; |
| | | |
| | | // è·å订åæç» |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == pickingRecord.OrderDetailId); |
| | | |
| | | if (orderDetail == null) |
| | | throw new Exception($"æªæ¾å°è®¢åæç»ï¼ID: {pickingRecord.OrderDetailId}"); |
| | | |
| | | // å
³é®ä¿®å¤ï¼æ£æ¥åæ¶åæ°éä¸ä¼ä¸ºè´æ° |
| | | decimal newOverOutQuantity = orderDetail.OverOutQuantity - cancelQty; |
| | | decimal newPickedQty = orderDetail.PickedQty - cancelQty; |
| | | |
| | | if (newOverOutQuantity < 0 || newPickedQty < 0) |
| | | { |
| | | throw new Exception($"忶忣å°å¯¼è´å·²åºåºæ°éæå·²æ£éæ°éä¸ºè´æ°"); |
| | | } |
| | | |
| | | // å¤çåæ¶é»è¾ |
| | | if (lockInfo.IsSplitted == 1 && lockInfo.ParentLockId.HasValue) |
| | | { |
| | | await HandleSplitBarcodeCancel(lockInfo, pickingRecord, cancelQty); |
| | | } |
| | | else |
| | | { |
| | | await HandleNormalBarcodeCancel(lockInfo, pickingRecord, cancelQty); |
| | | } |
| | | |
| | | // æ´æ°è®¢åæç» |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(it => new Dt_OutboundOrderDetail |
| | | { |
| | | PickedQty = newPickedQty, |
| | | OverOutQuantity = newOverOutQuantity |
| | | }) |
| | | .Where(it => it.Id == pickingRecord.OrderDetailId) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // å 餿£éè®°å½ |
| | | await Db.Deleteable<Dt_PickingRecord>() |
| | | .Where(x => x.Id == pickingRecord.Id) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // éæ°æ£æ¥è®¢åç¶æ |
| | | await CheckAndUpdateOrderStatus(orderNo); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | return WebResponseContent.Instance.OK($"忶忣æåï¼æ¢å¤æ°éï¼{cancelQty}"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"CancelPicking失败 - OrderNo: {orderNo}, PalletCode: {palletCode}, Barcode: {barcode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"åæ¶åæ£å¤±è´¥ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | private async Task HandleSplitBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty) |
| | | { |
| | | // æ¥æ¾ç¶éå®ä¿¡æ¯ |
| | | var parentLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.Id == lockInfo.ParentLockId.Value) |
| | | .FirstAsync(); |
| | | |
| | | if (parentLockInfo == null) |
| | | { |
| | | throw new Exception("æªæ¾å°ç¶éå®ä¿¡æ¯ï¼æ æ³åæ¶æå
忣"); |
| | | } |
| | | |
| | | // æ¢å¤ç¶éå®ä¿¡æ¯çåé
æ°é |
| | | parentLockInfo.AssignQuantity += cancelQty; |
| | | await _outStockLockInfoService.Db.Updateable(parentLockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ¢å¤åºå |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == parentLockInfo.CurrentBarcode && x.StockId == parentLockInfo.StockId) |
| | | .FirstAsync(); |
| | | |
| | | if (stockDetail != null) |
| | | { |
| | | stockDetail.StockQuantity += cancelQty; |
| | | stockDetail.OutboundQuantity += cancelQty; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | // æ´æ°æå
è®°å½ç¶æ |
| | | await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>() |
| | | .SetColumns(x => new Dt_SplitPackageRecord |
| | | { |
| | | Status = (int)SplitPackageStatusEnum.å·²æ¤é, |
| | | IsReverted = true |
| | | }) |
| | | .Where(x => x.NewBarcode == lockInfo.CurrentBarcode && !x.IsReverted) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // å 餿å
产ççéå®ä¿¡æ¯ |
| | | await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.Id == lockInfo.Id) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | |
| | | private async Task HandleNormalBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty) |
| | | { |
| | | // æ¢å¤éå®ä¿¡æ¯ |
| | | lockInfo.PickedQty -= cancelQty; |
| | | if (lockInfo.PickedQty < 0) lockInfo.PickedQty = 0; |
| | | |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.åºåºä¸; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ¢å¤åºå |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == pickingRecord.Barcode && x.StockId == pickingRecord.StockId) |
| | | .FirstAsync(); |
| | | |
| | | if (stockDetail != null) |
| | | { |
| | | stockDetail.StockQuantity += cancelQty; |
| | | stockDetail.OutboundQuantity += cancelQty; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ååºæä½ |
| | | /// </summary> |
| | |
| | | return outboundFinished && hasRemainingGoods; |
| | | } |
| | | |
| | | // åæ¶æ£éåè½ |
| | | public async Task<WebResponseContent> CancelPicking(string orderNo, string palletCode, string barcode) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | //æ¥æ¾æ£éè®°å½ |
| | | var pickingRecord = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(it => it.OrderNo == orderNo && |
| | | it.PalletCode == palletCode && |
| | | it.Barcode == barcode) |
| | | .OrderByDescending(it => it.PickTime) |
| | | .FirstAsync(); |
| | | |
| | | if (pickingRecord == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçæ£éè®°å½"); |
| | | |
| | | // æ¥æ¾åºåºéå®ä¿¡æ¯ |
| | | var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(it => it.Id == pickingRecord.OutStockLockId) |
| | | .FirstAsync(); |
| | | |
| | | if (lockInfo == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°å¯¹åºçåºåºéå®ä¿¡æ¯"); |
| | | |
| | | //æ£æ¥æ¯å¦å¯ä»¥åæ¶ï¼ç¶æå¿
é¡»æ¯æ£éå®æï¼ |
| | | if (lockInfo.Status != (int)OutLockStockStatusEnum.æ£é宿) |
| | | return WebResponseContent.Instance.Error("å½åç¶æä¸å
è®¸åæ¶åæ£"); |
| | | |
| | | decimal cancelQty = pickingRecord.PickQuantity; |
| | | |
| | | // æ£æ¥æå
é¾å
³ç³» |
| | | var splitChain = await GetSplitChain(barcode); |
| | | |
| | | if (splitChain.Any()) |
| | | { |
| | | // æ
åµAï¼å¤çæå
é¾çåæ¶ï¼å¤æ¬¡æå¨æå
ï¼ |
| | | await HandleSplitChainCancel(orderNo, palletCode, barcode, cancelQty, lockInfo, pickingRecord, splitChain); |
| | | } |
| | | else |
| | | { |
| | | // æ
åµBï¼å¤çæ®éæ¡ç çåæ¶ |
| | | await HandleNormalBarcodeCancel(orderNo, palletCode, barcode, cancelQty, lockInfo, pickingRecord); |
| | | } |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | return WebResponseContent.Instance.OK($"忶忣æåï¼æ¢å¤æ°éï¼{cancelQty}"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return WebResponseContent.Instance.Error($"åæ¶åæ£å¤±è´¥ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// è·åæå
é¾ï¼ä»å½åæ¡ç 追溯å°åå§æ¡ç ï¼ |
| | | /// </summary> |