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 string CreateScrapOrderByWorkorder(DefectApproveDto parm)
{
try
{
// 验证工单号
if (string.IsNullOrEmpty(parm.Workorder))
{
throw new Exception("工单号不能为空");
}
// 工单信息查看
var workorderInfo = Context
.Queryable()
.Where(it => it.Workorder == parm.Workorder)
.First();
if (workorderInfo == null)
{
throw new Exception($"工单信息为空{parm.Workorder}");
}
var inboundRecordInfo = Context
.Queryable()
.Where(it => it.Id == parm.Id)
.First();
if (inboundRecordInfo == null)
{
throw new Exception($"入库记录不存在{parm.Id}");
}
// 不良出库
MmInventoryService mmInventoryService = new();
OutboundReceiptDto outboundRecepitDto = new()
{
ReceiptType = 1,
InventoryId = -1,
MaterialCode = inboundRecordInfo.MaterialCode,
SupplierCode = inboundRecordInfo.SupplierCode,
BatchNo = inboundRecordInfo.BatchNo,
StoveCode = inboundRecordInfo.StoveCode,
LocationCode = inboundRecordInfo.LocationCode,
WarehouseCode = inboundRecordInfo.WarehouseCode,
OrderNo = workorderInfo.CustomerOrder,
Workorder = inboundRecordInfo.Workorder,
WorkorderRaw = inboundRecordInfo.WorkorderRaw,
Operator = parm.Operator,
Quantity = parm.ScrapQuantity,
TransactionType = "不良出库",
Remarks = $"不良品报废出库,数量为{parm.ScrapQuantity}",
};
string outboundReceiptResult = mmInventoryService.CreateOutboundReceipt(
outboundRecepitDto
);
if (outboundReceiptResult != "ok")
{
throw new Exception(outboundReceiptResult);
}
// 报废入库
InboundReceiptDto inboundRecepitDto = new()
{
ReceiptType = 1,
MaterialCode = inboundRecordInfo.MaterialCode,
BatchNo = parm.BatchNo,
LocationCode = "BFK001",
WarehouseCode = "WH006",
SupplierCode = inboundRecordInfo.SupplierCode,
StoveCode = inboundRecordInfo.StoveCode,
Workorder = inboundRecordInfo.Workorder,
WorkorderRaw = inboundRecordInfo.WorkorderRaw,
Operator = parm.Operator,
Quantity = parm.ScrapQuantity,
TransactionType = "报废入库",
Remarks = $"报废入库,来源不良单号:{inboundRecordInfo.InboundNo}",
};
string inboundReceiptresult = mmInventoryService.CreateInboundReceipt(inboundRecepitDto);
if (inboundReceiptresult != "ok")
{
throw new Exception(inboundReceiptresult);
}
inboundRecordInfo.Remarks += $"[已报废{parm.ScrapQuantity}]";
Context.Updateable(inboundRecordInfo).UpdateColumns(it => new { it.Remarks }).ExecuteCommand();
return "ok";
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
///
/// 根据工单号填写转用单
///
/// 转用单数据
///
public string CreateTransferOrderByWorkorder(DefectApproveDto parm)
{
try
{
// 验证工单号
if (string.IsNullOrEmpty(parm.Workorder))
{
throw new Exception("工单号不能为空");
}
// 工单信息查看
var workorderInfo = Context
.Queryable()
.Where(it => it.Workorder == parm.Workorder)
.First();
if (workorderInfo == null)
{
throw new Exception($"工单信息为空{parm.Workorder}");
}
var inboundRecordInfo = Context
.Queryable()
.Where(it => it.Id == parm.Id)
.First();
if (inboundRecordInfo == null)
{
throw new Exception($"入库记录不存在{parm.Id}");
}
// 不良出库
MmInventoryService mmInventoryService = new();
OutboundReceiptDto outboundRecepitDto = new()
{
ReceiptType = 1,
InventoryId = -1,
MaterialCode = inboundRecordInfo.MaterialCode,
SupplierCode = inboundRecordInfo.SupplierCode,
BatchNo = inboundRecordInfo.BatchNo,
StoveCode = inboundRecordInfo.StoveCode,
LocationCode = inboundRecordInfo.LocationCode,
WarehouseCode = inboundRecordInfo.WarehouseCode,
OrderNo = workorderInfo.CustomerOrder,
Workorder = inboundRecordInfo.Workorder,
WorkorderRaw = inboundRecordInfo.WorkorderRaw,
Operator = parm.Operator,
Quantity = parm.ScrapQuantity,
TransactionType = "不良出库",
Remarks = $"不良品报废出库,数量为{parm.ScrapQuantity}",
};
string outboundReceiptResult = mmInventoryService.CreateOutboundReceipt(
outboundRecepitDto
);
if (outboundReceiptResult != "ok")
{
throw new Exception(outboundReceiptResult);
}
// 报废入库
InboundReceiptDto inboundRecepitDto = new()
{
ReceiptType = 1,
MaterialCode = inboundRecordInfo.MaterialCode,
BatchNo = parm.BatchNo,
LocationCode = "ZYK001",
WarehouseCode = "WH005",
SupplierCode = inboundRecordInfo.SupplierCode,
StoveCode = inboundRecordInfo.StoveCode,
Workorder = inboundRecordInfo.Workorder,
WorkorderRaw = inboundRecordInfo.WorkorderRaw,
Operator = parm.Operator,
Quantity = parm.ScrapQuantity,
TransactionType = "转用入库",
Remarks = $"转用入库,来源不良单号:{inboundRecordInfo.InboundNo}",
};
string inboundReceiptresult = mmInventoryService.CreateInboundReceipt(inboundRecepitDto);
if (inboundReceiptresult != "ok")
{
throw new Exception(inboundReceiptresult);
}
inboundRecordInfo.Remarks += $"[已转用{parm.ScrapQuantity}]";
Context.Updateable(inboundRecordInfo).UpdateColumns(it => new { it.Remarks }).ExecuteCommand();
return "ok";
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
///
/// 根据工单号填写不良品单据
///
/// 不良品单数据
///
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();
}
}
}