| | |
| | | using System.Reflection.Emit; |
| | | using AutoMapper; |
| | | using AutoMapper; |
| | | using Dm.filter; |
| | | using MailKit.Search; |
| | | using Mapster; |
| | | using Microsoft.IdentityModel.Tokens; |
| | | using Newtonsoft.Json; |
| | | using Newtonsoft.Json.Serialization; |
| | | using OfficeOpenXml.FormulaParsing.Excel.Functions.Math; |
| | | using Org.BouncyCastle.Asn1.Ocsp; |
| | | using Org.BouncyCastle.Crypto; |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Reflection.Emit; |
| | | using WIDESEA_BasicService; |
| | | using WIDESEA_Common.CommonEnum; |
| | | using WIDESEA_Common.LocationEnum; |
| | |
| | | using WIDESEA_DTO.Base; |
| | | using WIDESEA_DTO.Basic; |
| | | using WIDESEA_DTO.CalcOut; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_DTO.ReturnMES; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_IRecordService; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Model.Models.Basic; |
| | | using WIDESEA_Model.Models.Check; |
| | | using static HslCommunication.Profinet.Knx.KnxCode; |
| | | |
| | |
| | | private readonly IESSApiService _eSSApiService; |
| | | private readonly IRepository<Dt_AllocateOrder> _allocateOrderRepository; |
| | | private readonly IRepository<Dt_AllocateMaterialInfo> _allocateMaterialInfoRepository; |
| | | public readonly IRepository<Dt_InboundOrderDetail> _inboundOrderDetailRepository; |
| | | public readonly IRepository<Dt_InboundOrder> _inboundOrderRepository; |
| | | public readonly IRepository<Dt_WarehouseArea> _warehouseAreaRepository; |
| | | public readonly IRepository<Dt_LocationType> _locationTypeRepository; |
| | | |
| | | private Dictionary<string, string> stations = new Dictionary<string, string> |
| | | { |
| | |
| | | {"3-1","3-5" }, |
| | | }; |
| | | |
| | | public OutboundService(IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_OutboundOrderDetail> detailRepository, IRepository<Dt_OutboundOrder> outboundRepository, IRepository<Dt_OutStockLockInfo> outboundLockInfoRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_StockInfoDetail> stockDetailRepository, IRepository<Dt_StockQuantityChangeRecord> stockChangeRepository, IRepository<Dt_StockInfoDetail_Hty> stockDetailHistoryRepository, IBasicService basicService, IOutboundOrderDetailService outboundOrderDetailService, IOutboundOrderService outboundOrderService, IOutStockLockInfoService outboundStockLockInfoService, IFeedbackMesService feedbackMesService, IRepository<Dt_Task> taskRepository, ILocationInfoService locationInfoService, IESSApiService eSSApiService, IRepository<Dt_AllocateOrder> allocateOrderRepository, IRepository<Dt_AllocateMaterialInfo> allocateMaterialInfoRepository) |
| | | public OutboundService(IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_OutboundOrderDetail> detailRepository, IRepository<Dt_OutboundOrder> outboundRepository, IRepository<Dt_OutStockLockInfo> outboundLockInfoRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_StockInfoDetail> stockDetailRepository, IRepository<Dt_StockQuantityChangeRecord> stockChangeRepository, IRepository<Dt_StockInfoDetail_Hty> stockDetailHistoryRepository, IBasicService basicService, IOutboundOrderDetailService outboundOrderDetailService, IOutboundOrderService outboundOrderService, IOutStockLockInfoService outboundStockLockInfoService, IFeedbackMesService feedbackMesService, IRepository<Dt_Task> taskRepository, ILocationInfoService locationInfoService, IESSApiService eSSApiService, IRepository<Dt_AllocateOrder> allocateOrderRepository, IRepository<Dt_AllocateMaterialInfo> allocateMaterialInfoRepository, IRepository<Dt_InboundOrderDetail> inboundOrderDetailRepository, IRepository<Dt_InboundOrder> inboundOrderRepository, IRepository<Dt_LocationType> locationTypeRepository, IRepository<Dt_WarehouseArea> warehouseAreaRepository) |
| | | { |
| | | _mapper = mapper; |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | |
| | | _eSSApiService = eSSApiService; |
| | | _allocateOrderRepository = allocateOrderRepository; |
| | | _allocateMaterialInfoRepository = allocateMaterialInfoRepository; |
| | | _inboundOrderDetailRepository = inboundOrderDetailRepository; |
| | | _inboundOrderRepository = inboundOrderRepository; |
| | | _locationTypeRepository = locationTypeRepository; |
| | | _warehouseAreaRepository = warehouseAreaRepository; |
| | | } |
| | | |
| | | public WebResponseContent PrintFromData (string barcode) |
| | | { |
| | | var detail = _inboundOrderDetailRepository.QueryFirst(x => x.Barcode == barcode); |
| | | if(detail == null) |
| | | { |
| | | return WebResponseContent.Instance.Error(); |
| | | } |
| | | |
| | | var inbound = _inboundOrderRepository.QueryFirst(x=>x.Id == detail.OrderId); |
| | | if(inbound == null) |
| | | { |
| | | return WebResponseContent.Instance.Error(); |
| | | } |
| | | var printFormData = new PrintFromDataDTO { |
| | | materialCode = detail.MaterielCode, |
| | | materialName = detail.MaterielName, |
| | | materialSpec = detail.Unit, |
| | | batchNo = detail.BatchNo, |
| | | pruchaseOrderNo = inbound.UpperOrderNo, |
| | | factoryArea = inbound.FactoryArea, |
| | | suplierCode = detail.SupplyCode, |
| | | quantity = detail.BarcodeQty |
| | | }; |
| | | |
| | | return WebResponseContent.Instance.OK(data:printFormData); |
| | | } |
| | | |
| | | #region åºåºåé
|
| | |
| | | PickingOutboundResponseDTO response = new PickingOutboundResponseDTO(); |
| | | decimal totalNeedAllocate = 0; // æ»éæ±åé
é |
| | | decimal totalActualAllocate = 0; // å®é
æ»åé
é |
| | | string targetWarehouse = string.Empty;// ç®æ ä»åº |
| | | string targetLocationCode = string.Empty; // ç®æ è´§ä½ |
| | | bool isWholeCaseOutbound = false; // æ¯å¦æ´ç®±åºåº |
| | | List<string> wholeCasePallets = new List<string>(); |
| | | Dictionary<string, string> palletLocationMap = new Dictionary<string, string>(); |
| | | Dictionary<string, bool> palletIsWholeCaseMap = new Dictionary<string, bool>(); |
| | | int? targetLocationType = null; |
| | | |
| | | |
| | | try |
| | | { |
| | |
| | | // è®°å½æ»éæ±æ°é |
| | | totalNeedAllocate = calculationResult.MaterielCalculations.Sum(x => x.UnallocatedQuantity); |
| | | |
| | | |
| | | // 2. å¤çç©æåé
|
| | | List<PickedStockDetailDTO> pickedDetails = new List<PickedStockDetailDTO>(); |
| | | Dt_OutboundOrder outboundOrder = calculationResult.OutboundOrder; |
| | |
| | | materielCalc.OutStockLockInfos.Add(item); |
| | | } |
| | | outStockLockInfos.Add(item); |
| | | } |
| | | |
| | | if (outboundOrder.OrderType == 117) |
| | | { |
| | | // å¹é
å½ååæ®çéå®è®°å½ |
| | | if (outboundOrder.OrderNo == item.OrderNo) |
| | | { |
| | | // æ¥è¯¢åºåä¿¡æ¯ |
| | | var stockInfo = _stockInfoRepository.QueryFirst(x => x.PalletCode == item.PalletCode); |
| | | if (stockInfo == null) |
| | | { |
| | | content = WebResponseContent.Instance.Error($"æç{item.PalletCode}æªæ¥è¯¢å°åºåä¿¡æ¯ï¼æ æ³å¤çæ´ç®±åºåº"); |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return content; |
| | | } |
| | | |
| | | // 计ç®åºåæ»éï¼å¤ææ¯å¦æ´ç®±ï¼å¢å 0å¼ä¿æ¤ï¼ |
| | | decimal stockQuantity = _stockDetailRepository.QueryData(x => x.StockId == stockInfo.Id).Sum(x => x.StockQuantity); |
| | | if (stockQuantity > 0 && stockQuantity == item.AssignQuantity) |
| | | { |
| | | // æ è®°å½åæç为æ´ç®±ï¼æ ¸å¿ä¿®å¤ï¼ææç维度记å½ç¶æï¼ |
| | | if (!palletIsWholeCaseMap.ContainsKey(item.PalletCode)) |
| | | { |
| | | palletIsWholeCaseMap.Add(item.PalletCode, true); |
| | | } |
| | | else |
| | | { |
| | | palletIsWholeCaseMap[item.PalletCode] = true; |
| | | } |
| | | |
| | | // ç®æ ä»åº/è´§ä½ç±»ååªæ¥è¯¢ä¸æ¬¡ï¼æ§è½ä¼å+空å¼ä¿æ¤ï¼ |
| | | if (string.IsNullOrEmpty(targetWarehouse)) |
| | | { |
| | | targetWarehouse = GetToWarehouseByOrderNo(request.OrderNo); |
| | | if (string.IsNullOrEmpty(targetWarehouse)) |
| | | { |
| | | content = WebResponseContent.Instance.Error("æºä»è°æºä»æ´ç®±åºåºåæ®æªé
ç½®ç®æ ä»åº"); |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return content; |
| | | } |
| | | |
| | | // æ¿æ¢First()为FirstOrDefault()ï¼é¿å
空å¼å¼å¸¸ |
| | | string warehouseAreaName = _warehouseAreaRepository.Db.Queryable<Dt_WarehouseArea>() |
| | | .Where(x => x.Code == targetWarehouse) |
| | | .Select(x => x.Name) |
| | | .First(); |
| | | if (string.IsNullOrEmpty(warehouseAreaName)) |
| | | { |
| | | content = WebResponseContent.Instance.Error($"ç®æ ä»åº{targetWarehouse}æªæ¥è¯¢å°å¯¹åºçåºåºåç§°"); |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return content; |
| | | } |
| | | |
| | | int? locationType = _locationTypeRepository.Db.Queryable<Dt_LocationType>() |
| | | .Where(x => string.Equals(x.LocationTypeDesc, warehouseAreaName, StringComparison.OrdinalIgnoreCase)) |
| | | .Select(x => x.LocationType) |
| | | .First(); |
| | | if (!locationType.HasValue) |
| | | { |
| | | content = WebResponseContent.Instance.Error($"åºåº{warehouseAreaName}æªå¹é
å°å¯¹åºçè´§ä½ç±»å"); |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return content; |
| | | } |
| | | targetLocationType = locationType.Value; |
| | | } |
| | | |
| | | // åé
ç®æ è´§ä½ï¼æ¯ä¸ªæçç¬ç«è´§ä½ï¼ |
| | | if (!palletLocationMap.ContainsKey(item.PalletCode) && targetLocationType.HasValue) |
| | | { |
| | | Dt_LocationInfo locationInfo = _locationInfoService.AssignLocation(targetLocationType.Value); |
| | | if (locationInfo == null || string.IsNullOrEmpty(locationInfo.LocationCode)) |
| | | { |
| | | content = WebResponseContent.Instance.Error($"è´§ä½ç±»å{targetLocationType.Value}æªåé
å°å¯ç¨è´§ä½ï¼æçï¼{item.PalletCode}ï¼"); |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return content; |
| | | } |
| | | palletLocationMap.Add(item.PalletCode, locationInfo.LocationCode); |
| | | } |
| | | |
| | | // å å
¥æ´ç®±æçå表 |
| | | if (!wholeCasePallets.Contains(item.PalletCode)) |
| | | { |
| | | wholeCasePallets.Add(item.PalletCode); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (!palletIsWholeCaseMap.ContainsKey(item.PalletCode)) |
| | | { |
| | | palletIsWholeCaseMap.Add(item.PalletCode, false); |
| | | } |
| | | else |
| | | { |
| | | palletIsWholeCaseMap[item.PalletCode] = false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // å¤çä»»å¡ |
| | | foreach (var item in materielPickedDetails.Tasks) |
| | | { |
| | | if (outboundOrder.OrderType == 117 |
| | | && palletIsWholeCaseMap.ContainsKey(item.PalletCode) |
| | | && palletIsWholeCaseMap[item.PalletCode] |
| | | && palletLocationMap.ContainsKey(item.PalletCode)) |
| | | { |
| | | item.TaskType = (int)TaskTypeEnum.Relocation; |
| | | item.TargetAddress = palletLocationMap[item.PalletCode]; |
| | | } |
| | | if (tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode) == null) |
| | | tasks.Add(item); |
| | | } |
| | |
| | | foreach (var detail in materielCalc.Details) |
| | | { |
| | | if (remainingToLock <= 0) break; |
| | | decimal maxLockableQty = detail.OrderQuantity - detail.OverOutQuantity; |
| | | decimal maxLockableQty = 0; |
| | | if (detail.LockQuantity > detail.OverOutQuantity && detail.OverOutQuantity > 0) |
| | | { |
| | | maxLockableQty = detail.OrderQuantity - detail.LockQuantity; |
| | | } |
| | | else if(detail.OverOutQuantity > 0) |
| | | { |
| | | maxLockableQty = detail.OrderQuantity - detail.OverOutQuantity; |
| | | } |
| | | else |
| | | { |
| | | maxLockableQty = detail.OrderQuantity - detail.OverOutQuantity - detail.LockQuantity; |
| | | } |
| | | if (maxLockableQty <= 0) continue; |
| | | decimal currentLockQty = Math.Min(remainingToLock, maxLockableQty); |
| | | detail.LockQuantity += currentLockQty; |
| | |
| | | |
| | | if (tasks.Any()) _taskRepository.AddData(tasks); |
| | | |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | if (outboundOrder.OrderType == 117 && wholeCasePallets.Any()) |
| | | { |
| | | foreach (var palletCode in wholeCasePallets) |
| | | { |
| | | var completeReq = new OutboundCompletePalletRequestDTO |
| | | { |
| | | OrderNo = request.OrderNo, |
| | | PalletCode = palletCode |
| | | }; |
| | | |
| | | var res = CompleteOutboundWithPallet(completeReq); |
| | | if (!res.Status) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return res; |
| | | } |
| | | } |
| | | } |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | // 4. æé ååºï¼åºåãå
¨é¨åé
ãåãé¨ååé
ã |
| | | string responseMsg = totalActualAllocate == totalNeedAllocate |
| | | ? "忣任å¡åé
æå" |
| | | : $"忣任å¡åé
宿ï¼å®é
åé
{totalActualAllocate}ï¼éæ±{totalNeedAllocate}ï¼åºåä¸è¶³é¨åæªåé
ï¼"; |
| | | Dt_OutboundOrder outboundOrder1 = _outboundRepository.Db.Queryable<Dt_OutboundOrder>().Where(x => x.OrderNo == request.OrderNo).Includes(x=>x.Details).First(); |
| | | if(totalActualAllocate == 0 && !outboundOrder1.Details.Any(x=>x.LockQuantity >0)) |
| | | { |
| | | UpdateOutboundOrderStatus(request.OrderNo, (int)OutOrderStatusEnum.æªå¼å§); |
| | | return WebResponseContent.Instance.Error("åé
åºåæ°é为0ï¼æ æ³åºåº"); |
| | | } |
| | | response.Success = true; |
| | | response.Message = responseMsg; |
| | | response.Tasks = tasks; |
| | |
| | | content = WebResponseContent.Instance.Error("å¤çæ£è´§åºåºå¤±è´¥ï¼" + ex.Message); |
| | | } |
| | | return content; |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®åæ®å·è·åç®æ ä»åº |
| | | /// </summary> |
| | | /// <param name="orderNo"></param> |
| | | /// <returns></returns> |
| | | public String GetToWarehouseByOrderNo(string orderNo) |
| | | { |
| | | var order =_allocateOrderRepository.QueryFirst(x => x.OrderNo == orderNo); |
| | | return order.ToWarehouse; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | { |
| | | barcodeQuantity = item.LockQuantity - item.OverOutQuantity; |
| | | allocatedQuantity -= (item.LockQuantity - item.OverOutQuantity); |
| | | item.CurrentDeliveryQty = item.LockQuantity - item.OverOutQuantity; |
| | | if(item.ReturnToMESStatus == 0) |
| | | { |
| | | item.CurrentDeliveryQty = item.LockQuantity; |
| | | } |
| | | else |
| | | { |
| | | item.CurrentDeliveryQty += item.LockQuantity - item.OverOutQuantity; |
| | | } |
| | | item.OverOutQuantity = item.LockQuantity; |
| | | } |
| | | |
| | |
| | | response.Success = true; |
| | | response.Message = "åºåºå®æ"; |
| | | response.UpdatedDetails = updateDetails; |
| | | |
| | | |
| | | if (CheckOutboundOrderDetailCompletedByMatCode(request.OrderNo, lockInfo.MaterielCode, outboundOrderDetails)) |
| | | { |
| | | Func<Dt_OutStockLockInfo, bool> supWhere = x => string.IsNullOrEmpty(outboundOrderDetails.First().SupplyCode) ? true : x.SupplyCode == outboundOrderDetails.First().SupplyCode; |
| | | |
| | | Func<Dt_OutStockLockInfo, bool> wareWhere = x => string.IsNullOrEmpty(outboundOrderDetails.First().WarehouseCode) ? true : x.WarehouseCode == outboundOrderDetails.First().WarehouseCode; |
| | | |
| | | List<Dt_OutStockLockInfo> stockLockInfos = _outboundLockInfoRepository.QueryData(x => |
| | | x.OrderNo == request.OrderNo && |
| | | x.MaterielCode == stockInfoDetail.MaterielCode).Where(supWhere).Where(wareWhere).ToList(); |
| | | if (stockLockInfos != null && stockLockInfos.Any()) |
| | | { |
| | | _outboundLockInfoRepository.DeleteAndMoveIntoHty(stockLockInfos, WIDESEA_Core.Enums.OperateTypeEnum.èªå¨å é¤); |
| | | } |
| | | |
| | | outboundOrderDetails.FirstOrDefault().OrderDetailStatus = (int)OrderDetailStatusEnum.Over; |
| | | _detailRepository.UpdateData(outboundOrderDetails); |
| | | } |
| | | |
| | | // æ£æ¥åºåºåæ¯å¦å®æ |
| | | if (CheckOutboundOrderCompleted(request.OrderNo)) |
| | | { |
| | |
| | | _stockDetailHistoryRepository.AddData(historyRecords); |
| | | |
| | | // å é¤åºåæç»è®°å½ |
| | | _stockDetailRepository.DeleteData(stockInfo.Details); |
| | | var orderNo =_outboundRepository.QueryFirst(x => x.OrderNo == request.OrderNo); |
| | | if(orderNo.OrderType != 117) |
| | | { |
| | | _stockDetailRepository.DeleteData(stockInfo.Details); |
| | | } |
| | | _stockChangeRepository.AddData(changeRecords); |
| | | } |
| | | |
| | | |
| | | #endregion |
| | | |
| | | #region æ£é |
| | |
| | | { |
| | | barcodeQuantity = item.LockQuantity - item.OverOutQuantity; |
| | | allocatedQuantity -= (item.LockQuantity - item.OverOutQuantity); |
| | | if (item.ReturnToMESStatus == 0) |
| | | { |
| | | item.CurrentDeliveryQty = item.LockQuantity; |
| | | } |
| | | else |
| | | { |
| | | item.CurrentDeliveryQty += item.LockQuantity - item.OverOutQuantity; |
| | | } |
| | | item.OverOutQuantity = item.LockQuantity; |
| | | item.CurrentDeliveryQty = item.LockQuantity; |
| | | } |
| | | |
| | | if (item.OverOutQuantity == item.OrderQuantity) |
| | | { |
| | | item.OrderDetailStatus = (int)OrderDetailStatusEnum.Over; |
| | | } |
| | | updateDetails.Add(item); |
| | | |
| | | List<Barcodes> barcodesList = new List<Barcodes>(); |
| | |
| | | _feedbackMesService.BarcodeFeedback(newBarcode); |
| | | } |
| | | |
| | | if (CheckOutboundOrderDetailCompletedByMatCode(request.OrderNo, lockInfo.MaterielCode, outboundOrderDetails.First())) |
| | | if (CheckOutboundOrderDetailCompletedByMatCode(request.OrderNo, lockInfo.MaterielCode, outboundOrderDetails)) |
| | | { |
| | | Func<Dt_OutStockLockInfo, bool> supWhere = x => string.IsNullOrEmpty(outboundOrderDetails.First().SupplyCode) ? true : x.SupplyCode == outboundOrderDetails.First().SupplyCode; |
| | | |
| | |
| | | // æ£æ¥åºåºåæ¯å¦å®æ |
| | | if (CheckOutboundOrderCompleted(request.OrderNo)) |
| | | { |
| | | UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.åºåºå®æ.ObjToInt()); |
| | | |
| | | if (outboundOrder.OrderType != OutOrderTypeEnum.InternalAllocat.ObjToInt() && outboundOrder.CreateType!=OrderCreateTypeEnum.CreateInSystem.ObjToInt()) |
| | | if(outboundOrder.OrderType != OutOrderTypeEnum.InternalAllocat.ObjToInt()) |
| | | { |
| | | _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo); |
| | | UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.åºåºå®æ.ObjToInt()); |
| | | |
| | | if (outboundOrder.CreateType != OrderCreateTypeEnum.CreateInSystem.ObjToInt()) |
| | | { |
| | | _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | OperateType = "åºåºå®æ", |
| | | InsertTime = DateTime.Now, |
| | | StockId = stockDetail.StockId, |
| | | Barcode = stockDetail.Barcode, |
| | | MaterielCode = stockDetail.MaterielCode, |
| | | MaterielName = stockDetail.MaterielName, |
| | | OrderNo = stockDetail.OrderNo, |
| | |
| | | Creater = stockDetail.Creater, |
| | | CreateDate = stockDetail.CreateDate, |
| | | WarehouseCode = stockDetail.WarehouseCode, |
| | | ValidDate = stockDetail.ValidDate, |
| | | Remark = $"åºåºå®æå é¤ï¼æ¡ç ï¼{request.Barcode}ï¼åæ°éï¼{stockDetail.StockQuantity}ï¼åºåºæ°éï¼{actualOutboundQuantity}ï¼æä½è
ï¼{request.Operator}" |
| | | }; |
| | | _stockDetailHistoryRepository.AddData(historyRecord); |
| | |
| | | /// <summary> |
| | | /// æ£æ¥åºåºåæç»æ¯å¦å®æ |
| | | /// </summary> |
| | | public bool CheckOutboundOrderDetailCompletedByMatCode(string orderNo, string materialCode, Dt_OutboundOrderDetail outboundOrderDetail) |
| | | public bool CheckOutboundOrderDetailCompletedByMatCode(string orderNo, string materialCode, List<Dt_OutboundOrderDetail> outboundOrderDetails) |
| | | { |
| | | if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(materialCode) || outboundOrderDetails == null || !outboundOrderDetails.Any()) |
| | | return false; |
| | | |
| | | // æ¥è¯¢ä¸»è®¢åï¼ä¸åå¨ç´æ¥è¿åfalse |
| | | Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(x => x.OrderNo == orderNo); |
| | | if (outboundOrder == null) return false; |
| | | |
| | | List<Dt_OutboundOrderDetail> details = _detailRepository.QueryData(x => x.OrderId == outboundOrder.Id && x.MaterielCode == materialCode && (string.IsNullOrEmpty(outboundOrderDetail.SupplyCode) || x.SupplyCode == outboundOrderDetail.SupplyCode) && (string.IsNullOrEmpty(outboundOrderDetail.WarehouseCode) || x.WarehouseCode == outboundOrderDetail.WarehouseCode)); |
| | | var firstDetail = outboundOrderDetails.FirstOrDefault(); |
| | | string supplyCode = firstDetail.SupplyCode; |
| | | string warehouseCode = firstDetail.WarehouseCode; |
| | | List<int> ids = outboundOrderDetails.Select(x => x.Id).ToList(); |
| | | |
| | | // æ£æ¥æææç»çå·²åºæ°éæ¯å¦é½çäºåæ®æ°é |
| | | List<Dt_OutboundOrderDetail> details = _detailRepository.QueryData(x => |
| | | x.OrderId == outboundOrder.Id |
| | | && x.MaterielCode == materialCode |
| | | && ids.Contains(x.Id) |
| | | && (string.IsNullOrEmpty(supplyCode) || x.SupplyCode == supplyCode) |
| | | && (string.IsNullOrEmpty(warehouseCode) || x.WarehouseCode == warehouseCode) |
| | | ); |
| | | |
| | | if (!details.Any()) return false; |
| | | |
| | | return details.All(x => x.OverOutQuantity >= x.OrderQuantity - x.MoveQty); |
| | | } |
| | | |
| | |
| | | if (stock.Details.Count <= 0) |
| | | { |
| | | stock.PalletType = (int)PalletTypeEnum.Empty; |
| | | stock.StockStatus = (int)StockStatusEmun.ç»çæå; |
| | | stock.StockStatus = (int)StockStatusEmun.å
¥åºç¡®è®¤; |
| | | stock.LocationCode = ""; |
| | | } |
| | | else if (stock.Details.Count > 0) |
| | | { |
| | | Dt_OutStockLockInfo lockInfo = _outboundLockInfoRepository.QueryFirst(x => |
| | | x.OrderNo == OrderNo && |
| | | x.StockId == stock.Id && |
| | | x.PalletCode == palletCode); |
| | | |
| | | if (lockInfo != null && lockInfo.SortedQuantity != lockInfo.AssignQuantity) |
| | | { |
| | | return content.Error($"æç{palletCode}åºåæªæ£éå®ä¸å
许ååº"); |
| | | // 1. 计ç®éè¦åæ»çæ»æ°é |
| | | decimal? rollbackTotalQuantity = lockInfo.AssignQuantity - lockInfo.SortedQuantity; |
| | | // ç¡®ä¿åæ»æ°éä¸ºæ£æ° |
| | | if (rollbackTotalQuantity <= 0) |
| | | { |
| | | // 没æéè¦åæ»çæ°é |
| | | stock.StockStatus = (int)StockStatusEmun.å
¥åºç¡®è®¤; |
| | | stock.LocationCode = ""; |
| | | } |
| | | |
| | | try |
| | | { |
| | | //å¤çOrderDetailIdsï¼åå²å¹¶è½¬æ¢ä¸ºIDå表 |
| | | List<long> orderDetailIds = new List<long>(); |
| | | if (!string.IsNullOrEmpty(lockInfo.OrderDetailIds)) |
| | | { |
| | | orderDetailIds = lockInfo.OrderDetailIds.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) |
| | | .Select(id => |
| | | { |
| | | if (long.TryParse(id.Trim(), out long result)) |
| | | { |
| | | return result; |
| | | } |
| | | return 0; // æ æIDæ 记为0 |
| | | }) |
| | | .Where(id => id > 0) |
| | | .OrderByDescending(id => id) |
| | | .ToList(); |
| | | } |
| | | |
| | | if (orderDetailIds.Count == 0) |
| | | { |
| | | return WebResponseContent.Instance.Error("åæ®éå®åºåºåæç»Idæ æï¼æ£æ¥éå®åºåºæ°æ®æ¯å¦æ£ç¡®"); |
| | | } |
| | | |
| | | //æ¥è¯¢å¯¹åºç订åæç» |
| | | List<Dt_OutboundOrderDetail> orderDetails = _outboundRepository.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .Where(x => orderDetailIds.Contains(x.Id)) |
| | | .ToList(); |
| | | |
| | | if (orderDetails.Count == 0) |
| | | { |
| | | return WebResponseContent.Instance.Error("æªæ¾å°å¯åæ»æç»ï¼è¯·æ£æ¥åºåºåæç»"); |
| | | } |
| | | |
| | | decimal remainingRollbackQty = (decimal)rollbackTotalQuantity; |
| | | foreach (var detail in orderDetails) |
| | | { |
| | | if (remainingRollbackQty <= 0) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | // 计ç®è¯¥æç»çå¯åæ»æ°é |
| | | decimal availableRollbackQty = detail.LockQuantity - detail.OverOutQuantity - detail.MoveQty; |
| | | |
| | | availableRollbackQty = Math.Max(0, availableRollbackQty); |
| | | |
| | | if (availableRollbackQty <= 0) |
| | | { |
| | | continue; // 该æç»æ å¯åæ»æ°éï¼è·³è¿ |
| | | } |
| | | |
| | | // è®¡ç®æ¬æ¬¡å®é
åæ»æ°éï¼åå¯åæ»æ°éåå©ä½éè¦åæ»æ°éçè¾å°å¼ï¼ |
| | | decimal actualRollbackQty = Math.Min(availableRollbackQty, remainingRollbackQty); |
| | | |
| | | detail.LockQuantity -= actualRollbackQty; |
| | | detail.LockQuantity = Math.Max(0, detail.LockQuantity); |
| | | |
| | | _detailRepository.UpdateData(detail); |
| | | |
| | | //æ´æ°å©ä½éè¦åæ»çæ°é |
| | | remainingRollbackQty -= actualRollbackQty; |
| | | } |
| | | |
| | | if (remainingRollbackQty > 0) |
| | | { |
| | | return WebResponseContent.Instance.Error($"å©ä½åæ»æ°é{remainingRollbackQty}"); |
| | | } |
| | | _outboundLockInfoRepository.DeleteAndMoveIntoHty(lockInfo, WIDESEA_Core.Enums.OperateTypeEnum.人工å é¤); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | } |
| | | stock.StockStatus = (int)StockStatusEmun.ç»çæå; |
| | | |
| | | stock.StockStatus = (int)StockStatusEmun.å
¥åºç¡®è®¤; |
| | | stock.LocationCode = ""; |
| | | } |
| | | |
| | |
| | | |
| | | // åé
æ°è´§ä½ |
| | | var newLocation = _locationInfoService.AssignLocation(stock.LocationType); |
| | | |
| | | if(newLocation == null) |
| | | { |
| | | return WebResponseContent.Instance.Error("没æç©ºé²åºä½å¯ååº"); |
| | | } |
| | | |
| | | var newTask = new Dt_Task() |
| | | { |
| | |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æ¤éæ£é |
| | | /// <summary> |
| | | /// æ¤éæ£éæ¡ç ï¼åååæ»åºåºæ£éæä½ï¼ |
| | | /// </summary> |
| | | /// <param name="request">æ¤éæ£é请æ±ï¼è³å°å
嫿¡ç ã订åå·ãæçå·ï¼</param> |
| | | /// <returns>æ¤éååº</returns> |
| | | public WebResponseContent ReversePicking(ReversePickingRequestDTO request) |
| | | { |
| | | WebResponseContent content = WebResponseContent.Instance; |
| | | ReversePickingResponseDTO response = new ReversePickingResponseDTO(); |
| | | |
| | | try |
| | | { |
| | | if (string.IsNullOrWhiteSpace(request.Barcode) || string.IsNullOrWhiteSpace(request.OrderNo) || string.IsNullOrWhiteSpace(request.PalletCode)) |
| | | { |
| | | response.Success = false; |
| | | response.Message = "æ¡ç ã订åå·ãæçå·ä¸è½ä¸ºç©º"; |
| | | return WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | | Dt_StockInfo stockInfo = _stockInfoRepository.QueryFirst(x => x.PalletCode == request.PalletCode); |
| | | if (stockInfo == null) |
| | | { |
| | | response.Success = false; |
| | | response.Message = $"æçå· {request.PalletCode} 对åºçåºåä¸åå¨"; |
| | | return WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | | 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_Hty historyDetail = _stockDetailHistoryRepository.QueryFirst(x => |
| | | x.Barcode == request.Barcode && |
| | | |
| | | (x.OperateType == "åºåºå®æ" || x.OperateType == "æå
-åå§è®°å½")); |
| | | |
| | | if(historyDetail != null) |
| | | { |
| | | double minutesDiff = (DateTime.Now - historyDetail.InsertTime).TotalMinutes; |
| | | if (minutesDiff >= 30) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æ¡ç {request.Barcode}å·²æ æ³æ¤é"); |
| | | } |
| | | } |
| | | |
| | | Dt_OutStockLockInfo lockInfo = _outboundLockInfoRepository.QueryFirst(x => |
| | | x.OrderNo == request.OrderNo && |
| | | x.StockId == stockInfo.Id && |
| | | x.MaterielCode == historyDetail.MaterielCode && |
| | | x.PalletCode == stockInfo.PalletCode); |
| | | |
| | | _unitOfWorkManage.BeginTran(); |
| | | try |
| | | { |
| | | if(lockInfo == null) |
| | | { |
| | | return WebResponseContent.Instance.Error("该æçå·²å
¨é¨æ£éå®,ä¸å
许æ¤é"); |
| | | } |
| | | bool isUnpack = historyDetail.OperateType == "æå
-åå§è®°å½"; |
| | | if (isUnpack) |
| | | { |
| | | return WebResponseContent.Instance.Error("该æ¡ç å·²æå
ï¼ä¸å
许æ¤é"); |
| | | } |
| | | else |
| | | { |
| | | ReverseFullOutboundOperation(historyDetail, stockInfo, request); |
| | | } |
| | | RollbackOutboundOrderDetails(historyDetail.MaterielCode, request.OrderNo, historyDetail.StockQuantity, stockInfo.Id); |
| | | |
| | | if (lockInfo != null) |
| | | { |
| | | lockInfo.SortedQuantity = Math.Max(0, (decimal)(lockInfo.SortedQuantity - historyDetail.StockQuantity)); |
| | | |
| | | if (lockInfo.SortedQuantity == 0) |
| | | { |
| | | _outboundLockInfoRepository.UpdateData(lockInfo); |
| | | } |
| | | else |
| | | { |
| | | _outboundLockInfoRepository.UpdateData(lockInfo); |
| | | } |
| | | } |
| | | |
| | | _stockDetailHistoryRepository.DeleteData(historyDetail); |
| | | |
| | | DeleteStockChangeRecord(request.Barcode, request.OrderNo); |
| | | |
| | | if (!CheckOutboundOrderCompleted(request.OrderNo)) |
| | | { |
| | | UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.åºåºä¸.ObjToInt()); |
| | | } |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | response.Success = true; |
| | | response.Message = $"æ¡ç {request.Barcode} æ¤éæ£éæå"; |
| | | response.Barcode = request.Barcode; |
| | | response.RestoredQuantity = historyDetail.StockQuantity; |
| | | |
| | | content = WebResponseContent.Instance.OK(data: response); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | response.Success = false; |
| | | response.Message = $"æ¤éæ£é失败ï¼{ex.Message}"; |
| | | content = WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | response.Success = false; |
| | | response.Message = $"å¤çæ¤éæ£é失败ï¼{ex.Message}"; |
| | | content = WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | | return content; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¤éæå
åºåºæä½ï¼å忢夿å
åç¶æï¼ |
| | | /// </summary> |
| | | private void ReverseUnpackOperation(Dt_StockInfoDetail_Hty historyDetail, Dt_StockInfo stockInfo, ReversePickingRequestDTO request, Dt_OutboundOrder outboundOrder) |
| | | { |
| | | Dt_StockInfoDetail currentDetail = _stockDetailRepository.QueryFirst(x => |
| | | x.Barcode == request.Barcode && |
| | | x.StockId == stockInfo.Id && |
| | | x.MaterielCode == historyDetail.MaterielCode); |
| | | |
| | | if (currentDetail != null) |
| | | { |
| | | currentDetail.StockQuantity = historyDetail.StockQuantity; |
| | | currentDetail.Remark = $"æ¤éæå
æ£éï¼æ¢å¤åå§æ°éï¼{historyDetail.StockQuantity}ï¼æä½è
ï¼{request.Operator}"; |
| | | _stockDetailRepository.UpdateData(currentDetail); |
| | | } |
| | | else |
| | | { |
| | | Dt_StockInfoDetail restoreDetail = new Dt_StockInfoDetail |
| | | { |
| | | StockId = historyDetail.StockId, |
| | | MaterielCode = historyDetail.MaterielCode, |
| | | MaterielName = historyDetail.MaterielName, |
| | | Barcode =historyDetail.Barcode, |
| | | OrderNo = historyDetail.OrderNo, |
| | | BatchNo = historyDetail.BatchNo, |
| | | ProductionDate = historyDetail.ProductionDate, |
| | | EffectiveDate = historyDetail.EffectiveDate, |
| | | SerialNumber = historyDetail.SerialNumber, |
| | | StockQuantity = historyDetail.StockQuantity, |
| | | OutboundQuantity = historyDetail.OutboundQuantity, |
| | | Status = historyDetail.Status, |
| | | Unit = historyDetail.Unit, |
| | | InboundOrderRowNo = historyDetail.InboundOrderRowNo, |
| | | SupplyCode = historyDetail.SupplyCode, |
| | | Creater = request.Operator, |
| | | CreateDate = DateTime.Now, |
| | | FactoryArea = historyDetail.FactoryArea, |
| | | WarehouseCode = historyDetail.WarehouseCode, |
| | | Remark = $"æ¤éæå
æ£éï¼éæ°å建åºåæç»ï¼æ¡ç ï¼{request.Barcode}ï¼æä½è
ï¼{request.Operator}" |
| | | }; |
| | | _stockDetailRepository.AddData(restoreDetail); |
| | | } |
| | | |
| | | List<Dt_MaterialCodeInfo> materialCodeInfos = _basicService.MaterielCodeInfoService.Repository.QueryData(x => |
| | | x.OldBarcode == request.Barcode && |
| | | x.OrderNo == request.OrderNo); |
| | | if (materialCodeInfos.Any()) |
| | | { |
| | | _basicService.MaterielCodeInfoService.Repository.DeleteData(materialCodeInfos); |
| | | } |
| | | |
| | | if (outboundOrder.OrderType == InOrderTypeEnum.InternalAllocat.ObjToInt()) |
| | | { |
| | | Dt_AllocateMaterialInfo allocateMaterialInfo = _allocateMaterialInfoRepository.QueryFirst(x => |
| | | x.Barcode == request.Barcode && |
| | | x.OrderNo == request.OrderNo); |
| | | if (allocateMaterialInfo != null) |
| | | { |
| | | _allocateMaterialInfoRepository.DeleteData(allocateMaterialInfo); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¤é宿´åºåºæä½ï¼æ¢å¤è¢«å é¤çåºåæç»ï¼ |
| | | /// </summary> |
| | | private void ReverseFullOutboundOperation(Dt_StockInfoDetail_Hty historyDetail, Dt_StockInfo stockInfo, ReversePickingRequestDTO request) |
| | | { |
| | | Dt_StockInfoDetail restoreDetail = new Dt_StockInfoDetail |
| | | { |
| | | |
| | | StockId = historyDetail.StockId, |
| | | MaterielCode = historyDetail.MaterielCode, |
| | | MaterielName = historyDetail.MaterielName, |
| | | Barcode = historyDetail.Barcode, |
| | | OrderNo = historyDetail.OrderNo, |
| | | BatchNo = historyDetail.BatchNo, |
| | | ProductionDate = historyDetail.ProductionDate, |
| | | EffectiveDate = historyDetail.EffectiveDate, |
| | | SerialNumber = historyDetail.SerialNumber, |
| | | StockQuantity = historyDetail.StockQuantity, |
| | | OutboundQuantity = historyDetail.OutboundQuantity - historyDetail.StockQuantity, |
| | | Status = historyDetail.Status, |
| | | Unit = historyDetail.Unit, |
| | | InboundOrderRowNo = historyDetail.InboundOrderRowNo, |
| | | SupplyCode = historyDetail.SupplyCode, |
| | | Creater = request.Operator, |
| | | CreateDate = DateTime.Now, |
| | | FactoryArea = historyDetail.FactoryArea, |
| | | WarehouseCode = historyDetail.WarehouseCode, |
| | | Remark = $"æ¤é宿´åºåºæ£éï¼æ¢å¤åºåæç»ï¼æ¡ç ï¼{request.Barcode}ï¼æä½è
ï¼{request.Operator}" |
| | | }; |
| | | |
| | | _stockDetailRepository.AddData(restoreDetail); |
| | | |
| | | if (request.OrderType == InOrderTypeEnum.InternalAllocat.ObjToInt()) |
| | | { |
| | | Dt_AllocateMaterialInfo allocateMaterialInfo = _allocateMaterialInfoRepository.QueryFirst(x => |
| | | x.Barcode == request.Barcode && |
| | | x.OrderNo == request.OrderNo); |
| | | if (allocateMaterialInfo != null) |
| | | { |
| | | _allocateMaterialInfoRepository.DeleteData(allocateMaterialInfo); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åæ»åºåºåæç»ï¼æ£åå·²åºåºæ°éï¼ |
| | | /// </summary> |
| | | private void RollbackOutboundOrderDetails(string materielCode, string orderNo, decimal rollbackQuantity, int stockId) |
| | | { |
| | | Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(x => x.OrderNo == orderNo); |
| | | List<Dt_OutboundOrderDetail> details = _detailRepository.QueryData(x => |
| | | x.OrderId == outboundOrder.Id && |
| | | x.MaterielCode == materielCode && |
| | | x.OverOutQuantity > 0); |
| | | |
| | | if (!details.Any()) return; |
| | | |
| | | decimal remainingRollbackQty = rollbackQuantity; |
| | | foreach (var detail in details) |
| | | { |
| | | if (remainingRollbackQty <= 0) break; |
| | | |
| | | decimal rollbackQty = Math.Min(remainingRollbackQty, detail.OverOutQuantity); |
| | | |
| | | detail.OverOutQuantity -= rollbackQty; |
| | | detail.CurrentDeliveryQty -= rollbackQty; |
| | | |
| | | if (detail.OrderDetailStatus == (int)OrderDetailStatusEnum.Over && detail.OverOutQuantity < detail.OrderQuantity - detail.MoveQty) |
| | | { |
| | | detail.OrderDetailStatus = (int)OrderDetailStatusEnum.New; |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(detail.ReturnJsonData)) |
| | | { |
| | | List<Barcodes> barcodesList = JsonConvert.DeserializeObject<List<Barcodes>>(detail.ReturnJsonData) ?? new List<Barcodes>(); |
| | | var targetBarcode = barcodesList.FirstOrDefault(x => x.Barcode == materielCode); |
| | | if (targetBarcode != null) |
| | | { |
| | | barcodesList.Remove(targetBarcode); |
| | | detail.ReturnJsonData = JsonConvert.SerializeObject(barcodesList, new JsonSerializerSettings |
| | | { |
| | | ContractResolver = new CamelCasePropertyNamesContractResolver() |
| | | }); |
| | | } |
| | | } |
| | | |
| | | _detailRepository.UpdateData(detail); |
| | | remainingRollbackQty -= rollbackQty; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å é¤åºååå¨è®°å½ï¼æ£éæ¶çæçï¼ |
| | | /// </summary> |
| | | private void DeleteStockChangeRecord(string barcode, string orderNo) |
| | | { |
| | | Dt_StockQuantityChangeRecord changeRecord = _stockChangeRepository.QueryFirst(x => |
| | | x.OriginalSerilNumber == barcode && |
| | | x.OrderNo == orderNo && |
| | | x.ChangeType == (int)StockChangeTypeEnum.Outbound); |
| | | if (changeRecord != null) |
| | | { |
| | | _stockChangeRepository.DeleteData(changeRecord); |
| | | } |
| | | } |
| | | |
| | | |
| | | #endregion |
| | | |
| | | |
| | | } |
| | | } |