| | |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_BasicService; |
| | | using WIDESEA_Common.CommonEnum; |
| | | using WIDESEA_Common.OrderEnum; |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_IAllocateService; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IOutboundService; |
| | |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Model.Models.Basic; |
| | | using WIDESEA_Model.Models.Outbound; |
| | | using static WIDESEA_OutboundService.OutboundBatchPickingService; |
| | | |
| | | namespace WIDESEA_OutboundService |
| | | { |
| | |
| | | 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) : base(BaseDal) |
| | | IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_OutboundBatch> outboundBatchRepository) : base(BaseDal) |
| | | { |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | | _stockInfoService = stockInfoService; |
| | |
| | | _invokeMESService = invokeMESService; |
| | | _dailySequenceService = dailySequenceService; |
| | | _allocateService = allocateService; |
| | | _outboundBatchRepository = outboundBatchRepository; |
| | | } |
| | | |
| | | // <summary> |
| | | /// è·åæççéå®ä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<List<PalletLockInfoDto>> GetPalletLockInfos(string orderNo, string palletCode) |
| | | { |
| | | var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode) |
| | | .Select(x => new |
| | | { |
| | | x.Id, |
| | | x.OrderNo, |
| | | x.BatchNo, |
| | | x.MaterielCode, |
| | | x.CurrentBarcode, |
| | | x.AssignQuantity, |
| | | x.PickedQty, |
| | | x.Status, |
| | | x.LocationCode, |
| | | x.PalletCode |
| | | }).ToListAsync(); |
| | | |
| | | var lockInfoDtos = lockInfos.Select(x => new PalletLockInfoDto |
| | | { |
| | | Id = x.Id, |
| | | OrderNo = x.OrderNo, |
| | | BatchNo = x.BatchNo, |
| | | MaterielCode = x.MaterielCode, |
| | | CurrentBarcode = x.CurrentBarcode, |
| | | AssignQuantity = x.AssignQuantity, |
| | | PickedQty = x.PickedQty, |
| | | Status = x.Status, |
| | | LocationCode = x.LocationCode, |
| | | PalletCode = x.PalletCode, |
| | | CanSplit = (x.Status == (int)OutLockStockStatusEnum.åºåºä¸ && x.AssignQuantity - x.PickedQty > 0), |
| | | CanPick = (x.Status == (int)OutLockStockStatusEnum.åºåºä¸ && x.PickedQty < x.AssignQuantity) |
| | | }).ToList(); |
| | | |
| | | return lockInfoDtos; |
| | | } |
| | | #region æ¥è¯¢æ¹æ³ |
| | | |
| | | /// <summary> |
| | | /// è·åæççå·²æ£éå表 |
| | | /// </summary> |
| | | public async Task<List<PalletPickedInfoDto>> GetPalletPickedList(string orderNo, string palletCode) |
| | | { |
| | | var pickedList = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode == palletCode && |
| | | !x.IsCancelled) |
| | | .Select(x => new PalletPickedInfoDto |
| | | { |
| | | Id = x.Id, |
| | | OrderNo = x.OrderNo, |
| | | OrderDetailId = x.OrderDetailId, |
| | | PalletCode = x.PalletCode, |
| | | Barcode = x.Barcode, |
| | | MaterielCode = x.MaterielCode, |
| | | PickedQty = x.PickQuantity, |
| | | PickTime = x.PickTime, |
| | | Operator = x.Operator, |
| | | LocationCode = x.LocationCode |
| | | }) |
| | | .ToListAsync(); |
| | | |
| | | return pickedList; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæçç¶æ |
| | | /// </summary> |
| | | public async Task<PalletStatusDto> GetPalletStatus(string orderNo, string palletCode) |
| | | { |
| | | // è·åæççéå®ä¿¡æ¯ |
| | | var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode) |
| | | .ToListAsync(); |
| | | |
| | | if (!lockInfos.Any()) |
| | | { |
| | | return new PalletStatusDto |
| | | { |
| | | OrderNo = orderNo, |
| | | PalletCode = palletCode, |
| | | Status = (int)PalletStatusEnum.æ ä»»å¡, |
| | | StatusText = "æ ä»»å¡", |
| | | TotalItems = 0, |
| | | CompletedItems = 0, |
| | | PendingItems = 0 |
| | | }; |
| | | } |
| | | |
| | | var totalItems = lockInfos.Count; |
| | | var completedItems = lockInfos.Count(x => x.Status == (int)OutLockStockStatusEnum.æ£é宿); |
| | | var pendingItems = lockInfos.Count(x => x.Status == (int)OutLockStockStatusEnum.åºåºä¸); |
| | | |
| | | var status = PalletStatusEnum.æ£éä¸; |
| | | if (pendingItems == 0 && completedItems > 0) |
| | | { |
| | | status = PalletStatusEnum.已宿; |
| | | } |
| | | else if (pendingItems > 0 && completedItems == 0) |
| | | { |
| | | status = PalletStatusEnum.æªå¼å§; |
| | | } |
| | | else if (pendingItems > 0 && completedItems > 0) |
| | | { |
| | | status = PalletStatusEnum.æ£éä¸; |
| | | } |
| | | |
| | | return new PalletStatusDto |
| | | { |
| | | OrderNo = orderNo, |
| | | PalletCode = palletCode, |
| | | Status = (int)status, |
| | | StatusText = GetPalletStatusText(status), |
| | | TotalItems = totalItems, |
| | | CompletedItems = completedItems, |
| | | PendingItems = pendingItems |
| | | }; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæå
ä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<SplitPackageInfoDto> GetSplitPackageInfo(string orderNo, string palletCode, string barcode) |
| | | { |
| | | // æ¥æ¾éå®ä¿¡æ¯ |
| | | var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode == palletCode && |
| | | x.CurrentBarcode == barcode |
| | | //&& x.Status == (int)OutLockStockStatusEnum.åºåºä¸ |
| | | ) |
| | | .FirstAsync(); |
| | | |
| | | if (lockInfo == null) |
| | | throw new Exception("æªæ¾å°ææçéå®ä¿¡æ¯"); |
| | | |
| | | // 计ç®å©ä½å¯ææ°é |
| | | var remainQuantity = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | |
| | | return new SplitPackageInfoDto |
| | | { |
| | | OrderNo = orderNo, |
| | | PalletCode = palletCode, |
| | | Barcode = barcode, |
| | | MaterielCode = lockInfo.MaterielCode, |
| | | RemainQuantity = remainQuantity, |
| | | AssignQuantity = lockInfo.AssignQuantity, |
| | | PickedQty = lockInfo.PickedQty |
| | | }; |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region å走空箱é»è¾ |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// å走空箱 - æ¸
ç已宿æ£éçæçæ°æ® |
| | | /// </summary> |
| | | public async Task<WebResponseContent> RemoveEmptyPallet(string orderNo, string palletCode) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // éªè¯æçæ¯å¦å¯ä»¥åèµ°ï¼å¿
é¡»å
¨é¨å®ææ£éï¼ |
| | | var validationResult = await ValidateEmptyPalletRemoval(orderNo, palletCode); |
| | | if (!validationResult.IsValid) |
| | | return WebResponseContent.Instance.Error(validationResult.ErrorMessage); |
| | | |
| | | var completedLocks = validationResult.Data; |
| | | |
| | | // æ¸
çéå®è®°å½ï¼æ è®°ä¸ºå·²å®æï¼ |
| | | await CleanupCompletedLocks(completedLocks); |
| | | |
| | | // æ´æ°ç¸å
³è®¢åç¶æ |
| | | await UpdateOrderStatusAfterPalletRemoval(orderNo); |
| | | |
| | | // è®°å½æä½åå² |
| | | await RecordEmptyPalletRemoval(orderNo, palletCode, completedLocks); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK("å走空箱æå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"å走空箱失败 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"å走空箱失败ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éªè¯ç©ºç®±åèµ°æ¡ä»¶ |
| | | /// </summary> |
| | | private async Task<ValidationResult<List<Dt_OutStockLockInfo>>> ValidateEmptyPalletRemoval(string orderNo, string palletCode) |
| | | { |
| | | // è·åæççææéå®è®°å½ |
| | | var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode) |
| | | .ToListAsync(); |
| | | |
| | | if (!lockInfos.Any()) |
| | | return ValidationResult<List<Dt_OutStockLockInfo>>.Error("该æç没æéå®è®°å½"); |
| | | |
| | | // æ£æ¥æ¯å¦ææªå®æçéå®è®°å½ |
| | | var unfinishedLocks = lockInfos.Where(x => |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸ || |
| | | x.Status == (int)OutLockStockStatusEnum.ååºä¸).ToList(); |
| | | |
| | | if (unfinishedLocks.Any()) |
| | | { |
| | | var unfinishedCount = unfinishedLocks.Count; |
| | | var unfinishedQty = unfinishedLocks.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | return ValidationResult<List<Dt_OutStockLockInfo>>.Error( |
| | | $"æçè¿æ{unfinishedCount}æ¡æªå®æè®°å½ï¼å©ä½æ°é{unfinishedQty}ï¼ä¸è½å走空箱"); |
| | | } |
| | | |
| | | // è·å已宿çéå®è®°å½ |
| | | var completedLocks = lockInfos.Where(x => |
| | | x.Status == (int)OutLockStockStatusEnum.æ£é宿).ToList(); |
| | | |
| | | if (!completedLocks.Any()) |
| | | return ValidationResult<List<Dt_OutStockLockInfo>>.Error("该æç没æå·²å®ææ£éçè®°å½"); |
| | | |
| | | return ValidationResult<List<Dt_OutStockLockInfo>>.Success(completedLocks); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¸
ç已宿çéå®è®°å½ |
| | | /// </summary> |
| | | private async Task CleanupCompletedLocks(List<Dt_OutStockLockInfo> completedLocks) |
| | | { |
| | | foreach (var lockInfo in completedLocks) |
| | | { |
| | | // æ è®°éå®è®°å½ä¸ºå·²åèµ° |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²åèµ°; |
| | | lockInfo.Operator = App.User.UserName; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ¸
ç对åºçåºåè®°å½ç¶æ |
| | | await CleanupStockInfo(lockInfo); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¸
çåºåä¿¡æ¯ |
| | | /// </summary> |
| | | private async Task CleanupStockInfo(Dt_OutStockLockInfo lockInfo) |
| | | { |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId); |
| | | |
| | | if (stockDetail != null && stockDetail.Status == (int)StockStatusEmun.åºåºå®æ) |
| | | { |
| | | stockDetail.Status = (int)StockStatusEmun.å·²æ¸
ç; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// æ´æ°è®¢åç¶æ |
| | | /// </summary> |
| | | private async Task UpdateOrderStatusAfterPalletRemoval(string orderNo) |
| | | { |
| | | // æ£æ¥è®¢åæ¯å¦æææçé½å·²å®æ |
| | | var allLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ToListAsync(); |
| | | |
| | | var unfinishedPallets = allLocks |
| | | .GroupBy(x => x.PalletCode) |
| | | .Where(g => g.Any(x => x.Status == (int)OutLockStockStatusEnum.åºåºä¸ || |
| | | x.Status == (int)OutLockStockStatusEnum.ååºä¸)) |
| | | .ToList(); |
| | | |
| | | // å¦ææ²¡ææªå®æçæçï¼æ´æ°è®¢åç¶æä¸ºåºåºå®æ |
| | | if (!unfinishedPallets.Any()) |
| | | { |
| | | await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => new Dt_OutboundOrder |
| | | { |
| | | OrderStatus = (int)OutOrderStatusEnum.åºåºå®æ, |
| | | }) |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è®°å½ç©ºç®±åèµ°åå² |
| | | /// </summary> |
| | | private async Task RecordEmptyPalletRemoval(string orderNo, string palletCode, List<Dt_OutStockLockInfo> completedLocks) |
| | | { |
| | | var removalRecord = new Dt_EmptyPalletRemoval |
| | | { |
| | | OrderNo = orderNo, |
| | | PalletCode = palletCode, |
| | | RemovalTime = DateTime.Now, |
| | | Operator = App.User.UserName, |
| | | CompletedItemsCount = completedLocks.Count, |
| | | TotalPickedQuantity = completedLocks.Sum(x => x.PickedQty) |
| | | }; |
| | | |
| | | await Db.Insertable(removalRecord).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | |
| | | #region 忹忣 |
| | | |
| | | /// <summary> |
| | |
| | | return WebResponseContent.Instance.Error("æªæ¾å°åæ£è®°å½"); |
| | | |
| | | // æ¢å¤éå®ä¿¡æ¯ååºå |
| | | await RevertPickingData(pickingRecord); |
| | | var revertResult = await RevertPickingData(pickingRecord); |
| | | |
| | | //æ´æ°æ¹æ¬¡åè®¢åæ°æ® |
| | | await RevertBatchAndOrderData(pickingRecord); |
| | | // æ´æ°æ¹æ¬¡åè®¢åæ°æ® |
| | | await RevertBatchAndOrderData(pickingRecord, revertResult); |
| | | |
| | | // æ è®°åæ£è®°å½ä¸ºå·²åæ¶ |
| | | pickingRecord.IsCancelled = true; |
| | |
| | | return WebResponseContent.Instance.Error($"åæ¶åæ£å¤±è´¥ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æå¨æå
|
| | |
| | | |
| | | #endregion |
| | | |
| | | #region åæ¶æå
|
| | | |
| | | |
| | | #region åæ¶æå
|
| | | |
| | | /// <summary> |
| | | /// åæ¶æå
|
| | | /// åæ¶æå
|
| | | /// </summary> |
| | | public async Task<WebResponseContent> CancelSplitPackage(string orderNo, string palletCode, string newBarcode) |
| | | { |
| | |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // æ¥æ¾æå
è®°å½å¹¶éªè¯ |
| | | // 1. æ¥æ¾æå
è®°å½å¹¶éªè¯ |
| | | var validationResult = await ValidateCancelSplitRequest(orderNo, palletCode, newBarcode); |
| | | if (!validationResult.IsValid) |
| | | return WebResponseContent.Instance.Error(validationResult.ErrorMessage); |
| | | |
| | | var (splitRecord, newLockInfo, newStockDetail) = validationResult.Data; |
| | | |
| | | // æ§è¡åæ¶æå
é»è¾ |
| | | await ExecuteCancelSplitLogic(splitRecord, newLockInfo, newStockDetail); |
| | | // 2. æ¥æ¾åå§éå®ä¿¡æ¯ |
| | | var originalLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .FirstAsync(x => x.Id == splitRecord.OutStockLockInfoId); |
| | | |
| | | // 3. æ£æ¥è¯¥æ¡ç æ¯å¦è¢«å次æå
|
| | | var childSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => x.OriginalBarcode == newBarcode && !x.IsReverted) |
| | | .ToListAsync(); |
| | | |
| | | if (childSplitRecords.Any()) |
| | | { |
| | | return WebResponseContent.Instance.Error("该æ¡ç å·²è¢«åæ¬¡æå
ï¼è¯·å
åæ¶åç»çæå
æä½"); |
| | | } |
| | | |
| | | // 4. æ§è¡åæ¶æå
é»è¾ |
| | | await ExecuteCancelSplitLogic(splitRecord, originalLockInfo, newLockInfo, newStockDetail); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"åæ¶æå
失败 - OrderNo: {orderNo}, Barcode: {newBarcode}, Error: {ex.Message}"); |
| | | _logger.LogError($"åæ¶æå
失败 - OrderNo: {orderNo}, PalletCode: {palletCode}, Barcode: {newBarcode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"åæ¶æå
失败ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ§è¡åæ¶æå
é»è¾ |
| | | /// </summary> |
| | | private async Task ExecuteCancelSplitLogic(Dt_SplitPackageRecord splitRecord, |
| | | Dt_OutStockLockInfo originalLockInfo, Dt_OutStockLockInfo newLockInfo, |
| | | Dt_StockInfoDetail newStockDetail) |
| | | { |
| | | // 1. æ¢å¤åéå®ä¿¡æ¯ |
| | | // 注æï¼è¿ééè¦ç´¯å ï¼è䏿¯ç®åçèµå¼ï¼å 为å¯è½æå¤æ¬¡æå
|
| | | originalLockInfo.AssignQuantity += splitRecord.SplitQty; |
| | | originalLockInfo.OrderQuantity += splitRecord.SplitQty; |
| | | |
| | | // 妿åéå®ä¿¡æ¯çç¶ææ¯æ£é宿ï¼éè¦éæ°è®¾ç½®ä¸ºåºåºä¸ |
| | | if (originalLockInfo.Status == (int)OutLockStockStatusEnum.æ£é宿) |
| | | { |
| | | originalLockInfo.Status = (int)OutLockStockStatusEnum.åºåºä¸; |
| | | } |
| | | |
| | | await _outStockLockInfoService.Db.Updateable(originalLockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ¢å¤ååºåæç» |
| | | var originalStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == splitRecord.OriginalBarcode && x.StockId == splitRecord.StockId); |
| | | |
| | | originalStock.StockQuantity += splitRecord.SplitQty; |
| | | |
| | | // 妿ååºåç¶ææ¯åºåºå®æï¼éè¦éæ°è®¾ç½®ä¸ºåºåºéå® |
| | | if (originalStock.Status == (int)StockStatusEmun.åºåºå®æ) |
| | | { |
| | | originalStock.Status = (int)StockStatusEmun.åºåºéå®; |
| | | } |
| | | |
| | | await _stockInfoDetailService.Db.Updateable(originalStock).ExecuteCommandAsync(); |
| | | |
| | | // å 餿°éå®ä¿¡æ¯ |
| | | await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.Id == newLockInfo.Id) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | // å 餿°åºåæç» |
| | | await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == newLockInfo.CurrentBarcode) |
| | | .ExecuteCommandAsync(); |
| | | |
| | | //æ è®°æå
è®°å½ä¸ºå·²æ¤é |
| | | splitRecord.IsReverted = true; |
| | | splitRecord.RevertTime = DateTime.Now; |
| | | splitRecord.RevertOperator = App.User.UserName; |
| | | await _splitPackageService.Db.Updateable(splitRecord).ExecuteCommandAsync(); |
| | | |
| | | // æ£æ¥å¹¶æ´æ°æ¹æ¬¡å订åç¶æ |
| | | await CheckAndUpdateBatchStatus(originalLockInfo.BatchNo); |
| | | await CheckAndUpdateOrderStatus(originalLockInfo.OrderNo); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éªè¯åæ¶æå
è¯·æ± |
| | | /// </summary> |
| | | private async Task<ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>> ValidateCancelSplitRequest( |
| | | string orderNo, string palletCode, string newBarcode) |
| | | { |
| | | // æ¥æ¾æå
è®°å½ |
| | | var splitRecord = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => x.NewBarcode == newBarcode && |
| | | x.OrderNo == orderNo && |
| | | !x.IsReverted) |
| | | .FirstAsync(); |
| | | |
| | | if (splitRecord == null) |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("æªæ¾å°æå
è®°å½"); |
| | | |
| | | // æ¥æ¾æ°éå®ä¿¡æ¯ |
| | | var newLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.CurrentBarcode == newBarcode && |
| | | x.PalletCode == palletCode && |
| | | x.OrderNo == orderNo) |
| | | .FirstAsync(); |
| | | |
| | | if (newLockInfo == null) |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("æªæ¾å°æ°éå®ä¿¡æ¯"); |
| | | |
| | | // æ£æ¥æ°æ¡ç æ¯å¦å·²è¢«åæ£ |
| | | var pickingRecord = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(x => x.Barcode == newBarcode && !x.IsCancelled) |
| | | .FirstAsync(); |
| | | |
| | | if (pickingRecord != null) |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("该æ¡ç å·²è¢«åæ£ï¼æ æ³åæ¶æå
"); |
| | | |
| | | // æ£æ¥æ°æ¡ç æ¯å¦è¢«å次æå
|
| | | var childSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => x.OriginalBarcode == newBarcode && !x.IsReverted) |
| | | .ToListAsync(); |
| | | |
| | | if (childSplitRecords.Any()) |
| | | { |
| | | var childBarcodes = string.Join(", ", childSplitRecords.Select(x => x.NewBarcode)); |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error( |
| | | $"该æ¡ç å·²è¢«åæ¬¡æå
ï¼çæçæ°æ¡ç ï¼{childBarcodes}ï¼è¯·å
åæ¶åç»æå
"); |
| | | } |
| | | |
| | | var newStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == newBarcode); |
| | | |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Success((splitRecord, newLockInfo, newStockDetail)); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æ¹éåæ¶æå
é¾ |
| | | |
| | | /// <summary> |
| | | /// æ¹éåæ¶æå
é¾ - åæ¶æä¸ªæ¡ç åå
¶ææåç»æå
|
| | | /// </summary> |
| | | public async Task<WebResponseContent> CancelSplitPackageChain(string orderNo, string palletCode, string startBarcode) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // 1. æ¥æ¾ææç¸å
³çæå
è®°å½ï¼å½¢ææå
é¾ï¼ |
| | | var splitChain = await GetSplitPackageChain(orderNo, startBarcode); |
| | | |
| | | if (!splitChain.Any()) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°æå
è®°å½"); |
| | | |
| | | // 2. ææå
顺åºååºåæ¶ï¼ä»ææ°çå¼å§åæ¶ï¼ |
| | | var reversedChain = splitChain.OrderByDescending(x => x.SplitTime).ToList(); |
| | | |
| | | foreach (var splitRecord in reversedChain) |
| | | { |
| | | await CancelSingleSplitPackage(splitRecord, palletCode); |
| | | } |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK($"æååæ¶æå
é¾ï¼å
±{reversedChain.Count}次æå
æä½"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | _logger.LogError($"åæ¶æå
é¾å¤±è´¥ - OrderNo: {orderNo}, StartBarcode: {startBarcode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error($"åæ¶æå
é¾å¤±è´¥ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæå
é¾ - æ¥æ¾æä¸ªæ¡ç çæææå
è®°å½ï¼å
æ¬åç»æå
ï¼ |
| | | /// </summary> |
| | | public async Task<List<Dt_SplitPackageRecord>> GetSplitPackageChain(string orderNo, string startBarcode) |
| | | { |
| | | var allSplitRecords = new List<Dt_SplitPackageRecord>(); |
| | | var visitedBarcodes = new HashSet<string>(); // 鲿¢å¾ªç¯å¼ç¨ |
| | | |
| | | // 使ç¨éåè¿è¡å¹¿åº¦ä¼å
æç´¢ |
| | | var queue = new Queue<string>(); |
| | | queue.Enqueue(startBarcode); |
| | | visitedBarcodes.Add(startBarcode); |
| | | |
| | | while (queue.Count > 0) |
| | | { |
| | | var currentBarcode = queue.Dequeue(); |
| | | |
| | | // æ¥æ¾ä»¥å½åæ¡ç ä¸ºåæ¡ç çæææå
è®°å½ |
| | | var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => x.OriginalBarcode == currentBarcode && |
| | | x.OrderNo == orderNo && |
| | | !x.IsReverted) |
| | | .ToListAsync(); |
| | | |
| | | foreach (var record in splitRecords) |
| | | { |
| | | // é¿å
éå¤å¤ç |
| | | if (!visitedBarcodes.Contains(record.NewBarcode)) |
| | | { |
| | | allSplitRecords.Add(record); |
| | | queue.Enqueue(record.NewBarcode); |
| | | visitedBarcodes.Add(record.NewBarcode); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return allSplitRecords; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åæ¶å个æå
è®°å½ |
| | | /// </summary> |
| | | private async Task CancelSingleSplitPackage(Dt_SplitPackageRecord splitRecord, string palletCode) |
| | | { |
| | | // æ¥æ¾ç¸å
³æ°æ® |
| | | var newLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.CurrentBarcode == splitRecord.NewBarcode && |
| | | x.PalletCode == palletCode) |
| | | .FirstAsync(); |
| | | |
| | | var newStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == splitRecord.NewBarcode); |
| | | |
| | | var originalLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .FirstAsync(x => x.Id == splitRecord.OutStockLockInfoId); |
| | | |
| | | // æ§è¡åæ¶é»è¾ |
| | | await ExecuteCancelSplitLogic(splitRecord, originalLockInfo, newLockInfo, newStockDetail); |
| | | } |
| | | #endregion |
| | | |
| | | #region æå
ä¿¡æ¯æ¥è¯¢å¢å¼º |
| | | |
| | | /// <summary> |
| | | /// è·åæå
é¾ä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<WebResponseContent> GetSplitPackageChainInfo(string orderNo, string barcode) |
| | | { |
| | | try |
| | | { |
| | | var splitChain = await GetSplitPackageChain(orderNo, barcode); |
| | | |
| | | var chainInfo = new SplitPackageChainInfoDto |
| | | { |
| | | OriginalBarcode = barcode, |
| | | TotalSplitTimes = splitChain.Count, |
| | | SplitChain = splitChain.Select(x => new SplitChainItemDto |
| | | { |
| | | SplitTime = x.SplitTime, |
| | | OriginalBarcode = x.OriginalBarcode, |
| | | NewBarcode = x.NewBarcode, |
| | | SplitQuantity = x.SplitQty, |
| | | Operator = x.Operator, |
| | | IsReverted = x.IsReverted |
| | | }).ToList() |
| | | }; |
| | | |
| | | return WebResponseContent.Instance.OK("è·åæå", chainInfo); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError($"è·åæå
é¾ä¿¡æ¯å¤±è´¥ - OrderNo: {orderNo}, Barcode: {barcode}, Error: {ex.Message}"); |
| | | return WebResponseContent.Instance.Error("è·åæå
é¾ä¿¡æ¯å¤±è´¥"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// æ¥æ¾æ ¹æ¡ç |
| | | /// </summary> |
| | | public async Task<string> FindRootBarcode(string orderNo, string startBarcode) |
| | | { |
| | | var currentBarcode = startBarcode; |
| | | var visited = new HashSet<string>(); |
| | | |
| | | while (!string.IsNullOrEmpty(currentBarcode) && !visited.Contains(currentBarcode)) |
| | | { |
| | | visited.Add(currentBarcode); |
| | | |
| | | // æ¥æ¾å½åæ¡ç æ¯å¦æ¯ç±å
¶ä»æ¡ç æå
èæ¥ |
| | | var parentRecord = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => x.NewBarcode == currentBarcode && |
| | | x.OrderNo == orderNo && |
| | | !x.IsReverted) |
| | | .FirstAsync(); |
| | | |
| | | if (parentRecord == null) |
| | | { |
| | | // 没æç¶çº§æå
è®°å½ï¼è¯´æè¿æ¯æ ¹æ¡ç |
| | | return currentBarcode; |
| | | } |
| | | |
| | | currentBarcode = parentRecord.OriginalBarcode; |
| | | } |
| | | |
| | | // 妿åºç°å¾ªç¯å¼ç¨ï¼è¿åèµ·å§æ¡ç |
| | | return startBarcode; |
| | | } |
| | | #endregion |
| | | |
| | | #region æ´æ°æ¹æ¬¡ç¶ææ£æ¥ |
| | | |
| | | /// <summary> |
| | | /// æ£æ¥å¹¶æ´æ°æ¹æ¬¡ç¶æ |
| | | /// </summary> |
| | | private async Task CheckAndUpdateBatchStatus(string batchNo) |
| | | { |
| | | var batch = await _outboundBatchRepository.Db.Queryable<Dt_OutboundBatch>() |
| | | .FirstAsync(x => x.BatchNo == batchNo); |
| | | |
| | | if (batch != null) |
| | | { |
| | | // éæ°è®¡ç®æ¹æ¬¡å®ææ°é |
| | | var batchLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.BatchNo == batchNo) |
| | | .ToListAsync(); |
| | | |
| | | var completedQuantity = batchLocks.Where(x => x.Status == (int)OutLockStockStatusEnum.æ£é宿) |
| | | .Sum(x => x.PickedQty); |
| | | |
| | | batch.CompletedQuantity = completedQuantity; |
| | | |
| | | // æ´æ°æ¹æ¬¡ç¶æ |
| | | if (batch.CompletedQuantity >= batch.BatchQuantity) |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.已宿; |
| | | } |
| | | else if (batch.CompletedQuantity > 0) |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.æ§è¡ä¸; |
| | | } |
| | | else |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.åé
ä¸; |
| | | } |
| | | |
| | | await _outboundBatchRepository.Db.Updateable(batch).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | |
| | | |
| | | |
| | | #region åæ¹ååº |
| | | |
| | |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // æ¥æ¾æç䏿ªå®æçéå®è®°å½ |
| | | // æ¥æ¾æç䏿ªå®æçéå®è®°å½ï¼åªå¤çåºåºä¸çè®°å½ï¼ |
| | | var unfinishedLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderNo == orderNo && |
| | | x.PalletCode == palletCode && |
| | |
| | | if (!unfinishedLocks.Any()) |
| | | return WebResponseContent.Instance.Error("该æçæ²¡ææªå®æçéå®è®°å½"); |
| | | |
| | | // ææ¹æ¬¡åç»å¤ç |
| | | var batchGroups = unfinishedLocks.GroupBy(x => x.BatchNo); |
| | | // æåºåºæ¹æ¬¡åç»å¤ç |
| | | var batchGroups = unfinishedLocks.GroupBy(x => x.OutboundBatchNo); // ä½¿ç¨ OutboundBatchNo |
| | | |
| | | foreach (var batchGroup in batchGroups) |
| | | { |
| | | var batchNo = batchGroup.Key; |
| | | var outboundBatchNo = batchGroup.Key; |
| | | var batchLocks = batchGroup.ToList(); |
| | | |
| | | // éæ¾åºååéå®è®°å½ |
| | |
| | | } |
| | | |
| | | // æ´æ°æ¹æ¬¡ç¶æ |
| | | await UpdateBatchStatusForReturn(batchNo, batchLocks); |
| | | await UpdateBatchStatusForReturn(outboundBatchNo, batchLocks); |
| | | |
| | | // æ´æ°è®¢åæç»çå·²åé
æ°é |
| | | await UpdateOrderDetailAfterReturn(batchLocks); |
| | |
| | | return WebResponseContent.Instance.Error($"åæ¹ååºå¤±è´¥ï¼{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region éªè¯æ¹æ³ |
| | | private async Task<ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>> ValidatePickingRequest( |
| | | string orderNo, string palletCode, string barcode) |
| | | string orderNo, string palletCode, string barcode) |
| | | { |
| | | // æ¥æ¾éå®ä¿¡æ¯ |
| | | var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Error( |
| | | $"åºåæ°éä¸è¶³ï¼éè¦ï¼{lockInfo.AssignQuantity}ï¼å®é
ï¼{stockDetail.StockQuantity}"); |
| | | |
| | | // ä½¿ç¨ OutboundBatchNo æ¥æ¾æ¹æ¬¡ |
| | | var batch = await _outboundBatchRepository.Db.Queryable<Dt_OutboundBatch>() |
| | | .FirstAsync(x => x.BatchNo == lockInfo.BatchNo); |
| | | .FirstAsync(x => x.BatchNo == lockInfo.OutboundBatchNo); // ä¿®æ£ä¸º OutboundBatchNo |
| | | |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail, Dt_OutboundBatch)>.Success((lockInfo, orderDetail, stockDetail, batch)); |
| | | } |
| | | |
| | | private async Task<ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>> ValidateSplitRequest( |
| | | string orderNo, string palletCode, string originalBarcode, decimal splitQuantity) |
| | | { |
| | |
| | | |
| | | return ValidationResult<(Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Success((lockInfo, stockDetail)); |
| | | } |
| | | |
| | | private async Task<ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>> ValidateCancelSplitRequest( |
| | | string orderNo, string palletCode, string newBarcode) |
| | | { |
| | | var splitRecord = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => x.NewBarcode == newBarcode && |
| | | x.OrderNo == orderNo && |
| | | !x.IsReverted) |
| | | .FirstAsync(); |
| | | |
| | | if (splitRecord == null) |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("æªæ¾å°æå
è®°å½"); |
| | | |
| | | var newLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.CurrentBarcode == newBarcode && |
| | | x.PalletCode == palletCode && |
| | | x.OrderNo == orderNo) |
| | | .FirstAsync(); |
| | | |
| | | if (newLockInfo == null) |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("æªæ¾å°æ°éå®ä¿¡æ¯"); |
| | | |
| | | // æ£æ¥æ°æ¡ç æ¯å¦å·²è¢«åæ£ |
| | | var pickingRecord = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(x => x.Barcode == newBarcode && !x.IsCancelled) |
| | | .FirstAsync(); |
| | | |
| | | if (pickingRecord != null) |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Error("该æ¡ç å·²è¢«åæ£ï¼æ æ³åæ¶æå
"); |
| | | |
| | | var newStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == newBarcode); |
| | | |
| | | return ValidationResult<(Dt_SplitPackageRecord, Dt_OutStockLockInfo, Dt_StockInfoDetail)>.Success((splitRecord, newLockInfo, newStockDetail)); |
| | | } |
| | | |
| | | |
| | | #endregion |
| | | |
| | | #region æ ¸å¿é»è¾æ¹æ³ |
| | |
| | | .FirstAsync(x => x.Id == pickingRecord.OutStockLockId); |
| | | |
| | | lockInfo.PickedQty -= pickingRecord.PickQuantity; |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.åºåºä¸; |
| | | |
| | | // æ ¹æ®æ£éæ°éå¤æç¶æ |
| | | if (lockInfo.PickedQty <= 0) |
| | | { |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.åºåºä¸; |
| | | } |
| | | else if (lockInfo.PickedQty < lockInfo.AssignQuantity) |
| | | { |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.åºåºä¸; |
| | | } |
| | | |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ¢å¤åºå |
| | |
| | | |
| | | stockDetail.StockQuantity += pickingRecord.PickQuantity; |
| | | stockDetail.OutboundQuantity -= pickingRecord.PickQuantity; |
| | | stockDetail.Status = (int)StockStatusEmun.åºåºéå®; |
| | | |
| | | // æ¢å¤åºåç¶æ |
| | | if (stockDetail.StockQuantity > 0) |
| | | { |
| | | stockDetail.Status = (int)StockStatusEmun.åºåºéå®; |
| | | } |
| | | |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | return new RevertPickingResult |
| | |
| | | StockDetail = stockDetail |
| | | }; |
| | | } |
| | | |
| | | private async Task<SplitResultDto> ExecuteSplitLogic(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail, |
| | | decimal splitQuantity, string palletCode) |
| | | decimal splitQuantity, string palletCode) |
| | | { |
| | | // çææ°æ¡ç |
| | | string newBarcode = await GenerateNewBarcode(); |
| | |
| | | StockId = stockDetail.StockId, |
| | | MaterielCode = stockDetail.MaterielCode, |
| | | OrderNo = stockDetail.OrderNo, |
| | | BatchNo = stockDetail.BatchNo, |
| | | BatchNo = stockDetail.BatchNo, // ç©ææ¹æ¬¡ |
| | | StockQuantity = splitQuantity, |
| | | OutboundQuantity = 0, |
| | | Barcode = newBarcode, |
| | | Status = (int)StockStatusEmun.åºåºéå®, |
| | | SupplyCode = stockDetail.SupplyCode, |
| | | Unit = stockDetail.Unit |
| | | Unit = stockDetail.Unit, |
| | | BarcodeQty = stockDetail.BarcodeQty, |
| | | BarcodeUnit = stockDetail.BarcodeUnit, |
| | | BusinessType = stockDetail.BusinessType, |
| | | InboundOrderRowNo = stockDetail.InboundOrderRowNo, |
| | | }; |
| | | await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync(); |
| | | |
| | |
| | | stockDetail.StockQuantity -= splitQuantity; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | // å建æ°éå®ä¿¡æ¯ |
| | | // å建æ°éå®ä¿¡æ¯ - ä½¿ç¨æ£ç¡®ç OutboundBatchNo |
| | | var newLockInfo = new Dt_OutStockLockInfo |
| | | { |
| | | OrderNo = lockInfo.OrderNo, |
| | | OrderDetailId = lockInfo.OrderDetailId, |
| | | OutboundBatchNo = lockInfo.OutboundBatchNo, |
| | | OutboundBatchNo = lockInfo.OutboundBatchNo, // ä½¿ç¨ OutboundBatchNo |
| | | MaterielCode = lockInfo.MaterielCode, |
| | | MaterielName = lockInfo.MaterielName, |
| | | StockId = lockInfo.StockId, |
| | | OrderQuantity = splitQuantity, |
| | | AssignQuantity = splitQuantity, |
| | | PickedQty = 0, |
| | | LocationCode = lockInfo.LocationCode, |
| | | PalletCode = palletCode, |
| | | PalletCode = lockInfo.PalletCode, |
| | | TaskNum = lockInfo.TaskNum, |
| | | Status = (int)OutLockStockStatusEnum.åºåºä¸, |
| | | Unit = lockInfo.Unit, |
| | | SupplyCode = lockInfo.SupplyCode, |
| | | OrderType = lockInfo.OrderType, |
| | | CurrentBarcode = newBarcode, |
| | | IsSplitted = 1, |
| | | ParentLockId = lockInfo.Id, |
| | | Operator = App.User.UserName, |
| | | FactoryArea = lockInfo.FactoryArea, |
| | | lineNo = lockInfo.lineNo, |
| | | WarehouseCode = lockInfo.WarehouseCode, |
| | | BarcodeQty = lockInfo.BarcodeQty, |
| | | BarcodeUnit = lockInfo.BarcodeUnit, |
| | | }; |
| | | |
| | | await _outStockLockInfoService.Db.Insertable(newLockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ´æ°åéå®ä¿¡æ¯ |
| | |
| | | |
| | | return new SplitResultDto { NewBarcode = newBarcode }; |
| | | } |
| | | |
| | | private async Task ExecuteCancelSplitLogic(Dt_SplitPackageRecord splitRecord, Dt_OutStockLockInfo newLockInfo, Dt_StockInfoDetail newStockDetail) |
| | | { |
| | | // æ¢å¤ååºå |
| | |
| | | await CheckAndUpdateOrderStatus(orderNo); |
| | | } |
| | | |
| | | private async Task RevertBatchAndOrderData(Dt_PickingRecord pickingRecord) |
| | | private async Task RevertBatchAndOrderData(Dt_PickingRecord pickingRecord, RevertPickingResult revertResult) |
| | | { |
| | | // æ¢å¤æ¹æ¬¡å®ææ°é |
| | | var batch = await _outboundBatchRepository.Db.Queryable<Dt_OutboundBatch>() |
| | | .FirstAsync(x => x.BatchNo == pickingRecord.BatchNo); |
| | | .FirstAsync(x => x.BatchNo == revertResult.LockInfo.OutboundBatchNo); // ä½¿ç¨ OutboundBatchNo |
| | | |
| | | batch.CompletedQuantity -= pickingRecord.PickQuantity; |
| | | batch.BatchStatus = (int)BatchStatusEnum.æ§è¡ä¸; |
| | | await _outboundBatchRepository.Db.Updateable(batch).ExecuteCommandAsync(); |
| | | if (batch != null) |
| | | { |
| | | batch.CompletedQuantity -= pickingRecord.PickQuantity; |
| | | |
| | | // éæ°è®¡ç®æ¹æ¬¡ç¶æ |
| | | if (batch.CompletedQuantity <= 0) |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.åé
ä¸; |
| | | } |
| | | else if (batch.CompletedQuantity < batch.BatchQuantity) |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.æ§è¡ä¸; |
| | | } |
| | | |
| | | await _outboundBatchRepository.Db.Updateable(batch).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | // æ¢å¤è®¢åæç» |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | |
| | | // éæ°æ£æ¥è®¢åç¶æ |
| | | await CheckAndUpdateOrderStatus(pickingRecord.OrderNo); |
| | | } |
| | | |
| | | private async Task ReleaseLockAndStock(Dt_OutStockLockInfo lockInfo) |
| | | { |
| | | // æ¢å¤åºåç¶æ |
| | | // æ¢å¤åºåç¶æ - ååºååºåå为å¯ç¨ç¶æ |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .FirstAsync(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId); |
| | | |
| | | if (stockDetail != null) |
| | | { |
| | | // ååºååºåç¶ææ¢å¤ä¸ºå
¥åºå®æï¼å¯ç¨ç¶æï¼ |
| | | stockDetail.Status = (int)StockStatusEmun.å
¥åºå®æ; |
| | | await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | // æ´æ°éå®è®°å½ç¶æä¸ºååº |
| | | // æ´æ°éå®è®°å½ç¶æä¸ºå·²ååº |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | lockInfo.Operator = App.User.UserName; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | private async Task UpdateBatchStatusForReturn(string batchNo, List<Dt_OutStockLockInfo> returnedLocks) |
| | | /// <summary> |
| | | /// æ´æ°æ¹æ¬¡ç¶æï¼ååºï¼ |
| | | /// </summary> |
| | | private async Task UpdateBatchStatusForReturn(string outboundBatchNo, List<Dt_OutStockLockInfo> returnedLocks) |
| | | { |
| | | var batch = await _outboundBatchRepository.Db.Queryable<Dt_OutboundBatch>() |
| | | .FirstAsync(x => x.BatchNo == batchNo); |
| | | .FirstAsync(x => x.BatchNo == outboundBatchNo); |
| | | |
| | | // 计ç®ååºæ°é |
| | | var returnedQty = returnedLocks.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | batch.CompletedQuantity -= returnedQty; |
| | | |
| | | if (batch.CompletedQuantity <= 0) |
| | | if (batch != null) |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.å·²ååº; |
| | | } |
| | | else |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.æ§è¡ä¸; |
| | | } |
| | | // 计ç®ååºæ°éï¼æªæ£éçé¨åï¼ |
| | | var returnedQty = returnedLocks.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | batch.CompletedQuantity -= returnedQty; |
| | | |
| | | batch.Operator = App.User.UserName; |
| | | await _outboundBatchRepository.Db.Updateable(batch).ExecuteCommandAsync(); |
| | | // æ´æ°æ¹æ¬¡ç¶æ |
| | | if (batch.CompletedQuantity <= 0) |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.å·²ååº; |
| | | } |
| | | else if (batch.CompletedQuantity < batch.BatchQuantity) |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.æ§è¡ä¸; |
| | | } |
| | | else |
| | | { |
| | | batch.BatchStatus = (int)BatchStatusEnum.已宿; |
| | | } |
| | | |
| | | batch.Operator = App.User.UserName; |
| | | await _outboundBatchRepository.Db.Updateable(batch).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ´æ°è®¢åæç»ï¼ååºåï¼ |
| | | /// </summary> |
| | | private async Task UpdateOrderDetailAfterReturn(List<Dt_OutStockLockInfo> returnedLocks) |
| | | { |
| | | var orderDetailGroups = returnedLocks.GroupBy(x => x.OrderDetailId); |
| | |
| | | var orderDetailId = group.Key; |
| | | var returnedQty = group.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | |
| | | await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>() |
| | | .SetColumns(x => x.AllocatedQuantity == x.AllocatedQuantity - returnedQty) |
| | | .Where(x => x.Id == orderDetailId) |
| | | .ExecuteCommandAsync(); |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .FirstAsync(x => x.Id == orderDetailId); |
| | | |
| | | if (orderDetail != null) |
| | | { |
| | | orderDetail.AllocatedQuantity -= returnedQty; |
| | | await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region è¾
婿¹æ³ |
| | |
| | | PickTime = DateTime.Now, |
| | | Operator = App.User.UserName, |
| | | OutStockLockId = result.FinalLockInfo.Id, |
| | | |
| | | BarcodeUnit = result.FinalLockInfo.BarcodeUnit, |
| | | BarcodeQty = result.FinalLockInfo.BarcodeQty, |
| | | BatchNo = result.FinalLockInfo.BatchNo, |
| | | lineNo = result.FinalLockInfo.lineNo, |
| | | SupplyCode = result.FinalLockInfo.SupplyCode, |
| | | WarehouseCode = result.FinalLockInfo.WarehouseCode, |
| | | // IsCancelled = false |
| | | }; |
| | | |
| | |
| | | .Where(x => x.OrderNo == orderNo) |
| | | .ExecuteCommandAsync(); |
| | | } |
| | | |
| | | private string GetPalletStatusText(PalletStatusEnum status) |
| | | { |
| | | return status switch |
| | | { |
| | | PalletStatusEnum.æªå¼å§ => "æªå¼å§", |
| | | PalletStatusEnum.æ£éä¸ => "æ£éä¸", |
| | | PalletStatusEnum.已宿 => "已宿", |
| | | PalletStatusEnum.æ ä»»å¡ => "æ ä»»å¡", |
| | | _ => "æªç¥" |
| | | }; |
| | | } |
| | | #endregion |
| | | |
| | | |
| | | #region DTOç±» |
| | | |