| | |
| | | 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_Core.BaseRepository; |
| | | using WIDESEA_Core.CodeConfigEnum; |
| | | using WIDESEA_Core.Helper; |
| | | 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; |
| | | |
| | | namespace WIDESEA_OutboundService |
| | |
| | | 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 åºåºåé
|
| | |
| | | public WebResponseContent ProcessPickingOutbound(PickingOutboundRequestDTO request) |
| | | { |
| | | WebResponseContent content = WebResponseContent.Instance; |
| | | |
| | | 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 |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | // 1. 计ç®åºåºæ°éé»è¾ |
| | | OutboundCalculationDTO calculationResult = CalcOutboundQuantity(request); |
| | | |
| | | if (!calculationResult.CanOutbound) |
| | | { |
| | | content = WebResponseContent.Instance.Error("æ æ³å¤çæ£è´§åºåºï¼" + calculationResult.ErrorMessage); |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return content; |
| | | } |
| | | // è®°å½æ»éæ±æ°é |
| | | totalNeedAllocate = calculationResult.MaterielCalculations.Sum(x => x.UnallocatedQuantity); |
| | | |
| | | // 2. è°ç¨åºåºå¤çé»è¾ï¼éå®åºåï¼çæåºåºè®°å½ç |
| | | |
| | | // 2. å¤çç©æåé
|
| | | List<PickedStockDetailDTO> pickedDetails = new List<PickedStockDetailDTO>(); |
| | | |
| | | // è·ååºåºåä¿¡æ¯ |
| | | Dt_OutboundOrder outboundOrder = calculationResult.OutboundOrder; |
| | | |
| | | // åºåºè¯¦æ
æ·»å æä¿®æ¹éå |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>(); |
| | | |
| | | List<Dt_OutboundOrderDetail> outboundOrderDetails = new(); |
| | | |
| | | List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>(); |
| | | List<Dt_Task> tasks = new List<Dt_Task>(); |
| | | |
| | | foreach (var materielCalc in calculationResult.MaterielCalculations) |
| | | { |
| | | (List<PickedStockDetailDTO> PickedDetails, List<Dt_Task> Tasks, List<Dt_OutStockLockInfo> OutStockLockInfo) materielPickedDetails = ProcessMaterielTaskGeneration(outboundOrder, materielCalc, request, calculationResult.FactoryArea); |
| | | var materielPickedDetails = ProcessMaterielTaskGeneration(outboundOrder, materielCalc, request, calculationResult.FactoryArea); |
| | | // 计ç®å½åç©æå®é
åé
é |
| | | decimal actualAllocatedQuantity = materielPickedDetails.PickedDetails.Sum(x => x.OutboundQuantity); |
| | | actualAllocatedQuantity = Math.Min(actualAllocatedQuantity, materielCalc.UnallocatedQuantity); |
| | | totalActualAllocate += actualAllocatedQuantity; // ç´¯å è³æ»å®é
åé
é |
| | | materielCalc.UnallocatedQuantity = materielCalc.UnallocatedQuantity - actualAllocatedQuantity; |
| | | |
| | | // å¤çåºåºéå®è®°å½ |
| | | foreach (var item in materielPickedDetails.OutStockLockInfo) |
| | | { |
| | | Dt_OutStockLockInfo? outStockLockInfo = materielCalc.OutStockLockInfos.FirstOrDefault(x => x.Id == item.Id && x.Id > 0); |
| | | if (outStockLockInfo != null) |
| | | Dt_OutStockLockInfo? existLockInfo = materielCalc.OutStockLockInfos.FirstOrDefault(x => x.Id == item.Id && x.Id > 0); |
| | | if (existLockInfo != null) |
| | | { |
| | | outStockLockInfo = item; |
| | | existLockInfo = item; |
| | | Dt_Task? task = tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode); |
| | | if (task != null) |
| | | { |
| | | outStockLockInfo.TaskNum = task.TaskNum; |
| | | } |
| | | if (task != null) existLockInfo.TaskNum = task.TaskNum; |
| | | } |
| | | else |
| | | { |
| | | Dt_Task? task = tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode); |
| | | if (task != null) |
| | | { |
| | | item.TaskNum = task.TaskNum; |
| | | } |
| | | if (task != null) item.TaskNum = task.TaskNum; |
| | | 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) |
| | | { |
| | | Dt_Task? task = tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode); |
| | | if (task == null) |
| | | if (outboundOrder.OrderType == 117 |
| | | && palletIsWholeCaseMap.ContainsKey(item.PalletCode) |
| | | && palletIsWholeCaseMap[item.PalletCode] |
| | | && palletLocationMap.ContainsKey(item.PalletCode)) |
| | | { |
| | | tasks.Add(item); |
| | | item.TaskType = (int)TaskTypeEnum.Relocation; |
| | | item.TargetAddress = palletLocationMap[item.PalletCode]; |
| | | } |
| | | if (tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode) == null) |
| | | tasks.Add(item); |
| | | } |
| | | |
| | | // æ±æ»åæ£æç» |
| | | pickedDetails.AddRange(materielPickedDetails.PickedDetails); |
| | | |
| | | decimal allallocatedQuantity = Math.Min(materielCalc.UnallocatedQuantity, materielPickedDetails.PickedDetails.Sum(x => x.OutboundQuantity)); |
| | | materielCalc.UnallocatedQuantity = allallocatedQuantity; |
| | | // æ´æ°åºåºåæç»ï¼å¢å é宿°éï¼ä¸å¢å å·²åºæ°éï¼ |
| | | // æå®é
åé
éæ´æ°åæ®é宿°é |
| | | decimal remainingToLock = actualAllocatedQuantity; |
| | | foreach (var detail in materielCalc.Details) |
| | | { |
| | | if (allallocatedQuantity <= 0) break; |
| | | if (remainingToLock <= 0) break; |
| | | decimal maxLockableQty = detail.OrderQuantity - detail.OverOutQuantity-detail.LockQuantity; |
| | | if (maxLockableQty <= 0) continue; |
| | | decimal currentLockQty = Math.Min(remainingToLock, maxLockableQty); |
| | | detail.LockQuantity += currentLockQty; |
| | | outboundOrderDetails.Add(detail); |
| | | remainingToLock -= currentLockQty; |
| | | } |
| | | } |
| | | |
| | | decimal lockQuantity = (detail.OrderQuantity - detail.OverOutQuantity); |
| | | if (lockQuantity < materielCalc.UnallocatedQuantity) |
| | | // 3. æ¹éæ´æ°ç¶æï¼åæé»è¾ä¸åï¼ |
| | | UpdateOutboundOrderStatus(request.OrderNo, (int)OutOrderStatusEnum.åºåºä¸); |
| | | _detailRepository.UpdateData(outboundOrderDetails); |
| | | if (pickedDetails.Any()) |
| | | { |
| | | UpdateStockStatus(pickedDetails.Select(x => x.PalletCode).ToList(), StockStatusEmun.åºåºéå®.ObjToInt()); |
| | | UpdateLocationStatus(pickedDetails.Select(x => x.LocationCode).ToList(), LocationStatusEnum.Lock.ObjToInt()); |
| | | } |
| | | //鿣å䏿£éï¼å»æéå®è®°å½ååºï¼å次ç»çæ¶æ£é¤åæ¡ç |
| | | if (outboundOrder.OrderType != InOrderTypeEnum.ReCheck.ObjToInt()) |
| | | { |
| | | UpdateOutStockLockInfo(outStockLockInfos); |
| | | } |
| | | |
| | | if (tasks.Any()) _taskRepository.AddData(tasks); |
| | | |
| | | if (outboundOrder.OrderType == 117 && wholeCasePallets.Any()) |
| | | { |
| | | foreach (var palletCode in wholeCasePallets) |
| | | { |
| | | var completeReq = new OutboundCompletePalletRequestDTO |
| | | { |
| | | detail.LockQuantity += lockQuantity; // å¢å é宿°é 䏿´æ° OverOutQuantity å OrderDetailStatusï¼å ä¸ºè¿æ²¡æå®é
åºåº |
| | | outboundOrderDetails.Add(detail); |
| | | materielCalc.UnallocatedQuantity -= lockQuantity; |
| | | } |
| | | else |
| | | OrderNo = request.OrderNo, |
| | | PalletCode = palletCode |
| | | }; |
| | | |
| | | var res = CompleteOutboundWithPallet(completeReq); |
| | | if (!res.Status) |
| | | { |
| | | detail.LockQuantity += materielCalc.UnallocatedQuantity; |
| | | outboundOrderDetails.Add(detail); |
| | | break; |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return res; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 3. æ´æ°åºåºåç¶æä¸ºåºåºä¸ï¼è¡¨ç¤ºå·²æä»»å¡åé
ï¼ |
| | | UpdateOutboundOrderStatus(request.OrderNo, (int)OutOrderStatusEnum.åºåºä¸); |
| | | |
| | | // 4. æ´æ°åºåºåæç»é宿°é |
| | | _detailRepository.UpdateData(outboundOrderDetails); |
| | | |
| | | // 5. æ´æ°åºåç¶æ |
| | | UpdateStockStatus(pickedDetails.Select(x => x.PalletCode).ToList(), StockStatusEmun.åºåºéå®.ObjToInt()); |
| | | |
| | | // 6. æ´æ°è´§ä½ç¶æ |
| | | UpdateLocationStatus(pickedDetails.Select(x => x.LocationCode).ToList(), LocationStatusEnum.Lock.ObjToInt()); |
| | | |
| | | // 7. æ´æ°åºå详æ
|
| | | UpdateOutStockLockInfo(outStockLockInfos); |
| | | |
| | | // 8. æ·»å 任塿°æ® |
| | | _taskRepository.AddData(tasks); |
| | | |
| | | _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 = "忣任å¡åé
æå"; |
| | | response.Tasks = tasks; // è¿å第ä¸ä¸ªä»»å¡å· |
| | | response.PickedDetails = pickedDetails; // è¿å第ä¸ä¸ªåæ£æç» |
| | | content = WebResponseContent.Instance.OK("忣任å¡åé
æå", response); |
| | | return content; |
| | | response.Message = responseMsg; |
| | | response.Tasks = tasks; |
| | | response.PickedDetails = pickedDetails; |
| | | content = WebResponseContent.Instance.OK(responseMsg, response); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | |
| | | content = WebResponseContent.Instance.Error("å¤çæ£è´§åºåºå¤±è´¥ï¼" + ex.Message); |
| | | } |
| | | return content; |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 计ç®åºåºæ°éé»è¾ |
| | | /// æ ¹æ®åæ®å·è·åç®æ ä»åº |
| | | /// </summary> |
| | | /// <param name="request"></param> |
| | | /// <param name="orderNo"></param> |
| | | /// <returns></returns> |
| | | public String GetToWarehouseByOrderNo(string orderNo) |
| | | { |
| | | var order =_allocateOrderRepository.QueryFirst(x => x.OrderNo == orderNo); |
| | | return order.ToWarehouse; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 计ç®åºåºæ°éé»è¾ï¼åæé»è¾ä¸åï¼ |
| | | /// </summary> |
| | | public OutboundCalculationDTO CalcOutboundQuantity(PickingOutboundRequestDTO request) |
| | | { |
| | | OutboundCalculationDTO result = new(); |
| | | |
| | | OutboundCalculationDTO result = new OutboundCalculationDTO(); |
| | | try |
| | | { |
| | | Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(x => x.OrderNo == request.OrderNo); |
| | |
| | | |
| | | result.FactoryArea = outboundOrder.FactoryArea; |
| | | List<Dt_OutboundOrderDetail> selectedDetails = new List<Dt_OutboundOrderDetail>(); |
| | | |
| | | if(request.DetailIds == null || !request.DetailIds.Any()) |
| | | if (request.DetailIds == null || !request.DetailIds.Any()) |
| | | { |
| | | selectedDetails = _detailRepository.QueryData(x => x.OrderId == outboundOrder.Id); |
| | | } |
| | | else |
| | | { |
| | | // è·åéæ©çåºåºæç» |
| | | selectedDetails = _detailRepository.QueryData(x => x.OrderId == outboundOrder.Id && request.DetailIds.Contains(x.Id)); |
| | | selectedDetails = _detailRepository.QueryData(x => x.OrderId == outboundOrder.Id && request.DetailIds.Contains(x.Id)); |
| | | } |
| | | |
| | | |
| | | //if (outboundOrder.IsBatch == 1 && request.DetailIds.Count == 1) |
| | | //{ |
| | | // selectedDetails = _detailRepository.QueryData(x => x.OrderId == selectedDetails.First().OrderId && x.WarehouseCode == selectedDetails.First().WarehouseCode && x.MaterielCode == selectedDetails.First().MaterielCode && x.BatchNo == selectedDetails.First().BatchNo && x.SupplyCode == selectedDetails.First().SupplyCode); |
| | | //} |
| | | |
| | | |
| | | if (!selectedDetails.Any()) |
| | | { |
| | |
| | | if (selectedDetails.Any(x => x.LockQuantity > x.OrderQuantity - x.MoveQty || x.OverOutQuantity > x.OrderQuantity - x.MoveQty)) |
| | | { |
| | | List<int> selectDetailIds = selectedDetails.Where(x => x.LockQuantity > x.OrderQuantity - x.MoveQty || x.OverOutQuantity > x.OrderQuantity - x.MoveQty).Select(x => x.Id).ToList(); |
| | | |
| | | result.CanOutbound = false; |
| | | result.ErrorMessage = $"åºåºæç»ä¿¡æ¯{string.Join(",", selectDetailIds)}å·²åé
宿"; |
| | | return result; |
| | | } |
| | | |
| | | outboundOrder.Details = selectedDetails; |
| | | result.OutboundOrder = outboundOrder; |
| | | result.SelectedDetails = selectedDetails; |
| | | |
| | | if (outboundOrder.IsBatch == 0 || request.DetailIds.Count != 1) |
| | | { |
| | | // 夿ç»åºåºï¼æç©æåç»å¤ç |
| | | result.MaterielCalculations = CalcMaterielOutboundQuantities(outboundOrder, selectedDetails.ToList()); |
| | | } |
| | | else |
| | | { |
| | | // åæç»åºåºï¼éªè¯è¾å
¥çåºåºæ°é |
| | | if (!request.OutboundQuantity.HasValue || request.OutboundQuantity.Value <= 0) |
| | | { |
| | | result.CanOutbound = false; |
| | |
| | | decimal orderQuantity = selectedDetails.Sum(x => x.OrderQuantity); |
| | | decimal moveQuantity = selectedDetails.Sum(x => x.MoveQty); |
| | | decimal overQuantity = selectedDetails.Sum(x => x.OverOutQuantity); |
| | | |
| | | Dt_OutboundOrderDetail? singleDetail = selectedDetails.First(); |
| | | |
| | | //夿å¯åºåºæ°é |
| | | if (orderQuantity - lockQuantity - moveQuantity < request.OutboundQuantity.Value || orderQuantity - overQuantity - moveQuantity < request.OutboundQuantity.Value) |
| | | { |
| | | result.CanOutbound = false; |
| | |
| | | { |
| | | inputQuantity -= (item.OrderQuantity - item.MoveQty - item.LockQuantity); |
| | | outboundOrderDetails.Add(item); |
| | | if (inputQuantity <= 0) |
| | | { |
| | | break; |
| | | } |
| | | if (inputQuantity <= 0) break; |
| | | } |
| | | |
| | | result.MaterielCalculations = new List<MaterielOutboundCalculationDTO>() |
| | |
| | | Details = outboundOrderDetails |
| | | } |
| | | }; |
| | | |
| | | outboundOrder.Details = outboundOrderDetails; |
| | | } |
| | | |
| | | result.CanOutbound = true; |
| | | return result; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | result.CanOutbound = false; |
| | | result.ErrorMessage = ex.Message; |
| | | return result; |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤åºåºåæç»æ¶ï¼æç©æåç»è®¡ç®åºåºæ°é |
| | | /// æç©æåç»è®¡ç®åºåºæ°éï¼åæé»è¾ä¸åï¼ |
| | | /// </summary> |
| | | /// <param name="selectedDetails"></param> |
| | | /// <returns></returns> |
| | | private List<MaterielOutboundCalculationDTO> CalcMaterielOutboundQuantities(Dt_OutboundOrder outboundOrder, List<Dt_OutboundOrderDetail> selectedDetails) |
| | | { |
| | | // æç©æåç»ï¼ç©æç¼å·ãæ¹æ¬¡å·ãä¾åºåç¼å·ãä»åºç¼å· |
| | | List<MaterielOutboundCalculationDTO> materielGroups = selectedDetails |
| | | return selectedDetails |
| | | .GroupBy(x => new |
| | | { |
| | | x.MaterielCode, |
| | |
| | | UnallocatedQuantity = g.Sum(x => x.OrderQuantity - x.LockQuantity - x.MoveQty), |
| | | MovedQuantity = g.Sum(x => x.MoveQty), |
| | | Details = g.ToList(), |
| | | OutStockLockInfos = _outboundLockInfoRepository.QueryData(x => x.MaterielCode == g.Key.MaterielCode && x.BatchNo == g.Key.BatchNo && x.OrderType == (int)outboundOrder.OrderType && x.OrderNo == outboundOrder.OrderNo) |
| | | OutStockLockInfos = _outboundLockInfoRepository.QueryData(x => |
| | | x.MaterielCode == g.Key.MaterielCode && |
| | | x.BatchNo == g.Key.BatchNo && |
| | | x.OrderType == (int)outboundOrder.OrderType && |
| | | x.OrderNo == outboundOrder.OrderNo) |
| | | }) |
| | | .ToList(); |
| | | |
| | | return materielGroups; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çç©æçä»»å¡çæ |
| | | /// å¤çç©æä»»å¡çæï¼æ ¸å¿ï¼æå¤å°åå¤å°+ç§»é¤åºåä¸è¶³å¼å¸¸ï¼ |
| | | /// </summary> |
| | | /// <param name="outboundOrder">åºåºè®¢å</param> |
| | | /// <param name="materielCalc">æç©æçåºåºè®¡ç®ç»æ</param> |
| | | /// <param name="request">忣åºåºè¯·æ±</param> |
| | | /// <param name="factoryArea"></param> |
| | | /// <returns></returns> |
| | | /// <exception cref="Exception"></exception> |
| | | private (List<PickedStockDetailDTO> PickedDetails, List<Dt_Task> Tasks, List<Dt_OutStockLockInfo> OutStockLockInfo) ProcessMaterielTaskGeneration(Dt_OutboundOrder outboundOrder, MaterielOutboundCalculationDTO materielCalc, PickingOutboundRequestDTO request, string factoryArea) |
| | | private (List<PickedStockDetailDTO> PickedDetails, List<Dt_Task> Tasks, List<Dt_OutStockLockInfo> OutStockLockInfo) ProcessMaterielTaskGeneration( |
| | | Dt_OutboundOrder outboundOrder, |
| | | MaterielOutboundCalculationDTO materielCalc, |
| | | PickingOutboundRequestDTO request, |
| | | string factoryArea) |
| | | { |
| | | List<PickedStockDetailDTO> pickedDetails = new List<PickedStockDetailDTO>(); |
| | | List<Dt_Task> generatedTasks = new List<Dt_Task>(); |
| | | |
| | | // æå»ºåºåæ¥è¯¢æ¡ä»¶ï¼å
å«åºå表ãåºåæç»ï¼ |
| | | List<Dt_StockInfo> stockQuery = BuildStockQueryWithInfo(materielCalc, factoryArea); |
| | | |
| | | if (!stockQuery.Any()) |
| | | { |
| | | throw new Exception($"ç©æ {materielCalc.MaterielCode} 对åºçåºåä¸åå¨"); |
| | | } |
| | | |
| | | // æ¹éè®¡ç®æ»å¯ç¨åºåæ°é |
| | | (Dictionary<int, decimal> AvailableStockMap, Dictionary<int, List<Dt_OutStockLockInfo>> LockStockMap) data = GetBatchAvailableStockQuantities(materielCalc, stockQuery); |
| | | |
| | | // å¯ç¨åºåæ°éæ å° |
| | | Dictionary<int, decimal> availableStockMap = data.AvailableStockMap; |
| | | |
| | | // ç©ææ»å¯ç¨åºåæ°é |
| | | decimal totalAvailableStock = availableStockMap.Values.Sum(); |
| | | |
| | | // å·²éå®åºåæ°éæ å° |
| | | Dictionary<int, List<Dt_OutStockLockInfo>> lockStockMap = data.LockStockMap; |
| | | |
| | | // éªè¯æ»å¯ç¨åºåæ¯å¦æ»¡è¶³åºåºéæ± |
| | | //if (totalAvailableStock < materielCalc.UnallocatedQuantity) |
| | | //{ |
| | | // throw new Exception($"ç©æ {materielCalc.MaterielCode} å¯ç¨åºå {totalAvailableStock} ä¸è¶³åºåºæ°é {materielCalc.UnallocatedQuantity}"); |
| | | //} |
| | | // éåé
æ°é |
| | | decimal remainingQuantity = Math.Min(totalAvailableStock, materielCalc.UnallocatedQuantity); |
| | | |
| | | // éåé
æ°é |
| | | //decimal remainingQuantity = materielCalc.UnallocatedQuantity; |
| | | |
| | | // å·²åé
çæçå表 |
| | | List<string> allocatedPallets = new List<string>(); |
| | | |
| | | // è·å第ä¸ä¸ªåºåºæç» |
| | | Dt_OutboundOrderDetail firstDetail = materielCalc.Details.First(); |
| | | |
| | | // é¢å è½½åºåæç»åéå®è®°å½ |
| | | List<int> stockIds = stockQuery.Select(x => x.Id).ToList(); |
| | | Dictionary<int, List<Dt_StockInfoDetail>> stockDetailMap = stockQuery.ToDictionary(x => x.Id, x => x.Details); |
| | | |
| | | // è®°å½æ¯ä¸ªæççå®é
åé
é |
| | | Dictionary<string, decimal> palletAllocations = new Dictionary<string, decimal>(); |
| | | |
| | | List<Dt_Task> generatedTasks = new List<Dt_Task>(); // åå§ç©ºä»»å¡å表 |
| | | List<Dt_OutStockLockInfo> lockInfoList = new List<Dt_OutStockLockInfo>(); |
| | | foreach (var stock in stockQuery) |
| | | decimal remainingQuantity = materielCalc.UnallocatedQuantity; |
| | | |
| | | // 1. ä¼å
å¤çæå®åºåæç» |
| | | if (request.StockDetailIds?.Any() == true) |
| | | { |
| | | if (remainingQuantity <= 0) break; |
| | | var specifiedResult = AllocateSpecifiedStockDetails(outboundOrder, materielCalc, request, factoryArea, remainingQuantity); |
| | | pickedDetails.AddRange(specifiedResult.PickedDetails); |
| | | lockInfoList.AddRange(specifiedResult.LockInfoList); |
| | | remainingQuantity -= specifiedResult.ActualAllocatedQuantity; |
| | | |
| | | // å½ååºåå¯ç¨æ°é |
| | | decimal availableQuantity = availableStockMap.GetValueOrDefault(stock.Id, 0); |
| | | if (availableQuantity <= 0) continue; |
| | | |
| | | // 计ç®è¯¥æçå¯åé
æ°é |
| | | decimal allocateQuantity = Math.Min(remainingQuantity, availableQuantity); |
| | | (decimal ActualAllocatedQuantity, List<Dt_OutStockLockInfo> LockInfoList) actualAllocated = AllocateStockQuantity(stock, allocateQuantity, availableQuantity, outboundOrder, firstDetail, request, lockStockMap.GetValueOrDefault(stock.Id, new List<Dt_OutStockLockInfo>()), stockDetailMap); |
| | | |
| | | // æ¬æ¬¡åé
çæ°é |
| | | decimal actualAllocatedQuantity = actualAllocated.ActualAllocatedQuantity; |
| | | |
| | | if (actualAllocatedQuantity > 0) |
| | | // ===== æ ¸å¿ä¿®å¤ï¼æå®åºååé
åï¼ç«å³çæä»»å¡ï¼æ 论å©ä½éå¤å°ï¼===== |
| | | if (specifiedResult.PickedDetails.Any()) // ææå®åºååé
ç»æå°±çæä»»å¡ |
| | | { |
| | | allocatedPallets.Add(stock.PalletCode); |
| | | palletAllocations[stock.PalletCode] = actualAllocatedQuantity; // è®°å½å®é
åé
é |
| | | remainingQuantity -= actualAllocatedQuantity; |
| | | lockInfoList.AddRange(actualAllocated.LockInfoList); |
| | | var specifiedTasks = GenerateTasksForSpecifiedStock(specifiedResult.PickedDetails, request.OutboundTargetLocation); |
| | | generatedTasks.AddRange(specifiedTasks); // æ·»å æå®åºåä»»å¡å°æ»ä»»å¡å表 |
| | | } |
| | | |
| | | // å©ä½é<=0æ¶ï¼ç´æ¥è¿åï¼å·²çææå®åºåä»»å¡ï¼ |
| | | if (remainingQuantity <= 0) |
| | | { |
| | | return (pickedDetails, generatedTasks, lockInfoList); |
| | | } |
| | | } |
| | | |
| | | foreach (var palletCode in allocatedPallets) |
| | | // 2. å¤çå©ä½æ°éçèªå¨åé
ï¼åæé»è¾ä¸åï¼èªå¨åé
çä»»å¡ä¼è¿½å å°generatedTasksï¼ |
| | | List<Dt_StockInfo> stockQuery = BuildStockQueryWithInfo(materielCalc, factoryArea); |
| | | var allocatedPalletCodes = pickedDetails.Select(x => x.PalletCode).Distinct().ToList(); |
| | | stockQuery = stockQuery.Where(x => !allocatedPalletCodes.Contains(x.PalletCode)).ToList(); |
| | | |
| | | var stockData = GetBatchAvailableStockQuantities(materielCalc, stockQuery); |
| | | decimal totalAutoAvailable = stockData.AvailableStockMap.Values.Sum(); |
| | | decimal autoAllocateQuantity = Math.Min(remainingQuantity, totalAutoAvailable); |
| | | remainingQuantity -= autoAllocateQuantity; |
| | | |
| | | if (autoAllocateQuantity > 0 && stockQuery.Any()) |
| | | { |
| | | Dt_StockInfo stock = stockQuery.First(x => x.PalletCode == palletCode); |
| | | Dt_OutboundOrderDetail firstDetail = materielCalc.Details.First(); |
| | | Dictionary<int, List<Dt_StockInfoDetail>> stockDetailMap = stockQuery.ToDictionary(x => x.Id, x => x.Details); |
| | | Dictionary<string, decimal> palletAllocations = new Dictionary<string, decimal>(); |
| | | |
| | | // è·åå®é
åé
çæ°é |
| | | decimal actualAllocatedQuantity = palletAllocations.GetValueOrDefault(palletCode, 0); |
| | | |
| | | // 计ç®åé
åå©ä½çåºåæ°é |
| | | decimal originalAvailableQuantity = availableStockMap.GetValueOrDefault(stock.Id, 0); |
| | | decimal remainingStockQuantity = Math.Max(0, originalAvailableQuantity - actualAllocatedQuantity); |
| | | |
| | | pickedDetails.Add(new PickedStockDetailDTO |
| | | foreach (var stock in stockQuery) |
| | | { |
| | | PalletCode = palletCode, |
| | | MaterielCode = materielCalc.MaterielCode, |
| | | OutboundQuantity = actualAllocatedQuantity, // æ¬æ¬¡å®é
åé
çåºåºé |
| | | RemainingQuantity = remainingStockQuantity, // åé
åå©ä½çå¯ç¨åºå |
| | | LocationCode = stock.LocationCode, |
| | | OutStockLockInfos = lockInfoList |
| | | }); |
| | | if (autoAllocateQuantity <= 0) break; |
| | | decimal availableQuantity = stockData.AvailableStockMap.GetValueOrDefault(stock.Id, 0); |
| | | if (availableQuantity <= 0) continue; |
| | | |
| | | Dt_OutStockLockInfo? outStockLockInfo = lockInfoList.FirstOrDefault(x => x.PalletCode == palletCode); |
| | | int taskNum = outStockLockInfo?.TaskNum ?? Db.Ado.GetScalar($"SELECT NEXT VALUE FOR SeqTaskNum").ObjToInt(); |
| | | // èªå¨åé
æ¶æ¥è¯¢æçæ»åºåï¼åæä¼åé»è¾ä¸åï¼ |
| | | decimal palletMaterielTotalStock = _stockDetailRepository.QueryData( |
| | | x => x.StockId == stock.Id && x.MaterielCode == materielCalc.MaterielCode |
| | | ).Sum(x => x.StockQuantity); |
| | | |
| | | Dt_Task task = GenerationOutTask(stock, TaskTypeEnum.Outbound, taskNum, request.OutboundTargetLocation); |
| | | if (generatedTasks.FirstOrDefault(x => x.PalletCode == stock.PalletCode) == null) generatedTasks.Add(task); |
| | | decimal allocateQuantity = Math.Min(autoAllocateQuantity, availableQuantity); |
| | | var actualAllocated = AllocateStockQuantity( |
| | | stock, allocateQuantity, availableQuantity, outboundOrder, firstDetail, |
| | | request, stockData.LockStockMap.GetValueOrDefault(stock.Id, new List<Dt_OutStockLockInfo>()), |
| | | stockDetailMap, palletMaterielTotalStock); |
| | | |
| | | if (actualAllocated.ActualAllocatedQuantity > 0) |
| | | { |
| | | palletAllocations[stock.PalletCode] = actualAllocated.ActualAllocatedQuantity; |
| | | autoAllocateQuantity -= actualAllocated.ActualAllocatedQuantity; |
| | | lockInfoList.AddRange(actualAllocated.LockInfoList); |
| | | } |
| | | } |
| | | |
| | | // çæèªå¨åé
çä»»å¡ï¼è¿½å å°generatedTasksï¼ä¸ä¼éå¤ï¼ |
| | | foreach (var palletCode in palletAllocations.Keys) |
| | | { |
| | | Dt_StockInfo stock = stockQuery.First(x => x.PalletCode == palletCode); |
| | | decimal actualQty = palletAllocations[palletCode]; |
| | | decimal originalAvailable = stockData.AvailableStockMap.GetValueOrDefault(stock.Id, 0); |
| | | |
| | | pickedDetails.Add(new PickedStockDetailDTO |
| | | { |
| | | PalletCode = palletCode, |
| | | MaterielCode = materielCalc.MaterielCode, |
| | | OutboundQuantity = actualQty, |
| | | RemainingQuantity = Math.Max(0, originalAvailable - actualQty), |
| | | LocationCode = stock.LocationCode, |
| | | OutStockLockInfos = lockInfoList.Where(x => x.PalletCode == palletCode).ToList() |
| | | }); |
| | | |
| | | int taskNum = lockInfoList.FirstOrDefault(x => x.PalletCode == palletCode)?.TaskNum ?? |
| | | Db.Ado.GetScalar($"SELECT NEXT VALUE FOR SeqTaskNum").ObjToInt(); |
| | | Dt_Task task = GenerationOutTask(stock, TaskTypeEnum.Outbound, taskNum, request.OutboundTargetLocation); |
| | | // è¿æ»¤éå¤ä»»å¡ï¼æå®åºåçæçå·²çæï¼ä¸ä¼é夿·»å ï¼ |
| | | if (generatedTasks.FirstOrDefault(x => x.PalletCode == palletCode) == null) |
| | | generatedTasks.Add(task); |
| | | } |
| | | } |
| | | |
| | | // è¿åãæå®åºåä»»å¡+èªå¨åé
ä»»å¡ãçåå¹¶å表 |
| | | return (pickedDetails, generatedTasks, lockInfoList); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// çæåºåºä»»å¡ |
| | | /// åé
æå®åºåæç»ï¼æ ¸å¿ä¼åï¼æ¥è¯¢æçç©ææ»åºåå¹¶ä¼ éï¼ |
| | | /// </summary> |
| | | /// <param name="stockInfo"></param> |
| | | /// <param name="taskType"></param> |
| | | /// <param name="outStation"></param> |
| | | /// <returns></returns> |
| | | private (decimal ActualAllocatedQuantity, List<PickedStockDetailDTO> PickedDetails, List<Dt_OutStockLockInfo> LockInfoList) AllocateSpecifiedStockDetails( |
| | | Dt_OutboundOrder outboundOrder, |
| | | MaterielOutboundCalculationDTO materielCalc, |
| | | PickingOutboundRequestDTO request, |
| | | string factoryArea, |
| | | decimal needAllocateQuantity) |
| | | { |
| | | List<PickedStockDetailDTO> pickedDetails = new List<PickedStockDetailDTO>(); |
| | | List<Dt_OutStockLockInfo> lockInfoList = new List<Dt_OutStockLockInfo>(); |
| | | decimal actualAllocated = 0; |
| | | |
| | | List<Dt_StockInfoDetail> specifiedStockDetails = _stockDetailRepository.QueryData( |
| | | x => request.StockDetailIds.Contains(x.Id) |
| | | && x.MaterielCode == materielCalc.MaterielCode |
| | | && x.StockQuantity > 0 |
| | | && (x.Status == (int)StockStatusEmun.å
¥åºå®æ || x.Status == (int)StockStatusEmun.æå¨å»ç» || x.Status == (int)StockStatusEmun.æå¨è§£é || x.Status == (int)StockStatusEmun.è¿æ)); |
| | | |
| | | if (!specifiedStockDetails.Any()) |
| | | { |
| | | throw new Exception($"æå®åºåæç»ID [{string.Join(",", request.StockDetailIds)}] ä¸å卿ä¸å¯ç¨"); |
| | | } |
| | | |
| | | List<int> stockIds = specifiedStockDetails.Select(x => x.StockId).Distinct().ToList(); |
| | | List<Dt_StockInfo> specifiedStocks = _stockInfoRepository.QueryData(x => stockIds.Contains(x.Id)); |
| | | Dictionary<int, Dt_StockInfo> stockMap = specifiedStocks.ToDictionary(x => x.Id); |
| | | |
| | | foreach (var stockDetail in specifiedStockDetails) |
| | | { |
| | | if (needAllocateQuantity <= 0) break; |
| | | if (!stockMap.ContainsKey(stockDetail.StockId)) continue; |
| | | |
| | | Dt_StockInfo stock = stockMap[stockDetail.StockId]; |
| | | decimal availableQty = stockDetail.StockQuantity; |
| | | decimal allocateQty = Math.Min(needAllocateQuantity, availableQty); |
| | | if (allocateQty <= 0) continue; |
| | | |
| | | // ===== æ ¸å¿ä¼å1ï¼æ¥è¯¢è¯¥æçä¸å½åç©æçæ»åºå ===== |
| | | decimal palletMaterielTotalStock = _stockDetailRepository.QueryData( |
| | | x => x.StockId == stock.Id && x.MaterielCode == materielCalc.MaterielCode |
| | | ).Sum(x => x.StockQuantity); // 该æçè¯¥ç©æçæ»åºåï¼èéæ¬æ¬¡åé
éï¼ |
| | | |
| | | var lockInfos = materielCalc.OutStockLockInfos |
| | | .Where(x => x.StockId == stock.Id && x.MaterielCode == materielCalc.MaterielCode) |
| | | .ToList(); |
| | | |
| | | // ===== ä¼ éæ»åºåå°AllocateStockQuantity ===== |
| | | var allocateResult = AllocateStockQuantity( |
| | | stock, allocateQty, availableQty, outboundOrder, materielCalc.Details.First(), |
| | | request, lockInfos, |
| | | new Dictionary<int, List<Dt_StockInfoDetail>> { { stock.Id, new List<Dt_StockInfoDetail> { stockDetail } } }, |
| | | palletMaterielTotalStock // æ°å¢ï¼ä¼ å
¥æçç©ææ»åºå |
| | | ); |
| | | |
| | | if (allocateResult.ActualAllocatedQuantity > 0) |
| | | { |
| | | pickedDetails.Add(new PickedStockDetailDTO |
| | | { |
| | | PalletCode = stock.PalletCode, |
| | | MaterielCode = materielCalc.MaterielCode, |
| | | OutboundQuantity = allocateResult.ActualAllocatedQuantity, |
| | | RemainingQuantity = Math.Max(0, availableQty - allocateResult.ActualAllocatedQuantity), |
| | | LocationCode = stock.LocationCode, |
| | | OutStockLockInfos = allocateResult.LockInfoList |
| | | }); |
| | | |
| | | actualAllocated += allocateResult.ActualAllocatedQuantity; |
| | | needAllocateQuantity -= allocateResult.ActualAllocatedQuantity; |
| | | lockInfoList.AddRange(allocateResult.LockInfoList); |
| | | } |
| | | } |
| | | |
| | | return (actualAllocated, pickedDetails, lockInfoList); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 为æå®åºåçæä»»å¡ï¼åæé»è¾ä¸åï¼ |
| | | /// </summary> |
| | | private List<Dt_Task> GenerateTasksForSpecifiedStock(List<PickedStockDetailDTO> pickedDetails, string outboundTargetLocation) |
| | | { |
| | | List<Dt_Task> tasks = new List<Dt_Task>(); |
| | | var palletCodes = pickedDetails.Select(x => x.PalletCode).Distinct().ToList(); |
| | | |
| | | foreach (var palletCode in palletCodes) |
| | | { |
| | | Dt_StockInfo stock = _stockInfoRepository.QueryFirst(x => x.PalletCode == palletCode); |
| | | if (stock == null) continue; |
| | | |
| | | int taskNum = pickedDetails.First(x => x.PalletCode == palletCode) |
| | | .OutStockLockInfos.FirstOrDefault()?.TaskNum ?? |
| | | Db.Ado.GetScalar($"SELECT NEXT VALUE FOR SeqTaskNum").ObjToInt(); |
| | | |
| | | Dt_Task task = GenerationOutTask(stock, TaskTypeEnum.Outbound, taskNum, outboundTargetLocation); |
| | | if (tasks.FirstOrDefault(x => x.PalletCode == palletCode) == null) |
| | | tasks.Add(task); |
| | | } |
| | | |
| | | return tasks; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå»ºåºåæ¥è¯¢æ¡ä»¶ï¼åæé»è¾ä¸åï¼ |
| | | /// </summary> |
| | | private List<Dt_StockInfo> BuildStockQueryWithInfo(MaterielOutboundCalculationDTO materielCalc, string factoryArea) |
| | | { |
| | | ISugarQueryable<Dt_StockInfoDetail> stockDetails = _stockDetailRepository.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.MaterielCode == materielCalc.MaterielCode && x.StockQuantity > 0 |
| | | && (x.Status == (int)StockStatusEmun.å
¥åºå®æ || x.Status == (int)StockStatusEmun.æå¨è§£é)); |
| | | |
| | | if (!string.IsNullOrEmpty(materielCalc.SupplyCode)) |
| | | stockDetails = stockDetails.Where(x => x.SupplyCode == materielCalc.SupplyCode); |
| | | if (!string.IsNullOrEmpty(materielCalc.WarehouseCode)) |
| | | stockDetails = stockDetails.Where(x => x.WarehouseCode == materielCalc.WarehouseCode); |
| | | if (!string.IsNullOrEmpty(factoryArea)) |
| | | stockDetails = stockDetails.Where(x => x.FactoryArea == factoryArea); |
| | | if (!string.IsNullOrEmpty(materielCalc.BatchNo)) |
| | | stockDetails = stockDetails.Where(x => x.BatchNo == materielCalc.BatchNo); |
| | | |
| | | List<Dt_StockInfoDetail> stockDetailList = stockDetails.ToList(); |
| | | List<string> locationCodes = _locationInfoRepository.QueryData(x => |
| | | (x.LocationStatus == LocationStatusEnum.InStock.ObjToInt() || x.LocationStatus == LocationStatusEnum.Lock.ObjToInt()) |
| | | && x.EnableStatus == EnableStatusEnum.Normal.ObjToInt()).Select(x => x.LocationCode).ToList(); |
| | | |
| | | List<int> stockIds = stockDetailList.GroupBy(x => x.StockId).Select(x => x.Key).ToList(); |
| | | List<Dt_StockInfo> stockInfos = _stockInfoRepository.QueryData(x => |
| | | stockIds.Contains(x.Id) && (x.StockStatus == StockStatusEmun.å
¥åºå®æ.ObjToInt()) |
| | | && !string.IsNullOrEmpty(x.LocationCode) && locationCodes.Contains(x.LocationCode)); |
| | | |
| | | foreach (var stockInfo in stockInfos) |
| | | { |
| | | stockInfo.Details = stockDetailList.Where(x => x.StockId == stockInfo.Id).ToList(); |
| | | } |
| | | |
| | | return stockInfos; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¹éè·åæçå¯ç¨åºåä¿¡æ¯ï¼åæé»è¾ä¸åï¼ |
| | | /// </summary> |
| | | private (Dictionary<int, decimal> AvailableStockMap, Dictionary<int, List<Dt_OutStockLockInfo>> LockStockMap) GetBatchAvailableStockQuantities( |
| | | MaterielOutboundCalculationDTO materielCalc, List<Dt_StockInfo> stockInfos) |
| | | { |
| | | List<int> stockIds = stockInfos.Select(x => x.Id).ToList(); |
| | | Dictionary<int, decimal> availableStockMap = new Dictionary<int, decimal>(); |
| | | Dictionary<int, List<Dt_OutStockLockInfo>> lockStockMap = new Dictionary<int, List<Dt_OutStockLockInfo>>(); |
| | | |
| | | List<Dt_OutStockLockInfo> allocatedData = materielCalc.OutStockLockInfos |
| | | .Where(x => stockIds.Contains(x.StockId) && x.MaterielCode == materielCalc.MaterielCode).ToList(); |
| | | |
| | | foreach (var stockInfo in stockInfos) |
| | | { |
| | | decimal totalQuantity = stockInfo.Details.Sum(x => x.StockQuantity); |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = allocatedData |
| | | .Where(x => x.StockId == stockInfo.Id && x.MaterielCode == materielCalc.MaterielCode).ToList(); |
| | | decimal allocatedQuantity = outStockLockInfos.Sum(x => x.AllocatedQuantity); |
| | | |
| | | availableStockMap[stockInfo.Id] = Math.Max(0, totalQuantity - allocatedQuantity); |
| | | lockStockMap[stockInfo.Id] = outStockLockInfos; |
| | | } |
| | | |
| | | return (availableStockMap, lockStockMap); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åé
åºåï¼æ ¸å¿ä¼åï¼OriginalQuantityèµå¼ä¸ºæçç©ææ»åºåï¼ |
| | | /// </summary> |
| | | private (decimal ActualAllocatedQuantity, List<Dt_OutStockLockInfo> LockInfoList) AllocateStockQuantity( |
| | | Dt_StockInfo stockInfo, decimal allocateQuantity, decimal availableQuantity, |
| | | Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail detail, |
| | | PickingOutboundRequestDTO request, List<Dt_OutStockLockInfo> lockInfos, |
| | | Dictionary<int, List<Dt_StockInfoDetail>> stockDetailMap = null, |
| | | decimal palletMaterielTotalStock = 0 // æ°å¢ï¼æçç©ææ»åºååæ° |
| | | ) |
| | | { |
| | | decimal actualAllocatedQuantity = Math.Min(allocateQuantity, availableQuantity); |
| | | List<Dt_OutStockLockInfo> lockInfoList = new List<Dt_OutStockLockInfo>(); |
| | | |
| | | if (actualAllocatedQuantity > 0) |
| | | { |
| | | // æ£æ¥ç®æ ä½ç½®ä¸è´æ§ |
| | | if (lockInfos.Any() && !string.IsNullOrEmpty(lockInfos.First().OutboundTargetLocation) |
| | | && !string.Equals(lockInfos.First().OutboundTargetLocation, request.OutboundTargetLocation, StringComparison.OrdinalIgnoreCase)) |
| | | { |
| | | return (0, lockInfoList); |
| | | } |
| | | |
| | | Dt_OutStockLockInfo? lockInfo = lockInfos.FirstOrDefault(x => |
| | | x.StockId == stockInfo.Id && x.Status == OutLockStockStatusEnum.å·²åé
.ObjToInt() |
| | | && x.PalletCode == stockInfo.PalletCode && x.OrderNo == outboundOrder.OrderNo); |
| | | |
| | | if (lockInfo != null) |
| | | { |
| | | List<string> currentIds = lockInfo.OrderDetailIds?.Split(',').ToList() ?? new List<string>(); |
| | | if (!currentIds.Contains(detail.Id.ToString())) |
| | | { |
| | | currentIds.Add(detail.Id.ToString()); |
| | | lockInfo.OrderDetailIds = string.Join(",", currentIds); |
| | | } |
| | | |
| | | decimal totalAllocatedQuantity = CalcTotalAllocatedQuantity(lockInfos, stockInfo.Id, detail.MaterielCode); |
| | | lockInfo.AssignQuantity += actualAllocatedQuantity; |
| | | lockInfo.AllocatedQuantity = totalAllocatedQuantity; |
| | | if (palletMaterielTotalStock > 0) |
| | | lockInfo.OriginalQuantity = palletMaterielTotalStock; |
| | | lockInfoList.Add(lockInfo); |
| | | } |
| | | else |
| | | { |
| | | decimal originalQuantity = palletMaterielTotalStock; |
| | | |
| | | List<string> allDetailIds = outboundOrder.Details.Where(x => |
| | | x.OrderId == outboundOrder.Id && x.MaterielCode == detail.MaterielCode |
| | | && x.BatchNo == detail.BatchNo && x.SupplyCode == detail.SupplyCode |
| | | && x.WarehouseCode == detail.WarehouseCode) |
| | | .Select(x => x.Id.ToString()).ToList(); |
| | | |
| | | decimal totalAllocatedQuantity = CalcTotalAllocatedQuantity(lockInfos, stockInfo.Id, detail.MaterielCode); |
| | | |
| | | lockInfo = new Dt_OutStockLockInfo |
| | | { |
| | | OrderNo = request.OrderNo, |
| | | OrderDetailIds = string.Join(",", allDetailIds), |
| | | OrderType = outboundOrder.OrderType, |
| | | BatchNo = detail.BatchNo, |
| | | MaterielCode = detail.MaterielCode, |
| | | MaterielName = detail.MaterielName, |
| | | StockId = stockInfo.Id, |
| | | OrderQuantity = allDetailIds.Count > 1 |
| | | ? outboundOrder.Details.Where(x => |
| | | x.OrderId == outboundOrder.Id && x.MaterielCode == detail.MaterielCode |
| | | && x.BatchNo == detail.BatchNo && x.SupplyCode == detail.SupplyCode |
| | | && x.WarehouseCode == detail.WarehouseCode).Sum(x => x.OrderQuantity) |
| | | : detail.OrderQuantity, |
| | | OriginalQuantity = originalQuantity, // ç°å¨èµå¼ä¸ºæçç©ææ»åºå |
| | | AssignQuantity = actualAllocatedQuantity, |
| | | AllocatedQuantity = totalAllocatedQuantity, |
| | | LocationCode = stockInfo.LocationCode, |
| | | PalletCode = stockInfo.PalletCode, |
| | | Unit = detail.Unit, |
| | | OutboundTargetLocation = request.OutboundTargetLocation, |
| | | Status = OutLockStockStatusEnum.å·²åé
.ObjToInt(), |
| | | SupplyCode = detail.SupplyCode, |
| | | WarehouseCode = detail.WarehouseCode, |
| | | FactoryArea = outboundOrder.FactoryArea, |
| | | TaskNum = Db.Ado.GetScalar($"SELECT NEXT VALUE FOR SeqTaskNum").ObjToInt(), |
| | | OrderDetailId = 0 |
| | | }; |
| | | lockInfoList.Add(lockInfo); |
| | | } |
| | | } |
| | | |
| | | return (actualAllocatedQuantity, lockInfoList); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 计ç®è¯¥æç累计已åé
æ°éï¼åæé»è¾ä¸åï¼ |
| | | /// </summary> |
| | | private decimal CalcTotalAllocatedQuantity(List<Dt_OutStockLockInfo> lockInfos, int stockId, string materielCode) |
| | | { |
| | | List<Dt_OutStockLockInfo> lockRecords = _outboundLockInfoRepository.QueryData(x => |
| | | x.StockId == stockId && x.MaterielCode == materielCode); |
| | | |
| | | return lockRecords?.Sum(x => x.AssignQuantity) ?? 0; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// çæåºåºä»»å¡ï¼åæé»è¾ä¸åï¼ |
| | | /// </summary> |
| | | public Dt_Task GenerationOutTask(Dt_StockInfo stockInfo, TaskTypeEnum taskType, int taskNum, string outStation) |
| | | { |
| | | |
| | | Dt_Task task = new() |
| | | return new Dt_Task |
| | | { |
| | | CurrentAddress = stockInfo.LocationCode, |
| | | Grade = 0, |
| | |
| | | PalletType = stockInfo.PalletType, |
| | | WarehouseId = stockInfo.WarehouseId, |
| | | }; |
| | | |
| | | return task; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå»ºåºåæ¥è¯¢æ¡ä»¶ï¼å
å«åºåä¿¡æ¯ååºåæç»ï¼ |
| | | /// </summary> |
| | | /// <param name="materielCalc"></param> |
| | | /// <param name="factoryArea"></param> |
| | | /// <returns></returns> |
| | | private List<Dt_StockInfo> BuildStockQueryWithInfo(MaterielOutboundCalculationDTO materielCalc, string factoryArea) |
| | | { |
| | | // åºç¡æ¥è¯¢æ¡ä»¶ï¼ç©æç¼å·ãæ¹æ¬¡å·ï¼å¦ææä¾ï¼ãåºåæ°é>0 |
| | | ISugarQueryable<Dt_StockInfoDetail> stockDetails = _stockDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.MaterielCode == materielCalc.MaterielCode && x.StockQuantity > 0); |
| | | |
| | | // æ ¹æ®æ¡ä»¶æ·»å ä¾åºåç¼å·å¹é
ï¼ä¸ä¸ºç©ºæ¶æéè¦å¹é
ï¼ |
| | | if (!string.IsNullOrEmpty(materielCalc.SupplyCode)) |
| | | { |
| | | stockDetails = stockDetails.Where(x => x.SupplyCode == materielCalc.SupplyCode); |
| | | } |
| | | |
| | | // æ ¹æ®æ¡ä»¶æ·»å ä»åºç¼å·å¹é
ï¼ä¸ä¸ºç©ºæ¶æéè¦å¹é
ï¼ |
| | | if (!string.IsNullOrEmpty(materielCalc.WarehouseCode)) |
| | | { |
| | | stockDetails = stockDetails.Where(x => x.WarehouseCode == materielCalc.WarehouseCode); |
| | | } |
| | | |
| | | // æ ¹æ®æ¡ä»¶æ·»å ååºå¹é
ï¼ä¸ä¸ºç©ºæ¶æéè¦å¹é
ï¼ |
| | | if (!string.IsNullOrEmpty(factoryArea)) |
| | | { |
| | | stockDetails = stockDetails.Where(x => x.FactoryArea == factoryArea); |
| | | } |
| | | |
| | | // æ ¹æ®æ¹æ¬¡å·è¿è¡è¿æ»¤ï¼å¦ææä¾ï¼ |
| | | if (!string.IsNullOrEmpty(materielCalc.BatchNo)) |
| | | { |
| | | stockDetails = stockDetails.Where(x => x.BatchNo == materielCalc.BatchNo); |
| | | } |
| | | |
| | | List<Dt_StockInfoDetail> stockDetailList = stockDetails.ToList(); |
| | | |
| | | // è·åå¯ç¨è´§ä½ç¼å· |
| | | List<string> locationCodes = _locationInfoRepository.QueryData(x => (x.LocationStatus == LocationStatusEnum.InStock.ObjToInt() /*|| x.LocationStatus == LocationStatusEnum.Lock.ObjToInt()*/) && x.EnableStatus == EnableStatusEnum.Normal.ObjToInt()).Select(x => x.LocationCode).ToList(); |
| | | |
| | | // è·åææç¸å
³çåºåä¿¡æ¯ |
| | | List<int> stockIds = stockDetailList.GroupBy(x => x.StockId).Select(x => x.Key).ToList(); |
| | | List<Dt_StockInfo> stockInfos = _stockInfoRepository.QueryData(x => stockIds.Contains(x.Id) && (x.StockStatus == StockStatusEmun.å
¥åºå®æ.ObjToInt() /*|| x.StockStatus == StockStatusEmun.åºåºéå®.ObjToInt()*/) && !string.IsNullOrEmpty(x.LocationCode) && locationCodes.Contains(x.LocationCode)); |
| | | |
| | | // å¨å
åä¸å
³èæ°æ® |
| | | foreach (var stockInfo in stockInfos) |
| | | { |
| | | stockInfo.Details = new List<Dt_StockInfoDetail>(); |
| | | stockInfo.Details = stockDetailList.Where(x => x.StockId == stockInfo.Id).ToList(); |
| | | } |
| | | |
| | | return stockInfos; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¹éè·åæçå¯ç¨åºåä¿¡æ¯ |
| | | /// </summary> |
| | | /// <param name="stockInfos">åºåä¿¡æ¯å表</param> |
| | | /// <param name="materielCode">ç©æç¼å·</param> |
| | | /// <returns>è¿åå¼ä¸º(åºå主é®ï¼å¯ç¨æ°é)åå
¸</returns> |
| | | private (Dictionary<int, decimal> AvailableStockMap, Dictionary<int, List<Dt_OutStockLockInfo>> LockStockMap) GetBatchAvailableStockQuantities(MaterielOutboundCalculationDTO materielCalc, List<Dt_StockInfo> stockInfos) |
| | | { |
| | | List<int> stockIds = stockInfos.Select(x => x.Id).ToList(); |
| | | |
| | | Dictionary<int, decimal> availableStockMap = new Dictionary<int, decimal>(); // å¯ç¨åºåæ°é |
| | | Dictionary<int, List<Dt_OutStockLockInfo>> lockStockMap = new Dictionary<int, List<Dt_OutStockLockInfo>>(); // å·²éå®åºåæ°é |
| | | |
| | | // æ¹éæ¥è¯¢å·²åé
æ°é |
| | | List<Dt_OutStockLockInfo> allocatedData = materielCalc.OutStockLockInfos.Where(x => stockIds.Contains(x.StockId) && x.MaterielCode == materielCalc.MaterielCode).ToList(); |
| | | |
| | | foreach (var stockInfo in stockInfos) |
| | | { |
| | | // è®¡ç®æ»åºåæ°é |
| | | decimal totalQuantity = stockInfo.Details.Sum(x => x.StockQuantity); |
| | | |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = allocatedData.Where(x => x.StockId == stockInfo.Id && x.MaterielCode == materielCalc.MaterielCode).ToList(); |
| | | |
| | | // 计ç®å·²åé
æ°é |
| | | decimal allocatedQuantity = outStockLockInfos.Sum(x => x.AllocatedQuantity); |
| | | availableStockMap[stockInfo.Id] = Math.Max(0, totalQuantity - allocatedQuantity); |
| | | |
| | | lockStockMap[stockInfo.Id] = outStockLockInfos; |
| | | } |
| | | |
| | | return (availableStockMap, lockStockMap); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åé
åºå |
| | | /// </summary> |
| | | /// <param name="stockInfo">åºåä¿¡æ¯</param> |
| | | /// <param name="allocateQuantity">è¦åé
çæ°é</param> |
| | | /// <param name="availableQuantity">å¯åé
çæ°é</param> |
| | | /// <param name="outboundOrder">åºåºå</param> |
| | | /// <param name="detail">åºåºåæç»</param> |
| | | /// <param name="request"></param> |
| | | /// <param name="lockInfos"></param> |
| | | /// <param name="stockDetailMap"></param> |
| | | /// <returns></returns> |
| | | private (decimal ActualAllocatedQuantity, List<Dt_OutStockLockInfo> LockInfoList) AllocateStockQuantity(Dt_StockInfo stockInfo, decimal allocateQuantity, decimal availableQuantity, Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail detail, PickingOutboundRequestDTO request, List<Dt_OutStockLockInfo> lockInfos, Dictionary<int, List<Dt_StockInfoDetail>> stockDetailMap = null) |
| | | { |
| | | decimal actualAllocatedQuantity = Math.Min(allocateQuantity, availableQuantity); // å®é
åé
æ°é |
| | | List<Dt_OutStockLockInfo> lockInfoList = new List<Dt_OutStockLockInfo>(); |
| | | if (actualAllocatedQuantity > 0) |
| | | { |
| | | //æ£æ¥ç®æ ä½ç½®ä¸è´æ§ï¼å¦ææçå·²æéå®è®°å½ä¸ç®æ ä½ç½®ä¸åï¼åä¸å
许åé
|
| | | if (lockInfos.Any() && !string.IsNullOrEmpty(lockInfos.First().OutboundTargetLocation)) |
| | | { |
| | | if (!string.Equals(lockInfos.First().OutboundTargetLocation, request.OutboundTargetLocation, StringComparison.OrdinalIgnoreCase)) |
| | | { |
| | | // æççç®æ ä½ç½®ä¸æ°è¯·æ±çç®æ ä½ç½®ä¸åï¼ä¸å
许使ç¨è¯¥æç |
| | | return (0, lockInfoList); |
| | | } |
| | | } |
| | | |
| | | Dt_OutStockLockInfo? lockInfo = lockInfos.FirstOrDefault(x => x.StockId == stockInfo.Id && x.Status == OutLockStockStatusEnum.å·²åé
.ObjToInt() && x.PalletCode == stockInfo.PalletCode && x.OrderNo == outboundOrder.OrderNo); |
| | | |
| | | if (lockInfo != null) |
| | | { |
| | | // 追å å½åæç»IDå°OrderDetailIdsåæ®µï¼é¿å
éå¤ï¼ |
| | | List<string> currentIds = lockInfo.OrderDetailIds?.Split(',').ToList() ?? new List<string>(); |
| | | if (!currentIds.Contains(detail.Id.ToString())) |
| | | { |
| | | currentIds.Add(detail.Id.ToString()); |
| | | lockInfo.OrderDetailIds = string.Join(",", currentIds); |
| | | } |
| | | |
| | | // 计ç®è¯¥æçè¯¥ç©æçæ»ç´¯è®¡å·²åºåºæ°éï¼è·¨ææåæ®ï¼ |
| | | decimal totalAllocatedQuantity = CalcTotalAllocatedQuantity(lockInfos, stockInfo.Id, detail.MaterielCode); |
| | | |
| | | // æ´æ°åé
åºåºé |
| | | decimal beforeAssignQuantity = totalAllocatedQuantity; // æ¬æ¬¡åé
åçæ»ç´¯è®¡é |
| | | lockInfo.AssignQuantity += actualAllocatedQuantity; // æ¬æ¬¡åé
æ°é |
| | | lockInfo.AllocatedQuantity = beforeAssignQuantity; // è®°å½æ¬æ¬¡åé
åçæ»ç´¯è®¡é |
| | | |
| | | lockInfoList.Add(lockInfo); |
| | | } |
| | | else |
| | | { |
| | | // å建æ°çéå®è®°å½ï¼ä½¿ç¨é¢å è½½çåºåæç»ï¼ |
| | | decimal originalQuantity = 0; |
| | | if (stockDetailMap?.ContainsKey(stockInfo.Id) == true) |
| | | { |
| | | originalQuantity = stockDetailMap[stockInfo.Id].Sum(x => x.StockQuantity); |
| | | } |
| | | |
| | | // è·åè¯¥ç©æå¨è¯¥è®¢åä¸çæææç»ID |
| | | List<string> allDetailIds = (outboundOrder.Details.Where(x => |
| | | x.OrderId == outboundOrder.Id && |
| | | x.MaterielCode == detail.MaterielCode && |
| | | x.BatchNo == detail.BatchNo && |
| | | x.SupplyCode == detail.SupplyCode && |
| | | x.WarehouseCode == detail.WarehouseCode)) |
| | | .Select(x => x.Id.ToString()) |
| | | .ToList(); |
| | | |
| | | // 计ç®è¯¥æçè¯¥ç©æçæ»ç´¯è®¡å·²åºåºæ°éï¼è·¨ææåæ®ï¼ |
| | | decimal totalAllocatedQuantity = CalcTotalAllocatedQuantity(lockInfos, stockInfo.Id, detail.MaterielCode); |
| | | |
| | | lockInfo = new Dt_OutStockLockInfo |
| | | { |
| | | OrderNo = request.OrderNo, |
| | | OrderDetailIds = string.Join(",", allDetailIds), // è®°å½è¯¥ç©æçæææç»ID |
| | | OrderType = outboundOrder.OrderType, |
| | | BatchNo = detail.BatchNo, |
| | | MaterielCode = detail.MaterielCode, |
| | | MaterielName = detail.MaterielName, |
| | | StockId = stockInfo.Id, |
| | | OrderQuantity = allDetailIds.SelectMany(id => allDetailIds).Count() > 1 |
| | | ? (outboundOrder.Details.Where(x => |
| | | x.OrderId == outboundOrder.Id && |
| | | x.MaterielCode == detail.MaterielCode && |
| | | x.BatchNo == detail.BatchNo && |
| | | x.SupplyCode == detail.SupplyCode && |
| | | x.WarehouseCode == detail.WarehouseCode)) |
| | | .Sum(x => x.OrderQuantity) |
| | | : detail.OrderQuantity, // å¦æåªæä¸ä¸ªæç»ï¼ä½¿ç¨æç»æ°é |
| | | OriginalQuantity = originalQuantity, |
| | | AssignQuantity = actualAllocatedQuantity, // æ¬æ¬¡åé
æ°é |
| | | AllocatedQuantity = totalAllocatedQuantity, // æ¬æ¬¡åé
åçæ»ç´¯è®¡å·²åºåºæ°éï¼è·¨ææåæ®ï¼ |
| | | LocationCode = stockInfo.LocationCode, |
| | | PalletCode = stockInfo.PalletCode, |
| | | Unit = detail.Unit, |
| | | OutboundTargetLocation = request.OutboundTargetLocation, |
| | | Status = OutLockStockStatusEnum.å·²åé
.ObjToInt(), |
| | | SupplyCode = detail.SupplyCode, |
| | | WarehouseCode = detail.WarehouseCode, |
| | | FactoryArea = outboundOrder.FactoryArea, |
| | | TaskNum = Db.Ado.GetScalar($"SELECT NEXT VALUE FOR SeqTaskNum").ObjToInt(), |
| | | OrderDetailId = 0 // æªå
³èå
·ä½æç»ID |
| | | }; |
| | | lockInfoList.Add(lockInfo); |
| | | } |
| | | } |
| | | return (actualAllocatedQuantity, lockInfoList); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 计ç®è¯¥æç累计已åé
æ°é |
| | | /// </summary> |
| | | /// <param name="lockInfos"></param> |
| | | /// <param name="stockId"></param> |
| | | /// <param name="materielCode"></param> |
| | | /// <returns></returns> |
| | | private decimal CalcTotalAllocatedQuantity(List<Dt_OutStockLockInfo> lockInfos, int stockId, string materielCode) |
| | | { |
| | | // æ¥è¯¢è¯¥æçè¯¥ç©æå¨ææéå®è®°å½ä¸çæå¤§å·²åé
æ°é |
| | | List<Dt_OutStockLockInfo> lockRecords = _outboundLockInfoRepository.QueryData(x => |
| | | x.StockId == stockId && |
| | | x.MaterielCode == materielCode); |
| | | |
| | | if (lockRecords == null || !lockRecords.Any()) |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | // è¿å累计已åé
æ°é |
| | | return lockRecords.Sum(x => x.AssignQuantity); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ´æ°åºåºåç¶æ |
| | | /// </summary> |
| | | public bool UpdateOutboundOrderStatus(string orderNo, int status) |
| | | { |
| | | try |
| | | { |
| | | Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(x => x.OrderNo == orderNo); |
| | | if (outboundOrder == null) return false; |
| | | |
| | | outboundOrder.OrderStatus = status; |
| | | if(outboundOrder.CreateType == OrderCreateTypeEnum.CreateInSystem.ObjToInt()) |
| | | { |
| | | outboundOrder.ReturnToMESStatus = 5; |
| | | } |
| | | _outboundRepository.UpdateData(outboundOrder); |
| | | return true; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="palletCodes"></param> |
| | | /// <param name="status"></param> |
| | | /// <returns></returns> |
| | | public bool UpdateStockStatus(List<string> palletCodes, int status) |
| | | { |
| | | try |
| | | { |
| | | List<Dt_StockInfo> stockInfos = _stockInfoRepository.QueryData(x => palletCodes.Contains(x.PalletCode)); |
| | | stockInfos.ForEach(stockInfo => |
| | | { |
| | | stockInfo.StockStatus = status; |
| | | }); |
| | | |
| | | stockInfos.ForEach(stockInfo => stockInfo.StockStatus = status); |
| | | _stockInfoRepository.UpdateData(stockInfos); |
| | | return true; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="locationCodes"></param> |
| | | /// <param name="status"></param> |
| | | /// <returns></returns> |
| | | public bool UpdateLocationStatus(List<string> locationCodes, int status) |
| | | { |
| | | try |
| | | { |
| | | List<Dt_LocationInfo> locationInfos = _locationInfoRepository.QueryData(x => locationCodes.Contains(x.LocationCode)); |
| | | locationInfos.ForEach(x => |
| | | { |
| | | x.LocationStatus = status; |
| | | }); |
| | | |
| | | locationInfos.ForEach(x => x.LocationStatus = status); |
| | | _locationInfoRepository.UpdateData(locationInfos); |
| | | return true; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="outStockLockInfos"></param> |
| | | /// <returns></returns> |
| | | public bool UpdateOutStockLockInfo(List<Dt_OutStockLockInfo> outStockLockInfos) |
| | | { |
| | | try |
| | | { |
| | | List<Dt_OutStockLockInfo> updateData = outStockLockInfos.Where(x => x.Id > 0).ToList(); |
| | | _outboundLockInfoRepository.UpdateData(updateData); |
| | | |
| | | List<Dt_OutStockLockInfo> addData = outStockLockInfos.Where(x => x.Id <= 0).ToList(); |
| | | _outboundLockInfoRepository.AddData(addData); |
| | | |
| | | return true; |
| | | } |
| | | catch |
| | |
| | | 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.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; |
| | | bool isMatMixed = false; |
| | | |
| | | bool includeBatchNo = !string.IsNullOrEmpty(lockInfo.BatchNo); |
| | | bool includeSupplyCode = !string.IsNullOrEmpty(lockInfo.SupplyCode); |
| | | |
| | | if (includeBatchNo && includeSupplyCode) |
| | | { |
| | | isMatMixed = stockInfo.Details.GroupBy(x => new |
| | | { |
| | | x.MaterielCode, |
| | | x.MaterielName, |
| | | x.BatchNo, |
| | | x.SupplyCode, |
| | | x.WarehouseCode |
| | | }).Count() > 1; |
| | | } |
| | | else if (includeBatchNo && !includeSupplyCode) |
| | | { |
| | | isMatMixed = stockInfo.Details.GroupBy(x => new |
| | | { |
| | | x.MaterielCode, |
| | | x.MaterielName, |
| | | x.BatchNo, |
| | | x.WarehouseCode |
| | | }).Count() > 1; |
| | | } |
| | | else if (!includeBatchNo && includeSupplyCode) |
| | | { |
| | | isMatMixed = stockInfo.Details.GroupBy(x => new |
| | | { |
| | | x.MaterielCode, |
| | | x.MaterielName, |
| | | x.SupplyCode, |
| | | x.WarehouseCode |
| | | }).Count() > 1; |
| | | } |
| | | else |
| | | { |
| | | isMatMixed = stockInfo.Details.GroupBy(x => new |
| | | { |
| | | x.MaterielCode, |
| | | x.MaterielName, |
| | | x.WarehouseCode |
| | | }).Count() > 1; |
| | | } |
| | | |
| | | if (isMatMixed) |
| | | { |
| | | response.Success = false; |
| | | response.Message = $"æ··ææç {request.PalletCode} ä¸è½æ´ç®±åºåº"; |
| | | return WebResponseContent.Instance.Error(response.Message); |
| | | } |
| | | |
| | |
| | | // æ´ç®±åºåºæ éæå
|
| | | PerformFullOutboundOperation(stockInfo, request, lockInfo.TaskNum.GetValueOrDefault()); |
| | | |
| | | if (outboundOrder.OrderType != 0) |
| | | if (outboundOrder.OrderType == InOrderTypeEnum.InternalAllocat.ObjToInt()) |
| | | { |
| | | Dt_AllocateOrder allocateOrder = _allocateOrderRepository.QueryFirst(x => x.OrderNo == outboundOrder.OrderNo); |
| | | if (allocateOrder != null) |
| | |
| | | _allocateMaterialInfoRepository.AddData(allocateMaterialInfos); |
| | | } |
| | | } |
| | | else if(outboundOrder.OrderType == InOrderTypeEnum.ReCheck.ObjToInt()) |
| | | { |
| | | List<Dt_AllocateMaterialInfo> allocateMaterialInfos = new List<Dt_AllocateMaterialInfo>(); |
| | | foreach (var item in stockInfo.Details) |
| | | { |
| | | Dt_AllocateMaterialInfo allocateMaterialInfo = new Dt_AllocateMaterialInfo() |
| | | { |
| | | Barcode = item.Barcode??"", |
| | | BatchNo = item.BatchNo, |
| | | FactoryArea = item.FactoryArea, |
| | | MaterialCode = item.MaterielCode, |
| | | MaterialName = item.MaterielName, |
| | | OrderId = outboundOrder.Id, |
| | | OrderNo = outboundOrder.OrderNo, |
| | | Quantity = item.StockQuantity, |
| | | SupplyCode = item.SupplyCode??"", |
| | | Unit = item.Unit, |
| | | WarehouseCode = item.WarehouseCode??"" |
| | | }; |
| | | allocateMaterialInfos.Add(allocateMaterialInfo); |
| | | } |
| | | _allocateMaterialInfoRepository.AddData(allocateMaterialInfos); |
| | | } |
| | | |
| | | decimal allocatedQuantity = actualOutboundQuantity; |
| | | List<Dt_OutboundOrderDetail> updateDetails = new(); |
| | |
| | | //} |
| | | List<Barcodes> barcodesList = new List<Barcodes>(); |
| | | List<Dt_StockInfoDetail> stockInfoDetails = stockInfo.Details.Where((x => x.StockQuantity > x.OutboundQuantity)).ToList(); |
| | | |
| | | decimal itemQuantity = item.LockQuantity - item.OverOutQuantity; |
| | | decimal unitbarcodeQuantity; |
| | | foreach (var stockDetail in stockInfoDetails) |
| | | { |
| | | if (item.LockQuantity - item.OverOutQuantity >= stockDetail.StockQuantity - stockInfoDetail.OutboundQuantity) |
| | | |
| | | |
| | | if (itemQuantity >= stockDetail.StockQuantity - stockDetail.OutboundQuantity) |
| | | { |
| | | unitbarcodeQuantity = stockDetail.StockQuantity - stockDetail.OutboundQuantity; |
| | | UnitConvertResultDTO currentResult = _basicService.UnitQuantityConvert(item.MaterielCode, item.Unit, item.BarcodeUnit, unitbarcodeQuantity); |
| | | |
| | | Barcodes barcodes = new Barcodes |
| | | { |
| | | Barcode = stockDetail.Barcode, |
| | | Qty = stockDetail.StockQuantity - stockInfoDetail.OutboundQuantity, |
| | | Qty = currentResult.ToQuantity, |
| | | SupplyCode = stockDetail?.SupplyCode ?? "", |
| | | BatchNo = stockDetail?.BatchNo ?? "", |
| | | Unit = stockDetail?.Unit ?? "" |
| | | Unit = currentResult.ToUnit ?? "" |
| | | }; |
| | | |
| | | stockDetail.StockQuantity = stockInfoDetail.OutboundQuantity; |
| | | itemQuantity -= (stockDetail.StockQuantity - stockDetail.OutboundQuantity); |
| | | stockDetail.OutboundQuantity = stockDetail.StockQuantity; |
| | | barcodesList.Add(barcodes); |
| | | |
| | | if (itemQuantity <= 0) break; |
| | | } |
| | | else |
| | | { |
| | | UnitConvertResultDTO currentResult = _basicService.UnitQuantityConvert(item.MaterielCode, item.Unit, item.BarcodeUnit, itemQuantity); |
| | | Barcodes barcodes = new Barcodes |
| | | { |
| | | Barcode = stockDetail.Barcode, |
| | | Qty = item.LockQuantity - item.OverOutQuantity, |
| | | Qty = currentResult.ToQuantity, |
| | | SupplyCode = stockDetail?.SupplyCode ?? "", |
| | | BatchNo = stockDetail?.BatchNo ?? "", |
| | | Unit = stockDetail?.Unit ?? "" |
| | | Unit = currentResult.ToUnit ?? "" |
| | | }; |
| | | stockInfoDetail.OutboundQuantity += item.LockQuantity - item.OverOutQuantity; |
| | | stockDetail.OutboundQuantity += itemQuantity; |
| | | barcodesList.Add(barcodes); |
| | | break; |
| | | } |
| | | } |
| | | |
| | |
| | | { |
| | | 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; |
| | | } |
| | | |
| | | updateDetails.Add(item); |
| | |
| | | ContractResolver = new CamelCasePropertyNamesContractResolver() |
| | | }; |
| | | item.ReturnJsonData = JsonConvert.SerializeObject(barcodesList, settings); |
| | | //鿣åºåºä¸éè¦åä¼ |
| | | if (outboundOrder.OrderType == InOrderTypeEnum.ReCheck.ObjToInt()) |
| | | { |
| | | item.ReturnJsonData = ""; |
| | | } |
| | | } |
| | | |
| | | lockInfo.SortedQuantity = lockInfo.SortedQuantity + actualOutboundQuantity; |
| | |
| | | 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)) |
| | | { |
| | | UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.åºåºå®æ.ObjToInt()); |
| | | |
| | | _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo); |
| | | if (outboundOrder.OrderType != OutOrderTypeEnum.InternalAllocat.ObjToInt()&& outboundOrder.OrderType!= InOrderTypeEnum.ReCheck.ObjToInt()) |
| | | { |
| | | _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo); |
| | | } |
| | | |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | |
| | | _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 æ£é |
| | |
| | | |
| | | MaterialCodeReturnDTO returnDTO = returnDTOs.First(x => x.Barcode == newBarcode); |
| | | |
| | | if (outboundOrder.OrderType != 0) |
| | | if (outboundOrder.OrderType == InOrderTypeEnum.ReCheck.ObjToInt()||outboundOrder.OrderType == InOrderTypeEnum.InternalAllocat.ObjToInt()) |
| | | { |
| | | allocateMaterialInfo = new Dt_AllocateMaterialInfo() |
| | | { |
| | |
| | | { |
| | | PerformFullOutboundOperation(stockDetail, stockInfo, actualOutboundQuantity, request, beforeQuantity, lockInfo.TaskNum.GetValueOrDefault()); |
| | | |
| | | if (outboundOrder.OrderType != 0) |
| | | if (outboundOrder.OrderType == InOrderTypeEnum.ReCheck.ObjToInt() || outboundOrder.OrderType == InOrderTypeEnum.InternalAllocat.ObjToInt()) |
| | | { |
| | | allocateMaterialInfo = new Dt_AllocateMaterialInfo() |
| | | { |
| | |
| | | |
| | | } |
| | | |
| | | // 夿æ¯å¦æ¯è°æ¨å |
| | | if (outboundOrder.OrderType != 0) |
| | | // 夿æ¯å¦æ¯æºä»è°æºä»å |
| | | if ( outboundOrder.OrderType == InOrderTypeEnum.InternalAllocat.ObjToInt()) |
| | | { |
| | | Dt_AllocateOrder allocateOrder = _allocateOrderRepository.QueryFirst(x => x.OrderNo == outboundOrder.OrderNo); |
| | | if (allocateOrder != null) |
| | |
| | | foreach (var item in outboundOrderDetails) |
| | | { |
| | | if (allocatedQuantity <= 0) break; |
| | | |
| | | |
| | | //if (item.OrderQuantity - item.MoveQty - item.OverOutQuantity >= allocatedQuantity) |
| | | //{ |
| | |
| | | { |
| | | 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>(); |
| | | UnitConvertResultDTO currentResult = _basicService.UnitQuantityConvert(item.MaterielCode, item.Unit, item.BarcodeUnit, barcodeQuantity); |
| | | |
| | | Barcodes barcodes = new Barcodes |
| | | { |
| | | Barcode = request.Barcode, |
| | | Qty = barcodeQuantity, |
| | | Barcode = isUnpacked ? newBarcode : stockDetail?.Barcode, |
| | | Qty = currentResult.ToQuantity, |
| | | SupplyCode = stockDetail?.SupplyCode ?? "", |
| | | BatchNo = stockDetail?.BatchNo ?? "", |
| | | Unit = stockDetail?.Unit ?? "" |
| | | Unit = currentResult.ToUnit ?? "" |
| | | }; |
| | | if (!string.IsNullOrEmpty(item.ReturnJsonData)) |
| | | { |
| | |
| | | |
| | | lockInfo.SortedQuantity = lockInfo.SortedQuantity + actualOutboundQuantity; |
| | | |
| | | if (lockInfo.SortedQuantity == lockInfo.AssignQuantity) |
| | | if (lockInfo.SortedQuantity >= lockInfo.AssignQuantity) |
| | | { |
| | | _outboundLockInfoRepository.DeleteAndMoveIntoHty(lockInfo, WIDESEA_Core.Enums.OperateTypeEnum.èªå¨å®æ); |
| | | } |
| | |
| | | _feedbackMesService.BarcodeFeedback(newBarcode); |
| | | } |
| | | |
| | | 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 == stockDetail.MaterielCode).Where(supWhere).Where(wareWhere).ToList(); |
| | | if (stockLockInfos != null && stockLockInfos.Any()) |
| | | { |
| | | _outboundLockInfoRepository.DeleteAndMoveIntoHty(stockLockInfos, WIDESEA_Core.Enums.OperateTypeEnum.èªå¨å é¤); |
| | | } |
| | | } |
| | | |
| | | |
| | | // æ£æ¥åºåºåæ¯å¦å®æ |
| | | if (CheckOutboundOrderCompleted(request.OrderNo)) |
| | | { |
| | | UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.åºåºå®æ.ObjToInt()); |
| | | if(outboundOrder.OrderType != OutOrderTypeEnum.InternalAllocat.ObjToInt()) |
| | | { |
| | | UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.åºåºå®æ.ObjToInt()); |
| | | |
| | | _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo); |
| | | if (outboundOrder.CreateType != OrderCreateTypeEnum.CreateInSystem.ObjToInt()) |
| | | { |
| | | _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | |
| | | /// </summary> |
| | | private decimal CalculateActualOutboundQuantity(Dt_StockInfoDetail stockDetail, List<Dt_OutboundOrderDetail> outboundDetails, Dt_OutStockLockInfo lockInfo) |
| | | { |
| | | // decimal availableOutboundQuantity = lockInfo.AssignQuantity - lockInfo.SortedQuantity; |
| | | |
| | | decimal availableOutboundQuantity = lockInfo.AssignQuantity; |
| | | decimal detailRemainingQuantity = outboundDetails.Sum(x => x.OrderQuantity - x.OverOutQuantity - x.MoveQty);//outboundDetail.OrderQuantity - outboundDetail.OverOutQuantity; |
| | | |
| | |
| | | /// <param name="beforeQuantity"></param> |
| | | /// <param name="taskNum"></param> |
| | | /// <returns></returns> |
| | | private (string NewBarcode, List<MaterialCodeReturnDTO> MaterialCodeReturnDTOs) PerformUnpackOperation(Dt_StockInfoDetail stockDetail, Dt_StockInfo stockInfo, |
| | | public (string NewBarcode, List<MaterialCodeReturnDTO> MaterialCodeReturnDTOs) PerformUnpackOperation(Dt_StockInfoDetail stockDetail, Dt_StockInfo stockInfo, |
| | | decimal actualOutboundQuantity, OutboundCompleteRequestDTO request, decimal beforeQuantity, int taskNum, int orderId, string orderNo) |
| | | { |
| | | string newBarcode = GenerateNewBarcode(); |
| | |
| | | /// <summary> |
| | | /// æ§è¡å®æ´åºåºæä½ï¼ä¸æå
ï¼ |
| | | /// </summary> |
| | | private void PerformFullOutboundOperation(Dt_StockInfoDetail stockDetail, Dt_StockInfo stockInfo, |
| | | public void PerformFullOutboundOperation(Dt_StockInfoDetail stockDetail, Dt_StockInfo stockInfo, |
| | | decimal actualOutboundQuantity, OutboundCompleteRequestDTO request, decimal beforeQuantity, int taskNum) |
| | | { |
| | | // ä¿ååºåæç»å°åå²è®°å½ |
| | |
| | | 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); |
| | |
| | | return details.All(x => x.OverOutQuantity >= x.OrderQuantity - x.MoveQty); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ£æ¥åºåºåæç»æ¯å¦å®æ |
| | | /// </summary> |
| | | 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; |
| | | |
| | | 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); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region å空箱 |
| | |
| | | try |
| | | { |
| | | var stock = await _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Includes(x => x.Details).Where(x => x.PalletCode == palletCode).FirstAsync(); |
| | | |
| | | Dt_Task task = _taskRepository.QueryFirst(x => x.PalletCode == palletCode); |
| | | if (task != null) |
| | | { |
| | | return WebResponseContent.Instance.Error("ä»»å¡ä¿¡æ¯å表åå¨è¯¥æççä»»å¡ä¿¡æ¯ï¼ä¸å¯å走空箱ï¼è¯·æ£æ¥ä»»å¡æ¯å¦å®æ"); |
| | | } |
| | | |
| | | if (stock == null) |
| | | { |
| | |
| | | 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() |
| | | { |
| | | CurrentAddress = stations[station], |
| | | CurrentAddress = stations.GetValueOrDefault(station) ?? "", |
| | | Grade = 0, |
| | | PalletCode = palletCode, |
| | | NextAddress = "", |
| | | OrderNo = OrderNo, |
| | | Roadway = newLocation.RoadwayNo, |
| | | SourceAddress = stations[station], |
| | | SourceAddress = stations.GetValueOrDefault(station) ?? "", |
| | | TargetAddress = newLocation.LocationCode, |
| | | TaskStatus = (int)TaskStatusEnum.New, |
| | | TaskType = stock.Details.Count > 0 ? (int)TaskTypeEnum.InPick : (int)TaskTypeEnum.InEmpty, |
| | |
| | | _stockInfoRepository.UpdateData(stock); |
| | | _taskRepository.AddData(newTask); |
| | | |
| | | //var moveResult = await _eSSApiService.MoveContainerAsync(new MoveContainerRequest |
| | | //{ |
| | | // slotCode = movestations[station], |
| | | // containerCode = palletCode |
| | | //}); |
| | | var moveResult = await _eSSApiService.MoveContainerAsync(new MoveContainerRequest |
| | | { |
| | | slotCode = movestations[station], |
| | | containerCode = palletCode |
| | | }); |
| | | return content.OK(); |
| | | |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | public WebResponseContent RecheckPicking(RecheckPickingDTO pickingDTO) |
| | | { |
| | | try |
| | | { |
| | | Dt_ReCheckOrder reCheckOrder = _outboundRepository.Db.Queryable<Dt_ReCheckOrder>().Where(x => x.OrderNo == pickingDTO.orderNo && x.Result == 0).First(); |
| | | if(reCheckOrder == null) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æªæ¾å°è¯¥å¾
鿣çåæ®{pickingDTO.orderNo}"); |
| | | } |
| | | Dt_StockInfoDetail stockInfoDetail = _stockDetailRepository.QueryFirst(x=>x.Barcode == pickingDTO.barCode && x.Status == StockStatusEmun.æå¨å»ç».ObjToInt() ); |
| | | if(stockInfoDetail == null) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æªå¨åºå䏿¾å°è¯¥å»ç»/é离æ¡ç {pickingDTO.barCode}"); |
| | | } |
| | | if (stockInfoDetail.MaterielCode != reCheckOrder.MaterielCode || stockInfoDetail.BatchNo != reCheckOrder.BatchNo) |
| | | { |
| | | return WebResponseContent.Instance.Error("该æ¡ç çç©æç¼ç åæ¹æ¬¡åè¯¥éæ£åä¸ç¬¦"); |
| | | } |
| | | stockInfoDetail.OrderNo = pickingDTO.orderNo; |
| | | stockInfoDetail.Status = StockStatusEmun.鿣ä¸.ObjToInt(); |
| | | var currentRemark = _outboundRepository.Db.Queryable<Dt_OutboundOrder>() |
| | | .Where(x => x.OrderNo == pickingDTO.orderNo) |
| | | .Select(x => x.Remark) |
| | | .First(); |
| | | |
| | | string newRemark; |
| | | if (string.IsNullOrWhiteSpace(currentRemark)) |
| | | { |
| | | newRemark = pickingDTO.barCode; |
| | | } |
| | | else |
| | | { |
| | | var existingCodes = currentRemark.Split(',', StringSplitOptions.RemoveEmptyEntries) |
| | | .Select(s => s.Trim()) |
| | | .ToList(); |
| | | |
| | | if (!existingCodes.Contains(pickingDTO.barCode)) |
| | | { |
| | | existingCodes.Add(pickingDTO.barCode); |
| | | newRemark = string.Join(",", existingCodes); |
| | | } |
| | | else |
| | | { |
| | | newRemark = currentRemark; |
| | | } |
| | | } |
| | | _outboundRepository.Db.Updateable<Dt_OutboundOrder>() |
| | | .SetColumns(x => x.Remark == newRemark) |
| | | .SetColumns(x=>x.OrderStatus == (int)OutOrderStatusEnum.åºåºå®æ) |
| | | .Where(x => x.OrderNo == pickingDTO.orderNo) |
| | | .ExecuteCommand(); |
| | | _stockDetailRepository.UpdateData(stockInfoDetail); |
| | | |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | | catch(Exception ex) |
| | | { |
| | | return WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | } |
| | | |
| | | #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 |
| | | |
| | | |
| | | } |
| | | } |