heshaofeng
2025-12-29 266e4bf654c55ce2f7e9271048e4625f1b8b49f6
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs
@@ -1,6 +1,15 @@
using Newtonsoft.Json;
using System.Reflection.Emit;
using AutoMapper;
using Dm.filter;
using MailKit.Search;
using Mapster;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Org.BouncyCastle.Asn1.Ocsp;
using Org.BouncyCastle.Crypto;
using SqlSugar;
using WIDESEA_BasicService;
using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.OrderEnum;
using WIDESEA_Common.StockEnum;
@@ -9,6 +18,7 @@
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.CodeConfigEnum;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Basic;
using WIDESEA_DTO.CalcOut;
using WIDESEA_DTO.ReturnMES;
using WIDESEA_IBasicService;
@@ -16,12 +26,13 @@
using WIDESEA_IRecordService;
using WIDESEA_IStockService;
using WIDESEA_Model.Models;
using static HslCommunication.Profinet.Knx.KnxCode;
namespace WIDESEA_OutboundService
{
    public partial class OutboundService : IOutboundService
    {
        private readonly IMapper _mapper;
        public IUnitOfWorkManage _unitOfWorkManage { get; }
        public IOutboundOrderDetailService OutboundOrderDetailService { get; }
@@ -42,9 +53,28 @@
        private readonly IRepository<Dt_LocationInfo> _locationInfoRepository;
        private readonly IRepository<Dt_StockQuantityChangeRecord> _stockChangeRepository;
        private readonly IRepository<Dt_StockInfoDetail_Hty> _stockDetailHistoryRepository;
        private readonly IFeedbackMesService _feedbackMesService;
        private readonly IRepository<Dt_Task> _taskRepository;
        private readonly ILocationInfoService _locationInfoService;
        private readonly IESSApiService _eSSApiService;
        private readonly IRepository<Dt_AllocateOrder> _allocateOrderRepository;
        private readonly IRepository<Dt_AllocateMaterialInfo> _allocateMaterialInfoRepository;
        public OutboundService(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)
        private Dictionary<string, string> stations = new Dictionary<string, string>
        {
            {"2-1","2-9" },
            {"3-1","3-9" },
        };
        private Dictionary<string, string> movestations = new Dictionary<string, string>
        {
            {"2-1","2-5" },
            {"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)
        {
            _mapper = mapper;
            _unitOfWorkManage = unitOfWorkManage;
            Db = _unitOfWorkManage.GetDbClient();
            OutboundOrderDetailService = outboundOrderDetailService;
@@ -59,8 +89,15 @@
            _stockChangeRepository = stockChangeRepository;
            _stockDetailHistoryRepository = stockDetailHistoryRepository;
            _basicService = basicService;
            _feedbackMesService = feedbackMesService;
            _taskRepository = taskRepository;
            _locationInfoService = locationInfoService;
            _eSSApiService = eSSApiService;
            _allocateOrderRepository = allocateOrderRepository;
            _allocateMaterialInfoRepository = allocateMaterialInfoRepository;
        }
        #region å‡ºåº“分配
        /// <summary>
        /// åˆ†æ‹£å‡ºåº“操作
        /// </summary>
@@ -73,6 +110,7 @@
            PickingOutboundResponseDTO response = new PickingOutboundResponseDTO();
            try
            {
                _unitOfWorkManage.BeginTran();
                // 1. è®¡ç®—出库数量逻辑
                OutboundCalculationDTO calculationResult = CalcOutboundQuantity(request);
@@ -133,14 +171,19 @@
                    pickedDetails.AddRange(materielPickedDetails.PickedDetails);
                    decimal allallocatedQuantity = Math.Min(materielCalc.UnallocatedQuantity, materielPickedDetails.PickedDetails.Sum(x => x.OutboundQuantity));
                    materielCalc.UnallocatedQuantity = allallocatedQuantity;
                    // æ›´æ–°å‡ºåº“单明细(增加锁定数量,不增加已出数量)
                    foreach (var detail in materielCalc.Details)
                    {
                        if (allallocatedQuantity <= 0) break;
                        decimal lockQuantity = (detail.OrderQuantity - detail.OverOutQuantity);
                        if (lockQuantity < materielCalc.UnallocatedQuantity)
                        {
                            detail.LockQuantity += lockQuantity; // å¢žåŠ é”å®šæ•°é‡ ä¸æ›´æ–° OverOutQuantity å’Œ OrderDetailStatus,因为还没有实际出库
                            outboundOrderDetails.Add(detail);
                            materielCalc.UnallocatedQuantity -= lockQuantity;
                        }
                        else
                        {
@@ -165,6 +208,9 @@
                // 7. æ›´æ–°åº“存详情
                UpdateOutStockLockInfo(outStockLockInfos);
                // 8. æ·»åŠ ä»»åŠ¡æ•°æ®
                _taskRepository.AddData(tasks);
                _unitOfWorkManage.CommitTran();
@@ -204,14 +250,23 @@
                }
                result.FactoryArea = outboundOrder.FactoryArea;
                List<Dt_OutboundOrderDetail> selectedDetails = new List<Dt_OutboundOrderDetail>();
                // èŽ·å–é€‰æ‹©çš„å‡ºåº“æ˜Žç»†
                List<Dt_OutboundOrderDetail> selectedDetails = _detailRepository.QueryData(x => x.OrderId == outboundOrder.Id && request.DetailIds.Contains(x.Id));
                if (outboundOrder.IsBatch == 1)
                if (request.DetailIds == null || !request.DetailIds.Any())
                {
                    selectedDetails = _detailRepository.QueryData(x => x.WarehouseCode == selectedDetails.First().WarehouseCode && x.MaterielCode == selectedDetails.First().MaterielCode && x.BatchNo == selectedDetails.First().BatchNo && x.SupplyCode == selectedDetails.First().SupplyCode);
                    selectedDetails = _detailRepository.QueryData(x => x.OrderId == outboundOrder.Id);
                }
                else
                {
                    // èŽ·å–é€‰æ‹©çš„å‡ºåº“æ˜Žç»†
                    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())
@@ -232,7 +287,7 @@
                result.OutboundOrder = outboundOrder;
                result.SelectedDetails = selectedDetails;
                if (outboundOrder.IsBatch == 0)
                if (outboundOrder.IsBatch == 0 || request.DetailIds.Count != 1)
                {
                    // å¤šæ˜Žç»†å‡ºåº“:按物料分组处理
                    result.MaterielCalculations = CalcMaterielOutboundQuantities(outboundOrder, selectedDetails.ToList());
@@ -262,6 +317,18 @@
                        return result;
                    }
                    decimal inputQuantity = request.OutboundQuantity.Value;
                    List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>();
                    foreach (var item in selectedDetails)
                    {
                        inputQuantity -= (item.OrderQuantity - item.MoveQty - item.LockQuantity);
                        outboundOrderDetails.Add(item);
                        if (inputQuantity <= 0)
                        {
                            break;
                        }
                    }
                    result.MaterielCalculations = new List<MaterielOutboundCalculationDTO>()
                    {
                        new MaterielOutboundCalculationDTO
@@ -276,9 +343,11 @@
                            AssignedQuantity = lockQuantity,
                            UnallocatedQuantity = request.OutboundQuantity.Value,
                            MovedQuantity = moveQuantity,
                            Details = selectedDetails
                            Details = outboundOrderDetails
                        }
                    };
                    outboundOrder.Details = outboundOrderDetails;
                }
                result.CanOutbound = true;
@@ -305,7 +374,6 @@
                .GroupBy(x => new
                {
                    x.MaterielCode,
                    x.MaterielName,
                    x.BatchNo,
                    x.SupplyCode,
                    x.WarehouseCode
@@ -313,7 +381,6 @@
                .Select(g => new MaterielOutboundCalculationDTO
                {
                    MaterielCode = g.Key.MaterielCode,
                    MaterielName = g.Key.MaterielName,
                    BatchNo = g.Key.BatchNo,
                    SupplyCode = g.Key.SupplyCode,
                    WarehouseCode = g.Key.WarehouseCode,
@@ -365,13 +432,15 @@
            Dictionary<int, List<Dt_OutStockLockInfo>> lockStockMap = data.LockStockMap;
            // éªŒè¯æ€»å¯ç”¨åº“存是否满足出库需求
            if (totalAvailableStock < materielCalc.UnallocatedQuantity)
            {
                throw new Exception($"物料 {materielCalc.MaterielCode} å¯ç”¨åº“å­˜ {totalAvailableStock} ä¸è¶³å‡ºåº“数量 {materielCalc.UnallocatedQuantity}");
            }
            //if (totalAvailableStock < materielCalc.UnallocatedQuantity)
            //{
            //    throw new Exception($"物料 {materielCalc.MaterielCode} å¯ç”¨åº“å­˜ {totalAvailableStock} ä¸è¶³å‡ºåº“数量 {materielCalc.UnallocatedQuantity}");
            //}
            // éœ€åˆ†é…æ•°é‡
            decimal remainingQuantity = Math.Min(totalAvailableStock, materielCalc.UnallocatedQuantity);
            // éœ€åˆ†é…æ•°é‡
            decimal remainingQuantity = materielCalc.UnallocatedQuantity;
            //decimal remainingQuantity = materielCalc.UnallocatedQuantity;
            // å·²åˆ†é…çš„æ‰˜ç›˜åˆ—表
            List<string> allocatedPallets = new List<string>();
@@ -480,7 +549,7 @@
        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);
            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))
@@ -783,8 +852,374 @@
                return false;
            }
        }
        #endregion
        #region æ•´ç®±å‡ºåº“
        public WebResponseContent CompleteOutboundWithPallet(OutboundCompletePalletRequestDTO request)
        {
            WebResponseContent content = WebResponseContent.Instance;
            OutboundCompleteResponseDTO response = new();
            try
            {
                // 1. æ ¹æ®æ‰˜ç›˜å·æŸ¥æ‰¾åº“存信息
                Dt_StockInfo stockInfo = _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == request.PalletCode).Includes(x => x.Details).First();
                if (stockInfo == null)
                {
                    response.Success = false;
                    response.Message = $"托盘号 {request.PalletCode} å¯¹åº”的库存不存在";
                    return WebResponseContent.Instance.Error(response.Message);
                }
                if (!stockInfo.Details.Any())
                {
                    response.Success = false;
                    response.Message = $"托盘 {request.PalletCode} å¯¹åº”的库存明细不存在";
                    return WebResponseContent.Instance.Error(response.Message);
                }
                bool isMatMixed = stockInfo.Details.GroupBy(x => new
                {
                    x.MaterielCode,
                    x.MaterielName,
                    x.BatchNo,
                    x.SupplyCode,
                    x.WarehouseCode
                }).Count() > 1;
                if (isMatMixed)
                {
                    response.Success = false;
                    response.Message = $"混料托盘 {request.PalletCode} ä¸èƒ½æ•´ç®±å‡ºåº“";
                    return WebResponseContent.Instance.Error(response.Message);
                }
                // 2. æŸ¥æ‰¾å‡ºåº“单信息
                Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(o => o.OrderNo == request.OrderNo);
                if (outboundOrder == null)
                {
                    response.Success = false;
                    response.Message = $"出库单 {request.OrderNo} ä¸å­˜åœ¨";
                    return WebResponseContent.Instance.Error(response.Message);
                }
                Dt_StockInfoDetail stockInfoDetail = stockInfo.Details.First();
                // 3. æŸ¥æ‰¾é”å®šè®°å½•
                Dt_OutStockLockInfo lockInfo = _outboundLockInfoRepository.QueryFirst(x =>
                    x.OrderNo == request.OrderNo &&
                    x.StockId == stockInfo.Id &&
                    x.MaterielCode == stockInfoDetail.MaterielCode &&
                    x.PalletCode == stockInfo.PalletCode);
                if (lockInfo == null || lockInfo.AssignQuantity <= 0)
                {
                    response.Success = false;
                    response.Message = $"该库存没有分配出库量,托盘号:{request.PalletCode}";
                    return WebResponseContent.Instance.Error(response.Message);
                }
                // æ‰¾å‡ºå·²åˆ†é…çš„订单明细Id
                List<int> detailIds = new List<int>();
                string[] ids = lockInfo.OrderDetailIds.Split(",");
                foreach (string id in ids)
                {
                    if (int.TryParse(id, out int detailId))
                    {
                        detailIds.Add(detailId);
                    }
                }
                // 4. æŸ¥æ‰¾å‡ºåº“单明细信息
                List<Dt_OutboundOrderDetail> outboundOrderDetails = FindMatchingOutboundDetails(outboundOrder.Id, stockInfoDetail, detailIds);
                if (!outboundOrderDetails.Any())
                {
                    response.Success = false;
                    response.Message = $"未找到匹配的出库单明细,物料:{stockInfoDetail.MaterielCode},批次:{stockInfoDetail.BatchNo}";
                    return WebResponseContent.Instance.Error(response.Message);
                }
                decimal totalStockQuantity = stockInfo.Details.Sum(x => x.StockQuantity);
                // 5. è®¡ç®—实际出库量
                decimal actualOutboundQuantity = CalculateActualOutboundQuantity(stockInfo.Details, outboundOrderDetails, lockInfo);// éœ€å‡ºåº“量
                if (actualOutboundQuantity <= 0)
                {
                    decimal totalAllocatedQuantity = lockInfo.AllocatedQuantity;
                    decimal availableOutboundQuantity = lockInfo.AssignQuantity - totalAllocatedQuantity;
                    decimal detailRemainingQuantity = outboundOrderDetails.Sum(x => x.OrderQuantity - x.OverOutQuantity - x.MoveQty);
                    response.Success = false;
                    response.Message = $"无法出库,托盘号:{request.PalletCode},库存量:{totalStockQuantity},已出库:{totalAllocatedQuantity},分配量:{lockInfo.AssignQuantity},明细剩余:{detailRemainingQuantity}";
                    return WebResponseContent.Instance.Error(response.Message);
                }
                if (lockInfo.AssignQuantity != totalStockQuantity)
                {
                    response.Success = false;
                    response.Message = $"无法出库,托盘号:{request.PalletCode},库存量:{totalStockQuantity},分配量:{lockInfo.AssignQuantity}";
                    return WebResponseContent.Instance.Error(response.Message);
                }
                // 6. å¼€å¯äº‹åŠ¡
                _unitOfWorkManage.BeginTran();
                try
                {
                    // æ•´ç®±å‡ºåº“无需拆包
                    PerformFullOutboundOperation(stockInfo, request, lockInfo.TaskNum.GetValueOrDefault());
                    if (outboundOrder.OrderType != 0)
                    {
                        Dt_AllocateOrder allocateOrder = _allocateOrderRepository.QueryFirst(x => x.OrderNo == outboundOrder.OrderNo);
                        if (allocateOrder != null)
                        {
                            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 = allocateOrder.ToWarehouse
                                };
                                allocateMaterialInfos.Add(allocateMaterialInfo);
                            }
                            _allocateMaterialInfoRepository.AddData(allocateMaterialInfos);
                        }
                    }
                    decimal allocatedQuantity = actualOutboundQuantity;
                    List<Dt_OutboundOrderDetail> updateDetails = new();
                    foreach (var item in outboundOrderDetails)
                    {
                        if (allocatedQuantity <= 0) break;
                        //if (item.OrderQuantity - item.MoveQty - item.OverOutQuantity >= allocatedQuantity)
                        //{
                        //    item.OverOutQuantity += allocatedQuantity;
                        //    allocatedQuantity = 0;
                        //}
                        //else
                        //{
                        //    allocatedQuantity -= (item.OrderQuantity - item.MoveQty - item.OverOutQuantity);
                        //    item.OverOutQuantity = item.OrderQuantity - item.MoveQty;
                        //}
                        List<Barcodes> barcodesList = new List<Barcodes>();
                        List<Dt_StockInfoDetail> stockInfoDetails = stockInfo.Details.Where((x => x.StockQuantity > x.OutboundQuantity)).ToList();
                        decimal itemQuantity = item.LockQuantity - item.OverOutQuantity;
                        foreach (var stockDetail in stockInfoDetails)
                        {
                            if (itemQuantity >= stockDetail.StockQuantity - stockDetail.OutboundQuantity)
                            {
                                Barcodes barcodes = new Barcodes
                                {
                                    Barcode = stockDetail.Barcode,
                                    Qty = stockDetail.StockQuantity - stockDetail.OutboundQuantity,
                                    SupplyCode = stockDetail?.SupplyCode ?? "",
                                    BatchNo = stockDetail?.BatchNo ?? "",
                                    Unit = stockDetail?.Unit ?? ""
                                };
                                itemQuantity -= (stockDetail.StockQuantity - stockDetail.OutboundQuantity);
                                stockDetail.OutboundQuantity = stockDetail.StockQuantity;
                                barcodesList.Add(barcodes);
                                if (itemQuantity <= 0) break;
                            }
                            else
                            {
                                Barcodes barcodes = new Barcodes
                                {
                                    Barcode = stockDetail.Barcode,
                                    Qty = itemQuantity,
                                    SupplyCode = stockDetail?.SupplyCode ?? "",
                                    BatchNo = stockDetail?.BatchNo ?? "",
                                    Unit = stockDetail?.Unit ?? ""
                                };
                                stockDetail.OutboundQuantity += itemQuantity;
                                barcodesList.Add(barcodes);
                                break;
                            }
                        }
                        decimal barcodeQuantity = allocatedQuantity;
                        if (item.LockQuantity - item.OverOutQuantity >= allocatedQuantity)
                        {
                            item.OverOutQuantity += allocatedQuantity;
                            item.CurrentDeliveryQty += allocatedQuantity;
                            allocatedQuantity = 0;
                        }
                        else
                        {
                            barcodeQuantity = item.LockQuantity - item.OverOutQuantity;
                            allocatedQuantity -= (item.LockQuantity - item.OverOutQuantity);
                            item.OverOutQuantity = item.LockQuantity;
                            item.CurrentDeliveryQty = item.LockQuantity;
                        }
                        updateDetails.Add(item);
                        if (!string.IsNullOrEmpty(item.ReturnJsonData))
                        {
                            barcodesList.AddRange(JsonConvert.DeserializeObject<List<Barcodes>>(item.ReturnJsonData) ?? new List<Barcodes>());
                        }
                        JsonSerializerSettings settings = new JsonSerializerSettings
                        {
                            ContractResolver = new CamelCasePropertyNamesContractResolver()
                        };
                        item.ReturnJsonData = JsonConvert.SerializeObject(barcodesList, settings);
                    }
                    lockInfo.SortedQuantity = lockInfo.SortedQuantity + actualOutboundQuantity;
                    if (lockInfo.SortedQuantity == lockInfo.AssignQuantity)
                    {
                        _outboundLockInfoRepository.DeleteAndMoveIntoHty(lockInfo, WIDESEA_Core.Enums.OperateTypeEnum.自动完成);
                    }
                    else
                    {
                        // æ›´æ–°é”å®šè®°å½•
                        _outboundLockInfoRepository.UpdateData(lockInfo);
                    }
                    // æ›´æ–°å‡ºåº“单明细的已出库数量
                    _detailRepository.UpdateData(updateDetails);
                    // æ›´æ–°é”å®šè®°å½•的累计已出库数量(需要更新该托盘该物料的所有相关记录)
                    //UpdateLockInfoAllocatedQuantity(stockInfo.Id, stockDetail.MaterielCode, stockDetail.BatchNo, actualOutboundQuantity);
                    // æäº¤äº‹åŠ¡
                    _unitOfWorkManage.CommitTran();
                    response.Success = true;
                    response.Message = "出库完成";
                    response.UpdatedDetails = updateDetails;
                    // æ£€æŸ¥å‡ºåº“单是否完成
                    if (CheckOutboundOrderCompleted(request.OrderNo))
                    {
                        UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.出库完成.ObjToInt());
                        if (outboundOrder.OrderType != OutOrderTypeEnum.InternalAllocat.ObjToInt())
                        {
                            _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _unitOfWorkManage.RollbackTran();
                    response.Success = false;
                    response.Message = $"出库处理失败:{ex.Message}";
                    return WebResponseContent.Instance.Error(ex.Message);
                }
                content = WebResponseContent.Instance.OK(data: response);
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error("处理出库完成失败:" + ex.Message);
            }
            return content;
        }
        /// <summary>
        /// è®¡ç®—实际出库数量
        /// </summary>
        private decimal CalculateActualOutboundQuantity(List<Dt_StockInfoDetail> stockDetails, List<Dt_OutboundOrderDetail> outboundDetails, Dt_OutStockLockInfo lockInfo)
        {
            decimal availableOutboundQuantity = lockInfo.AssignQuantity;
            decimal detailRemainingQuantity = outboundDetails.Sum(x => x.OrderQuantity - x.OverOutQuantity - x.MoveQty);//outboundDetail.OrderQuantity - outboundDetail.OverOutQuantity;
            return Math.Min(
                Math.Min(availableOutboundQuantity, detailRemainingQuantity),
                stockDetails.Sum(x => x.StockQuantity));
        }
        /// <summary>
        /// æ‰§è¡Œå®Œæ•´å‡ºåº“操作(不拆包)
        /// </summary>
        private void PerformFullOutboundOperation(Dt_StockInfo stockInfo, OutboundCompletePalletRequestDTO request, int taskNum)
        {
            List<Dt_StockInfoDetail_Hty> historyRecords = new List<Dt_StockInfoDetail_Hty>();
            List<Dt_StockQuantityChangeRecord> changeRecords = new List<Dt_StockQuantityChangeRecord>();
            foreach (var item in stockInfo.Details)
            {
                // ä¿å­˜åº“存明细到历史记录
                Dt_StockInfoDetail_Hty historyRecord = new Dt_StockInfoDetail_Hty
                {
                    SourceId = item.Id,
                    OperateType = "出库完成",
                    InsertTime = DateTime.Now,
                    StockId = item.StockId,
                    MaterielCode = item.MaterielCode,
                    MaterielName = item.MaterielName,
                    OrderNo = item.OrderNo,
                    BatchNo = item.BatchNo,
                    ProductionDate = item.ProductionDate,
                    EffectiveDate = item.EffectiveDate,
                    SerialNumber = item.SerialNumber,
                    StockQuantity = item.StockQuantity,
                    OutboundQuantity = item.StockQuantity,
                    Status = item.Status,
                    Unit = item.Unit,
                    InboundOrderRowNo = item.InboundOrderRowNo,
                    SupplyCode = item.SupplyCode,
                    FactoryArea = item.FactoryArea,
                    WarehouseCode = item.WarehouseCode,
                    Barcode = item.Barcode,
                    CreateDate = item.CreateDate,
                    Creater = item.Creater,
                    Remark = $"整箱出库完成删除,条码:{request.PalletCode},原数量:{item.StockQuantity},出库数量:{item.StockQuantity},操作者:{request.Operator}"
                };
                historyRecords.Add(historyRecord);
                // è®°å½•库存变动
                Dt_StockQuantityChangeRecord changeRecord = new Dt_StockQuantityChangeRecord
                {
                    StockDetailId = item.Id,
                    PalleCode = stockInfo.PalletCode,
                    MaterielCode = item.MaterielCode,
                    MaterielName = item.MaterielName,
                    BatchNo = item.BatchNo,
                    OriginalSerilNumber = item.Barcode,
                    NewSerilNumber = "",
                    OrderNo = request.OrderNo,
                    TaskNum = taskNum,
                    ChangeType = (int)StockChangeTypeEnum.Outbound,
                    ChangeQuantity = -item.StockQuantity,
                    BeforeQuantity = item.StockQuantity,
                    AfterQuantity = 0,
                    SupplyCode = item.SupplyCode,
                    WarehouseCode = item.WarehouseCode,
                    Remark = $"整箱出库完成删除库存明细,条码:{request.PalletCode},出库数量:{item.StockQuantity},操作者:{request.Operator}"
                };
                changeRecords.Add(changeRecord);
            }
            _stockDetailHistoryRepository.AddData(historyRecords);
            // åˆ é™¤åº“存明细记录
            _stockDetailRepository.DeleteData(stockInfo.Details);
            _stockChangeRepository.AddData(changeRecords);
        }
        #endregion
        #region æ‹£é€‰
        /// <summary>
        /// å‡ºåº“完成处理(扫描条码扣减库存)
        /// </summary>
@@ -879,31 +1314,86 @@
                    return WebResponseContent.Instance.Error($"无法出库,条码:{request.Barcode},库存:{stockDetail.StockQuantity},已出库:{totalAllocatedQuantity},分配量:{lockInfo.AssignQuantity},明细剩余:{detailRemainingQuantity}");
                }
                if (actualOutboundQuantity + lockInfo.SortedQuantity > lockInfo.AssignQuantity)
                {
                    response.Success = false;
                    response.Message = $"无法出库,条码:{request.Barcode},库存:{stockDetail.StockQuantity},出库量{actualOutboundQuantity + lockInfo.SortedQuantity}大于分配量{lockInfo.AssignQuantity}";
                    return WebResponseContent.Instance.Error($"无法出库,条码:{request.Barcode},库存:{stockDetail.StockQuantity},出库量{actualOutboundQuantity + lockInfo.SortedQuantity}大于分配量{lockInfo.AssignQuantity}");
                }
                //if (actualOutboundQuantity + lockInfo.SortedQuantity > lockInfo.AssignQuantity)
                //{
                //    response.Success = false;
                //    response.Message = $"无法出库,条码:{request.Barcode},库存:{stockDetail.StockQuantity},出库量{actualOutboundQuantity + lockInfo.SortedQuantity}大于分配量{lockInfo.AssignQuantity}";
                //    return WebResponseContent.Instance.Error($"无法出库,条码:{request.Barcode},库存:{stockDetail.StockQuantity},出库量{actualOutboundQuantity + lockInfo.SortedQuantity}大于分配量{lockInfo.AssignQuantity}");
                //}
                // 8. åˆ¤æ–­æ˜¯å¦éœ€è¦æ‹†åŒ…(当出库数量小于库存数量时需要拆包)
                bool isUnpacked = actualOutboundQuantity < stockDetail.StockQuantity;
                List<MaterialCodeReturnDTO> returnDTOs = new List<MaterialCodeReturnDTO>();
                string newBarcode = string.Empty;
                // 9. å¼€å¯äº‹åŠ¡
                _unitOfWorkManage.BeginTran();
                try
                {
                    decimal beforeQuantity = stockDetail.StockQuantity; // åŽŸå§‹åº“å­˜é‡
                    Dt_AllocateMaterialInfo allocateMaterialInfo = new Dt_AllocateMaterialInfo();
                    // æ ¹æ®æ˜¯å¦æ‹†åŒ…执行不同的操作
                    if (isUnpacked)
                    {
                        newBarcode = PerformUnpackOperation(stockDetail, stockInfo, actualOutboundQuantity, request, beforeQuantity, lockInfo.TaskNum.GetValueOrDefault());
                        (string NewBarcode, List<MaterialCodeReturnDTO> MaterialCodeReturnDTOs) result = PerformUnpackOperation(stockDetail, stockInfo, actualOutboundQuantity, request, beforeQuantity, lockInfo.TaskNum.GetValueOrDefault(), outboundOrder.Id, outboundOrder.OrderNo);
                        returnDTOs = result.MaterialCodeReturnDTOs;
                        newBarcode = result.NewBarcode;
                        MaterialCodeReturnDTO returnDTO = returnDTOs.First(x => x.Barcode == newBarcode);
                        if (outboundOrder.OrderType != 0)
                        {
                            allocateMaterialInfo = new Dt_AllocateMaterialInfo()
                            {
                                Barcode = returnDTO.Barcode,
                                BatchNo = returnDTO.BatchNo,
                                FactoryArea = returnDTO.FactoryArea,
                                MaterialCode = returnDTO.MaterialCode,
                                MaterialName = returnDTO.MaterialName,
                                OrderId = outboundOrder.Id,
                                OrderNo = outboundOrder.OrderNo,
                                Quantity = returnDTO.Quantity,
                                SupplyCode = returnDTO.SuplierCode,
                                Unit = stockDetail.Unit
                            };
                        }
                    }
                    else
                    {
                        PerformFullOutboundOperation(stockDetail, stockInfo, actualOutboundQuantity, request, beforeQuantity, lockInfo.TaskNum.GetValueOrDefault());
                        if (outboundOrder.OrderType != 0)
                        {
                            allocateMaterialInfo = new Dt_AllocateMaterialInfo()
                            {
                                Barcode = stockDetail.Barcode,
                                BatchNo = stockDetail.BatchNo,
                                FactoryArea = stockDetail.FactoryArea,
                                MaterialCode = stockDetail.MaterielCode,
                                MaterialName = stockDetail.MaterielName,
                                OrderId = outboundOrder.Id,
                                OrderNo = outboundOrder.OrderNo,
                                Quantity = stockDetail.StockQuantity,
                                SupplyCode = stockDetail.SupplyCode,
                                Unit = stockDetail.Unit
                            };
                        }
                    }
                    // åˆ¤æ–­æ˜¯å¦æ˜¯è°ƒæ‹¨å•
                    if (outboundOrder.OrderType != 0)
                    {
                        Dt_AllocateOrder allocateOrder = _allocateOrderRepository.QueryFirst(x => x.OrderNo == outboundOrder.OrderNo);
                        if (allocateOrder != null)
                        {
                            allocateMaterialInfo.WarehouseCode = allocateOrder.ToWarehouse;
                            _allocateMaterialInfoRepository.AddData(allocateMaterialInfo);
                        }
                    }
                    decimal allocatedQuantity = actualOutboundQuantity;
@@ -924,6 +1414,8 @@
                        //    item.OverOutQuantity = item.OrderQuantity - item.MoveQty;
                        //}
                        decimal barcodeQuantity = allocatedQuantity;
                        if (item.LockQuantity - item.OverOutQuantity >= allocatedQuantity)
                        {
                            item.OverOutQuantity += allocatedQuantity;
@@ -932,6 +1424,7 @@
                        }
                        else
                        {
                            barcodeQuantity = item.LockQuantity - item.OverOutQuantity;
                            allocatedQuantity -= (item.LockQuantity - item.OverOutQuantity);
                            item.OverOutQuantity = item.LockQuantity;
                            item.CurrentDeliveryQty = item.LockQuantity;
@@ -942,8 +1435,8 @@
                        List<Barcodes> barcodesList = new List<Barcodes>();
                        Barcodes barcodes = new Barcodes
                        {
                            Barcode = request.Barcode,
                            Qty = actualOutboundQuantity,
                            Barcode = isUnpacked ? newBarcode : stockDetail?.Barcode,
                            Qty = barcodeQuantity,
                            SupplyCode = stockDetail?.SupplyCode ?? "",
                            BatchNo = stockDetail?.BatchNo ?? "",
                            Unit = stockDetail?.Unit ?? ""
@@ -993,21 +1486,30 @@
                        BeforeQuantity = beforeQuantity,
                        AfterQuantity = isUnpacked ? actualOutboundQuantity : 0,
                        ChangeQuantity = -actualOutboundQuantity,
                        IsUnpacked = isUnpacked
                        IsUnpacked = isUnpacked,
                        MaterialCodes = returnDTOs
                    };
                    response.Success = true;
                    response.Message = isUnpacked ? $"拆包出库完成,已生成新条码:{newBarcode}" : "出库完成";
                    response.Message = "出库完成";
                    response.ScannedDetail = scannedDetail;
                    response.UpdatedDetails = updateDetails;
                    response.NewBarcode = newBarcode;
                    if (!string.IsNullOrEmpty(newBarcode))
                    {
                        // ç‰©æ–™æ–°æ¡ç å›žä¼ 
                        _feedbackMesService.BarcodeFeedback(newBarcode);
                    }
                    // æ£€æŸ¥å‡ºåº“单是否完成
                    if (CheckOutboundOrderCompleted(request.OrderNo))
                    {
                        UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.出库完成.ObjToInt());
                        //todo: å›žä¼ MES
                        if (outboundOrder.OrderType != OutOrderTypeEnum.InternalAllocat.ObjToInt())
                        {
                            _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo);
                        }
                    }
                }
                catch (Exception ex)
@@ -1074,10 +1576,16 @@
        /// <param name="beforeQuantity"></param>
        /// <param name="taskNum"></param>
        /// <returns></returns>
        private string PerformUnpackOperation(Dt_StockInfoDetail stockDetail, Dt_StockInfo stockInfo,
            decimal actualOutboundQuantity, OutboundCompleteRequestDTO request, decimal beforeQuantity, int taskNum)
        private (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();
            string remark = $"拆包记录,原条码:{request.Barcode},原数量:{stockDetail.StockQuantity},出库条码:{newBarcode}, å‡ºåº“数量:{actualOutboundQuantity},回库条码:{request.Barcode},回库数量:{stockDetail.StockQuantity - actualOutboundQuantity},操作者:{request.Operator}";
            List<Dt_MaterialCodeInfo> materialCodeInfos = CreateMaterialCodeInfos(stockDetail, newBarcode, actualOutboundQuantity, remark, taskNum, orderId, orderNo);
            List<MaterialCodeReturnDTO> returnDTOs = _mapper.Map<List<MaterialCodeReturnDTO>>(materialCodeInfos);
            // ä¿å­˜åŽŸå§‹åº“å­˜æ˜Žç»†åˆ°åŽ†å²è®°å½•
            Dt_StockInfoDetail_Hty originalHistoryRecord = new Dt_StockInfoDetail_Hty
@@ -1099,9 +1607,11 @@
                Unit = stockDetail.Unit,
                InboundOrderRowNo = stockDetail.InboundOrderRowNo,
                SupplyCode = stockDetail.SupplyCode,
                Creater = stockDetail.Creater,
                CreateDate = stockDetail.CreateDate,
                FactoryArea = stockDetail.FactoryArea,
                WarehouseCode = stockDetail.WarehouseCode,
                Remark = $"拆包前原始记录,原条码:{request.Barcode},原数量:{stockDetail.StockQuantity},出库数量:{actualOutboundQuantity},操作者:{request.Operator}"
                Remark = $"拆包前原始记录,出库单号:{orderNo},出库单主键:{orderId},原条码:{request.Barcode},原数量:{stockDetail.StockQuantity},出库数量:{actualOutboundQuantity},操作者:{request.Operator}"
            };
            _stockDetailHistoryRepository.AddData(originalHistoryRecord);
@@ -1112,7 +1622,7 @@
                // æ›´æ–°åŽŸåº“å­˜æ˜Žç»†
                stockDetail.StockQuantity = remainingQuantity;
                //stockDetail.Barcode = newBarcode;
                stockDetail.Remark = $"拆包后更新,原条码:{request.Barcode},新数量:{remainingQuantity},操作者:{request.Operator}";
                stockDetail.Remark = $"拆包后更新,出库单号:{orderNo},出库单主键:{orderId},原条码:{request.Barcode},新数量:{remainingQuantity},操作者:{request.Operator}";
                _stockDetailRepository.UpdateData(stockDetail);
            }
@@ -1134,11 +1644,11 @@
                AfterQuantity = beforeQuantity - actualOutboundQuantity,
                SupplyCode = stockDetail.SupplyCode,
                WarehouseCode = stockDetail.WarehouseCode,
                Remark = $"拆包出库,原条码:{request.Barcode},新条码:{newBarcode},出库数量:{actualOutboundQuantity},剩余:{remainingQuantity},操作者:{request.Operator}"
                Remark = $"拆包出库,出库单号:{orderNo},出库单主键:{orderId},原条码:{request.Barcode},新条码:{newBarcode},出库数量:{actualOutboundQuantity},剩余:{remainingQuantity},操作者:{request.Operator}"
            };
            _stockChangeRepository.AddData(unpackChangeRecord);
            return newBarcode;
            return (newBarcode, returnDTOs);
        }
        /// <summary>
@@ -1168,6 +1678,8 @@
                InboundOrderRowNo = stockDetail.InboundOrderRowNo,
                SupplyCode = stockDetail.SupplyCode,
                FactoryArea = stockDetail.FactoryArea,
                Creater = stockDetail.Creater,
                CreateDate = stockDetail.CreateDate,
                WarehouseCode = stockDetail.WarehouseCode,
                Remark = $"出库完成删除,条码:{request.Barcode},原数量:{stockDetail.StockQuantity},出库数量:{actualOutboundQuantity},操作者:{request.Operator}"
            };
@@ -1214,6 +1726,72 @@
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="stockDetail"></param>
        /// <param name="newBarcode"></param>
        /// <param name="splitQuantity"></param>
        /// <param name="afterQuantity"></param>
        /// <param name="remark"></param>
        /// <returns></returns>
        private List<Dt_MaterialCodeInfo> CreateMaterialCodeInfos(Dt_StockInfoDetail stockDetail, string newBarcode, decimal splitQuantity, string remark, int taskNum, int orderId, string orderNo)
        {
            List<Dt_MaterialCodeInfo> materialCodeInfos = new List<Dt_MaterialCodeInfo>();
            Dt_MaterielInfo? materielInfo = _basicService.MaterielInfoService.Repository.QueryFirst(x => x.MaterielCode == stockDetail.MaterielCode);
            Dt_MaterialCodeInfo outMaterialCodeInfo = new Dt_MaterialCodeInfo()
            {
                AfterQuantity = splitQuantity,
                BatchNo = stockDetail.BatchNo,
                FactoryArea = stockDetail.FactoryArea,
                MaterialName = materielInfo?.MaterielName ?? stockDetail.MaterielName,
                MaterialSpec = materielInfo?.MaterielSpec ?? "",
                MaterialCode = stockDetail.MaterielCode,
                NewBarcode = newBarcode,
                OldBarcode = stockDetail.Barcode,
                OriginalQuantity = stockDetail.StockQuantity,
                PruchaseOrderNo = stockDetail.OrderNo,
                SuplierCode = stockDetail.SupplyCode,
                Unit = stockDetail.Unit,
                Date = DateTime.Now.ToString("yyyy-MM-dd"),
                Remark = remark,
                WarehouseCode = stockDetail.WarehouseCode,
                OrderNo = orderNo,
                OrderId = orderId,
                ReturnStatus = 0
            };
            materialCodeInfos.Add(outMaterialCodeInfo);
            Dt_MaterialCodeInfo returnMaterialCodeInfo = new Dt_MaterialCodeInfo()
            {
                AfterQuantity = stockDetail.StockQuantity - splitQuantity,
                BatchNo = stockDetail.BatchNo,
                FactoryArea = stockDetail.FactoryArea,
                MaterialName = materielInfo?.MaterielName ?? stockDetail.MaterielName,
                MaterialSpec = materielInfo?.MaterielSpec ?? "",
                MaterialCode = stockDetail.MaterielCode,
                NewBarcode = stockDetail.Barcode,
                OldBarcode = stockDetail.Barcode,
                OriginalQuantity = stockDetail.StockQuantity,
                PruchaseOrderNo = stockDetail.OrderNo,
                SuplierCode = stockDetail.SupplyCode,
                Unit = stockDetail.Unit,
                Date = DateTime.Now.ToString("yyyy-MM-dd"),
                Remark = remark,
                WarehouseCode = stockDetail.WarehouseCode,
                OrderNo = orderNo,
                OrderId = orderId,
                ReturnStatus = 0
            };
            materialCodeInfos.Add(returnMaterialCodeInfo);
            _basicService.MaterielCodeInfoService.Repository.AddData(materialCodeInfos);
            return materialCodeInfos;
        }
        /// <summary>
        /// æ›´æ–°è¯¥æ‰˜ç›˜è¯¥ç‰©æ–™çš„æ‰€æœ‰é”å®šè®°å½•的累计已出库数量
        /// </summary>
        /// <param name="stockId">库存ID</param>
@@ -1255,5 +1833,123 @@
            // æ£€æŸ¥æ‰€æœ‰æ˜Žç»†çš„已出数量是否都等于单据数量
            return details.All(x => x.OverOutQuantity >= x.OrderQuantity - x.MoveQty);
        }
        #endregion
        #region å–空箱
        public async Task<WebResponseContent> EmptyBox(string palletCode)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                var stock = await _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Includes(x => x.Details).Where(x => x.PalletCode == palletCode).FirstAsync();
                if (stock == null)
                {
                    return content.Error($"未找到托盘{palletCode}库存信息");
                }
                if (stock.Details.Count > 0)
                {
                    return content.Error($"托盘{palletCode}还存在库存信息不允许取走");
                }
                Dt_StockInfo_Hty stockInfo_Hty = stock.Adapt<Dt_StockInfo_Hty>();
                stockInfo_Hty.SourceId = stock.Id;
                stockInfo_Hty.OperateType = "取空箱";
                stockInfo_Hty.InsertTime = DateTime.Now;
                _unitOfWorkManage.BeginTran();
                await _outboundRepository.Db.InsertNav(stockInfo_Hty).IncludesAllFirstLayer().ExecuteCommandAsync();
                await _stockInfoRepository.DeleteDataByIdAsync(stock.Id);
                _unitOfWorkManage.CommitTran();
                return content.OK();
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return content.Error(ex.Message);
            }
        }
        #endregion
        #region å›žåº“
        public async Task<WebResponseContent> ReturnToWarehouse(string palletCode, string OrderNo, string station)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                var stock = await _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Includes(x => x.Details).Where(x => x.PalletCode == palletCode).FirstAsync();
                if (stock == null)
                {
                    return content.Error($"未找到托盘{palletCode}库存信息不允许回库");
                }
                if (stock.Details.Count <= 0)
                {
                    stock.PalletType = (int)PalletTypeEnum.Empty;
                    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}库存未拣选完不允许回库");
                    }
                    stock.StockStatus = (int)StockStatusEmun.组盘暂存;
                    stock.LocationCode = "";
                }
                var task = await _taskRepository.Db.Queryable<Dt_Task>()
                    .Where(x => x.PalletCode == palletCode)
                    .FirstAsync();
                if (task != null)
                {
                    return content.Error($"托盘{palletCode}存在任务回库失败!");
                }
                // åˆ†é…æ–°è´§ä½
                var newLocation = _locationInfoService.AssignLocation(stock.LocationType);
                var newTask = new Dt_Task()
                {
                    CurrentAddress = stations.GetValueOrDefault(station) ?? "",
                    Grade = 0,
                    PalletCode = palletCode,
                    NextAddress = "",
                    OrderNo = OrderNo,
                    Roadway = newLocation.RoadwayNo,
                    SourceAddress = stations.GetValueOrDefault(station) ?? "",
                    TargetAddress = newLocation.LocationCode,
                    TaskStatus = (int)TaskStatusEnum.New,
                    TaskType = stock.Details.Count > 0 ? (int)TaskTypeEnum.InPick : (int)TaskTypeEnum.InEmpty,
                    PalletType = stock.PalletType,
                    WarehouseId = stock.WarehouseId
                };
                _stockInfoRepository.UpdateData(stock);
                _taskRepository.AddData(newTask);
                var moveResult = await _eSSApiService.MoveContainerAsync(new MoveContainerRequest
                {
                    slotCode = movestations[station],
                    containerCode = palletCode
                });
                return content.OK();
            }
            catch (Exception ex)
            {
                return content.Error(ex.Message);
            }
        }
        #endregion
    }
}