using System.Collections.Generic; using Aliyun.OSS; using DOAN.Model.BZFM; using DOAN.Model.MES.order; using DOAN.Model.MES.order.Dto; using DOAN.Model.MES.product; using DOAN.Model.MES.product.Dto; using DOAN.Model.Mobile.Dto; using DOAN.Repository; using DOAN.Service.MES.product.IService; using DOAN.Service.Mobile; using Infrastructure.Attribute; using MailKit.Search; using Microsoft.Data.SqlClient; using Microsoft.IdentityModel.Tokens; using SqlSugar.DistributedSystem.Snowflake; namespace DOAN.Service.MES.product { /// /// 工单物料服务实现 /// [AppService( ServiceType = typeof(IProWorkorderMaterialService), ServiceLifetime = LifeTime.Transient )] public class ProWorkorderMaterialService : BaseService, IProWorkorderMaterialService { /// /// 根据工单号查询工单已领料清单 /// /// 工单号 /// 领料清单数据 public List GetMaterialTakeList(string workorder) { var result = Context .Queryable() .Where(it => it.Workorder == workorder) .Where(it => it.TransactionType == "领料出库") .Where(it => it.Remarks != "已撤销" || it.Remarks == null) //.WhereIF(isHideZero, it => it != "已撤销") .Select(it => new MaterialTakeDto { Id = it.Id, MaterialCode = it.MaterialCode, MaterialName = it.MaterialName, SupplierCode = it.SupplierCode, SupplierName = it.SupplierName, BatchNo = it.BatchNo, StoveCode = it.StoveCode, Quantity = it.Quantity, Unit = it.Unit, CreatedTime = it.CreatedTime.Value, Operator = it.Operator, OutboundNo = it.OutboundNo, Workorder = it.Workorder, WorkorderRaw = it.WorkorderRaw, }) .ToList(); foreach (var item in result) { if (!string.IsNullOrEmpty(item.WorkorderRaw)) { var workorderRawInfo = Context .Queryable() .Where(x => x.Workorder == item.WorkorderRaw) .First(); if (workorderRawInfo != null) { item.StoveCode = workorderRawInfo.StoveCode; item.BatchNo = workorderRawInfo.FeedOrder; } } } return result; } /// /// 根据工单号查询工单已成品入库清单 /// /// 工单号 /// 是否隐藏0库存 /// 成品入库清单数据 public List GetProductStorageList(string workorder) { var result = Context .Queryable() .Where(it => it.Workorder == workorder) .Where(it => it.TransactionType == "生产入库") .Where(it => it.Remarks != "已撤销" || it.Remarks == null) .Select(it => new ProductStorageDto { Id = it.Id, MaterialCode = it.MaterialCode, MaterialName = it.MaterialName, BatchNo = it.BatchNo, Quantity = it.Quantity, Unit = it.Unit, CreatedTime = it.CreatedTime.Value, Operator = it.Operator, InboundNo = it.InboundNo, Workorder = it.Workorder, WorkorderRaw = it.WorkorderRaw, }) .ToList(); return result; } /// /// 根据工单号查询工单已出货清单 /// /// 工单号 /// 是否隐藏0库存 /// 出货清单数据 public List GetShipmentList(string workorder) { var result = Context .Queryable() .Where(it => it.Workorder == workorder) .Where(it => it.TransactionType == "出货出库") .Where(it => it.Remarks != "已撤销" || it.Remarks == null) .Select(it => new ShipmentDto { Id = it.Id, MaterialCode = it.MaterialCode, MaterialName = it.MaterialName, BatchNo = it.BatchNo, Quantity = it.Quantity, Unit = it.Unit, CreatedTime = it.CreatedTime.Value, Operator = it.Operator, OutboundNo = it.OutboundNo, Workorder = it.Workorder, WorkorderRaw = it.WorkorderRaw, CustomerOrder = it.OrderNo, }) .ToList(); return result; } /// /// 根据工单查询物料库存接口 /// /// 工单号 /// 是否隐藏0 /// 查询范围 1-物料库 2-转用库 /// 物料库存信息列表 public PagedInfo GetMaterialInventoryList( WorkorderMaterialQueryDto query ) { try { // 参数验证 if (string.IsNullOrEmpty(query.Workorder)) { throw new ArgumentNullException(nameof(query.Workorder), "工单号不能为空"); } string workorder = query.Workorder; bool isHideZero = query.IsHideZero; var workorderInfo = Context .Queryable() .First(it => it.Workorder == workorder); if (workorderInfo == null) { throw new ArgumentException("工单号不存在", nameof(workorder)); } var result = new PagedInfo(); result.Result = new List(); // 单原材料 if (workorderInfo.RouteCode != "10") { var materialCode = workorderInfo.MaterialCode; var InventoryList = Context .Queryable() .Where(it => it.MaterialCode == materialCode) .Where(it => it.LocationCode == "YCL001") .WhereIF(isHideZero, it => it.CurrentQty > 0) .Select(it => new MaterialInventoryDto { MaterialId = it.Id, MaterialCode = it.MaterialCode, MaterialName = it.MaterialName, CurrentQuantity = it.CurrentQty, SupplierCode = it.SupplierCode, SupplierName = it.SupplierName, Unit = it.Unit, BatchNo = it.BatchNo, }) .OrderBy(it => it.MaterialCode) .OrderBy(it => it.BatchNo) .ToPage(query); result = InventoryList; } else { //组合材料 var bomList = Context .Queryable() .Where(it => it.ParentMaterialCode == workorderInfo.productionCode) .ToList(); foreach (MmMaterial mmMaterial in bomList) { var InventoryList = Context .Queryable() .Where(it => it.MaterialCode == mmMaterial.MaterialCode) .Where(it => it.SupplierCode == mmMaterial.SupplierCode) .Where(it => it.LocationCode == "YCL001" || it.LocationCode == "CP001") .WhereIF(isHideZero, it => it.CurrentQty > 0) .Select(it => new MaterialInventoryDto { MaterialId = it.Id, MaterialCode = it.MaterialCode, MaterialName = it.MaterialName, CurrentQuantity = it.CurrentQty, SupplierCode = it.SupplierCode, SupplierName = it.SupplierName, Unit = it.Unit, BatchNo = it.BatchNo, }) .OrderBy(it => it.MaterialCode) .OrderBy(it => it.BatchNo) .ToList(); result.Result.AddRange(InventoryList); result.TotalNum += 1; } } return result; } catch (Exception ex) { // 集成现有系统的日志记录 // Log.Error("查询物料库存失败", ex); throw; } } /// /// 根据工单号获取可领料工单清单(产成品领取半成品) /// /// 工单号 /// 是否隐藏0记录 /// 查询范围 1-物料库 2-转用库 /// 可领料工单清单 public PagedInfo GetPickableWorkordersByWorkorder( WorkorderMaterialQueryDto query ) { try { // 参数验证 if (string.IsNullOrEmpty(query.Workorder)) { throw new ArgumentNullException(nameof(query.Workorder), "工单号不能为空"); } string workorder = query.Workorder; var workorderInfo = Context .Queryable() .First(it => it.Workorder == workorder); if (workorderInfo == null) { throw new ArgumentException("工单不存在", nameof(workorder)); } // 需要领取半成品 if (workorderInfo.RouteCode == "10") { return Context .Queryable() .LeftJoin((mri, pro) => mri.Workorder == pro.Workorder) .Where((mri, pro) => mri.MaterialCode == workorderInfo.MaterialCode) .Where((mri, pro) => mri.TransactionType == "生产入库") .Where((mri, pro) => mri.Remarks != "已撤销" || mri.Remarks == null) //.Where((mri, pro) => pro.ShipmentNum < pro.PlanNum) .OrderByDescending((mri, pro) => mri.Workorder) .Select( (mri, pro) => new ProWorkorderDto { Id = pro.Id, Workorder = mri.Workorder, productionName = mri.MaterialCode, productionCode = mri.MaterialName, MaterialCode = mri.MaterialCode, MaterialName = mri.MaterialName, ShipmentNum = pro.ShipmentNum, PlanNum = pro.PlanNum, Remark01 = mri.Remarks, }, true ) .ToPage(query); } else { // 非10线则返回库存 // 示例返回空列表 return new PagedInfo(); } } catch (Exception ex) { // 集成现有系统的日志记录 // Log.Error("获取可领料工单清单失败", ex); throw; } } /// /// 根据工单号查询成品库存 /// /// 工单号 /// 是否隐藏为0记录 /// 成品库存信息列表 public PagedInfo GetProductInventoryList( WorkorderMaterialQueryDto query ) { try { // 参数验证 if (string.IsNullOrEmpty(query.Workorder)) { throw new ArgumentNullException(nameof(query.Workorder), "工单号不能为空"); } string workorder = query.Workorder; bool isHideZero = query.IsHideZero; var workorderInfo = Context .Queryable() .First(it => it.Workorder == workorder); if (workorderInfo == null) { throw new ArgumentException("工单不存在", nameof(workorder)); } var result = Context .Queryable() .Where(it => it.MaterialCode == workorderInfo.productionCode) .Where(it => it.LocationCode == "CP001") .WhereIF(isHideZero, it => it.CurrentQty > 0) .Select(it => new MaterialInventoryDto { MaterialId = it.Id, MaterialCode = it.MaterialCode, MaterialName = it.MaterialName, CurrentQuantity = it.CurrentQty, SupplierCode = it.SupplierCode, SupplierName = it.SupplierName, Unit = it.Unit, BatchNo = it.BatchNo, }) .OrderByDescending(it => it.BatchNo) .ToPage(query); return result; } catch (Exception ex) { // 集成现有系统的日志记录 // Log.Error("查询成品库存失败", ex); throw; } } /// /// 根据工单号获取可出货订单清单 /// /// 工单号 /// 是否隐藏为0记录 /// 可出货订单清单 public PagedInfo GetShippableOrdersByWorkorder( WorkorderMaterialQueryDto query ) { try { // 参数验证 if (string.IsNullOrEmpty(query.Workorder)) { throw new ArgumentNullException(nameof(query.Workorder), "工单号不能为空"); } string workorder = query.Workorder; var workorderInfo = Context .Queryable() .First(it => it.Workorder == workorder); if (workorderInfo == null) { throw new ArgumentException("工单不存在", nameof(workorder)); } var orderPurchaseList = Context .Queryable() .Where(o => o.MaterialCode == workorderInfo.productionCode) .Where(it => it.Orderindicator != 1) //.Where(it => it.Orderindicator != -1) .OrderBy(it => it.DeliveryDate) .Select( o => new OrderPurchaseDto { Id = o.Id, OrderNoMes = o.OrderNoMes, MaterialCode = o.MaterialCode, MaterialName = o.MaterialName, DemandQuantity = o.DemandQuantity, DeliveryQuantity = o.DeliveryQuantity, DeliveryDate = o.DeliveryDate, }, true ) .ToPage(query); // 示例返回空列表 return orderPurchaseList; } catch (Exception ex) { // 集成现有系统的日志记录 // Log.Error("获取可出货订单清单失败", ex); throw; } } /// /// 工单领料接口 /// /// 领料请求参数 /// 操作结果 public bool TakeMaterial(MaterialTakeRequestDto request) { try { // 参数验证 if (request == null) { throw new ArgumentNullException(nameof(request), "领料请求参数不能为空"); } if (string.IsNullOrEmpty(request.Workorder)) { throw new ArgumentNullException(nameof(request.Workorder), "工单号不能为空"); } if (request.Quantity <= 0) { throw new ArgumentException("领料数量必须大于0", nameof(request.Quantity)); } var materialInventory = Context .Queryable() .First(it => it.Id == request.MaterialInventoryId); if (materialInventory == null) { throw new ArgumentNullException( nameof(request.MaterialInventoryId), "物料库存ID查询失败" ); } // 业务逻辑实现部分留空待后续补充 // 此处应实现验证库存是否充足,更新库存数量,记录领料记录 ReportFlowService _reportFlowService = new ReportFlowService(); string workorder = request.Workorder; string workorderRaw = request.WorkorderRaw; int processId = 10; int finishNum = (int)request.Quantity; string stoveCode = request.StoveCode; string feedOrder = materialInventory.BatchNo; string worker = request.Operator; var result = _reportFlowService.FeedProcessReportwork( workorder, processId, finishNum, stoveCode, feedOrder, worker, workorderRaw, materialInventory.Id ); // 示例返回true return result; } catch (Exception ex) { // 集成现有系统的日志记录 // Log.Error("领料操作失败", ex); throw; } } /// /// 工单批量领料 /// /// /// public int BatchTakeMaterialByIds(WorkOrderBatchDto parm) { try { // 删除参数校验 if (parm == null) { throw new Exception("传入参数parm为空"); } List workorderIds = parm.Ids; if (workorderIds.Count == 0) { throw new Exception("传入参数Ids为空,无修改工单"); } // 检查是否有采购记录 var inboundRecordInfo = Context .Queryable() .Where(it => it.BatchNo == parm.BatchNo) .Where(it => it.TransactionType == "采购入库") .Where(it => it.Remarks != "已撤销" || it.Remarks == null) .First(); if (inboundRecordInfo == null) { throw new Exception($"批次号{parm.BatchNo}无对应采购记录,请检查"); } // 批量领料业务 int result = 0; string standardMaterialCode = string.Empty; // 业务处理前校验 List batchTakeMaterialWorkOrderList = new(); foreach (string workOrderId in workorderIds) { ProWorkorder workOrderInfo = Context .Queryable() .Where(it => it.Id == workOrderId) .First(); if (workOrderInfo == null || string.IsNullOrEmpty(workOrderInfo.Workorder)) { throw new Exception($"工单异常{workOrderId},未找到工单"); } if (workOrderInfo.RouteCode == "10") { throw new Exception("10线工单不可批量领料"); } if (string.IsNullOrEmpty(standardMaterialCode)) { standardMaterialCode = workOrderInfo.MaterialCode; } else { if (standardMaterialCode != workOrderInfo.MaterialCode) { throw new Exception( $"工单{workOrderInfo.Workorder}原材料与上一个工单不一致,上一个工单{standardMaterialCode}" ); } } string workOrder = workOrderInfo.Workorder; // 是否有领料记录 bool hasOutMaterialRecord = Context .Queryable() .Where(it => it.Workorder == workOrder) .Where(it => it.TransactionType == "领料出库") .Where(it => it.Remarks != "已撤销" || it.Remarks == null) .Any(); if (hasOutMaterialRecord) { throw new Exception($"该工单{workOrder}已存在领料记录,无法再次领料"); } batchTakeMaterialWorkOrderList.Add(workOrderInfo); } if (batchTakeMaterialWorkOrderList.Count == 0) { throw new Exception($"待领料工单数量异常"); } // 检查库存容量是否足够 var inventoryInfo = Context .Queryable() .Where(it => it.BatchNo == parm.BatchNo) .Where(it => it.MaterialCode == batchTakeMaterialWorkOrderList[0].MaterialCode) .Where(it => it.LocationCode == "YCL001") .First(); if (inventoryInfo.CurrentQty < batchTakeMaterialWorkOrderList.Count * parm.Quantity) { throw new Exception( $"该批次库存数不足,目前库存数{inventoryInfo.CurrentQty},需要{batchTakeMaterialWorkOrderList.Count * parm.Quantity}" ); } foreach (var workorderInfo in batchTakeMaterialWorkOrderList) { MaterialTakeRequestDto takeDto = new() { Workorder = workorderInfo.Workorder, WorkorderRaw = string.Empty, Quantity = parm.Quantity, MaterialInventoryId = inventoryInfo.Id, StoveCode = inboundRecordInfo.StoveCode, Operator = parm.Operator, }; bool isOk = TakeMaterial(takeDto); if (isOk) { result++; } else { throw new Exception($"领料异常结束,只成功{result}个工单"); } } return result; } catch (Exception) { throw; } } /// /// 工单成品入库接口 /// /// 成品入库请求参数 /// 操作结果 public bool StoreProduct(ProductStorageRequestDto request) { try { // 参数验证 if (request == null) { throw new ArgumentNullException(nameof(request), "成品入库请求参数不能为空"); } if (string.IsNullOrEmpty(request.Workorder)) { throw new ArgumentNullException(nameof(request.Workorder), "工单号不能为空"); } if (request.Quantity <= 0) { throw new ArgumentException("成品数量必须大于0", nameof(request.Quantity)); } var workorderInfo = Context .Queryable() .First(it => it.Workorder == request.Workorder); if (workorderInfo == null) { throw new ArgumentException("工单不存在", nameof(request.Workorder)); } var materialTakeInfo = Context .Queryable() .Where(sub => sub.Workorder == request.Workorder) .Where(sub => sub.TransactionType == "领料出库") .Where(sub => sub.Remarks != "已撤销" || sub.Remarks == null) .First(); if (materialTakeInfo == null) { throw new Exception("该工单还未领料"); } if ( workorderInfo.RouteCode != "10" && Math.Abs(materialTakeInfo.Quantity) < request.Quantity ) { throw new Exception("该工单成品入库数大于领料数"); } ReportFlowService _reportFlowService = new ReportFlowService(); string workorder = request.Workorder; int processId = 70; int finishNum = (int)request.Quantity; int badNum = 0; string worker = request.Operator; var result = _reportFlowService.ProcessReportWork( workorder, processId, finishNum, badNum, worker ); // 示例返回true return result; } catch (Exception ex) { // 集成现有系统的日志记录 // Log.Error("成品入库操作失败", ex); throw; } } /// /// 工单出货接口 /// /// 出货请求参数 /// 操作结果 public bool ShipProduct(ShipmentRequestDto request) { try { // 参数验证 if (request == null) { throw new ArgumentNullException(nameof(request), "出货请求参数不能为空"); } if (string.IsNullOrEmpty(request.Workorder)) { throw new ArgumentNullException(nameof(request.Workorder), "工单号不能为空"); } if (string.IsNullOrEmpty(request.OrderId)) { throw new ArgumentNullException(nameof(request.OrderId), "订单ID不能为空"); } // 业务逻辑实现部分留空待后续补充 // 此处应实现验证库存是否充足,更新库存状态,记录出货信息 OrderPurchase orderPurchase = Context .Queryable() .Where(o => o.Id == request.OrderId) .First(); ReportFlowService _reportFlowService = new ReportFlowService(); string workorder = request.Workorder; int processId = 90; int finishNum = (int)request.Quantity; int badNum = 0; string customerOrder = orderPurchase.OrderNoMes; string worker = request.Operator; var result = _reportFlowService.ShipmentProcessReportwork( workorder, processId, finishNum, badNum, customerOrder, worker ); if (result == 0) { throw new Exception("数据库操作失败"); } if (result == 2) { throw new Exception("订单号不存在"); } if (result == 3) { throw new Exception("订单超额"); } if (result == 4) { throw new Exception("工单不存在"); } if (result == 5) { throw new Exception("主体型号和订单物料不匹配"); } return result == 1; } catch (Exception ex) { // 集成现有系统的日志记录 // Log.Error("出货操作失败", ex); throw new Exception(ex.Message); } } } }