using DOAN.Model.BZFM; using DOAN.Model.BZFM.Dto; using DOAN.Model.MES.product; using DOAN.Repository; using DOAN.Service.BZFM.IService; using Infrastructure.Attribute; using Infrastructure.Extensions; using SqlSugar.DistributedSystem.Snowflake; namespace DOAN.Service.BZFM { /// /// Service业务层处理 /// [AppService(ServiceType = typeof(IQcScrapRecordsService), ServiceLifetime = LifeTime.Transient)] public class QcScrapRecordsService : BaseService, IQcScrapRecordsService { /// /// 查询报废记录表列表 /// /// /// public PagedInfo GetList(QcScrapRecordsQueryDto parm) { var predicate = QueryExp(parm); var response = Queryable() .Where(predicate.ToExpression()) .OrderByDescending(it => it.CreatedTime) .ToPage(parm); return response; } /// /// 获取详情 /// /// /// public QcScrapRecords GetInfo(long Id) { var response = Queryable().Where(x => x.Id == Id).First(); return response; } /// /// 添加报废记录表 /// /// /// public QcScrapRecords AddQcScrapRecords(QcScrapRecords model) { // 如果没有提供报废单号,则生成一个 if (string.IsNullOrEmpty(model.ScrapOrderNo)) { // 根据报废类型选择前缀 string prefix = model.ScrapType == "转用" ? "ZY" : "BF"; model.ScrapOrderNo = GenerateScrapOrderNo(prefix); } return Context.Insertable(model).ExecuteReturnEntity(); } /// /// 修改报废记录表 /// /// /// public int UpdateQcScrapRecords(QcScrapRecords model) { return Update(model, true); } /// /// 查询导出表达式 /// /// /// private static Expressionable QueryExp(QcScrapRecordsQueryDto parm) { var predicate = Expressionable .Create() // 模糊搜索字段 .AndIF( !string.IsNullOrEmpty(parm.ScrapOrderNo), it => it.ScrapOrderNo.Contains(parm.ScrapOrderNo) ) .AndIF( !string.IsNullOrEmpty(parm.Workorder), it => it.Workorder.Contains(parm.Workorder) ) .AndIF( !string.IsNullOrEmpty(parm.StoveCode), it => it.StoveCode.Contains(parm.StoveCode) ) .AndIF( !string.IsNullOrEmpty(parm.ProductCode), it => it.ProductCode.Contains(parm.ProductCode) ) .AndIF(!string.IsNullOrEmpty(parm.BatchNo), it => it.BatchNo.Contains(parm.BatchNo)) // 精确搜索字段 .AndIF( !string.IsNullOrEmpty(parm.MaterialCode), it => it.MaterialCode == parm.MaterialCode ) .AndIF( !string.IsNullOrEmpty(parm.SupplierCode), it => it.SupplierCode == parm.SupplierCode ) .AndIF(!string.IsNullOrEmpty(parm.ScrapType), it => it.ScrapType == parm.ScrapType) .AndIF(!string.IsNullOrEmpty(parm.LineCode), it => it.LineCode == parm.LineCode) .AndIF(!string.IsNullOrEmpty(parm.Status), it => it.Status == parm.Status); return predicate; } /// /// 生成不良单号 /// /// 前缀,默认BF表示报废 /// private string GenerateScrapOrderNo(string prefix = "BF") { var datePart = DateTime.Now.ToString("yyyyMMdd"); var baseNo = prefix + datePart + "-"; // 尝试从报废记录表中获取当天最大的编号后缀 try { var last = Context .Queryable() .Where(it => it.ScrapOrderNo.StartsWith(prefix + datePart)) .OrderByDescending(it => it.ScrapOrderNo) .Select(it => it.ScrapOrderNo) .First(); if (string.IsNullOrEmpty(last)) { return baseNo + "001"; } var suf = last.Substring((prefix + datePart).Length).TrimStart('-', '_'); if (int.TryParse(suf, out var n)) { return baseNo + (n + 1).ToString("D3"); } return baseNo + "001"; } catch { return baseNo + "001"; } } /// /// 创建报废单 /// /// /// public QcScrapRecords CreateScrapOrder(QcScrapRecords parm) { try { QcScrapRecords newQcScrapRecords = parm; var workorderInfo = Context .Queryable() .Where(x => x.Workorder == parm.Workorder) .First(); // 工单号创建,根据工单信息填充报废单的相关字段 if (workorderInfo != null) { newQcScrapRecords.ProductCode = workorderInfo.productionCode; newQcScrapRecords.ProductName = workorderInfo.productionName; newQcScrapRecords.LineCode = workorderInfo.RouteCode; newQcScrapRecords.StoveCode = workorderInfo.StoveCode; newQcScrapRecords.BatchNo = workorderInfo.FeedOrder; newQcScrapRecords.MaterialCode = workorderInfo.MaterialCode; newQcScrapRecords.MaterialName = workorderInfo.MaterialName; // 如有领料记录,则绑定采购记录 var purchaseInfo = Context .Queryable() .Where(it => it.BatchNo == workorderInfo.FeedOrder) .Where(it => it.TransactionType == "采购入库") .Where(it => it.Remarks != "已撤销") .First(); if (purchaseInfo != null) { newQcScrapRecords.SupplierCode = purchaseInfo.SupplierCode; newQcScrapRecords.SupplierName = purchaseInfo.SupplierName; newQcScrapRecords.StoveCode = purchaseInfo.StoveCode; newQcScrapRecords.Unit = purchaseInfo.Unit; } } // 生成报废单号 newQcScrapRecords.ScrapOrderNo = GenerateScrapOrderNo(); // 设置状态为待审批 newQcScrapRecords.Status = "待审批"; newQcScrapRecords.ScrapType = "报废"; newQcScrapRecords.TenantId = 0; newQcScrapRecords.Version = 1; return Context.Insertable(newQcScrapRecords).ExecuteReturnEntity(); } catch (Exception ex) { throw new Exception(ex.Message); } } /// /// 创建转用单 /// /// /// public QcScrapRecords CreateTransferOrder(QcScrapRecords parm) { // 验证工单号 if (string.IsNullOrEmpty(parm.Workorder)) { throw new Exception("工单号不能为空"); } QcScrapRecords newQcScrapRecords = parm; var workorderInfo = Context .Queryable() .Where(x => x.Workorder == parm.Workorder) .First(); // 工单号创建,根据工单信息填充报废单的相关字段 if (workorderInfo != null) { newQcScrapRecords.ProductCode = workorderInfo.productionCode; newQcScrapRecords.ProductName = workorderInfo.productionName; newQcScrapRecords.LineCode = workorderInfo.RouteCode; newQcScrapRecords.StoveCode = workorderInfo.StoveCode; newQcScrapRecords.BatchNo = workorderInfo.FeedOrder; newQcScrapRecords.MaterialCode = workorderInfo.MaterialCode; newQcScrapRecords.MaterialName = workorderInfo.MaterialName; // 如有领料记录,则绑定采购记录 var purchaseInfo = Context .Queryable() .Where(it => it.BatchNo == workorderInfo.FeedOrder) .Where(it => it.TransactionType == "采购入库") .Where(it => it.Remarks != "已撤销") .First(); if (purchaseInfo != null) { newQcScrapRecords.SupplierCode = purchaseInfo.SupplierCode; newQcScrapRecords.SupplierName = purchaseInfo.SupplierName; newQcScrapRecords.StoveCode = purchaseInfo.StoveCode; newQcScrapRecords.Unit = purchaseInfo.Unit; } } // 生成单号 newQcScrapRecords.ScrapOrderNo = GenerateScrapOrderNo("ZY"); // ZY表示转用 // 设置状态为待审批,类型为转用 newQcScrapRecords.Status = "待审批"; newQcScrapRecords.ScrapType = "转用"; newQcScrapRecords.TenantId = 0; newQcScrapRecords.Version = 1; return Context.Insertable(newQcScrapRecords).ExecuteReturnEntity(); } /// /// 审批报废记录 /// /// 记录ID /// 是否批准 /// 审批人 /// public int ApproveScrapRecord(long id, bool isApproved, string approver) { int result = 0; UseTran2(() => { // 获取记录信息 var record = Context.Queryable().Where(x => x.Id == id).First(); if (record == null) { throw new Exception("记录不存在"); } // 只有待审批状态的记录才能被审批 if (record.Status != "待审批") { throw new Exception("只有待审批状态的记录才能被审批"); } // 更新审批信息 var updateObj = new QcScrapRecords { Id = id, Status = isApproved ? "已批准" : "已拒绝", ApprovalDate = DateTime.Now, SupervisorName = approver, UpdatedTime = DateTime.Now, }; result = Context .Updateable(updateObj) .UpdateColumns(x => new { x.Status, x.ApprovalDate, x.SupervisorName, x.UpdatedTime, }) .ExecuteCommand(); // 是否审批通过 if (isApproved) { // 如果有工单则工单报废数增加 if (!string.IsNullOrEmpty(record.Workorder)) { var workorderInfo = Context .Queryable() .Where(x => x.Workorder == record.Workorder) .First(); if (workorderInfo != null) { workorderInfo.DefectNum += (int)record.ScrapQuantity; Context .Updateable(workorderInfo) .UpdateColumns(x => new { x.DefectNum }) .ExecuteCommand(); } } // 调用入库单服务添加到不良库 InboundReceiptDto revokeRecepitDto = new() { ReceiptType = 1, MaterialCode = record.ProductCode, BatchNo = "000", LocationCode = "BL001", WarehouseCode = "WH007", SupplierCode = record.SupplierCode, StoveCode = record.StoveCode, Workorder = record.Workorder, WorkorderRaw = record.ScrapOrderNo, Operator = approver, Quantity = record.ScrapQuantity, TransactionType = "不良入库", Remarks = $"不良入库,不良单号:{record.ScrapOrderNo}", }; MmInventoryService mmInventoryService = new(); string createReceiptresult = mmInventoryService.CreateInboundReceipt( revokeRecepitDto ); if (createReceiptresult != "ok") { throw new Exception(createReceiptresult); } // 根据报废类型处理 //if (record.ScrapType == "转用") //{ // InboundReceiptDto revokeRecepitDto = new() // { // ReceiptType = 1, // MaterialCode = record.ProductCode, // BatchNo = "000", // LocationCode = "ZYK001", // WarehouseCode = "WH005", // SupplierCode = record.SupplierCode, // StoveCode = record.StoveCode, // Workorder = record.Workorder, // WorkorderRaw = record.ScrapOrderNo, // Operator = approver, // Quantity = record.ScrapQuantity, // TransactionType = "转用入库", // Remarks = $"转用入库,转用单号:{record.ScrapOrderNo}", // }; // MmInventoryService mmInventoryService = new(); // string createReceiptresult = mmInventoryService.CreateInboundReceipt( // revokeRecepitDto // ); // if (createReceiptresult != "ok") // { // throw new Exception(createReceiptresult); // } //} //else if (record.ScrapType == "报废") //{ // InboundReceiptDto revokeRecepitDto = new() // { // ReceiptType = 1, // MaterialCode = record.ProductCode, // BatchNo = "000", // LocationCode = "BFK001", // WarehouseCode = "WH006", // SupplierCode = record.SupplierCode, // StoveCode = record.StoveCode, // Workorder = record.Workorder, // WorkorderRaw = record.ScrapOrderNo, // Operator = approver, // Quantity = record.ScrapQuantity, // TransactionType = "报废入库", // Remarks = $"报废入库,报废单号:{record.ScrapOrderNo}", // }; // MmInventoryService mmInventoryService = new(); // string createReceiptresult = mmInventoryService.CreateInboundReceipt( // revokeRecepitDto // ); // if (createReceiptresult != "ok") // { // throw new Exception(createReceiptresult); // } //} } }); return result; } /// /// 撤销报废记录 /// /// 记录ID /// public int RevokeScrapRecord(long id) { int result = 0; UseTran2(() => { // 获取记录信息 var record = Context.Queryable().Where(x => x.Id == id).First(); if (record == null) { throw new Exception("记录不存在"); } // 只有待审批状态的记录才能被撤销 if (record.Status != "已批准") { throw new Exception("只有已批准状态的记录才能被撤销"); } // 撤销库存操作记录与工单不良数 var workorderInfo = Context .Queryable() .Where(it => it.Workorder == record.Workorder) .First(); if (workorderInfo != null) { workorderInfo.DefectNum -= (int)Math.Abs(record.ScrapQuantity); Context .Updateable(workorderInfo) .UpdateColumns(it => new { it.DefectNum }) .ExecuteCommand(); } MmInventoryService mmInventoryService = new(); int InBoundId = Context .Queryable() .Where(it => it.WorkorderRaw == record.ScrapOrderNo) .Select(it => it.Id) .First(); if (InBoundId > 0) { mmInventoryService.RevokeReceipt( new MmInventoryRevokeDto { Id = InBoundId, Type = 1 } ); } // 撤销:将状态改为待审批 var updateObj = new QcScrapRecords { Id = id, Status = "待审批", UpdatedTime = DateTime.Now, }; result = Context .Updateable(updateObj) .UpdateColumns(x => new { x.Status, x.UpdatedTime }) .ExecuteCommand(); }); return result; } /// /// 根据工单号查询不良品记录 /// /// 工单号 /// public PagedInfo GetQcScrapRecordsByWorkorder(string workorder) { var queryDto = new QcScrapRecordsQueryDto { Workorder = workorder }; var result = Context .Queryable() .Where(x => x.Workorder == workorder) .ToPage(queryDto); return result; } /// /// 根据工单号填写报废单 /// /// 报废单数据 /// public QcScrapRecords CreateScrapOrderByWorkorder(QcScrapRecords parm) { // 验证工单号 if (string.IsNullOrEmpty(parm.Workorder)) { throw new Exception("工单号不能为空"); } // 调用现有的创建报废单方法 return CreateScrapOrder(parm); } /// /// 根据工单号填写转用单 /// /// 转用单数据 /// public QcScrapRecords CreateTransferOrderByWorkorder(QcScrapRecords parm) { // 验证工单号 if (string.IsNullOrEmpty(parm.Workorder)) { throw new Exception("工单号不能为空"); } // 调用现有的创建转用单方法 return CreateTransferOrder(parm); } /// /// 根据工单号填写不良品单据 /// /// 不良品单数据 /// public QcScrapRecords CreateDefectOrderByWorkorder(QcScrapRecords parm) { // 验证工单号 if (string.IsNullOrEmpty(parm.Workorder)) { throw new Exception("工单号不能为空"); } QcScrapRecords newQcScrapRecords = parm; var workorderInfo = Context .Queryable() .Where(x => x.Workorder == parm.Workorder) .First(); // 单据不良数校验 if (parm.ScrapQuantity + workorderInfo.DefectNum > workorderInfo.PlanNum) { throw new Exception("不良数量总和大于计划数,请检查输入!"); } if (parm.ScrapQuantity < 0) { throw new Exception("不良数量需要为正数!"); } // 工单号创建,根据工单信息填充报废单的相关字段 if (workorderInfo != null) { newQcScrapRecords.ProductCode = workorderInfo.productionCode; newQcScrapRecords.ProductName = workorderInfo.productionName; newQcScrapRecords.LineCode = workorderInfo.RouteCode; newQcScrapRecords.StoveCode = workorderInfo.StoveCode; newQcScrapRecords.BatchNo = workorderInfo.FeedOrder; newQcScrapRecords.MaterialCode = workorderInfo.MaterialCode; newQcScrapRecords.MaterialName = workorderInfo.MaterialName; // 如有领料记录,则绑定采购记录 var purchaseInfo = Context .Queryable() .Where(it => it.BatchNo == workorderInfo.FeedOrder) .Where(it => it.TransactionType == "采购入库") .Where(it => it.Remarks != "已撤销") .First(); if (purchaseInfo != null) { newQcScrapRecords.SupplierCode = purchaseInfo.SupplierCode; newQcScrapRecords.SupplierName = purchaseInfo.SupplierName; newQcScrapRecords.StoveCode = purchaseInfo.StoveCode; newQcScrapRecords.Unit = purchaseInfo.Unit; } } // 生成单号 newQcScrapRecords.ScrapOrderNo = GenerateScrapOrderNo("BL"); // BL表示不良 // 设置状态为待审批,类型为转用 newQcScrapRecords.Status = "待审批"; newQcScrapRecords.ScrapType = "不良品"; newQcScrapRecords.TenantId = 0; newQcScrapRecords.Version = 1; return Context.Insertable(newQcScrapRecords).ExecuteReturnEntity(); } /// /// 根据不良品记录ID撤销不良品记录 /// /// 不良品记录ID /// public int RevokeScrapRecordById(long id) { // 调用现有的撤销方法 return RevokeScrapRecord(id); } /// /// 根据不良记录进行审批 /// /// /// /// public string ApproveDefectRecordById(DefectApproveDto parm) { throw new NotImplementedException(); } } }