diff --git a/DOAN.Admin.WebApi/Controllers/MES/Product/ProWorkorderController.cs b/DOAN.Admin.WebApi/Controllers/MES/Product/ProWorkorderController.cs index 5284dcb..395602c 100644 --- a/DOAN.Admin.WebApi/Controllers/MES/Product/ProWorkorderController.cs +++ b/DOAN.Admin.WebApi/Controllers/MES/Product/ProWorkorderController.cs @@ -22,9 +22,15 @@ namespace DOAN.Admin.WebApi.Controllers /// private readonly IProWorkorderService _ProWorkorderService; - public ProWorkorderController(IProWorkorderService ProWorkorderService) + /// + /// 工单物料接口 + /// + private readonly IProWorkorderMaterialService _ProWorkorderMaterialService; + + public ProWorkorderController(IProWorkorderService ProWorkorderService, IProWorkorderMaterialService ProWorkorderMaterialService) { _ProWorkorderService = ProWorkorderService; + _ProWorkorderMaterialService = ProWorkorderMaterialService; } /// @@ -397,5 +403,102 @@ namespace DOAN.Admin.WebApi.Controllers return ToResponse(500, ex.Message); } } + + /// + /// 获取工单生产进度 + /// + /// 工单号 + /// + [HttpGet("getWorkorderWithProgress/{workorder}")] + [ActionPermissionFilter(Permission = "productManagement:proworkorder:query")] + public IActionResult GetWorkorderWithProgress(string workorder) + { + try + { + var response = _ProWorkorderService.GetWorkorderWithProgress(workorder); + return SUCCESS(response); + } + catch (Exception ex) + { + + return ToResponse(500, ex.Message); + } + + } + + /// + /// 根据工单号查询领料清单 + /// + /// 工单号 + /// 领料清单数据 + [HttpGet("GetMaterialTakeList/{workorder}")] + [ActionPermissionFilter(Permission = "productManagement:proworkorder:query")] + public IActionResult GetMaterialTakeList(string workorder) + { + try + { + if (string.IsNullOrEmpty(workorder)) + { + return ToResponse(ApiResult.Error($"工单号不能为空")); + } + + var response = _ProWorkorderMaterialService.GetMaterialTakeList(workorder); + return SUCCESS(response); + } + catch (Exception ex) + { + return ToResponse(500, ex.Message); + } + } + + /// + /// 根据工单号查询成品入库清单 + /// + /// 工单号 + /// 成品入库清单数据 + [HttpGet("GetProductStorageList/{workorder}")] + [ActionPermissionFilter(Permission = "productManagement:proworkorder:query")] + public IActionResult GetProductStorageList(string workorder) + { + try + { + if (string.IsNullOrEmpty(workorder)) + { + return ToResponse(ApiResult.Error($"工单号不能为空")); + } + + var response = _ProWorkorderMaterialService.GetProductStorageList(workorder); + return SUCCESS(response); + } + catch (Exception ex) + { + return ToResponse(500, ex.Message); + } + } + + /// + /// 根据工单号查询出货清单 + /// + /// 工单号 + /// 出货清单数据 + [HttpGet("GetShipmentList/{workorder}")] + [ActionPermissionFilter(Permission = "productManagement:proworkorder:query")] + public IActionResult GetShipmentList(string workorder) + { + try + { + if (string.IsNullOrEmpty(workorder)) + { + return ToResponse(ApiResult.Error($"工单号不能为空")); + } + + var response = _ProWorkorderMaterialService.GetShipmentList(workorder); + return SUCCESS(response); + } + catch (Exception ex) + { + return ToResponse(500, ex.Message); + } + } } } diff --git a/DOAN.Model/MES/Material/Dto/MmRecordInboundDto.cs b/DOAN.Model/MES/Material/Dto/MmRecordInboundDto.cs index b71dd38..0587d91 100644 --- a/DOAN.Model/MES/Material/Dto/MmRecordInboundDto.cs +++ b/DOAN.Model/MES/Material/Dto/MmRecordInboundDto.cs @@ -201,7 +201,7 @@ namespace DOAN.Model.BZFM.Dto [ExcelColumn(Name = "创建时间")] [SugarColumn(ColumnName = "created_time")] public DateTime? CreatedTime { get; set; } - + [ExcelColumn(Name = "原材料工单号")] [SugarColumn(ColumnName = "workorder_raw")] public string WorkorderRaw { get; set; } @@ -214,15 +214,18 @@ namespace DOAN.Model.BZFM.Dto { [Required(ErrorMessage = "记录ID不能为空")] public int Id { get; set; } - + public string InboundNo { get; set; } [Required(ErrorMessage = "领料数量不能为空")] public decimal Quantity { get; set; } - [Required(ErrorMessage = "成品工单号不能为空")] + [Required(ErrorMessage = "原始工单号不能为空")] public string WorkorderRow { get; set; } - + + [Required(ErrorMessage = "工单号不能为空")] + public string Workorder { get; set; } + [Required(ErrorMessage = "领料人不能为空")] public string Operator { get; set; } } diff --git a/DOAN.Model/MES/Product/Dto/WorkorderMaterialDto.cs b/DOAN.Model/MES/Product/Dto/WorkorderMaterialDto.cs new file mode 100644 index 0000000..2758fc4 --- /dev/null +++ b/DOAN.Model/MES/Product/Dto/WorkorderMaterialDto.cs @@ -0,0 +1,183 @@ +using System; + +namespace DOAN.Model.MES.product.Dto +{ + /// + /// 领料清单数据传输对象 + /// + public class MaterialTakeDto + { + /// + /// 物料编码 + /// + public string MaterialCode { get; set; } + + /// + /// 物料名称 + /// + public string MaterialName { get; set; } + + /// + /// 批次号 + /// + public string BatchNo { get; set; } + + /// + /// 数量 + /// + public decimal Quantity { get; set; } + + /// + /// 单位 + /// + public string Unit { get; set; } + + /// + /// 操作时间 + /// + public DateTime CreatedTime { get; set; } + + /// + /// 操作人 + /// + public string Operator { get; set; } + + /// + /// 出库单号 + /// + public string OutboundNo { get; set; } + + /// + /// 工单号 + /// + public string Workorder { get; set; } + + /// + /// 原材料工单号 + /// + public string WorkorderRaw { get; set; } + } + + /// + /// 成品入库清单数据传输对象 + /// + public class ProductStorageDto + { + /// + /// 物料编码 + /// + public string MaterialCode { get; set; } + + /// + /// 物料名称 + /// + public string MaterialName { get; set; } + + /// + /// 批次号 + /// + public string BatchNo { get; set; } + + /// + /// 数量 + /// + public decimal Quantity { get; set; } + + /// + /// 单位 + /// + public string Unit { get; set; } + + + /// + /// 操作时间 + /// + public DateTime CreatedTime { get; set; } + + /// + /// 操作人 + /// + public string Operator { get; set; } + + /// + /// 入库单号 + /// + public string InboundNo { get; set; } + + /// + /// 工单号 + /// + public string Workorder { get; set; } + + /// + /// 原材料工单号 + /// + public string WorkorderRaw { get; set; } + + /// + /// 订单号 + /// + public string CustomerOrder { get; set; } + } + + /// + /// 出货清单数据传输对象 + /// + public class ShipmentDto + { + /// + /// 物料编码 + /// + public string MaterialCode { get; set; } + + /// + /// 物料名称 + /// + public string MaterialName { get; set; } + + /// + /// 批次号 + /// + public string BatchNo { get; set; } + + /// + /// 数量 + /// + public decimal Quantity { get; set; } + + /// + /// 单位 + /// + public string Unit { get; set; } + + /// + /// 操作时间 + /// + public DateTime CreatedTime { get; set; } + + /// + /// 操作人 + /// + public string Operator { get; set; } + + /// + /// 出货单号 + /// + public string OutboundNo { get; set; } + + /// + /// 工单号 + /// + public string Workorder { get; set; } + + /// + /// 订单号 + /// + public string CustomerOrder { get; set; } + + /// + /// 原材料工单号 + /// + public string WorkorderRaw { get; set; } + } +} diff --git a/DOAN.Service/MES/Material/IService/IMmRecordInboundService.cs b/DOAN.Service/MES/Material/IService/IMmRecordInboundService.cs index b21b621..ffebda4 100644 --- a/DOAN.Service/MES/Material/IService/IMmRecordInboundService.cs +++ b/DOAN.Service/MES/Material/IService/IMmRecordInboundService.cs @@ -32,5 +32,12 @@ namespace DOAN.Service.BZFM.IBZFMService /// /// string TakeMaterial(TakeMaterialRequestDto parm); + + /// + /// 初始化领料记录 + /// + /// + /// + TakeMaterialRequestDto InitializeMaterialTakeRecord(TakeMaterialRequestDto parm); } } diff --git a/DOAN.Service/MES/Material/MmRecordInboundService.cs b/DOAN.Service/MES/Material/MmRecordInboundService.cs index 1116bd8..df6f3bb 100644 --- a/DOAN.Service/MES/Material/MmRecordInboundService.cs +++ b/DOAN.Service/MES/Material/MmRecordInboundService.cs @@ -387,7 +387,9 @@ namespace DOAN.Service.BZFM { try { - + // 初始化领料记录参数 + parm = InitializeMaterialTakeRecord(parm); + var inboundInfo = Queryable().Where(x => x.Id == parm.Id).First(); if (inboundInfo == null) { @@ -397,7 +399,7 @@ namespace DOAN.Service.BZFM { return "该记录已撤销,无法领料!"; } - if(parm.Quantity > inboundInfo.Quantity) + if (parm.Quantity > inboundInfo.Quantity) { return "领料数量超过记录最大值!"; } @@ -409,7 +411,10 @@ namespace DOAN.Service.BZFM return "该入库记录对应的工单不存在!"; } Context.Ado.BeginTran(); - inboundInfo.WorkorderRaw = parm.WorkorderRow; + // 根据规范:WorkorderRaw字段用于永久性记录原材料最初关联的工单号信息,保持不变 + // 因此这里不应该修改WorkorderRaw,而是保持其原值 + // 只更新Workorder字段,动态记录当前操作环节所对应的工单号 + inboundInfo.Workorder = parm.Workorder; inboundInfo.Remarks += $"[已领料{parm.Quantity}]"; Context.Updateable(inboundInfo).ExecuteCommand(); // 填写出库单 @@ -421,10 +426,10 @@ namespace DOAN.Service.BZFM LocationCode = inboundInfo.LocationCode, WarehouseCode = inboundInfo.WarehouseCode, OrderNo = workorderInfo.CustomerOrder, - // 原材料工单号 - Workorder = inboundInfo.Workorder, - // 产成品工单号 - WorkorderRaw = parm.WorkorderRow, + // 原材料工单号:保持原材料最初关联的工单号 + Workorder = inboundInfo.WorkorderRaw, // 使用WorkorderRaw作为原材料工单号 + // 产成品工单号:动态记录当前操作对应的工单号 + WorkorderRaw = parm.Workorder, // 使用传入的Workorder作为产成品工单号 Operator = parm.Operator, Quantity = parm.Quantity, TransactionType = "领料出库", @@ -442,5 +447,177 @@ namespace DOAN.Service.BZFM } } + + /// + /// 初始化领料记录 + /// + /// + /// + public TakeMaterialRequestDto InitializeMaterialTakeRecord(TakeMaterialRequestDto parm) + { + try + { + // 数据验证 + if (parm == null) + { + throw new ArgumentNullException(nameof(parm), "领料请求参数不能为空"); + } + + // 验证必填字段 + if (parm.Id <= 0) + { + throw new ArgumentException("记录ID不能为空且必须大于0", nameof(parm.Id)); + } + + if (string.IsNullOrEmpty(parm.Workorder)) + { + throw new ArgumentException("成品工单号不能为空", nameof(parm.Workorder)); + } + + if (string.IsNullOrEmpty(parm.Operator)) + { + throw new ArgumentException("领料人不能为空", nameof(parm.Operator)); + } + + if (parm.Quantity <= 0) + { + throw new ArgumentException("领料数量必须大于0", nameof(parm.Quantity)); + } + + // 默认值设置 + if (string.IsNullOrEmpty(parm.InboundNo)) + { + // 尝试从入库记录中获取入库单号 + var inboundInfo = Queryable().Where(x => x.Id == parm.Id).First(); + if (inboundInfo != null) + { + parm.InboundNo = inboundInfo.InboundNo; + } + else + { + parm.InboundNo = string.Empty; + } + } + + // 确保WorkorderRaw和Workorder字段的正确设置 + // 这里Workorder已经通过验证,确保不为空 + // WorkorderRaw将在TakeMaterial方法中从入库记录中获取并保持不变 + + return parm; + } + catch (Exception ex) + { + // 异常处理 + throw new Exception($"初始化领料记录失败: {ex.Message}", ex); + } + } + + /// + /// 初始化入库记录数据(适用于成品入库和原材料入库) + /// + /// 入库记录对象 + /// 当前操作工单号 + /// 原材料工单号(如果有) + /// 初始化后的入库记录对象 + /// 参数验证异常 + public MmRecordInbound InitializeProductStorageRecord(MmRecordInbound inboundRecord, string currentWorkorder, string rawMaterialWorkorder = null) + { + // 参数验证 + if (inboundRecord == null) + { + throw new ArgumentNullException(nameof(inboundRecord), "入库记录对象不能为空"); + } + + if (string.IsNullOrWhiteSpace(currentWorkorder)) + { + throw new ArgumentException("当前操作工单号不能为空", nameof(currentWorkorder)); + } + + if (string.IsNullOrWhiteSpace(inboundRecord.MaterialCode)) + { + throw new ArgumentException("物料编码不能为空"); + } + + if (string.IsNullOrWhiteSpace(inboundRecord.WarehouseCode)) + { + throw new ArgumentException("仓库编码不能为空"); + } + + if (inboundRecord.Quantity <= 0) + { + throw new ArgumentException("入库数量必须大于0"); + } + + if (string.IsNullOrWhiteSpace(inboundRecord.TransactionType)) + { + throw new ArgumentException("入库类型不能为空"); + } + + // 设置默认值 + if (string.IsNullOrWhiteSpace(inboundRecord.InboundNo)) + { + // 生成入库单号:IN + 年月日时分秒 + inboundRecord.InboundNo = "IN" + DateTime.Now.ToString("yyyyMMddHHmmss"); + } + + if (inboundRecord.CreatedTime == null) + { + inboundRecord.CreatedTime = DateTime.Now; + } + + if (string.IsNullOrWhiteSpace(inboundRecord.Unit)) + { + inboundRecord.Unit = "个"; + } + + // 字段使用规范: + // WorkorderRaw:永久性记录原材料最初关联的工单号信息,保持不变 + // Workorder:动态记录当前操作环节所对应的工单号,根据实际业务操作场景实时更新 + if (!string.IsNullOrWhiteSpace(rawMaterialWorkorder)) + { + // 如果提供了原材料工单号,设置为WorkorderRaw + inboundRecord.WorkorderRaw = rawMaterialWorkorder; + } + else if (string.IsNullOrWhiteSpace(inboundRecord.WorkorderRaw)) + { + // 如果没有提供原材料工单号且WorkorderRaw为空,则使用当前工单号作为初始值 + inboundRecord.WorkorderRaw = currentWorkorder; + } + // 注意:如果WorkorderRaw已经有值,保持不变,确保其在整个生命周期中保持恒定 + + // 更新当前操作工单号 + inboundRecord.Workorder = currentWorkorder; + + return inboundRecord; + } + + /// + /// 创建并初始化入库记录 + /// + /// 入库记录对象 + /// 当前操作工单号 + /// 原材料工单号(如果有) + /// 创建的入库记录对象 + public MmRecordInbound CreateAndInitializeProductStorageRecord(MmRecordInbound inboundRecord, string currentWorkorder, string rawMaterialWorkorder = null) + { + try + { + // 初始化入库记录数据 + var initializedRecord = InitializeProductStorageRecord(inboundRecord, currentWorkorder, rawMaterialWorkorder); + + // 保存到数据库 + return Insertable(initializedRecord).ExecuteReturnEntity(); + } + catch (ArgumentException ex) + { + // 处理参数验证异常 + throw new Exception($"入库记录初始化失败:{ex.Message}", ex); + } + catch (Exception ex) + { + // 处理其他异常 + throw new Exception($"创建入库记录失败:{ex.Message}", ex); + } + } } } diff --git a/DOAN.Service/MES/Material/MmRecordOutboundService.cs b/DOAN.Service/MES/Material/MmRecordOutboundService.cs index ec4b925..d08e33a 100644 --- a/DOAN.Service/MES/Material/MmRecordOutboundService.cs +++ b/DOAN.Service/MES/Material/MmRecordOutboundService.cs @@ -370,9 +370,118 @@ namespace DOAN.Service.BZFM TransactionType = it.TransactionType, OrderNo = it.OrderNo, Operator = it.Operator, + WorkorderRaw = it.WorkorderRaw }); return query.ToPage(pager); } + + /// + /// 初始化出库记录数据 + /// + /// 出库记录对象 + /// 当前操作工单号 + /// 原材料工单号(如果有) + /// 初始化后的出库记录对象 + /// 参数验证异常 + public MmRecordOutbound InitializeShipmentRecord(MmRecordOutbound outboundRecord, string currentWorkorder, string rawMaterialWorkorder = null) + { + // 参数验证 + if (outboundRecord == null) + { + throw new ArgumentNullException(nameof(outboundRecord), "出库记录对象不能为空"); + } + + if (string.IsNullOrWhiteSpace(currentWorkorder)) + { + throw new ArgumentException("当前操作工单号不能为空", nameof(currentWorkorder)); + } + + if (string.IsNullOrWhiteSpace(outboundRecord.MaterialCode)) + { + throw new ArgumentException("物料编码不能为空"); + } + + if (string.IsNullOrWhiteSpace(outboundRecord.WarehouseCode)) + { + throw new ArgumentException("仓库编码不能为空"); + } + + if (outboundRecord.Quantity <= 0) + { + throw new ArgumentException("出库数量必须大于0"); + } + + if (string.IsNullOrWhiteSpace(outboundRecord.TransactionType)) + { + throw new ArgumentException("出库类型不能为空"); + } + + // 设置默认值 + if (string.IsNullOrWhiteSpace(outboundRecord.OutboundNo)) + { + // 生成出库单号:OUT + 年月日时分秒 + outboundRecord.OutboundNo = "OUT" + DateTime.Now.ToString("yyyyMMddHHmmss"); + } + + if (outboundRecord.CreatedTime == null) + { + outboundRecord.CreatedTime = DateTime.Now; + } + + if (string.IsNullOrWhiteSpace(outboundRecord.Unit)) + { + outboundRecord.Unit = "个"; + } + + // 字段使用规范: + // WorkorderRaw:永久性记录原材料最初关联的工单号信息,保持不变 + // Workorder:动态记录当前操作环节所对应的工单号,根据实际业务操作场景实时更新 + if (!string.IsNullOrWhiteSpace(rawMaterialWorkorder)) + { + // 如果提供了原材料工单号,设置为WorkorderRaw + outboundRecord.WorkorderRaw = rawMaterialWorkorder; + } + else if (string.IsNullOrWhiteSpace(outboundRecord.WorkorderRaw)) + { + // 如果没有提供原材料工单号且WorkorderRaw为空,则使用当前工单号作为初始值 + outboundRecord.WorkorderRaw = currentWorkorder; + } + // 注意:如果WorkorderRaw已经有值,保持不变,确保其在整个生命周期中保持恒定 + + // 更新当前操作工单号 + outboundRecord.Workorder = currentWorkorder; + + return outboundRecord; + } + + /// + /// 创建并初始化出库记录 + /// + /// 出库记录对象 + /// 当前操作工单号 + /// 原材料工单号(如果有) + /// 创建的出库记录对象 + public MmRecordOutbound CreateAndInitializeShipmentRecord(MmRecordOutbound outboundRecord, string currentWorkorder, string rawMaterialWorkorder = null) + { + try + { + // 初始化出库记录数据 + var initializedRecord = InitializeShipmentRecord(outboundRecord, currentWorkorder, rawMaterialWorkorder); + + // 保存到数据库 + return Insertable(initializedRecord).ExecuteReturnEntity(); + } + catch (ArgumentException ex) + { + // 处理参数验证异常 + throw new Exception($"出库记录初始化失败:{ex.Message}", ex); + } + catch (Exception ex) + { + // 处理其他异常 + throw new Exception($"创建出库记录失败:{ex.Message}", ex); + } + } } } diff --git a/DOAN.Service/MES/Product/IService/IProWorkorderMaterialService.cs b/DOAN.Service/MES/Product/IService/IProWorkorderMaterialService.cs new file mode 100644 index 0000000..189717a --- /dev/null +++ b/DOAN.Service/MES/Product/IService/IProWorkorderMaterialService.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using DOAN.Model.MES.product.Dto; + +namespace DOAN.Service.MES.product.IService +{ + /// + /// 工单物料服务接口 + /// + public interface IProWorkorderMaterialService + { + /// + /// 根据工单号查询领料清单 + /// + /// 工单号 + /// 领料清单数据 + List GetMaterialTakeList(string workorder); + + /// + /// 根据工单号查询成品入库清单 + /// + /// 工单号 + /// 成品入库清单数据 + List GetProductStorageList(string workorder); + + /// + /// 根据工单号查询出货清单 + /// + /// 工单号 + /// 出货清单数据 + List GetShipmentList(string workorder); + } +} diff --git a/DOAN.Service/MES/Product/IService/IProWorkorderQueryService.cs b/DOAN.Service/MES/Product/IService/IProWorkorderQueryService.cs index 9f3e583..ac95ad2 100644 --- a/DOAN.Service/MES/Product/IService/IProWorkorderQueryService.cs +++ b/DOAN.Service/MES/Product/IService/IProWorkorderQueryService.cs @@ -42,5 +42,12 @@ namespace DOAN.Service.MES.product.IService /// /// List SearchBOMNum(string workorder_num); + + /// + /// 获取工单生产进度 + /// + /// 工单号 + /// + int GetWorkorderWithProgress(string workorder); } } \ No newline at end of file diff --git a/DOAN.Service/MES/Product/IService/IProWorkorderService.cs b/DOAN.Service/MES/Product/IService/IProWorkorderService.cs index eba0d83..a92a8b0 100644 --- a/DOAN.Service/MES/Product/IService/IProWorkorderService.cs +++ b/DOAN.Service/MES/Product/IService/IProWorkorderService.cs @@ -66,5 +66,12 @@ namespace DOAN.Service.MES.product.IService Task<(string, Stream)> ExportPDFByQuestPDFDemo(string[] workorderArray); Task PrintTicketsByTemplate(ProWorkorderExportDto param); + + /// + /// 获取工单生产进度 + /// + /// 工单号 + /// + int GetWorkorderWithProgress(string workorder); } } diff --git a/DOAN.Service/MES/Product/ProWorkorderCoreService.cs b/DOAN.Service/MES/Product/ProWorkorderCoreService.cs index 59707f2..c716654 100644 --- a/DOAN.Service/MES/Product/ProWorkorderCoreService.cs +++ b/DOAN.Service/MES/Product/ProWorkorderCoreService.cs @@ -44,14 +44,16 @@ namespace DOAN.Service.MES.product /// public int UpdateProWorkorder(ProWorkorder model) { - //增加日志 - /*ProWorkorderUpdateLog logObj = new ProWorkorderUpdateLog(); - logObj.Id = XueHua; - logObj.Workorder = model.Workorder; - logObj.Log = "修改生产工单"; - logObj.ChangeTime = DateTime.Now; - logObj.Operator = model.CreatedBy; - Context.Insertable(logObj).ExecuteCommand();*/ + //增加修改日志 + ProWorkorderUpdateLog logObj = new ProWorkorderUpdateLog + { + Id = XueHua, + Workorder = model.Workorder, + Log = "修改生产工单", + ChangeTime = DateTime.Now, + Operator = model.CreatedBy + }; + Context.Insertable(logObj).ExecuteCommand(); var response = Update(model, true); return response; @@ -201,14 +203,15 @@ namespace DOAN.Service.MES.product proWorkorder.Status = 1; //增加日志 - ProWorkorderUpdateLog logObj = new ProWorkorderUpdateLog(); - logObj.Id = XueHua; - logObj.Workorder = proWorkorder.Workorder; - logObj.Log = "手动新增"; - logObj.ChangeTime = DateTime.Now; - logObj.Operator = proWorkorder.CreatedBy; - logObj.ChangeTime = DateTime.Now; - logObj.CreatedBy = proWorkorder.CreatedBy; + ProWorkorderUpdateLog logObj = new() + { + Id = XueHua, + Workorder = proWorkorder.Workorder, + Log = "手动新增", + ChangeTime = DateTime.Now, + Operator = proWorkorder.CreatedBy, + CreatedBy = proWorkorder.CreatedBy + }; UseTran2(() => { result = Context.Insertable(proWorkorder).ExecuteCommand(); @@ -315,5 +318,105 @@ namespace DOAN.Service.MES.product return Context.Updateable(proWorkorderList).ExecuteCommand(); } + + /// + /// 计算工单生产进度 + /// + /// 工单ID + /// 生产进度百分比(0-100) + public int CalculateProductionProgress(string workorderId) + { + // 获取工单信息 + var workorder = GetInfo(workorderId); + if (workorder == null) + { + throw new ArgumentException($"工单ID {workorderId} 不存在"); + } + + // 基于工单状态计算生产进度 + return CalculateProductionProgressByStatus(workorder.Status); + } + + /// + /// 根据工单状态计算生产进度 + /// + /// 工单状态(1 init, 2 start, 3 end) + /// 生产进度百分比(0-100) + public int CalculateProductionProgressByStatus(int? status) + { + // 工单状态与生产进度的映射关系 + switch (status) + { + case 1: // init - 初始化 + return 0; + case 2: // start - 开始 + return 50; + case 3: // end - 结束 + return 100; + default: + return 0; + } + } + + /// + /// 批量获取工单生产进度 + /// + /// 工单ID列表 + /// 工单ID与生产进度的映射 + public Dictionary BatchCalculateProductionProgress(List workorderIds) + { + var result = new Dictionary(); + + if (workorderIds == null || workorderIds.Count == 0) + { + return result; + } + + // 批量获取工单信息 + var workorders = Context.Queryable() + .Where(it => workorderIds.Contains(it.Id)) + .ToList(); + + // 计算每个工单的生产进度 + foreach (var workorder in workorders) + { + result[workorder.Id] = CalculateProductionProgressByStatus(workorder.Status); + } + + // 对于未找到的工单,设置进度为0 + foreach (var id in workorderIds) + { + if (!result.ContainsKey(id)) + { + result[id] = 0; + } + } + + return result; + } + + /// + /// 获取工单详细信息(包含生产进度) + /// + /// 工单ID + /// 包含生产进度的工单信息 + public dynamic GetWorkorderWithProgress(string workorderId) + { + var workorder = GetInfo(workorderId); + if (workorder == null) + { + throw new ArgumentException($"工单 {workorderId} 不存在"); + } + + // 计算生产进度 + int progress = CalculateProductionProgressByStatus(workorder.Status); + + // 返回包含生产进度的工单信息 + return new + { + Workorder = workorder, + ProductionProgress = progress + }; + } } } \ No newline at end of file diff --git a/DOAN.Service/MES/Product/ProWorkorderMaterialService.cs b/DOAN.Service/MES/Product/ProWorkorderMaterialService.cs new file mode 100644 index 0000000..36b3af9 --- /dev/null +++ b/DOAN.Service/MES/Product/ProWorkorderMaterialService.cs @@ -0,0 +1,109 @@ +using System.Collections.Generic; +using DOAN.Model.BZFM; +using DOAN.Model.MES.product; +using DOAN.Model.MES.product.Dto; +using DOAN.Service.MES.product.IService; +using Infrastructure.Attribute; + +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 != "已撤销") + .Select(it => new MaterialTakeDto + { + 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, + }) + .ToList(); + return result; + } + + /// + /// 根据工单号查询成品入库清单 + /// + /// 工单号 + /// 成品入库清单数据 + public List GetProductStorageList(string workorder) + { + var result = Context + .Queryable() + .Where(it => it.Workorder == workorder) + .Where(it => it.TransactionType == "生产入库") + .Where(it => it.Remarks != "已撤销") + .Select(it => new ProductStorageDto + { + 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; + } + + /// + /// 根据工单号查询出货清单 + /// + /// 工单号 + /// 出货清单数据 + public List GetShipmentList(string workorder) + { + var result = Context + .Queryable() + .Where(it => it.Workorder == workorder) + .Where(it => it.TransactionType == "出货出库") + .Where(it => it.Remarks != "已撤销") + .Select(it => new ShipmentDto + { + 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; + } + } +} diff --git a/DOAN.Service/MES/Product/ProWorkorderQueryService.cs b/DOAN.Service/MES/Product/ProWorkorderQueryService.cs index 94480c9..2452a77 100644 --- a/DOAN.Service/MES/Product/ProWorkorderQueryService.cs +++ b/DOAN.Service/MES/Product/ProWorkorderQueryService.cs @@ -11,7 +11,10 @@ namespace DOAN.Service.MES.product /// /// 工单查询服务 /// - [AppService(ServiceType = typeof(IProWorkorderQueryService), ServiceLifetime = LifeTime.Transient)] + [AppService( + ServiceType = typeof(IProWorkorderQueryService), + ServiceLifetime = LifeTime.Transient + )] public class ProWorkorderQueryService : BaseService, IProWorkorderQueryService { /// @@ -52,7 +55,9 @@ namespace DOAN.Service.MES.product .AndIF(!string.IsNullOrEmpty(parm.GroupCode), it => it.GroupCode == parm.GroupCode) .AndIF( parm.WorkorderDate != null && parm.WorkorderDate.Length > 0, - it => it.WorkorderDate >= parm.WorkorderDate[0] && it.WorkorderDate <= parm.WorkorderDate[1] + it => + it.WorkorderDate >= parm.WorkorderDate[0] + && it.WorkorderDate <= parm.WorkorderDate[1] ) .And(it => it.PlanNum > 0) .ToExpression(); @@ -103,7 +108,9 @@ namespace DOAN.Service.MES.product .AndIF(!string.IsNullOrEmpty(parm.GroupCode), it => it.GroupCode == parm.GroupCode) .AndIF( parm.WorkorderDate != null && parm.WorkorderDate.Length > 0, - it => it.WorkorderDate >= parm.WorkorderDate[0] && it.WorkorderDate <= parm.WorkorderDate[1] + it => + it.WorkorderDate >= parm.WorkorderDate[0] + && it.WorkorderDate <= parm.WorkorderDate[1] ) .And(it => it.PlanNum > 0) .ToExpression(); @@ -134,7 +141,9 @@ namespace DOAN.Service.MES.product /// /// /// - public PagedInfo GetWorkorderTraceProgressList(ProWorkorderQueryDto query) + public PagedInfo GetWorkorderTraceProgressList( + ProWorkorderQueryDto query + ) { // 这里需要实现工单进度跟踪列表的查询逻辑 // 暂时返回空列表 @@ -152,5 +161,32 @@ namespace DOAN.Service.MES.product // 暂时返回空列表 return new List(); } + + /// + /// 获取工单生产进度 + /// + /// 工单号 + /// + public int GetWorkorderWithProgress(string workorder) + { + var workorderInfo = Context + .Queryable() + .Where(it => it.Workorder == workorder) + .First(); + if (workorderInfo == null) + { + throw new Exception("工单不存在"); + } + var reportInfo = Context + .Queryable() + .Where(it => it.Workorder == workorder) + .OrderByDescending(it => it.ProcessId) + .First(); + if (reportInfo == null) + { + return 1; + } + return reportInfo.ProcessId; + } } -} \ No newline at end of file +} diff --git a/DOAN.Service/MES/Product/ProWorkorderService.cs b/DOAN.Service/MES/Product/ProWorkorderService.cs index 1277a6e..d8f67db 100644 --- a/DOAN.Service/MES/Product/ProWorkorderService.cs +++ b/DOAN.Service/MES/Product/ProWorkorderService.cs @@ -256,5 +256,15 @@ namespace DOAN.Service.MES.product { return _queryService.GetWorkorderTraceProgressList(query); } + + /// + /// 获取工单生产进度 + /// + /// 工单号 + /// + public int GetWorkorderWithProgress(string workorder) + { + return _queryService.GetWorkorderWithProgress(workorder); + } } }