| | |
| | | } |
| | | #endregion |
| | | |
| | | |
| | | |
| | | public WebResponseContent CompleteOutboundWithPallet(OutboundCompletePalletRequestDTO request) |
| | | { |
| | | WebResponseContent content = WebResponseContent.Instance; |
| | | |
| | | OutboundCompleteResponseDTO response = new(); |
| | | try |
| | | { |
| | | // 1. æ ¹æ®æçå·æ¥æ¾åºåä¿¡æ¯ |
| | | Dt_StockInfo stockInfo = _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == request.PalletCode).Includes(x => x.Details).First(); |
| | | if (stockInfo == null) |
| | | { |
| | | response.Success = false; |
| | | response.Message = $"æçå· {request.PalletCode} 对åºçåºåä¸åå¨"; |
| | | return WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | | if (!stockInfo.Details.Any()) |
| | | { |
| | | response.Success = false; |
| | | response.Message = $"æç {request.PalletCode} 对åºçåºåæç»ä¸åå¨"; |
| | | return WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | | bool isMatMixed = stockInfo.Details.GroupBy(x => new |
| | | { |
| | | x.MaterielCode, |
| | | x.MaterielName, |
| | | x.BatchNo, |
| | | x.SupplyCode, |
| | | x.WarehouseCode |
| | | }).Count() > 1; |
| | | |
| | | if (isMatMixed) |
| | | { |
| | | response.Success = false; |
| | | response.Message = $"æ··ææç {request.PalletCode} ä¸è½æ´ç®±åºåº"; |
| | | return WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | | // 2. æ¥æ¾åºåºåä¿¡æ¯ |
| | | Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(o => o.OrderNo == request.OrderNo); |
| | | if (outboundOrder == null) |
| | | { |
| | | response.Success = false; |
| | | response.Message = $"åºåºå {request.OrderNo} ä¸åå¨"; |
| | | return WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | | Dt_StockInfoDetail stockInfoDetail = stockInfo.Details.First(); |
| | | |
| | | // 3. æ¥æ¾éå®è®°å½ |
| | | Dt_OutStockLockInfo lockInfo = _outboundLockInfoRepository.QueryFirst(x => |
| | | x.OrderNo == request.OrderNo && |
| | | x.StockId == stockInfo.Id && |
| | | x.MaterielCode == stockInfoDetail.MaterielCode && |
| | | x.PalletCode == stockInfo.PalletCode); |
| | | |
| | | if (lockInfo == null || lockInfo.AssignQuantity <= 0) |
| | | { |
| | | response.Success = false; |
| | | response.Message = $"该åºå没æåé
åºåºéï¼æçå·ï¼{request.PalletCode}"; |
| | | return WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | | // æ¾åºå·²åé
ç订åæç»Id |
| | | List<int> detailIds = new List<int>(); |
| | | string[] ids = lockInfo.OrderDetailIds.Split(","); |
| | | foreach (string id in ids) |
| | | { |
| | | if (int.TryParse(id, out int detailId)) |
| | | { |
| | | detailIds.Add(detailId); |
| | | } |
| | | } |
| | | // 4. æ¥æ¾åºåºåæç»ä¿¡æ¯ |
| | | List<Dt_OutboundOrderDetail> outboundOrderDetails = FindMatchingOutboundDetails(outboundOrder.Id, stockInfoDetail, detailIds); |
| | | if (!outboundOrderDetails.Any()) |
| | | { |
| | | response.Success = false; |
| | | response.Message = $"æªæ¾å°å¹é
çåºåºåæç»ï¼ç©æï¼{stockInfoDetail.MaterielCode}ï¼æ¹æ¬¡ï¼{stockInfoDetail.BatchNo}"; |
| | | return WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | | decimal totalStockQuantity = stockInfo.Details.Sum(x => x.StockQuantity); |
| | | |
| | | // 5. 计ç®å®é
åºåºé |
| | | decimal actualOutboundQuantity = CalculateActualOutboundQuantity(stockInfo.Details, outboundOrderDetails, lockInfo);// éåºåºé |
| | | |
| | | if (actualOutboundQuantity <= 0) |
| | | { |
| | | decimal totalAllocatedQuantity = lockInfo.AllocatedQuantity; |
| | | decimal availableOutboundQuantity = lockInfo.AssignQuantity - totalAllocatedQuantity; |
| | | decimal detailRemainingQuantity = outboundOrderDetails.Sum(x => x.OrderQuantity - x.OverOutQuantity - x.MoveQty); |
| | | |
| | | response.Success = false; |
| | | response.Message = $"æ æ³åºåºï¼æçå·ï¼{request.PalletCode}ï¼åºåéï¼{totalStockQuantity}ï¼å·²åºåºï¼{totalAllocatedQuantity}ï¼åé
éï¼{lockInfo.AssignQuantity}ï¼æç»å©ä½ï¼{detailRemainingQuantity}"; |
| | | return WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | | if (lockInfo.AssignQuantity != totalStockQuantity) |
| | | { |
| | | response.Success = false; |
| | | response.Message = $"æ æ³åºåºï¼æçå·ï¼{request.PalletCode}ï¼åºåéï¼{totalStockQuantity}ï¼åé
éï¼{lockInfo.AssignQuantity}"; |
| | | return WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | | // 6. å¼å¯äºå¡ |
| | | _unitOfWorkManage.BeginTran(); |
| | | try |
| | | { |
| | | // æ´ç®±åºåºæ éæå
|
| | | PerformFullOutboundOperation(stockInfo, request, lockInfo.TaskNum.GetValueOrDefault()); |
| | | |
| | | |
| | | decimal allocatedQuantity = actualOutboundQuantity; |
| | | List<Dt_OutboundOrderDetail> updateDetails = new(); |
| | | foreach (var item in outboundOrderDetails) |
| | | { |
| | | if (allocatedQuantity <= 0) break; |
| | | |
| | | |
| | | //if (item.OrderQuantity - item.MoveQty - item.OverOutQuantity >= allocatedQuantity) |
| | | //{ |
| | | // item.OverOutQuantity += allocatedQuantity; |
| | | // allocatedQuantity = 0; |
| | | //} |
| | | //else |
| | | //{ |
| | | // allocatedQuantity -= (item.OrderQuantity - item.MoveQty - item.OverOutQuantity); |
| | | // item.OverOutQuantity = item.OrderQuantity - item.MoveQty; |
| | | //} |
| | | List<Barcodes> barcodesList = new List<Barcodes>(); |
| | | List<Dt_StockInfoDetail> stockInfoDetails = stockInfo.Details.Where((x => x.StockQuantity > x.OutboundQuantity)).ToList(); |
| | | foreach (var stockDetail in stockInfoDetails) |
| | | { |
| | | if (item.LockQuantity - item.OverOutQuantity >= stockDetail.StockQuantity - stockInfoDetail.OutboundQuantity) |
| | | { |
| | | Barcodes barcodes = new Barcodes |
| | | { |
| | | Barcode = stockDetail.Barcode, |
| | | Qty = stockDetail.StockQuantity - stockInfoDetail.OutboundQuantity, |
| | | SupplyCode = stockDetail?.SupplyCode ?? "", |
| | | BatchNo = stockDetail?.BatchNo ?? "", |
| | | Unit = stockDetail?.Unit ?? "" |
| | | }; |
| | | |
| | | stockDetail.StockQuantity = stockInfoDetail.OutboundQuantity; |
| | | barcodesList.Add(barcodes); |
| | | } |
| | | else |
| | | { |
| | | Barcodes barcodes = new Barcodes |
| | | { |
| | | Barcode = stockDetail.Barcode, |
| | | Qty = item.LockQuantity - item.OverOutQuantity, |
| | | SupplyCode = stockDetail?.SupplyCode ?? "", |
| | | BatchNo = stockDetail?.BatchNo ?? "", |
| | | Unit = stockDetail?.Unit ?? "" |
| | | }; |
| | | stockInfoDetail.OutboundQuantity += item.LockQuantity - item.OverOutQuantity; |
| | | barcodesList.Add(barcodes); |
| | | } |
| | | } |
| | | |
| | | decimal barcodeQuantity = allocatedQuantity; |
| | | |
| | | if (item.LockQuantity - item.OverOutQuantity >= allocatedQuantity) |
| | | { |
| | | item.OverOutQuantity += allocatedQuantity; |
| | | item.CurrentDeliveryQty += allocatedQuantity; |
| | | allocatedQuantity = 0; |
| | | } |
| | | else |
| | | { |
| | | barcodeQuantity = item.LockQuantity - item.OverOutQuantity; |
| | | allocatedQuantity -= (item.LockQuantity - item.OverOutQuantity); |
| | | item.OverOutQuantity = item.LockQuantity; |
| | | item.CurrentDeliveryQty = item.LockQuantity; |
| | | } |
| | | |
| | | updateDetails.Add(item); |
| | | |
| | | |
| | | if (!string.IsNullOrEmpty(item.ReturnJsonData)) |
| | | { |
| | | barcodesList.AddRange(JsonConvert.DeserializeObject<List<Barcodes>>(item.ReturnJsonData) ?? new List<Barcodes>()); |
| | | } |
| | | |
| | | JsonSerializerSettings settings = new JsonSerializerSettings |
| | | { |
| | | ContractResolver = new CamelCasePropertyNamesContractResolver() |
| | | }; |
| | | item.ReturnJsonData = JsonConvert.SerializeObject(barcodesList, settings); |
| | | } |
| | | |
| | | lockInfo.SortedQuantity = lockInfo.SortedQuantity + actualOutboundQuantity; |
| | | |
| | | if (lockInfo.SortedQuantity == lockInfo.AssignQuantity) |
| | | { |
| | | _outboundLockInfoRepository.DeleteAndMoveIntoHty(lockInfo, WIDESEA_Core.Enums.OperateTypeEnum.èªå¨å®æ); |
| | | } |
| | | else |
| | | { |
| | | // æ´æ°éå®è®°å½ |
| | | _outboundLockInfoRepository.UpdateData(lockInfo); |
| | | } |
| | | |
| | | // æ´æ°åºåºåæç»çå·²åºåºæ°é |
| | | _detailRepository.UpdateData(updateDetails); |
| | | |
| | | // æ´æ°éå®è®°å½ç累计已åºåºæ°éï¼éè¦æ´æ°è¯¥æçè¯¥ç©æçææç¸å
³è®°å½ï¼ |
| | | //UpdateLockInfoAllocatedQuantity(stockInfo.Id, stockDetail.MaterielCode, stockDetail.BatchNo, actualOutboundQuantity); |
| | | |
| | | // æäº¤äºå¡ |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | response.Success = true; |
| | | response.Message = "åºåºå®æ"; |
| | | response.UpdatedDetails = updateDetails; |
| | | |
| | | // æ£æ¥åºåºåæ¯å¦å®æ |
| | | if (CheckOutboundOrderCompleted(request.OrderNo)) |
| | | { |
| | | UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.åºåºå®æ.ObjToInt()); |
| | | |
| | | |
| | | //todo: åä¼ MES |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | response.Success = false; |
| | | response.Message = $"åºåºå¤ç失败ï¼{ex.Message}"; |
| | | return WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | |
| | | content = WebResponseContent.Instance.OK(data: response); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | content = WebResponseContent.Instance.Error("å¤çåºåºå®æå¤±è´¥ï¼" + ex.Message); |
| | | } |
| | | return content; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 计ç®å®é
åºåºæ°é |
| | | /// </summary> |
| | | private decimal CalculateActualOutboundQuantity(List<Dt_StockInfoDetail> stockDetails, List<Dt_OutboundOrderDetail> outboundDetails, Dt_OutStockLockInfo lockInfo) |
| | | { |
| | | decimal availableOutboundQuantity = lockInfo.AssignQuantity; |
| | | decimal detailRemainingQuantity = outboundDetails.Sum(x => x.OrderQuantity - x.OverOutQuantity - x.MoveQty);//outboundDetail.OrderQuantity - outboundDetail.OverOutQuantity; |
| | | |
| | | return Math.Min( |
| | | Math.Min(availableOutboundQuantity, detailRemainingQuantity), |
| | | stockDetails.Sum(x => x.StockQuantity)); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ§è¡å®æ´åºåºæä½ï¼ä¸æå
ï¼ |
| | | /// </summary> |
| | | private void PerformFullOutboundOperation(Dt_StockInfo stockInfo, OutboundCompletePalletRequestDTO request, int taskNum) |
| | | { |
| | | List<Dt_StockInfoDetail_Hty> historyRecords = new List<Dt_StockInfoDetail_Hty>(); |
| | | List<Dt_StockQuantityChangeRecord> changeRecords = new List<Dt_StockQuantityChangeRecord>(); |
| | | foreach (var item in stockInfo.Details) |
| | | { |
| | | // ä¿ååºåæç»å°åå²è®°å½ |
| | | Dt_StockInfoDetail_Hty historyRecord = new Dt_StockInfoDetail_Hty |
| | | { |
| | | SourceId = item.Id, |
| | | OperateType = "åºåºå®æ", |
| | | InsertTime = DateTime.Now, |
| | | StockId = item.StockId, |
| | | MaterielCode = item.MaterielCode, |
| | | MaterielName = item.MaterielName, |
| | | OrderNo = item.OrderNo, |
| | | BatchNo = item.BatchNo, |
| | | ProductionDate = item.ProductionDate, |
| | | EffectiveDate = item.EffectiveDate, |
| | | SerialNumber = item.SerialNumber, |
| | | StockQuantity = item.StockQuantity, |
| | | OutboundQuantity = item.StockQuantity, |
| | | Status = item.Status, |
| | | Unit = item.Unit, |
| | | InboundOrderRowNo = item.InboundOrderRowNo, |
| | | SupplyCode = item.SupplyCode, |
| | | FactoryArea = item.FactoryArea, |
| | | WarehouseCode = item.WarehouseCode, |
| | | Barcode = item.Barcode, |
| | | Remark = $"æ´ç®±åºåºå®æå é¤ï¼æ¡ç ï¼{request.PalletCode}ï¼åæ°éï¼{item.StockQuantity}ï¼åºåºæ°éï¼{item.StockQuantity}ï¼æä½è
ï¼{request.Operator}" |
| | | }; |
| | | historyRecords.Add(historyRecord); |
| | | |
| | | // è®°å½åºååå¨ |
| | | Dt_StockQuantityChangeRecord changeRecord = new Dt_StockQuantityChangeRecord |
| | | { |
| | | StockDetailId = item.Id, |
| | | PalleCode = stockInfo.PalletCode, |
| | | MaterielCode = item.MaterielCode, |
| | | MaterielName = item.MaterielName, |
| | | BatchNo = item.BatchNo, |
| | | OriginalSerilNumber = item.Barcode, |
| | | NewSerilNumber = "", |
| | | OrderNo = request.OrderNo, |
| | | TaskNum = taskNum, |
| | | ChangeType = (int)StockChangeTypeEnum.Outbound, |
| | | ChangeQuantity = -item.StockQuantity, |
| | | BeforeQuantity = item.StockQuantity, |
| | | AfterQuantity = 0, |
| | | SupplyCode = item.SupplyCode, |
| | | WarehouseCode = item.WarehouseCode, |
| | | Remark = $"æ´ç®±åºåºå®æå é¤åºåæç»ï¼æ¡ç ï¼{request.PalletCode}ï¼åºåºæ°éï¼{item.StockQuantity}ï¼æä½è
ï¼{request.Operator}" |
| | | }; |
| | | changeRecords.Add(changeRecord); |
| | | } |
| | | _stockDetailHistoryRepository.AddData(historyRecords); |
| | | |
| | | // å é¤åºåæç»è®°å½ |
| | | _stockDetailRepository.DeleteData(stockInfo.Details); |
| | | _stockChangeRepository.AddData(changeRecords); |
| | | } |
| | | |
| | | #region æ£é |
| | | /// <summary> |
| | | /// åºåºå®æå¤çï¼æ«ææ¡ç æ£ååºåï¼ |