using Admin.NET.Core.Service; using Admin.NET.Application.Entity; using Microsoft.AspNetCore.Http; using System.Data; using System.Web; using System.Text; using System.Linq.Expressions; using Furion.LinqBuilder; using Qiniu.Storage; using Admin.NET.Application.CommonHelper; using DocumentFormat.OpenXml.Office2013.Word; using Admin.NET.Core.Helper.ExcelHelper; using AngleSharp.Dom; using OracleInternal.Sharding; using System; namespace Admin.NET.Application; /// /// 盘点单据服务 /// [ApiDescriptionSettings(ApplicationConst.WmsInventoryCheckGroupName, Order = 100)] public class WmsInventoryCheckOrderService : IDynamicApiController, ITransient { private readonly UserManager _userManager; private readonly SqlSugarRepository _wmsInventoryCheckOrderRep; private readonly SqlSugarRepository _wmsInventoryCheckRangeRep; private readonly SqlSugarRepository _WmsNoCreateRuleRep; private readonly SqlSugarRepository _repSNRep; private readonly SqlSugarRepository _repRuleDetailRep; private readonly SqlSugarRepository _wmsInventoryCheckOrderDetailsRep; private readonly SqlSugarRepository _wmsContainerPlaceRep; private readonly SqlSugarRepository _wmsStockQuanRep; private readonly SqlSugarRepository _wareActionLogRep; private readonly SqlSugarRepository _v_wms_stock_quanRep; private readonly SqlSugarRepository _wmsTaskRep; private readonly SqlSugarRepository _wmsRecordReceivingDeliveryRep; private readonly SqlSugarRepository _wmsRecordTransRep; private readonly SqlSugarRepository _wmsMaterialRep; private readonly SqlSugarRepository _wmsOrderMovementRep; private readonly SqlSugarRepository _wmsOrderMovementDetailsRep; private readonly SqlSugarRepository _wmsContainerRep; private readonly SqlSugarRepository _wmsAreaRep; private readonly SqlSugarRepository _wmsPlaceRep; private readonly SqlSugarRepository _wmsBaseBusinessTypeRep; private readonly SqlSugarRepository _wmsStockQuanZeroRep; private readonly WmsStockQuanService _wmsStockQuanService; public WmsInventoryCheckOrderService( WmsStockQuanService wmsStockQuanService, UserManager userManager, SqlSugarRepository wmsInventoryCheckOrderRep, SqlSugarRepository wmsInventoryCheckRangeRep, SqlSugarRepository wmsNoCreateRuleRep, SqlSugarRepository repSNRep, SqlSugarRepository repRuleDetailRep, SqlSugarRepository wmsInventoryCheckOrderDetailsRep, SqlSugarRepository wareActionLogRep, SqlSugarRepository wmsStockQuanRep, SqlSugarRepository wmsContainerPlaceRep, SqlSugarRepository v_wms_stock_quanRep, SqlSugarRepository wmsTaskRep, SqlSugarRepository wmsRecordReceivingDeliveryRep, SqlSugarRepository wmsRecordTransRep, SqlSugarRepository wmsMaterialRep, SqlSugarRepository wmsOrderMovement, SqlSugarRepository wmsOrderMovementDetails, SqlSugarRepository wmsContainerRep, SqlSugarRepository wmsAreaRep, SqlSugarRepository wmsPlaceRep, SqlSugarRepository wmsBaseBusinessTypeRep, SqlSugarRepository wmsStockQuanZeroRep ) { _wmsStockQuanService = wmsStockQuanService; _userManager = userManager; _wmsInventoryCheckOrderRep = wmsInventoryCheckOrderRep; _wmsInventoryCheckRangeRep = wmsInventoryCheckRangeRep; _WmsNoCreateRuleRep = wmsNoCreateRuleRep; _repSNRep = repSNRep; _repRuleDetailRep = repRuleDetailRep; _wmsInventoryCheckOrderDetailsRep = wmsInventoryCheckOrderDetailsRep; _wmsRecordReceivingDeliveryRep = wmsRecordReceivingDeliveryRep; _wmsTaskRep = wmsTaskRep; _v_wms_stock_quanRep = v_wms_stock_quanRep; _wmsContainerPlaceRep = wmsContainerPlaceRep; _wmsStockQuanRep = wmsStockQuanRep; _wareActionLogRep = wareActionLogRep; _wmsRecordTransRep = wmsRecordTransRep; _wmsMaterialRep = wmsMaterialRep; _wmsOrderMovementRep = wmsOrderMovement; _wmsOrderMovementDetailsRep = wmsOrderMovementDetails; _wmsContainerRep = wmsContainerRep; _wmsAreaRep = wmsAreaRep; _wmsPlaceRep = wmsPlaceRep; _wmsBaseBusinessTypeRep = wmsBaseBusinessTypeRep; _wmsStockQuanZeroRep = wmsStockQuanZeroRep; } /// /// 分页查询盘点单据 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "Page")] [Description("WmsInventoryCheckOrder/Page")] public async Task> Page(WmsInventoryCheckOrderInput input) { var query = CommonPageFilter(input); return await query.OrderBuilder(input, "", "Id").ToPagedListAsync(input.Page, input.PageSize); } /// /// 不分页查询盘点单据 /// /// /// [HttpGet] [ApiDescriptionSettings(Name = "List")] [Description("WmsInventoryCheckOrder/List")] public async Task> List([FromQuery] WmsInventoryCheckOrderInput input) { var query = CommonPageFilter(input); return await query.OrderBuilder(input, "", "Id").Select().ToListAsync(); } /// /// 增加盘点单据 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "Add")] [Description("WmsInventoryCheckOrder/Add")] public async Task Add(DiyAddWmsInventoryCheckOrderInput input) { /** *ly-0710 1 添加盘点单据记录 +1 2 盘点范围表 +n ***/ if (input.CheckMode == null) { throw Oops.Oh($"盘点方式不能为空!"); } if (input.PlanStartDate == null) { throw Oops.Oh($"计划开始时间不能为空!"); } if (input.PlanEndDate == null) { throw Oops.Oh($"计划结束时间不能为空!"); } if (input.Materials?.Count <= 0 && string.IsNullOrWhiteSpace(input.AreaCode)) { throw Oops.Oh($"库区和物料至少选择一个!"); } // 获取当前时间 DateTime currentTime = DateTime.Now; // 格式化为年月日字符串 string formattedDate = currentTime.ToString("yyyyMMdd"); //按照单号规则生成单号 - 查找最新的创建的一条单据记录 var newestOrder = await _wmsInventoryCheckOrderRep.AsQueryable().Where(p => p.OrderNo.Contains(formattedDate)).OrderBy(it => it.CreateTime, OrderByType.Desc) .FirstAsync(); //按照单号规则生成单号-ly var planNo = await SerialUtilOrder.GetSerialOrder(OrderTypeEnum.盘点单, _WmsNoCreateRuleRep, _repSNRep, (int)BusinessTypeEnum.标准盘点, newestOrder == null ? null : newestOrder.OrderNo); if (planNo == null || planNo == "") { planNo = await SerialUtil.GetSerial(SerialTypeEnum.盘点单, _repRuleDetailRep, _repSNRep); } // 创建计划 var plan = new WmsInventoryCheckOrder { Id = Yitter.IdGenerator.YitIdHelper.NextId(), OrderNo = planNo, AreaCode = input.AreaCode, AreaName = input.AreaName, PlanStartDate = input.PlanStartDate, PlanEndDate = input.PlanEndDate, Remarks = input.Remarks, IsAudit = false, CheckStage = CheckStageEnum.新建, CheckStageName = CheckStageEnum.新建.GetDescription(), CheckMode = input.CheckMode, CheckModeName = GetEnumDescriptionUtil.GetEnumDescription(input.CheckMode) }; var planDetails = new List(); if (input.Materials != null || input.Materials.Count > 0) { // 按物料盘点 foreach (var item in input.Materials) { planDetails.Add(new WmsInventoryCheckRange { OrderId = plan.Id, OrderNo = plan.OrderNo, MaterialCode = item.MaterialCode, MaterialName = item.MaterialName }); } } try { await _wmsInventoryCheckOrderRep.AsTenant().BeginTranAsync(); await _wmsInventoryCheckOrderRep.InsertAsync(plan); //插入主表 if (planDetails.Count > 0) { await _wmsInventoryCheckRangeRep.InsertRangeAsync(planDetails); //插入明细表 } await _wmsInventoryCheckOrderRep.AsTenant().CommitTranAsync(); } catch { await _wmsInventoryCheckOrderRep.AsTenant().RollbackTranAsync(); throw; } return 200; //验证 //MyExtendHelper.ValidateCheckPlanForAddEdit(input, true, _rule, _planView); //bool isAddRule = false;//是否是新增规则 //var entity = input.Adapt(); ////重复性验证 //await CheckExist(entity); //await _wmsInventoryCheckOrderRep.InsertAsync(entity); //return entity.Id; } /// /// 盘点下发 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "Out")] [Description("WmsInventoryCheckOrder/Out")] public async Task Out(WmsInventoryCheckOrderOutInput input) { // update liuwq 2024 07 12 /* * 1.查找盘点单据 * 2.判断盘点阶段 * 2.1 校验开启盘点和初盘已完成的单据可以下发。 * 3.获取盘点明细 * 3.1 初盘操作:查询状态是未盘点 * 3.2 复盘操作:查询状态是已盘点 且 盘点结果是 盘盈或盘亏 * 4.根据盘点明细获取盘点的容器:只查询在库的 * 4.1 获取库位关系 * 4.2 获取在库的要盘点的容器 * 5.更新盘点单阶段 * 5.1 初盘操作:阶段=》初盘中 * 5.2 复盘操作:阶段=》复盘中 * 6.更新盘点单据明细的状态:同一个容器的盘点单明细 统一将 状态=》盘点中 * 7.更新盘点单据明细的盘点操作分类 * 7.1 初盘操作:操作分类=》不变,新建的时候就是初盘 * 7.2 复盘操作:操作分类=》复盘 * 8.容器分组去重,获取要出库的容器 * 9.校验容器是否存在活跃的调度任务:存在就抛异常-这种情况一定是出现了bug * 11.循环容器 * 11.1 根据容器创建盘点出库任务 * 11.2 根据容器获取库存 * 11.2.1 循环库存,创建盘点出库记录:表wms_record_receiving_delivery 插入出库记录 * 12.创建盘点下架单 */ //根据盘点操作类型定义盘点单据的阶段 CheckStageEnum checkStage = CheckStageEnum.初盘中; //获取盘点单据 var checkOrder = await _wmsInventoryCheckOrderRep.GetFirstAsync(u => u.Id == input.OrderId) ?? throw Oops.Oh($"盘点单不存在"); if (checkOrder.CheckStage != CheckStageEnum.初盘开启 && checkOrder.CheckStage != CheckStageEnum.复盘开启) { throw Oops.Oh($"单据{checkOrder.OrderNo}盘点阶段是{checkOrder.CheckStageName},不能下发"); } //根据盘点操作类型组成查询盘点明细的条件 Expression> predicate = u => u.OrderId == checkOrder.Id && u.CheckStatus == CheckStatusEnum.未盘点 && u.IsDelete == false; if (checkOrder.CheckStage != CheckStageEnum.初盘开启) { checkStage = CheckStageEnum.复盘中; } //获取业务类型信息 var businessTypeInfo = BusinessTypeHelper.GetBusinessTypeInfoFromDB((int)BusinessTypeEnum.盘点下架, _wmsBaseBusinessTypeRep); #region 获取上架的 目标库位、库区数据信息 string toPlace = OperationsPlaceEnum.PDKW.ToString();//盘点库位 // 查询上架的目标库位信息 WmsBasePlace toPlaceInfo = await BaseInfoHelper.GetPlace(toPlace, _wmsPlaceRep); //查询上架的目标库区信息 WmsBaseArea toAreaInfo = await BaseInfoHelper.GetAreaByPlace(toPlaceInfo, _wmsAreaRep); #endregion //获取盘点明细 List checkOrderDetailsList = await _wmsInventoryCheckOrderDetailsRep.AsQueryable().Where(predicate) .Select().ToListAsync(); //if (checkOrderDetailsList?.Count <= 0) //{ // throw Oops.Oh($"盘点单{checkOrder.OrderNo}没有获取到可盘点的盘点单明细"); //} //获取盘点单明细的容器 List containerList = checkOrderDetailsList.Select(u => u.ContainerCode).Distinct().ToList(); //获取库位关系 var allContainerPlaceList = await _wmsContainerPlaceRep.GetListAsync(u => containerList.Contains(u.ContainerCode) && u.IsDelete == false); //获取在库的要盘点的容器的库位信息-如果盘点单明细的容器不在库,要排除掉 var checkContainerPlaceList = allContainerPlaceList.Where(u => containerList.Contains(u.ContainerCode)).ToList(); //获取盘点容器所有库存详情-查询视图 var checkContainerStockQuanViewList = await _v_wms_stock_quanRep.GetListAsync(u => containerList.Contains(u.ContainerCode) && u.IsDelete == false); //if (checkContainerStockQuanViewList?.Count <= 0) //{ // throw Oops.Oh($"盘点单{checkOrder.OrderNo}没有获取到可盘点的库存详情"); //} List addWmsTaskList = new List(); List addWmsLogActionList = new List(); List addWmsRecordReceivingDeliveryList = new List(); List upadateWmsInventoryCheckOrderDetailsList = new List(); //盘点单明细 List addWmsOrderMovementDetailsList = new List(); WmsOrderMovement addWmsOrderMovement = null; //循环容器处理盘点单明细、创建调度任务、上架单 //没有找到库存,也支持用户盘点 if (checkContainerStockQuanViewList?.Count > 0) { int lineNumber = 0;//移动单明细行号 var hearId = Yitter.IdGenerator.YitIdHelper.NextId();//上架单ID //获取源仓库信息-用户只能看到同一个仓库的库存信息 string sourceWarehouseCode = checkContainerStockQuanViewList[0].WarehouseCode; string sourceWarehouseName = checkContainerStockQuanViewList[0].WarehouseName; //4 创建下架单 //update by liuwq 20240725 string orderNo = await OrderHelper.CreateOrderNoByRuleCommon(OrderTypeEnum.下架单, businessTypeInfo.BusinessTypeValue, _wmsOrderMovementRep, _WmsNoCreateRuleRep, _repSNRep); addWmsOrderMovement = new WmsOrderMovement() { Id = hearId, OrderNo = orderNo, //按照单号规则生成单号 OrderType = OrderTypeEnum.下架单, OrderTypeName = OrderTypeEnum.下架单.GetDescription(), BusinessType = businessTypeInfo.BusinessTypeValue, BusinessTypeName = businessTypeInfo.BusinessTypeName, OrderStatus = OrderStatusEnum.新建, OrderStatusName = OrderStatusEnum.新建.GetDescription(), SourceWarehouseCode = sourceWarehouseCode, SourceWarehouseName = sourceWarehouseName, ToAreaCode = toAreaInfo.AreaCode, ToAreaName = toAreaInfo.AreaName, ToPlaceCode = toPlaceInfo.PlaceCode, ToPlaceName = toPlaceInfo.PlaceName, OrderSocure = SourceByEnum.系统 }; foreach (var item in checkContainerPlaceList) { var checkStockQuanList = checkContainerStockQuanViewList.Where(a => a.ContainerCode.Equals(item.ContainerCode)).ToList(); if (checkStockQuanList?.Count <= 0) { throw Oops.Oh($"容器{item.ContainerCode}没有物料"); } //根据容器获取盘点单明细 var currentCheckOrderDetailsList = checkOrderDetailsList.Where(u => u.ContainerCode.Equals(item.ContainerCode)).ToList(); foreach (var checkItem in currentCheckOrderDetailsList) { OrderHelper.UpdateInventoryCheckOrderDetailsCheckStatus(checkItem, CheckStatusEnum.盘点中); upadateWmsInventoryCheckOrderDetailsList.Add(checkItem); var currentStockQuanView = checkContainerStockQuanViewList.FirstOrDefault(f => f.SNCode.Equals(checkItem.SNCode)); if (currentStockQuanView == null) { //找不到库存不需要下发调度任务,因为要兼容系统中无库存,但是实物有的情况 【Editby shaocx,2024-08-05】 continue; } //创建盘点下架单明细 //校验如果这个容器还在盘点库区库位上,就不要创建调度任务了 if (item.PlaceCode == OperationsPlaceEnum.PDKW.ToString()) { continue; } lineNumber++; #region 创建盘点下架单明细 //3.根据容器的库存创建上架单明细 var wmsOrderMovementDetails = new WmsOrderMovementDetails() { MovementId = hearId, MovementNo = addWmsOrderMovement.OrderNo, LineNumber = OrderHelper.AutoCompleEBELP(lineNumber.ToString(), 4), SNCode = currentStockQuanView.SNCode, SupplierCode = currentStockQuanView.SupplierCode, SupplierName = currentStockQuanView.SupplierName, Batch = currentStockQuanView.Batch, ErpOrderNo = currentStockQuanView.ErpOrderNo, ErpCode = currentStockQuanView.ErpCode, Unit = currentStockQuanView.MaterialUnit, SupplierBatch = currentStockQuanView.SupplierBatch, OrderStatus = OrderStatusEnum.新建, OrderStatusName = OrderStatusEnum.新建.GetDescription(), ContainerCode = currentStockQuanView.ContainerCode, ContainerName = currentStockQuanView.ContainerName, SourceWarehouseCode = currentStockQuanView.WarehouseCode, SourceWarehouseName = currentStockQuanView.WarehouseName, SourceAreaCode = currentStockQuanView.AreaCode, SourceAreaName = currentStockQuanView.AreaName, SourcePlaceCode = currentStockQuanView.PlaceCode, SourcePlaceName = currentStockQuanView.PlaceName, ToAreaCode = toAreaInfo.AreaCode, ToAreaName = toAreaInfo.AreaName, ToPlaceCode = toPlaceInfo.PlaceCode, ToPlaceName = toPlaceInfo.PlaceName, MaterialCode = currentStockQuanView.MaterialCode, MaterialName = currentStockQuanView.MaterialName, Quantity = checkItem.Quantity,//下架单的数量=盘点单明细的库存数量 ActionRemark = "盘点下发创建下架单", ActionTime = DateTime.Now }; addWmsOrderMovementDetailsList.Add(wmsOrderMovementDetails); #endregion } //校验如果这个容器还在盘点库区库位上,就不要创建调度任务了 if (item.PlaceCode == OperationsPlaceEnum.PDKW.ToString()) { continue; } //创建调度任务 string sourcePlaceCode = checkStockQuanList[0].PlaceCode;//获取当前容器第一个库存的库位作为源库位 var wmsTask = new WmsTask() { MoveType = businessTypeInfo.MoveType, MoveTypeName = businessTypeInfo.MoveTypeName, BusinessType = businessTypeInfo.BusinessTypeValue, BusinessTypeName = businessTypeInfo.BusinessTypeName, ContainerCode = item.ContainerCode, IsFlagFinish = false, OrderNo = addWmsOrderMovement.OrderNo,//盘点下架单号 RelationNo = checkOrder.OrderNo, TaskDescribe = businessTypeInfo.BusinessTypeName, TaskStatus = TaskStatusEnum.新建, TaskStatusName = TaskStatusEnum.新建.GetDescription(), TaskNo = Yitter.IdGenerator.YitIdHelper.NextId().ToString(), TaskPriority = 0, TaskName = businessTypeInfo.BusinessTypeName, SourcePlaceCode = sourcePlaceCode, ToAreaCode = toAreaInfo.AreaCode, ToPlaceCode = toPlaceInfo.PlaceCode }; addWmsTaskList.Add(wmsTask); } } //更新盘点单阶段 checkOrder.CheckStage = checkStage; checkOrder.CheckStageName = checkStage.GetDescription(); //ly 更新盘点开始时间 if (checkOrder.StartCheckTime == null) { checkOrder.StartCheckTime = DateTime.Now; } //创建操作日志 string title = "盘点单号" + checkOrder.OrderNo + BusinessTypeEnum.盘点下架.GetDescription(); WmsLogAction addWmsActionLog = LogActionHelper.CreateWmsLogAction(checkOrder.Id, title); addWmsLogActionList.Add(addWmsActionLog); var _tenant = _wmsInventoryCheckOrderRep.AsTenant(); try { await _tenant.BeginTranAsync(); #region 事务内执行操作 //更新盘点单 await _wmsInventoryCheckOrderRep.UpdateAsync(checkOrder); await _wmsInventoryCheckOrderDetailsRep.UpdateRangeAsync(upadateWmsInventoryCheckOrderDetailsList); //新增调度任务、上下架记录、操作日志 await _wareActionLogRep.InsertRangeAsync(addWmsLogActionList); await _wmsTaskRep.InsertRangeAsync(addWmsTaskList); await _wmsRecordReceivingDeliveryRep.InsertRangeAsync(addWmsRecordReceivingDeliveryList); if (addWmsOrderMovementDetailsList?.Count > 0 && addWmsOrderMovement != null) { //新增上架单 await _wmsOrderMovementRep.InsertAsync(addWmsOrderMovement); await _wmsOrderMovementDetailsRep.InsertRangeAsync(addWmsOrderMovementDetailsList); } #endregion await _tenant.CommitTranAsync(); } catch { await _tenant.RollbackTranAsync(); throw; } return 1; } /// /// 盘点调差 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "HandlingDifferences")] [Description("WmsInventoryCheckOrder/HandlingDifferences")] public async Task HandlingDifferences(WmsInventoryCheckOrderOutInput input) { // update liuwq 2024 07 12 /* * 1.查找盘点单据 * * 2.获取盘点结果是盘盈或盘亏的盘点明细 * 3.根据盘点明细更新库存数 * 4.更新盘点单阶段 阶段=》已调账 * 5.添加事务 * */ //获取盘点单据 var checkOrder = await _wmsInventoryCheckOrderRep.GetFirstAsync(u => u.Id == input.OrderId) ?? throw Oops.Oh($"盘点单不存在"); if (checkOrder.CheckStage != CheckStageEnum.初盘已完成 && checkOrder.CheckStage != CheckStageEnum.复盘已完成) { throw Oops.Oh($"单据{checkOrder.OrderNo}盘点阶段是{checkOrder.CheckStage.GetDescription()},不能调差"); } //所有盘点单明细 List allCheckOrderDetailsList = await _wmsInventoryCheckOrderDetailsRep.AsQueryable().Where(u => u.OrderId == checkOrder.Id && u.IsDelete == false) .Select().ToListAsync(); //获取有差异的盘点明细 List checkOrderDetailsList = allCheckOrderDetailsList. Where(u => u.CheckStatus == CheckStatusEnum.已盘点 && (u.CheckResult == CheckResultEnum.盘盈 || u.CheckResult == CheckResultEnum.盘亏)).ToList(); bool idDifference = false; if (checkOrderDetailsList?.Count > 0) { idDifference = true; } List addWmsRecordTransList = new List(); List addWmsLogActionList = new List(); List addWmsRecordReceivingDeliveryList = new List(); List addWmsStockQuanList = new List();//需要新增的库存 List upadteWmsStockQuanList = new List(); List deleteWmsStockQuanList = new List(); List addWmsStockQuanZeroList = new List();//转移库存归零表 List updateWmsInventoryCheckOrderDetails = new List(); var snCodeList = checkOrderDetailsList.Select(s => s.SNCode).ToList(); //获取要盘点的库存视图-根据盘点库区的容器和盘点范围的物料获取盘点库存-包含库位信息、库区信息,新增事务用 var all_v_wms_stock_quanList = await _v_wms_stock_quanRep.GetListAsync(x => x.IsDelete == false && snCodeList.Contains(x.SNCode)); ////获取库存信息-调差更新库存用 var checkStockQuanList = await _wmsStockQuanRep.GetListAsync(x => x.IsDelete == false && snCodeList.Contains(x.SNCode)); //获取所有业务类型 var allWmsBaseBusinessType = await _wmsBaseBusinessTypeRep.GetListAsync(x => x.IsDelete == false); //获取库位相信 var placeCodeList = all_v_wms_stock_quanList.Select(s => s.PlaceCode).Distinct().ToList(); var allPlaeList = await _wmsPlaceRep.GetListAsync(u => placeCodeList.Contains(u.PlaceCode) && u.IsDelete == false); //查询所有物料 var queryMaterialCodeList = checkOrderDetailsList.Select(x => x.MaterialCode).ToList(); var dbMaterialList = await _wmsMaterialRep.GetListAsync(x => queryMaterialCodeList.Contains(x.MaterialCode)); foreach (var item in checkOrderDetailsList) { bool isAdd = false; var viewStockQuan = all_v_wms_stock_quanList.FirstOrDefault(x => x.SNCode == item.SNCode && x.ContainerCode == item.ContainerCode); var checkStockQuan = checkStockQuanList.FirstOrDefault(x => x.SNCode == item.SNCode && x.ContainerCode == item.ContainerCode); if (viewStockQuan == null || checkStockQuan == null) {//在盘点容器中找不到库存 //看下系统数据在哪? var nowData = all_v_wms_stock_quanList.FirstOrDefault(x => x.SNCode == item.SNCode); if (nowData != null) { throw Oops.Oh($"盘点单{checkOrder.OrderNo}明细跟踪码{item.SNCode}在容器{item.ContainerCode}没有获取到库存信息,实物在容器{nowData.ContainerCode}中"); } else { //系统数据确实没有,就需要新增库存了,查找库存,赋值 var addStock = await _wmsStockQuanService.GetStockBySnCodeIncludeDelete(item.SNCode); if (addStock != null) { throw Oops.Oh($"盘点单{checkOrder.OrderNo}明细跟踪码{item.SNCode}没有获取到库存信息"); } //改变容器号和数量 addStock.ContainerCode = item.ContainerCode; addStock.Quantity = item.CheckQuantity; checkStockQuan = addStock; addWmsStockQuanList.Add(addStock); isAdd = true; } } else {//在盘点容器中找到了库存 } #region 调差-更新库存 #region 事务入参 decimal sourceQuantity = checkStockQuan.Quantity;//盘点前库存 if (isAdd) { sourceQuantity = 0; } decimal toQuantity = item.CheckQuantity;//盘点后库存 BusinessTypeEnum businessTypeEnum = BusinessTypeEnum.盘盈调差; if (item.CheckResult == CheckResultEnum.盘亏) { businessTypeEnum = BusinessTypeEnum.盘亏调差; } // 获取业务类型 update by liuwq 2024 07 30 var wmsBaseBusinessType = allWmsBaseBusinessType.FirstOrDefault(u => u.BusinessTypeValue == (int)businessTypeEnum); if (wmsBaseBusinessType == null) { throw Oops.Oh($"没有获取到业务类型{businessTypeEnum.GetDescription()}"); } //备注 string recordTransRemarks = wmsBaseBusinessType.BusinessTypeName; string remarks = $"盘点单{checkOrder.OrderNo}{businessTypeEnum.GetDescription()}"; #endregion #region 库存调差赋值 if (!isAdd) { checkStockQuan.Quantity = toQuantity; checkStockQuan.Remarks = remarks; LockInfo freezeInfo = new LockInfo() { LockReason = wmsBaseBusinessType.BusinessTypeName, LockTime = DateTime.Now, LockUser = _userManager.RealName,//登录人的真实姓名 LockStatus = LockStatusEnum.未锁定,//解冻 }; StockQuanHelper.UpdateStockLockStatus(checkStockQuan, freezeInfo); #endregion if (checkStockQuan.Quantity == 0) { //库存归零 清除原库存信息 deleteWmsStockQuanList.Add(checkStockQuan); var newWmsStockQuanOut = checkStockQuan.Adapt(); //库存归零 转移到 库存归零表 addWmsStockQuanZeroList.Add(newWmsStockQuanOut); } else { //库存更新集合 upadteWmsStockQuanList.Add(checkStockQuan); } //盘点明细的库存数量跟实时库存不一致的情况 //更新盘点明细的库存数量 if (item.Quantity != sourceQuantity) { item.Quantity = sourceQuantity;//盘点明细的库存数量,这是计划盘点数。 更新成 当前实时库存调差前的库存数,因为计算盘点结果是用实时库存的库存数和盘点明细的盘点数量计算的。 updateWmsInventoryCheckOrderDetails.Add(item); } } #endregion #region 添加收货记录 // 盘盈添加收货记录 InOutFlagEnum inOutFlagEnum = InOutFlagEnum.入; // 盘亏添加发货记录 var changeQty = 0M; if (item.CheckResult == CheckResultEnum.盘亏) { inOutFlagEnum = InOutFlagEnum.出; changeQty = sourceQuantity - toQuantity;//计算 减少数作为发货数量 } else { changeQty = toQuantity - sourceQuantity;//计算 增加数作为收货数量 } var material = dbMaterialList.Where(x => x.MaterialCode == item.MaterialCode).FirstOrDefault(); WmsRecordReceivingDelivery wmsRecordReceivingDelivery = CreateWmsRecordReceivingDelivery(material, changeQty, inOutFlagEnum, item, checkStockQuan, wmsBaseBusinessType, remarks); addWmsRecordReceivingDeliveryList.Add(wmsRecordReceivingDelivery); #endregion #region 添加事务 #region 创建事务日志入参 //获取源库存信息 v_wms_stock_quan sourceStockView = null; WmsBasePlace toPlace = null; if (isAdd) { sourceStockView = checkStockQuan.Adapt(); toPlace = await BaseInfoHelper.GetPlaceByContinerCode(item.ContainerCode, _wmsPlaceRep, _wmsContainerPlaceRep); } else { sourceStockView = StockQuanHelper.GetVMmsStockQuan(all_v_wms_stock_quanList, checkStockQuan.SNCode); toPlace = BaseInfoHelper.GetPlace(sourceStockView.PlaceCode, allPlaeList); } // 其他参数对象 TransferOtherDetail transferOtherDetail = new TransferOtherDetail() { RelationNo = "", RelationNoLineNumber = "", Remarks = recordTransRemarks, }; #endregion //新增事务记录 //仅变更库存数 addWmsRecordTransList.Add(LogRecordHelper.CreateWmsRecordTrans(wmsBaseBusinessType, sourceStockView, checkStockQuan, toPlace, transferOtherDetail)); #endregion } //update by liuwq 20240802 #region 盘点解冻库存 ////获取盘点明细 BusinessTypeEnum businessTypeEnumForFreeze = BusinessTypeEnum.盘点解冻; // 获取业务类型 var wmsBaseBusinessTypeForFreeze = BusinessTypeHelper.GetBusinessTypeInfoFromDB((int)businessTypeEnumForFreeze, _wmsBaseBusinessTypeRep); //盘点单所有容器的库存解冻、添加事务 await StockQuanHelper.BackStockStatusForPD(wmsBaseBusinessTypeForFreeze, allCheckOrderDetailsList, _wmsStockQuanRep, _v_wms_stock_quanRep, _wmsPlaceRep, checkOrder, upadteWmsStockQuanList, addWmsRecordTransList, _userManager); #endregion //创建操作日志 string title = "盘点单号" + checkOrder.OrderNo + "盘点调差"; WmsLogAction addWmsActionLog = LogActionHelper.CreateWmsLogAction(checkOrder.Id, title); addWmsLogActionList.Add(addWmsActionLog); //更新盘点单阶段 if (idDifference)//存在差异 { checkOrder.CheckStage = CheckStageEnum.已调账; checkOrder.CheckStageName = CheckStageEnum.已调账.GetDescription(); checkOrder.IsAudit = true;//是否已调账 } else { checkOrder.CheckStage = CheckStageEnum.已关闭; checkOrder.CheckStageName = CheckStageEnum.已关闭.GetDescription(); checkOrder.IsAudit = false;//是否已调账 } checkOrder.EndCheckTime = DateTime.Now; var _tenant = _wmsInventoryCheckOrderRep.AsTenant(); try { await _tenant.BeginTranAsync(); #region 事务内执行操作 //更新盘点单 await _wmsInventoryCheckOrderRep.UpdateAsync(checkOrder); if (updateWmsInventoryCheckOrderDetails?.Count > 0) { await _wmsInventoryCheckOrderDetailsRep.UpdateRangeAsync(updateWmsInventoryCheckOrderDetails); } if (addWmsStockQuanList?.Count > 0) {//新增库存 await _wmsStockQuanRep.InsertRangeAsync(addWmsStockQuanList); } if (deleteWmsStockQuanList?.Count > 0) { await _wmsStockQuanRep.DeleteAsync(deleteWmsStockQuanList); } if (addWmsStockQuanZeroList?.Count > 0) { await _wmsStockQuanZeroRep.InsertRangeAsync(addWmsStockQuanZeroList); } //添加收发货记录 if (addWmsRecordReceivingDeliveryList?.Count > 0) { await _wmsRecordReceivingDeliveryRep.InsertRangeAsync(addWmsRecordReceivingDeliveryList); } //更新库存 await _wmsStockQuanRep.UpdateRangeAsync(upadteWmsStockQuanList); //新增事务、操作日志 await _wareActionLogRep.InsertRangeAsync(addWmsLogActionList); await _wmsRecordTransRep.InsertRangeAsync(addWmsRecordTransList); #endregion await _tenant.CommitTranAsync(); } catch { await _tenant.RollbackTranAsync(); throw; } return 1; } /// /// 创建收发货记录 /// /// /// /// /// /// private WmsRecordReceivingDelivery CreateWmsRecordReceivingDelivery(WmsBaseMaterial material, decimal changeQty, InOutFlagEnum inOutFlagEnum, WmsInventoryCheckOrderDetails item, WmsStockQuan checkStockQuan, WmsBaseBusinessType wmsBaseBusinessType, string remarks) { WmsRecordReceivingDelivery wmsRecordReceivingDelivery = new WmsRecordReceivingDelivery() { Id = Yitter.IdGenerator.YitIdHelper.NextId(), InOutFlag = inOutFlagEnum,//出入标记 盘盈 入、盘亏 出 Remarks = remarks, OrderNoLineNumber = string.Empty, OrderNo = item.OrderNo, Batch = checkStockQuan.Batch,//根据批次规则创建的批次 OrderType = OrderTypeEnum.盘点单,//全部都是asn单收货 OrderTypeName = OrderTypeEnum.盘点单.GetDescription(), BusinessType = wmsBaseBusinessType.BusinessTypeValue, BusinessTypeName = wmsBaseBusinessType.BusinessTypeName, Quantity = changeQty,//盘点变化数量 盘盈收货、盘亏发货 //POQuantity = receivingItem.POQuantity,//发货记录 没有采购数量 ErpCode = checkStockQuan.ErpCode, ErpOrderNo = checkStockQuan.ErpOrderNo, Images = string.Empty,//上传图片暂时空着 MaterialCode = checkStockQuan.MaterialCode, MaterialName = checkStockQuan.MaterialName, MoveType = wmsBaseBusinessType.MoveType, MoveTypeName = wmsBaseBusinessType.MoveTypeName, RelationNoLineNumber = string.Empty, RelationNo = string.Empty, SNCode = checkStockQuan.SNCode, SupplierBatch = checkStockQuan.SupplierBatch,//供应商批次 SupplierCode = checkStockQuan.SupplierCode, SupplierName = checkStockQuan.SupplierName, POUnit = material?.POUnit, MaterialUnit = checkStockQuan.MaterialUnit, }; return wmsRecordReceivingDelivery; } /// /// 取消盘点单据 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "Delete")] [Description("WmsInventoryCheckOrder/Delete")] public async Task Delete(DeleteWmsInventoryCheckOrderInput input) { //ly-0710 只有新建状态才可以取消 var entity = await _wmsInventoryCheckOrderRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002); if (entity.CheckStage != CheckStageEnum.新建) { throw Oops.Oh($"单据盘点阶段{entity.CheckStageName},不允许取消"); } entity.CheckStage = CheckStageEnum.已取消; entity.CheckStageName = GetEnumDescriptionUtil.GetEnumDescription(CheckStageEnum.已取消); entity.EndCheckTime = DateTime.Now; try { await _wmsInventoryCheckOrderRep.AsTenant().BeginTranAsync(); await _wmsInventoryCheckOrderRep.UpdateAsync(entity); //更新状态 await _wmsInventoryCheckOrderRep.AsTenant().CommitTranAsync(); } catch { await _wmsInventoryCheckOrderRep.AsTenant().RollbackTranAsync(); throw; } } /// /// 更新盘点单据 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "Update")] [Description("WmsInventoryCheckOrder/Update")] public async Task Update(DiyAddWmsInventoryCheckOrderInput input) { var dbOrder = await _wmsInventoryCheckOrderRep.GetFirstAsync(w => w.OrderNo == input.OrderNo); if (dbOrder == null) { throw Oops.Oh($"订单{input.OrderNo}不存在"); } dbOrder.CheckMode = input.CheckMode; dbOrder.CheckModeName = GetEnumDescriptionUtil.GetEnumDescription(input.CheckMode); dbOrder.PlanStartDate = input.PlanStartDate; dbOrder.PlanEndDate = input.PlanEndDate; dbOrder.AreaCode = input.AreaCode; dbOrder.AreaName = input.AreaName; dbOrder.Remarks = input.Remarks; var purchaseOrderDetails = await _wmsInventoryCheckRangeRep.AsQueryable() .Where(x => x.OrderId == dbOrder.Id) .Where(u => u.IsDelete == false) .Select() .ToListAsync(); List addWarePurchaseOrderDetails = new List(); List updateWarePurchaseOrderDetails = new List(); List deleteWarePurchaseOrderDetails = new List(); if (input.Materials != null || input.Materials.Count > 0) { //寻找更新的 var updateList = purchaseOrderDetails.Where(x => input.Materials.Any(p => p.MaterialCode == x.MaterialCode)).ToList(); foreach (var item in updateList) { var orderDetails = input.Materials.FirstOrDefault(x => x.MaterialCode == item.MaterialCode); if (orderDetails == null) { continue; } else { item.MaterialCode = orderDetails.MaterialCode; item.MaterialName = orderDetails.MaterialName; } updateWarePurchaseOrderDetails.Add(item); } //寻找删除的 var deleteList = purchaseOrderDetails.Where(x => !input.Materials.Any(p => p.MaterialCode == x.MaterialCode)).ToList(); foreach (var item in deleteList) { deleteWarePurchaseOrderDetails.Add(item); } //寻找新增的 var addList = input.Materials.Where(x => !purchaseOrderDetails.Any(p => p.MaterialCode == x.MaterialCode)).ToList(); foreach (var w in addList) { //var materials = await _wmsMaterialRep.GetFirstAsync(u => u.MaterialCode == w.MaterialCode && u.IsDisabled == false); //if (materials == null) //{ // throw Oops.Oh("物料:" + w.MaterialCode + "不可用"); //} WmsInventoryCheckRange warePurchaseOrderDetails = new WmsInventoryCheckRange() { Id = Yitter.IdGenerator.YitIdHelper.NextId(), OrderId = dbOrder.Id, OrderNo = dbOrder.OrderNo, MaterialCode = w.MaterialCode, MaterialName = w.MaterialName }; addWarePurchaseOrderDetails.Add(warePurchaseOrderDetails); } } try { await _wmsInventoryCheckOrderRep.AsTenant().BeginTranAsync(); if (addWarePurchaseOrderDetails.Count > 0) { await _wmsInventoryCheckRangeRep.InsertRangeAsync(addWarePurchaseOrderDetails); } if (updateWarePurchaseOrderDetails.Count > 0) { await _wmsInventoryCheckRangeRep.UpdateRangeAsync(updateWarePurchaseOrderDetails); } if (deleteWarePurchaseOrderDetails.Count > 0) { await _wmsInventoryCheckRangeRep.DeleteAsync(deleteWarePurchaseOrderDetails); } await _wmsInventoryCheckOrderRep.UpdateAsync(dbOrder); await _wmsInventoryCheckOrderRep.AsTenant().CommitTranAsync(); } catch { await _wmsInventoryCheckOrderRep.AsTenant().RollbackTranAsync(); throw; } //var entity = input.Adapt(); ////重复性验证 //await CheckExist(entity,true); //await _wmsInventoryCheckOrderRep.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); } /// /// 获取盘点单据 /// /// /// [HttpGet] [ApiDescriptionSettings(Name = "Detail")] [Description("WmsInventoryCheckOrder/Detail")] public async Task Detail([FromQuery] QueryByIdWmsInventoryCheckOrderInput input) { return await _wmsInventoryCheckOrderRep.GetFirstAsync(u => u.Id == input.Id); } /// /// pda盘点-单据完成 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "FinishedOrder")] [Description("WmsInventoryCheckOrder/FinishedOrder")] public async Task FinishedOrder(FinishOrderWmsInventoryCheckOrderInput input) { /** ly-0712 1.改变单据状态 1.1 初盘中 - 初盘已完成 1.2 复盘中 - 复盘已完成 1.2 盘点明细中的 库存状态回归到原始状态 */ List addWmsRecordTransList = new List(); List upadteWmsStockQuanList = new List(); List updateWmsInventoryCheckOrderDetails = new List(); var entity = await _wmsInventoryCheckOrderRep.GetFirstAsync(u => u.OrderNo == input.OrderNo) ?? throw Oops.Oh(ErrorCodeEnum.D1002); if (entity == null) { throw Oops.Oh($"盘点单{input.OrderNo},不存在"); } if (entity.CheckStage == CheckStageEnum.初盘中) { entity.CheckStage = CheckStageEnum.初盘已完成; entity.CheckStageName = GetEnumDescriptionUtil.GetEnumDescription(CheckStageEnum.初盘已完成); } else if (entity.CheckStage == CheckStageEnum.复盘中) { entity.CheckStage = CheckStageEnum.复盘已完成; entity.CheckStageName = GetEnumDescriptionUtil.GetEnumDescription(CheckStageEnum.复盘已完成); } else { throw Oops.Oh($"盘点阶段{entity.CheckStageName},不允许操作"); } ////获取盘点明细 List checkOrderDetailsList = await _wmsInventoryCheckOrderDetailsRep.AsQueryable().Where(u => u.OrderId == entity.Id && u.IsDelete == false).Select().ToListAsync(); #region 没有盘点到的明细 更新状态为 未盘点 var notCheckDetailsList = checkOrderDetailsList.Where(w => w.CheckStatus == CheckStatusEnum.盘点中 && w.CheckResult == CheckResultEnum.未盘).ToList(); foreach (var item in notCheckDetailsList) { item.CheckCount += 1; if (item.CheckCount > 2) item.CheckCount = 2; item.CheckQuantity = 0; OrderHelper.UpdateInventoryCheckOrderDetailsCheckResult(item, CheckResultEnum.盘亏); OrderHelper.UpdateInventoryCheckOrderDetailsCheckStatus(item, CheckStatusEnum.已盘点); updateWmsInventoryCheckOrderDetails.Add(item); } #endregion try { await _wmsInventoryCheckOrderRep.AsTenant().BeginTranAsync(); await _wmsInventoryCheckOrderRep.UpdateAsync(entity); //更新状态 await _wmsStockQuanRep.UpdateRangeAsync(upadteWmsStockQuanList);//库存状态回归 if (updateWmsInventoryCheckOrderDetails?.Count > 0) { await _wmsInventoryCheckOrderDetailsRep.UpdateRangeAsync(updateWmsInventoryCheckOrderDetails);//更新盘点单明细状态 } if (addWmsRecordTransList?.Count > 0) { await _wmsRecordTransRep.InsertRangeAsync(addWmsRecordTransList);//新增事务记录 } await _wmsInventoryCheckOrderRep.AsTenant().CommitTranAsync(); } catch { await _wmsInventoryCheckOrderRep.AsTenant().RollbackTranAsync(); throw; } } /// /// pda单据完成验证:单据是否有未盘点的明细 /// /// /// [HttpGet] [ApiDescriptionSettings(Name = "ValidDetail")] [Description("WmsInventoryCheckOrder/ValidDetail")] public async Task ValidDetail([FromQuery] WmsInventoryCheckOrderForPdaValidInput input) { var Cont = 200; var List = await _wmsInventoryCheckOrderDetailsRep.GetFirstAsync(u => u.OrderNo == input.OrderNo && (u.CheckStatus == CheckStatusEnum.未盘点 || u.CheckStatus == CheckStatusEnum.盘点中)); //-先调用一个 验证:单据是否有未盘点 盘点中的明细 if (List != null) { Cont = 1; //有未盘点 盘点中的明细 } return Cont; } /// /// 关闭盘点单据-ly0712 /// /// /// [HttpPost] [ApiDescriptionSettings(Name = "CloseOrder")] [Description("WmsInventoryCheckOrder/CloseOrder")] public async Task CloseOrder(DeleteWmsInventoryCheckOrderInput input) { var entity = await _wmsInventoryCheckOrderRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002); if (entity.CheckStage == CheckStageEnum.已取消 || entity.CheckStage == CheckStageEnum.已关闭 || entity.CheckStage == CheckStageEnum.已调账) { throw Oops.Oh($"单据状态{entity.CheckStageName},不允许操作!"); } entity.CheckStage = CheckStageEnum.已关闭; entity.CheckStageName = GetEnumDescriptionUtil.GetEnumDescription(CheckStageEnum.已关闭); entity.EndCheckTime = DateTime.Now; BusinessTypeEnum businessTypeEnum = BusinessTypeEnum.盘点关闭; // 获取业务类型 var wmsBaseBusinessType = BusinessTypeHelper.GetBusinessTypeInfoFromDB((int)businessTypeEnum, _wmsBaseBusinessTypeRep); // ----------------记录操作日志 List addWareActionLogList = new List(); string actionTitle = $"{OrderTypeEnum.盘点单}{entity.CheckStage}{GetEnumDescriptionUtil.GetEnumDescription(OrderStatusEnum.已关闭)}";//操作履历标题 var idWmsLogAction = Yitter.IdGenerator.YitIdHelper.NextId(); WmsLogAction wareActionLog = LogActionHelper.CreateWmsLogAction(idWmsLogAction, actionTitle); addWareActionLogList.Add(wareActionLog); // ----------------记录操作日志 //----------库存状态回归 List upadteWmsStockQuanList = new List(); List addWmsRecordTransList = new List(); //库存解冻、添加事务 await StockQuanHelper.BackStockStatusForPD(wmsBaseBusinessType, _wmsInventoryCheckOrderDetailsRep, _wmsStockQuanRep, _v_wms_stock_quanRep, _wmsPlaceRep, entity, upadteWmsStockQuanList, addWmsRecordTransList, _userManager); //----------库存状态回归 try { await _wmsInventoryCheckOrderRep.AsTenant().BeginTranAsync(); await _wmsInventoryCheckOrderRep.UpdateAsync(entity); //更新状态 if (addWareActionLogList.Count > 0) { await _wareActionLogRep.InsertRangeAsync(addWareActionLogList); //操作日志 } if (upadteWmsStockQuanList.Count > 0) { await _wmsStockQuanRep.UpdateRangeAsync(upadteWmsStockQuanList);//库存状态回归 } await _wmsInventoryCheckOrderRep.AsTenant().CommitTranAsync(); } catch { await _wmsInventoryCheckOrderRep.AsTenant().RollbackTranAsync(); throw; } } #region 导入 /// /// Excel模板导入盘点单据功能 /// /// Excel模板文件 /// 导入的记录数 [HttpPost] [ApiDescriptionSettings(Name = "ImportExcel")] [Description("WmsInventoryCheckOrder/ImportExcel")] public async Task ImportExcelAsync(IFormFile file) { int _HeadStartLine = 2;//第1行是说明,第2行是列名 int _DataStartLine = 3;//第3行开始是数据 DataTable importDataTable = ExcelUtil.ImportExcelToDataTable(file, _HeadStartLine, _DataStartLine); var addList = await CommonImport(importDataTable, _DataStartLine); await _wmsInventoryCheckOrderRep.InsertRangeAsync(addList); return addList.Count; } /// /// DataTable转换实体对象列表 /// /// /// 模版列名开始行 /// private async Task> CommonImport(DataTable dataTable, int dataStartLine) { var details = new List(); int index = dataStartLine;//模版列名开始行 foreach (System.Data.DataRow row in dataTable.Rows) { index++; //导入模版定制化代码(替换模版使用) var addItem = new WmsInventoryCheckOrder(); #region 定义变量 var _OrderNo = "";//盘点单号 var _CheckMode = "";//盘点方式 var _CheckModeName = "";//盘点方式名称 var _CheckStage = "";//盘点阶段 var _CheckStageName = "";//盘点阶段名称 var _AreaCode = "";//库区编码 var _AreaName = "";//库区名称 var _PlanStartDate = "";//计划开始时间 var _PlanEndDate = "";//计划结束时间 var _StartCheckTime = "";//盘点开始日期 var _EndCheckTime = "";//盘点结束日期 var _Remarks = "";//备注 var _IsAudit = "";//是否已调账 #endregion #region 取值 _OrderNo = row["盘点单号"]?.ToString(); _CheckMode = row["盘点方式"]?.ToString(); _CheckModeName = row["盘点方式名称"]?.ToString(); _CheckStage = row["盘点阶段"]?.ToString(); _CheckStageName = row["盘点阶段名称"]?.ToString(); _AreaCode = row["库区编码"]?.ToString(); _AreaName = row["库区名称"]?.ToString(); _PlanStartDate = row["计划开始时间"]?.ToString(); _PlanEndDate = row["计划结束时间"]?.ToString(); _StartCheckTime = row["盘点开始日期"]?.ToString(); _EndCheckTime = row["盘点结束日期"]?.ToString(); _Remarks = row["备注"]?.ToString(); _IsAudit = row["是否已调账"]?.ToString(); #endregion #region 验证 if (string.IsNullOrEmpty(_OrderNo)) { throw Oops.Oh($"第{index}行[盘点单号]{_OrderNo}不能为空!"); } if (!string.IsNullOrEmpty(_OrderNo)) { addItem.OrderNo = (string)(_OrderNo.Trim()); } if (string.IsNullOrEmpty(_CheckMode)) { throw Oops.Oh($"第{index}行[盘点方式]{_CheckMode}不能为空!"); } if (!string.IsNullOrEmpty(_CheckMode)) { Admin.NET.Application.CheckModeEnum enumCheckMode = default(Admin.NET.Application.CheckModeEnum); if (!Enum.TryParse(_CheckMode, out enumCheckMode) && !string.IsNullOrEmpty(_CheckMode)) { throw Oops.Oh($"第{index}行[盘点方式]{_CheckMode}值不正确!"); } else { addItem.CheckMode = enumCheckMode; } } if (string.IsNullOrEmpty(_CheckModeName)) { throw Oops.Oh($"第{index}行[盘点方式名称]{_CheckModeName}不能为空!"); } if (!string.IsNullOrEmpty(_CheckModeName)) { addItem.CheckModeName = (string)(_CheckModeName.Trim()); } if (string.IsNullOrEmpty(_CheckStage)) { throw Oops.Oh($"第{index}行[盘点阶段]{_CheckStage}不能为空!"); } if (!string.IsNullOrEmpty(_CheckStage)) { Admin.NET.Application.CheckStageEnum enumCheckStage = default(Admin.NET.Application.CheckStageEnum); if (!Enum.TryParse(_CheckStage, out enumCheckStage) && !string.IsNullOrEmpty(_CheckStage)) { throw Oops.Oh($"第{index}行[盘点阶段]{_CheckStage}值不正确!"); } else { addItem.CheckStage = enumCheckStage; } } if (string.IsNullOrEmpty(_CheckStageName)) { throw Oops.Oh($"第{index}行[盘点阶段名称]{_CheckStageName}不能为空!"); } if (!string.IsNullOrEmpty(_CheckStageName)) { addItem.CheckStageName = (string)(_CheckStageName.Trim()); } if (!string.IsNullOrEmpty(_AreaCode)) { addItem.AreaCode = (string)(_AreaCode.Trim()); } if (!string.IsNullOrEmpty(_AreaName)) { addItem.AreaName = (string)(_AreaName.Trim()); } if (!string.IsNullOrEmpty(_PlanStartDate)) { addItem.PlanStartDate = Convert.ToDateTime(Convert.ToDateTime(_PlanStartDate.Trim()).ToShortDateString()); } if (!string.IsNullOrEmpty(_PlanEndDate)) { addItem.PlanEndDate = Convert.ToDateTime(Convert.ToDateTime(_PlanEndDate.Trim()).ToShortDateString()); } if (!string.IsNullOrEmpty(_StartCheckTime)) { addItem.StartCheckTime = Convert.ToDateTime(Convert.ToDateTime(_StartCheckTime.Trim()).ToShortDateString()); } if (!string.IsNullOrEmpty(_EndCheckTime)) { addItem.EndCheckTime = Convert.ToDateTime(Convert.ToDateTime(_EndCheckTime.Trim()).ToShortDateString()); } if (!string.IsNullOrEmpty(_Remarks)) { addItem.Remarks = (string)(_Remarks.Trim()); } if (!string.IsNullOrEmpty(_IsAudit)) { if (!_IsAudit.Equals("是") && !_IsAudit.Equals("否")) { throw Oops.Oh($"第{index}行[是否已调账]{_IsAudit}值不正确!"); } else { bool outIsAudit = _IsAudit.Equals("是") ? true : false; addItem.IsAudit = outIsAudit; } } #endregion details.Add(addItem); } //验重 await CheckExisitForImport(details); return details; } /// /// 根据版本下载盘点单据的Excel导入模板 /// /// 下载的模板文件 [HttpGet] [ApiDescriptionSettings(Name = "DownloadExcelTemplate")] [Description("WmsInventoryCheckOrder/DownloadExcelTemplate")] public IActionResult DownloadExcelTemplate() { string _path = TemplateConst.EXCEL_TEMPLATEFILE_导入模版路径 + $"\\盘点单据{TemplateConst.EXCEL_TEMPLATEFILE_导入模版名称后缀}.xlsx"; var fileName = HttpUtility.UrlEncode($"导入模板(盘点单据).xlsx", Encoding.GetEncoding("UTF-8")); return new FileStreamResult(new FileStream(_path, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName }; } #endregion /// /// 盘点报表-明细导出-ly0712 /// /// /// [HttpGet] [ApiDescriptionSettings(Name = "DiffOrderExcelOutting")] [Description("WmsInventoryCheckOrder/DiffOrderExcelOutting")] [AllowAnonymous] public async Task DiffOrderExcelOutting([FromQuery] WmsInventoryCheckOrderInput input) { var vs = (from p in _wmsInventoryCheckOrderDetailsRep.AsQueryable().ToList() join m in _wmsInventoryCheckOrderRep.AsQueryable() .WhereIF(!string.IsNullOrWhiteSpace(input.SearchKey), u => u.OrderNo.Contains(input.SearchKey.Trim()) || u.CheckModeName.Contains(input.SearchKey.Trim()) || u.CheckStageName.Contains(input.SearchKey.Trim()) || u.AreaCode.Contains(input.SearchKey.Trim()) || u.AreaName.Contains(input.SearchKey.Trim()) || u.Remarks.Contains(input.SearchKey.Trim()) || u.CreateUserName.Contains(input.SearchKey.Trim()) || u.UpdateUserName.Contains(input.SearchKey.Trim()) ) .WhereIF(!string.IsNullOrWhiteSpace(input.OrderNo), u => u.OrderNo.Contains(input.OrderNo.Trim())) .WhereIF(input.CheckMode.HasValue, u => u.CheckMode == input.CheckMode) .WhereIF(!string.IsNullOrWhiteSpace(input.CheckModeName), u => u.CheckModeName.Contains(input.CheckModeName.Trim())) .WhereIF(input.CheckStage.HasValue, u => u.CheckStage == input.CheckStage) .WhereIF(!string.IsNullOrWhiteSpace(input.CheckStageName), u => u.CheckStageName.Contains(input.CheckStageName.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.AreaCode), u => u.AreaCode.Contains(input.AreaCode.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.AreaName), u => u.AreaName.Contains(input.AreaName.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.Remarks), u => u.Remarks.Contains(input.Remarks.Trim())) .WhereIF(input.IsAudit.HasValue, u => u.IsAudit == input.IsAudit).ToList() on p.OrderId equals m.Id select new WmsInventoryCheckOrderExcelOutput { OrderNo = m.OrderNo, CheckModeName = m.CheckModeName, CheckStageName = m.CheckStageName, AreaCode = m.AreaCode, AreaName = m.AreaName, PlanStartDate = m.PlanStartDate, PlanEndDate = m.PlanEndDate, StartCheckTime = m.StartCheckTime, EndCheckTime = m.EndCheckTime, Remarks = m.Remarks, IsAudit = m.IsAudit == true ? "是" : "否", CreateTime = m.CreateTime, UpdateTime = m.UpdateTime, CreateUserName = m.CreateUserName, UpdateUserName = m.UpdateUserName, SNCode = p.SNCode, Batch = p.Batch, MaterialName = p.MaterialName, MaterialCode = p.MaterialCode, ContainerCode = p.ContainerCode, Quantity = p.Quantity, CheckQuantity = p.CheckQuantity, CheckStatusName = p.CheckStatusName, CheckResultName = p.CheckResultName, CheckCount = p.CheckCount, CheckOperatorClassifyName = p.CheckOperatorClassifyName, }).ToList(); var fileName = "盘点报表详情"; var excelBaseResult = new Excel2003Result(vs, fileName, false, "盘点报表导出详情"); return new FileStreamResult(excelBaseResult.GetExcelStream(), "application/vnd.ms-excel"); } #region 私有方法 /// /// 公共查询盘点单据条件 /// /// /// private ISugarQueryable CommonPageFilter(WmsInventoryCheckOrderInput input) { var query = _wmsInventoryCheckOrderRep.AsQueryable() .WhereIF(!string.IsNullOrWhiteSpace(input.SearchKey), u => u.OrderNo.Contains(input.SearchKey.Trim()) || u.CheckModeName.Contains(input.SearchKey.Trim()) || u.CheckStageName.Contains(input.SearchKey.Trim()) || u.AreaCode.Contains(input.SearchKey.Trim()) || u.AreaName.Contains(input.SearchKey.Trim()) || u.Remarks.Contains(input.SearchKey.Trim()) || u.CreateUserName.Contains(input.SearchKey.Trim()) || u.UpdateUserName.Contains(input.SearchKey.Trim()) ) .WhereIF(!string.IsNullOrWhiteSpace(input.OrderNo), u => u.OrderNo.Contains(input.OrderNo.Trim())) .WhereIF(input.CheckMode.HasValue, u => u.CheckMode == input.CheckMode) .WhereIF(!string.IsNullOrWhiteSpace(input.CheckModeName), u => u.CheckModeName.Contains(input.CheckModeName.Trim())) .WhereIF(input.CheckStage.HasValue, u => u.CheckStage == input.CheckStage) .WhereIF(input.CheckStageForPda == true, u => u.CheckStage == CheckStageEnum.初盘开启 || u.CheckStage == CheckStageEnum.复盘开启) //pda盘点下发筛查用 .WhereIF(input.CheckStageForPdaDoing == true, u => u.CheckStage == CheckStageEnum.初盘中 || u.CheckStage == CheckStageEnum.复盘中) //pda盘点页面筛查用 .WhereIF(input.CheckStageForcheckDifference == true, u => u.CheckStage == CheckStageEnum.初盘已完成 || u.CheckStage == CheckStageEnum.复盘已完成 || u.CheckStage == CheckStageEnum.已调账) //盘点调差 盘点报表页面传入 .WhereIF(!string.IsNullOrWhiteSpace(input.CheckStageName), u => u.CheckStageName.Contains(input.CheckStageName.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.AreaCode), u => u.AreaCode.Contains(input.AreaCode.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.AreaName), u => u.AreaName.Contains(input.AreaName.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.Remarks), u => u.Remarks.Contains(input.Remarks.Trim())) .WhereIF(input.IsAudit.HasValue, u => u.IsAudit == input.IsAudit) .Select(); if (input.PlanStartDateRange != null && input.PlanStartDateRange.Count > 0) { DateTime? start = input.PlanStartDateRange[0].Value.AddDays(-1); query = query.WhereIF(start.HasValue, u => u.PlanStartDate > start); if (input.PlanStartDateRange.Count > 1 && input.PlanStartDateRange[1].HasValue) { var end = input.PlanStartDateRange[1].Value.AddDays(1); query = query.Where(u => u.PlanStartDate < end); } } if (input.PlanEndDateRange != null && input.PlanEndDateRange.Count > 0) { DateTime? start = input.PlanEndDateRange[0].Value.AddDays(-1); query = query.WhereIF(start.HasValue, u => u.PlanEndDate > start); if (input.PlanEndDateRange.Count > 1 && input.PlanEndDateRange[1].HasValue) { var end = input.PlanEndDateRange[1].Value.AddDays(1); query = query.Where(u => u.PlanEndDate < end); } } if (input.StartCheckTimeRange != null && input.StartCheckTimeRange.Count > 0) { DateTime? start = input.StartCheckTimeRange[0].Value.AddDays(-1); query = query.WhereIF(start.HasValue, u => u.StartCheckTime > start); if (input.StartCheckTimeRange.Count > 1 && input.StartCheckTimeRange[1].HasValue) { var end = input.StartCheckTimeRange[1].Value.AddDays(1); query = query.Where(u => u.StartCheckTime < end); } } if (input.EndCheckTimeRange != null && input.EndCheckTimeRange.Count > 0) { DateTime? start = input.EndCheckTimeRange[0].Value.AddDays(-1); query = query.WhereIF(start.HasValue, u => u.EndCheckTime > start); if (input.EndCheckTimeRange.Count > 1 && input.EndCheckTimeRange[1].HasValue) { var end = input.EndCheckTimeRange[1].Value.AddDays(1); query = query.Where(u => u.EndCheckTime < end); } } return query; } /// /// 重复性验证 /// /// 验证对象 /// 是否是编辑 /// private async Task CheckExist(WmsInventoryCheckOrder input, bool isEdit = false) { //没有配置组合校验,不需要验重 //没有配置单独校验,不需要验重 } /// /// 根据组合校验和单独校验验证数据是否已存在-导入时验证 /// /// /// private async Task CheckExisitForImport(List inputs) { if (inputs?.Count <= 0) { throw Oops.Oh($"导入数据不能为空"); } //根据组合校验验证表格中中是否已存在相同数据 //根据单独校验验证表格中中是否已存在相同数据 } #endregion }