using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WIDESEA_Common.StockEnum; using WIDESEA_Core; using WIDESEA_Core.BaseRepository; using WIDESEA_Core.BaseServices; using WIDESEA_DTO.Outbound; using WIDESEA_IOutboundService; using WIDESEA_IStockService; using WIDESEA_Model.Models; namespace WIDESEA_OutboundService { internal class SplitPackageService : ServiceBase>, ISplitPackageService { private readonly IUnitOfWorkManage _unitOfWorkManage; public IRepository Repository => BaseDal; private readonly IStockInfoService _stockInfoService; private readonly IStockInfoDetailService _stockInfoDetailService; private readonly IOutStockLockInfoService _outStockLockInfoService; public SplitPackageService(IRepository BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService) : base(BaseDal) { _unitOfWorkManage = unitOfWorkManage; _stockInfoService = stockInfoService; _outStockLockInfoService = outStockLockInfoService; _stockInfoDetailService = stockInfoDetailService; } /// /// 拆包拆箱操作 /// public async Task SplitPackage(SplitPackageRequest request) { try { _unitOfWorkManage.BeginTran(); // 1. 验证出库锁定信息 var lockInfo = await Db.Queryable() .Where(x => x.Id == request.OutStockLockInfoId && x.Status == (int)OutLockStockStatusEnum.出库中) .FirstAsync(); if (lockInfo == null) return WebResponseContent.Instance.Error("未找到有效的出库锁定信息"); //// 2. 验证当前条码的可用数量 //var currentStockDetail = await _stockInfoDetailService.Db.Queryable() // .Where(x => x.Barcode == lockInfo.CurrentBarcode && // x.MaterielCode == request.MaterielCode && // x.StockId == lockInfo.StockId) // .FirstAsync(); //if (currentStockDetail == null) // return WebResponseContent.Instance.Error("当前条码在库存中不存在"); //// 3. 检查可用数量 //decimal availableQuantity = currentStockDetail.StockQuantity - currentStockDetail.OutboundQuantity; //if (request.SplitQuantity > availableQuantity) // return WebResponseContent.Instance.Error($"拆包数量不能大于可用数量,可用数量:{availableQuantity}"); // 2. 检查剩余锁定数量 decimal remainingLockQuantity = lockInfo.AssignQuantity - lockInfo.PickedQty; if (request.SplitQuantity > remainingLockQuantity) return WebResponseContent.Instance.Error($"拆包数量不能大于剩余锁定数量,剩余:{remainingLockQuantity}"); // 3. 生成新条码 string newBarcode = ""; // 4. 创建新的出库锁定信息(新条码) var newLockInfo = new Dt_OutStockLockInfo { OrderNo = lockInfo.OrderNo, OrderDetailId = lockInfo.OrderDetailId, BatchNo = lockInfo.BatchNo, MaterielCode = lockInfo.MaterielCode, MaterielName = lockInfo.MaterielName, StockId = lockInfo.StockId, OrderQuantity = lockInfo.OrderQuantity, OriginalQuantity = lockInfo.OriginalQuantity, AssignQuantity = request.SplitQuantity, // 新条码分配数量 PickedQty = 0, // 新条码未拣选 LocationCode = lockInfo.LocationCode, PalletCode = lockInfo.PalletCode, TaskNum = lockInfo.TaskNum, Status = (int)OutLockStockStatusEnum.出库中, Unit = lockInfo.Unit, CurrentBarcode = newBarcode, // 新条码 OriginalLockQuantity = request.SplitQuantity, IsSplitted = 1, ParentLockId = lockInfo.Id // 记录父级锁定ID }; await Db.Insertable(newLockInfo).ExecuteCommandAsync(); // 5. 更新原锁定信息的分配数量(减少拆包数量) lockInfo.AssignQuantity -= request.SplitQuantity; await Db.Updateable(lockInfo).ExecuteCommandAsync(); // 6. 记录拆包历史(用于追踪) var splitHistory = new Dt_SplitPackageRecord { OutStockLockInfoId = lockInfo.Id, OriginalBarcode = lockInfo.CurrentBarcode, NewBarcode = newBarcode, SplitQty = request.SplitQuantity, MaterielCode = request.MaterielCode, SplitTime = DateTime.Now, Operator = request.Operator, Status = (int)SplitPackageStatusEnum.已拆包 }; await Db.Insertable(splitHistory).ExecuteCommandAsync(); Db.Ado.CommitTran(); // 7. 回传新条码给MES // await SendBarcodeToMES(newBarcode, request.MaterielCode, request.SplitQuantity); return WebResponseContent.Instance.OK("拆包成功", new { NewBarcode = newBarcode, NewLockInfoId = newLockInfo.Id }); } catch (Exception ex) { Db.Ado.RollbackTran(); return WebResponseContent.Instance.Error($"拆包失败: {ex.Message}"); } } /// /// 获取可拆包的出库锁定信息 /// public async Task GetSplitableLockInfos(int orderDetailId) { var lockInfos = await _outStockLockInfoService.Db.Queryable() .Includes(x => x.StockInfo) .Where(x => x.OrderDetailId == orderDetailId && x.Status == (int)OutLockStockStatusEnum.出库中 && x.AssignQuantity > x.PickedQty) // 还有未拣选数量 .Select(x => new { x.Id, x.PalletCode, x.LocationCode, x.MaterielCode, LockQuantity = x.AssignQuantity - x.PickedQty, x.CurrentBarcode, x.IsSplitted, StockDetails = x.StockInfo.Details.Where(d => d.MaterielCode == x.MaterielCode) .Select(d => new { d.Barcode, AvailableQuantity = d.StockQuantity - d.OutboundQuantity }) .ToList() }) .ToListAsync(); return WebResponseContent.Instance.OK(null, lockInfos); } } }