Files
kunshan-bzfm-mes-backend/DOAN.Service/MES/Quality/IPQC/QcScrapRecordsService.cs
git_rabbit 6bc3343414 feat(IPQC): 添加根据工单号处理不良品记录功能
新增以下功能:
1. 根据工单号查询不良品记录
2. 根据工单号创建报废单和转用单
3. 根据ID撤销不良品记录
2026-02-09 17:46:24 +08:00

342 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Infrastructure.Attribute;
using Infrastructure.Extensions;
using DOAN.Model.BZFM.Dto;
using DOAN.Model.BZFM;
using DOAN.Repository;
using DOAN.Service.BZFM.IService;
namespace DOAN.Service.BZFM
{
/// <summary>
/// Service业务层处理
/// </summary>
[AppService(ServiceType = typeof(IQcScrapRecordsService), ServiceLifetime = LifeTime.Transient)]
public class QcScrapRecordsService : BaseService<QcScrapRecords>, IQcScrapRecordsService
{
/// <summary>
/// 查询报废记录表列表
/// </summary>
/// <param name="parm"></param>
/// <returns></returns>
public PagedInfo<QcScrapRecordsDto> GetList(QcScrapRecordsQueryDto parm)
{
var predicate = QueryExp(parm);
var response = Queryable()
.Where(predicate.ToExpression())
.ToPage<QcScrapRecords, QcScrapRecordsDto>(parm);
return response;
}
/// <summary>
/// 获取详情
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
public QcScrapRecords GetInfo(long Id)
{
var response = Queryable()
.Where(x => x.Id == Id)
.First();
return response;
}
/// <summary>
/// 添加报废记录表
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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();
}
/// <summary>
/// 修改报废记录表
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public int UpdateQcScrapRecords(QcScrapRecords model)
{
return Update(model, true);
}
/// <summary>
/// 查询导出表达式
/// </summary>
/// <param name="parm"></param>
/// <returns></returns>
private static Expressionable<QcScrapRecords> QueryExp(QcScrapRecordsQueryDto parm)
{
var predicate = Expressionable
.Create<QcScrapRecords>()
// 模糊搜索字段
.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;
}
/// <summary>
/// 生成报废单号
/// </summary>
/// <param name="prefix">前缀默认BF表示报废</param>
/// <returns></returns>
private string GenerateScrapOrderNo(string prefix = "BF")
{
var datePart = DateTime.Now.ToString("yyyyMMdd");
var baseNo = prefix + datePart + "-";
// 尝试从报废记录表中获取当天最大的编号后缀
try
{
var last = Context
.Queryable<QcScrapRecords>()
.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";
}
}
/// <summary>
/// 创建报废单
/// </summary>
/// <param name="parm"></param>
/// <returns></returns>
public QcScrapRecords CreateScrapOrder(QcScrapRecords parm)
{
// 验证物料编码
if (string.IsNullOrEmpty(parm.MaterialCode))
{
throw new Exception("物料编码不能为空");
}
// 生成报废单号
parm.ScrapOrderNo = GenerateScrapOrderNo();
// 设置状态为待审批
parm.Status = "待审批";
parm.ScrapType = "报废";
return Context.Insertable(parm).ExecuteReturnEntity();
}
/// <summary>
/// 创建转用单
/// </summary>
/// <param name="parm"></param>
/// <returns></returns>
public QcScrapRecords CreateTransferOrder(QcScrapRecords parm)
{
// 验证物料编码
if (string.IsNullOrEmpty(parm.MaterialCode))
{
throw new Exception("物料编码不能为空");
}
// 验证工单号
if (string.IsNullOrEmpty(parm.Workorder))
{
throw new Exception("工单号不能为空");
}
// 生成报废单号
parm.ScrapOrderNo = GenerateScrapOrderNo("ZY"); // ZY表示转用
// 设置状态为待审批,报废类型为转用
parm.Status = "待审批";
parm.ScrapType = "转用";
return Context.Insertable(parm).ExecuteReturnEntity();
}
/// <summary>
/// 审批报废记录
/// </summary>
/// <param name="id">记录ID</param>
/// <param name="isApproved">是否批准</param>
/// <param name="approver">审批人</param>
/// <returns></returns>
public int ApproveScrapRecord(long id, bool isApproved, string approver)
{
int result = 0;
UseTran2(() =>
{
// 获取记录信息
var record = Context.Queryable<QcScrapRecords>().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 (record.ScrapType == "转用")
{
// 转用单批准:生成新工单(这里需要根据实际业务调整工单生成逻辑)
// 注意:需要确保工单服务的命名空间和方法名正确
// 示例_proWorkorderService.GenerateWorkorder(record);
}
else
{
// 报废单批准:生成入库单到报废库(这里需要根据实际业务调整入库逻辑)
// 示例:调用入库单服务添加到报废库
}
}
});
return result;
}
/// <summary>
/// 撤销报废记录
/// </summary>
/// <param name="id">记录ID</param>
/// <returns></returns>
public int RevokeScrapRecord(long id)
{
// 获取记录信息
var record = Context.Queryable<QcScrapRecords>().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 = "待审批",
UpdatedTime = DateTime.Now
};
return Context.Updateable(updateObj).UpdateColumns(x => new { x.Status, x.UpdatedTime }).ExecuteCommand();
}
/// <summary>
/// 根据工单号查询不良品记录
/// </summary>
/// <param name="workorder">工单号</param>
/// <returns></returns>
public PagedInfo<QcScrapRecordsDto> GetQcScrapRecordsByWorkorder(string workorder)
{
var queryDto = new QcScrapRecordsQueryDto
{
Workorder = workorder
};
return GetList(queryDto);
}
/// <summary>
/// 根据工单号填写报废单
/// </summary>
/// <param name="parm">报废单数据</param>
/// <returns></returns>
public QcScrapRecords CreateScrapOrderByWorkorder(QcScrapRecords parm)
{
// 验证工单号
if (string.IsNullOrEmpty(parm.Workorder))
{
throw new Exception("工单号不能为空");
}
// 调用现有的创建报废单方法
return CreateScrapOrder(parm);
}
/// <summary>
/// 根据工单号填写转用单
/// </summary>
/// <param name="parm">转用单数据</param>
/// <returns></returns>
public QcScrapRecords CreateTransferOrderByWorkorder(QcScrapRecords parm)
{
// 验证工单号
if (string.IsNullOrEmpty(parm.Workorder))
{
throw new Exception("工单号不能为空");
}
// 调用现有的创建转用单方法
return CreateTransferOrder(parm);
}
/// <summary>
/// 根据不良品记录ID撤销不良品记录
/// </summary>
/// <param name="id">不良品记录ID</param>
/// <returns></returns>
public int RevokeScrapRecordById(long id)
{
// 调用现有的撤销方法
return RevokeScrapRecord(id);
}
}
}