using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using MES.Service.DB;
using MES.Service.Dto.service;
using MES.Service.Modes;
using MES.Service.util;
using SqlSugar;
using System.Data;
namespace MES.Service.service.QC;
public class THJService
{
private static readonly OracleSQLHelper SQLHelper = new();
private readonly BaseService _baseService = new();
///
/// 生成最新的检验单号
///
public string getMaxReleaseNo()
{
var db = SqlSugarHelper.GetInstance();
var date = DateTime.Now.ToString("yyyy-MM-dd");
// 使用朋乐的函数默认获取单据
var sql = "select getbillcode1('1000','1000','THJYD') from dual";
var maxBillNo = db.Ado.SqlQuerySingle(sql);
// 如果为空直接返回默认值
return maxBillNo ?? "THJ" + DateTime.Now.ToString("yyMMdd") + "0001";
}
///
/// 分页查询检验单列表
///
public List getPage(THJPageResult queryObj)
{
var db = SqlSugarHelper.GetInstance();
// 基于检验单号查询,关联退货明细获取退货单信息
var sql = @"
SELECT
a.ID as Id,
a.RELEASE_NO as ReleaseNo,
a.CREATE_DATE as CreateDate,
a.CREATE_BY as CreateBy,
a.ITEM_NO as ItemNo,
a.SL as Sl,
a.FCHECK_BY as StatusUser,
a.FCHECK_RESU as Result,
COALESCE(m.ITEM_NAME, '') as ItemName,
COALESCE(m.ITEM_MODEL, '') as ItemModel,
a.SL as WorkQty,
COALESCE(rd.RETURN_TYPE, '') as ReturnType,
COALESCE(rd.RETURN_NO, '') as ReturnNo,
COALESCE(rw.BILL_DATE, a.CREATE_DATE) as BillDate,
COALESCE(c.CUST_NAME, '') as CustomerName,
COALESCE(rd.REMARKS, '') as ReturnReason,
COALESCE(a.BHGYY, '') as Remarks
FROM QS_QA_ITEM_THJ a
LEFT JOIN MES_ITEMS m ON a.ITEM_NO = m.ITEM_NO
LEFT JOIN MES_RETURNWARE_DETAILS rd ON a.ITEM_NO = rd.ITEM_NO
AND a.BILL_NO = rd.RETURN_TYPE || '-' || rd.RETURN_NO
LEFT JOIN MES_RETURNWARE rw ON rd.RETURN_TYPE = rw.RETURN_TYPE
AND rd.RETURN_NO = rw.RETURN_NO
LEFT JOIN MES_CUSTOMER c ON rw.CUST_NO = c.CUST_NO
WHERE 1=1";
var parameters = new List();
// 根据ID筛选
if (queryObj.Id.HasValue && queryObj.Id > 0)
{
sql += " AND a.ID = :Id";
parameters.Add(new SugarParameter(":Id", queryObj.Id.Value));
}
// 根据状态筛选
if (!string.IsNullOrEmpty(queryObj.Result))
{
if (queryObj.Result == "未完成")
{
sql += " AND a.FCHECK_RESU IS NULL";
}
else if (queryObj.Result == "已完成")
{
sql += " AND a.FCHECK_RESU IS NOT NULL";
}
}
// 根据检验人筛选
//if (!string.IsNullOrEmpty(queryObj.StatusUser))
//{
// sql += " AND a.FCHECK_BY = :StatusUser";
// parameters.Add(new SugarParameter(":StatusUser", queryObj.StatusUser));
//}
// 根据物料编码筛选
if (!string.IsNullOrEmpty(queryObj.ItemNo))
{
sql += " AND a.ITEM_NO = :ItemNo";
parameters.Add(new SugarParameter(":ItemNo", queryObj.ItemNo));
}
// 根据检验单号筛选
if (!string.IsNullOrEmpty(queryObj.ReleaseNo))
{
sql += " AND a.RELEASE_NO = :ReleaseNo";
parameters.Add(new SugarParameter(":ReleaseNo", queryObj.ReleaseNo));
}
// 根据创建日期筛选
if (queryObj.CreateDate.HasValue)
{
sql += " AND TRUNC(a.CREATE_DATE) = TRUNC(:CreateDate)";
parameters.Add(new SugarParameter(":CreateDate", queryObj.CreateDate.Value));
}
// 排序
sql += " ORDER BY a.CREATE_DATE DESC";
// 分页查询
var pageList = db.Ado.SqlQuery(sql, parameters.ToArray());
if (pageList != null)
{
pageList = pageList.Skip((queryObj.PageIndex - 1) * queryObj.Limit)
.Take(queryObj.Limit)
.ToList();
}
return pageList ?? new List();
}
///
/// 获取检验项目列表
///
public List getQSItems(decimal? pid, decimal? id)
{
var db = SqlSugarHelper.GetInstance();
var qsQaItemThj01s = db.Queryable()
.Where(a => a.Pid == pid)
.ToList();
var array = qsQaItemThj01s.Select(s => s.Id).ToArray();
var qsQaItemDetails = db.Queryable()
.Where(s => array.Contains(s.Pid))
.GroupBy(s => s.Pid)
.Select(s => new
{
s.Pid,
itemCount = SqlFunc.AggregateCount(s.Id)
}).ToList();
qsQaItemThj01s.ForEach(s =>
{
var find = qsQaItemDetails.Find(a => s.Id == a.Pid);
if (find == null)
{
s.isCheck = 0;
s.result = "未完成";
}
else
{
s.isCheck = find.itemCount;
// 修复类型转换问题:将decimal?转换为int进行比较
var levelNum = s.LevelNum.HasValue ? (int)s.LevelNum.Value : 0;
if (find.itemCount == levelNum && s.IsPass == 1)
s.result = "合格";
else if (find.itemCount == levelNum && s.IsPass == 0)
s.result = "不合格";
else
s.result = "未完成";
}
// 过滤出图片id不为空的数据转为base64
if (s.Picture is { Length: > 0 })
s.imageData = Convert.ToBase64String(s.Picture);
});
// 排序,未完成的排在前面
qsQaItemThj01s = qsQaItemThj01s.OrderBy(s => s.isCheck).ToList();
return qsQaItemThj01s;
}
///
/// 根据ID获取检验项目详情
///
public ExpandoObject getThjDetail02ById(decimal id)
{
try
{
var db = SqlSugarHelper.GetInstance();
// 获取检验项目主表信息
var qsQaItemThj01 = db.Queryable()
.Where(s => s.Id == id)
.First();
if (qsQaItemThj01 == null)
{
throw new Exception($"检验项目不存在,ID: {id}");
}
if (qsQaItemThj01.IsPass == 0)
qsQaItemThj01.result = "不合格";
else if (qsQaItemThj01.IsPass == 1)
qsQaItemThj01.result = "合格";
else
qsQaItemThj01.result = "未完成";
// 获取主表信息(检验单信息)
var mainInfo = db.Queryable()
.Where(s => s.Id == qsQaItemThj01.Pid)
.First();
// 检查主表信息是否正确获取
if (mainInfo == null)
{
throw new Exception($"主表信息不存在,Pid: {qsQaItemThj01.Pid}");
}
// 直接从物料表获取物料名称
var itemInfo = db.Queryable()
.Where(i => i.ItemNo == mainInfo.ItemNo)
.Select(i => new { i.ItemName })
.First();
// 退货单号就是销售退货检验单的bill_no
string returnOrderNo = mainInfo.BillNo;
string itemName = null;
decimal? returnQty = mainInfo.Sl;
string returnReason = mainInfo.Remarks;
// 获取物料名称
if (itemInfo != null)
{
itemName = itemInfo.ItemName;
}
// 处理图片数据,避免JSON序列化问题
string imageData = null;
if (qsQaItemThj01.Picture is { Length: > 0 })
{
try
{
imageData = Convert.ToBase64String(qsQaItemThj01.Picture);
}
catch (Exception)
{
imageData = null;
}
}
// 创建扩展的itemThj01对象,包含所有需要的字段,确保所有字段都是可序列化的
var extendedItemThj01 = new
{
// 原有字段 - 确保所有字段都是可序列化的类型
Id = qsQaItemThj01.Id,
Pid = qsQaItemThj01.Pid,
ProjName = qsQaItemThj01.ProjName ?? "",
ItemMod = qsQaItemThj01.ItemMod ?? "",
InspectionMethod = qsQaItemThj01.InspectionMethod ?? "",
UsingInstruments = qsQaItemThj01.UsingInstruments ?? "",
LevelNum = qsQaItemThj01.LevelNum,
MaxValue = qsQaItemThj01.MaxValue,
StandardValue = qsQaItemThj01.StandardValue,
MinValue = qsQaItemThj01.MinValue,
Notes = qsQaItemThj01.Notes ?? "",
FcheckLevel = qsQaItemThj01.FcheckLevel ?? "",
FacLevel = qsQaItemThj01.FacLevel ?? "",
QsCode = qsQaItemThj01.QsCode ?? "",
QsName = qsQaItemThj01.QsName ?? "",
IsPass = qsQaItemThj01.IsPass,
Remarks = qsQaItemThj01.Remarks ?? "",
result = qsQaItemThj01.result ?? "",
// 主表字段
releaseNo = mainInfo.ReleaseNo ?? "",
itemNo = mainInfo.ItemNo ?? "",
billNo = mainInfo.BillNo ?? "",
// 添加不合格描述字段,映射到主表的BHGYY字段
bhgyy = mainInfo.Bhgyy ?? "",
// 退货明细字段
returnOrderNo = returnOrderNo ?? "",
itemName = itemName ?? "",
returnQty = returnQty,
returnReason = returnReason ?? "",
// 其他需要的字段
qualityStandard = qsQaItemThj01.QsName ?? "",
// 图片数据(转换为base64字符串,避免序列化问题)
imageData = imageData ?? ""
};
// 获取检验项目明细,确保返回的数据是可序列化的
var qsQaItemThj02s = db.Queryable()
.Where(s => s.Pid == id)
.OrderBy(s => s.Id)
.Select(s => new
{
Id = s.Id,
Pid = s.Pid,
Gid = s.Gid,
FcheckResu = s.FcheckResu ?? "",
Fstand = s.Fstand ?? "",
CreateDate = s.CreateDate,
CreateBy = s.CreateBy ?? "",
UpdateDate = s.UpdateDate,
UpdateBy = s.UpdateBy ?? "",
Remarks = s.Remarks ?? ""
})
.ToList();
var result = new ExpandoObject();
((IDictionary)result)["itemThj01"] = extendedItemThj01;
((IDictionary)result)["itemThj02s"] = qsQaItemThj02s;
return result;
}
catch (Exception ex)
{
throw;
}
}
///
/// 安全获取动态对象属性值
///
private object GetDynamicValue(dynamic obj, string propertyName)
{
try
{
if (obj == null) return null;
var dict = (IDictionary)obj;
return dict.ContainsKey(propertyName) ? dict[propertyName] : null;
}
catch
{
return null;
}
}
///
/// 获取退货单列表
///
public List getReturnOrders()
{
var db = SqlSugarHelper.GetInstance();
var sql = @"
SELECT DISTINCT
rd.RETURN_TYPE || '-' || rd.RETURN_NO as returnOrderNo,
I.ITEM_NAME as itemName,
rd.QUANTITY as returnQty,
rd.REMARKS as returnReason
FROM MES_RETURNWARE_DETAILS rd
LEFT JOIN MES_ITEMS I ON I.ITEM_NO = rd.ITEM_NO
WHERE rd.RETURN_TYPE IS NOT NULL
AND rd.RETURN_NO IS NOT NULL
ORDER BY rd.RETURN_TYPE, rd.RETURN_NO";
var result = db.Ado.SqlQuery(sql);
return result;
}
///
/// 获取退货明细信息
///
public List getReturnwareInfo(string returnType, string returnNo)
{
var db = SqlSugarHelper.GetInstance();
var sql = @"
SELECT
rd.RETURN_TYPE || '-' || rd.RETURN_NO as returnOrderNo,
I.ITEM_NAME as itemName,
rd.QUANTITY as returnQty,
rd.REMARKS as returnReason,
rd.ITEM_NO as itemNo
FROM MES_RETURNWARE_DETAILS rd
LEFT JOIN MES_ITEMS I ON I.ITEM_NO = rd.ITEM_NO
WHERE rd.RETURN_TYPE = :returnType
AND rd.RETURN_NO = :returnNo";
var result = db.Ado.SqlQuery(sql,
new SugarParameter(":returnType", returnType),
new SugarParameter(":returnNo", returnNo));
return result;
}
///
/// 获取退货明细 - 基于检验单的BILL_NO精确匹配
///
public List getReturnDetails(string pid)
{
var db = SqlSugarHelper.GetInstance();
var sql = @"
SELECT
rd.RETURN_TYPE as returntype,
rd.RETURN_NO as returnno,
rd.QUANTITY as quantity,
rd.REMARKS as remarks,
rd.ITEM_NO as itemno,
I.ITEM_NAME as itemname
FROM MES_RETURNWARE_DETAILS rd
LEFT JOIN MES_ITEMS I ON I.ITEM_NO = rd.ITEM_NO
LEFT JOIN QS_QA_ITEM_THJ q ON q.ITEM_NO = rd.ITEM_NO
AND q.BILL_NO = rd.RETURN_TYPE || '-' || rd.RETURN_NO
WHERE q.ID = :pid";
var result = db.Ado.SqlQuery(sql,
new SugarParameter(":pid", Convert.ToDecimal(pid)));
return result;
}
///
/// 设置检验项目 - 调用存储过程
///
public List setInspectItem(string gid, string updateBy = "系统")
{
var db = SqlSugarHelper.GetInstance();
// 验证gid参数
if (string.IsNullOrEmpty(gid) || !decimal.TryParse(gid, out decimal gidDecimal))
{
throw new Exception("检验单ID格式不正确");
}
try
{
// 先检查检验单是否存在
var thjExists = db.Queryable()
.Where(s => s.Id == gidDecimal)
.Any();
if (!thjExists)
{
throw new Exception($"检验单ID {gidDecimal} 不存在");
}
// 定义输出参数
var outputResult = new SugarParameter("c_result", null, System.Data.DbType.Int32, ParameterDirection.Output, 4000);
var outputMessage = new SugarParameter("c_msg", null, System.Data.DbType.String, ParameterDirection.Output, 4000);
// 定义输入参数 - 存储过程期望NUMBER类型
var parameters = new List
{
new("p_gid", gidDecimal, System.Data.DbType.Decimal, ParameterDirection.Input),
new("p_user", updateBy, System.Data.DbType.String, ParameterDirection.Input),
outputResult,
outputMessage
};
// 调用存储过程
db.Ado.ExecuteCommand(
"BEGIN PROC_ADD_INSPECT_ITEMS(:p_gid, :p_user, :c_result, :c_msg); END;",
parameters.ToArray());
// 获取输出参数的值
var resultValue = outputResult.Value;
var messageValue = outputMessage.Value?.ToString();
// 检查存储过程执行结果 - 支持多种数值类型比较
bool isError = false;
if (resultValue != null)
{
if (resultValue is int intVal && intVal == 1)
isError = true;
else if (resultValue is decimal decimalVal && decimalVal == 1)
isError = true;
else if (resultValue is double doubleVal && doubleVal == 1.0)
isError = true;
else if (resultValue.ToString() == "1")
isError = true;
}
if (isError)
{
// 存储过程执行失败,抛出异常
throw new Exception(messageValue ?? "获取检验项目失败");
}
// 存储过程执行成功,获取生成的检验项目
var items = db.Queryable()
.Where(s => s.Pid == gidDecimal)
.ToList();
// 为每个项目设置默认值
items.ForEach(item =>
{
item.result = "未检测";
item.isCheck = 0;
});
return items;
}
catch (Exception ex)
{
// 如果存储过程调用失败,抛出异常
throw new Exception($"获取检验项目失败: {ex.Message}");
}
}
///
/// 保存检验项目
///
public int saveItem(THJDto thjDto)
{
return SqlSugarHelper.UseTransactionWithOracle(db =>
{
var commit = 0;
// 保存主表
thjDto.from.CreateBy = thjDto.userNo;
thjDto.from.CreateDate = DateTime.Now;
var pid = db.Insertable(thjDto.from).ExecuteReturnIdentity();
thjDto.from.Id = pid;
thjDto.gid = pid;
// 保存检验项目
if (thjDto.items != null && thjDto.items.Count > 0)
{
foreach (var item in thjDto.items) item.Pid = pid;
commit += db.Insertable(thjDto.items).ExecuteCommand();
}
return commit;
});
}
///
/// 设置检验项目详情
///
public int SetQSItemDetail(decimal pid, decimal gid, string fstand, string fcheckResu, string updateBy, int count)
{
return SqlSugarHelper.UseTransactionWithOracle(db =>
{
List result = new();
for (var i = 0; i < count; i++)
{
var item = new QsQaItemThj02();
item.Pid = pid;
item.Gid = gid;
item.Fstand = fstand;
item.FcheckResu = fcheckResu;
item.CreateBy = updateBy;
item.CreateDate = DateTime.Now;
item.Factory = "1000";
item.Company = "1000";
result.Add(item);
}
var insertResult = db.Insertable(result).ExecuteCommand();
// 插入检验结果后,自动更新检验项目的IsPass状态
autoUpdateInspectionStatus(pid, db);
return insertResult;
});
}
///
/// 自动更新检验项目状态
///
private void autoUpdateInspectionStatus(decimal pid, ISqlSugarClient db)
{
// 获取检验项目信息
var qsQaItemThj01 = db.Queryable()
.Where(s => s.Id == pid)
.First();
if (qsQaItemThj01 == null) return;
// 查询这个检验项目下的检验结果总数
var totalCount = db.Queryable()
.Where(s => s.Pid == pid)
.Count();
// 查询合格数量
var passCount = db.Queryable()
.Where(s => s.Pid == pid && s.Fstand == "√")
.Count();
// 获取应该检验的数量
var levelNum = qsQaItemThj01.LevelNum.HasValue ? (int)qsQaItemThj01.LevelNum.Value : 1;
int isPass = 0; // 默认不合格
// 如果检验数量达到要求且全部合格,则设置为合格
if (totalCount >= levelNum && passCount == totalCount)
{
isPass = 1; // 合格
}
// 如果检验数量达到要求但有不合格的,则设置为不合格
else if (totalCount >= levelNum && passCount < totalCount)
{
isPass = 0; // 不合格
}
// 如果检验数量未达到要求,保持原状态(不更新IsPass字段)
// 只有当检验数量达到要求时才更新IsPass字段
if (totalCount >= levelNum)
{
db.Updateable()
.SetColumns(s => s.IsPass == isPass)
.Where(s => s.Id == pid)
.ExecuteCommand();
}
}
///
/// 更新检验项目详情
///
public int UpdateQSItemDetail(decimal id, decimal pid, decimal gid, string fstand, string fcheckResu, string updateBy)
{
return SqlSugarHelper.UseTransactionWithOracle(db =>
{
// 更新检验结果记录
var updateResult = db.Updateable()
.SetColumns(s => s.UpdateBy == updateBy)
.SetColumns(s => s.UpdateDate == DateTime.Now)
.SetColumnsIF(StringUtil.IsNotNullOrEmpty(fstand),
s => s.Fstand == fstand)
.SetColumnsIF(StringUtil.IsNotNullOrEmpty(fcheckResu),
s => s.FcheckResu == fcheckResu)
.Where(s => s.Id == id)
.ExecuteCommand();
// 更新检验结果后,重新计算检验项目状态
autoUpdateInspectionStatus(pid, db);
return updateResult;
});
}
///
/// 保存检验项目备注
///
public int saveRemarksPid(decimal pid, string remarks)
{
return SqlSugarHelper.UseTransactionWithOracle(db =>
{
return db.Updateable()
.SetColumns(it => it.Remarks == remarks)
.Where(it => it.Id == pid)
.ExecuteCommand();
});
}
///
/// 保存检验单备注(不合格描述)
///
public int saveRemarksGid(decimal gid, string remarks)
{
return SqlSugarHelper.UseTransactionWithOracle(db =>
{
return db.Updateable()
.SetColumns(it => it.Bhgyy == remarks)
.Where(it => it.Id == gid)
.ExecuteCommand();
});
}
///
/// 保存检验结果
///
public int saveInspectItem(string gid, string items, string userNo)
{
return SqlSugarHelper.UseTransactionWithOracle(db =>
{
var result = 0;
var gidDecimal = Convert.ToDecimal(gid);
// 这里可以根据需要解析items参数并更新检验结果
// 由于前端传递的是字符串,这里简化处理
result += db.Updateable()
.SetColumns(s => s.LastupdateBy == userNo)
.SetColumns(s => s.LastupdateDate == DateTime.Now)
.Where(s => s.Id == gidDecimal)
.ExecuteCommand();
return result;
});
}
///
/// 保存退货明细
///
public List SaveReturnDetails(string returnDetails)
{
// 这里可以根据需要处理退货明细数据
// 由于前端传递的是字符串,这里返回空列表
return new List();
}
///
/// 提交检验结果
///
public bool SubmitTHJResult(decimal gid, string userNo)
{
var result = SqlSugarHelper.UseTransactionWithOracle(db =>
{
// 1. 验证检验单是否存在
var inspectionOrder = db.Queryable()
.Where(s => s.Id == gid)
.First();
if (inspectionOrder == null)
{
throw new Exception($"检验单不存在,ID: {gid}");
}
// 2. 检查是否已经提交过
if (inspectionOrder.FcheckResu == "已完成")
{
throw new Exception("该检验单已经提交,无法重复提交");
}
// 3. 验证所有检验项目是否都已完成
var uncompletedItems = db.Queryable()
.Where(s => s.Pid == gid)
.Where(s => s.IsPass == null || s.IsPass == -1) // 假设-1表示未完成
.Count();
if (uncompletedItems > 0)
{
throw new Exception("存在未完成的检验项目,请完成所有检验后再提交");
}
// 4. 更新检验单状态
var updateResult = db.Updateable()
.SetColumns(s => s.FcheckResu == "已完成")
.SetColumns(s => s.FcheckBy == userNo)
.SetColumns(s => s.FcheckDate == DateTime.Now)
.SetColumns(s => s.LastupdateBy == userNo)
.SetColumns(s => s.LastupdateDate == DateTime.Now)
.Where(s => s.Id == gid)
.ExecuteCommand();
if (updateResult <= 0)
{
throw new Exception("更新检验单状态失败");
}
// 5. 记录提交日志(可选)
// 这里可以添加日志记录或其他业务逻辑
return updateResult;
});
return result > 0;
}
///
/// 通过存储过程提交检验结果
///
public (bool success, string message) SubmitTHJResultByProcedure(string releaseNo, string userNo)
{
try
{
var db = SqlSugarHelper.GetInstance();
// 定义输出参数
var outputResult = new SugarParameter("O_RESULT", null, System.Data.DbType.Int32, ParameterDirection.Output, 4000);
var outputMessage = new SugarParameter("O_MSG", null, System.Data.DbType.String, ParameterDirection.Output, 4000);
// 定义输入参数
var parameters = new List
{
new("P_RELEASE_NO", releaseNo, System.Data.DbType.String, ParameterDirection.Input),
new("P_USER", userNo, System.Data.DbType.String, ParameterDirection.Input),
outputResult,
outputMessage
};
// 调用存储过程
db.Ado.ExecuteCommand(
"BEGIN PRC_MES_THJ_QA_SUBMIT82(:P_RELEASE_NO, :P_USER, :O_RESULT, :O_MSG); END;",
parameters.ToArray());
// 获取输出参数的值
var resultValue = outputResult.Value;
var messageValue = outputMessage.Value?.ToString();
// 检查存储过程执行结果
bool isSuccess = false;
if (resultValue != null)
{
if (resultValue is int intVal && intVal == 0)
isSuccess = true;
else if (resultValue is decimal decimalVal && decimalVal == 0)
isSuccess = true;
else if (resultValue is double doubleVal && doubleVal == 0.0)
isSuccess = true;
else if (resultValue.ToString() == "0")
isSuccess = true;
}
return (isSuccess, messageValue ?? "未知错误");
}
catch (Exception ex)
{
return (false, $"调用存储过程失败: {ex.Message}");
}
}
}