IpqcInspectionService.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using Admin.NET.Plugin.AiDOP.Manufacturing.Dto;
  2. namespace Admin.NET.Plugin.AiDOP.Manufacturing;
  3. /// <summary>
  4. /// S6 过程检验单(IPQC)只读 list 服务。
  5. ///
  6. /// 数据源:DOP 数据中台标准层 mdp_std_ipqc_inspection(头)。
  7. /// 由 IpqcInspectionMdpSyncService 从归口后的 aidopdev.qms_gcjyd(过程检验单头)同步标准化而来。
  8. ///
  9. /// 本服务仅 SELECT:无新增/编辑/删除/写入。
  10. /// 当前上游尚未抽数,归口源表 qms_gcjyd 为空 → 标准层为空 → list 返回空数组(前端空态)。
  11. /// 明细(qms_gcjydzb)与详情不在本批范围,留待 IPQC-INSPECTION-DETAIL-READONLY-1。
  12. /// </summary>
  13. [ApiDescriptionSettings(Order = 306, Description = "过程检验单")]
  14. [Route("api/IpqcInspection")]
  15. [AllowAnonymous]
  16. [NonUnify]
  17. public class IpqcInspectionService : IDynamicApiController, ITransient
  18. {
  19. private readonly ISqlSugarClient _db;
  20. public IpqcInspectionService(ISqlSugarClient db)
  21. {
  22. _db = db;
  23. }
  24. /// <summary>
  25. /// 过程检验单列表(只读分页查询)。
  26. /// </summary>
  27. [DisplayName("过程检验单列表")]
  28. [HttpGet("list")]
  29. public async Task<object> GetList([FromQuery] IpqcInspectionListInput input)
  30. {
  31. var page = input.Page <= 0 ? 1 : input.Page;
  32. var pageSize = input.PageSize <= 0 ? 10 : input.PageSize;
  33. var offset = (page - 1) * pageSize;
  34. var where = new List<string> { "1=1" };
  35. var pars = new List<SugarParameter>();
  36. if (input.TenantId is > 0)
  37. {
  38. where.Add("m.tenant_id = @TenantId");
  39. pars.Add(new SugarParameter("@TenantId", input.TenantId));
  40. }
  41. if (!string.IsNullOrWhiteSpace(input.BillNo))
  42. {
  43. where.Add("m.bill_no LIKE @BillNo");
  44. pars.Add(new SugarParameter("@BillNo", $"%{input.BillNo.Trim()}%"));
  45. }
  46. if (!string.IsNullOrWhiteSpace(input.ProductionBatchNo))
  47. {
  48. where.Add("m.production_batch_no LIKE @ProductionBatchNo");
  49. pars.Add(new SugarParameter("@ProductionBatchNo", $"%{input.ProductionBatchNo.Trim()}%"));
  50. }
  51. var whereSql = string.Join(" AND ", where);
  52. var total = await _db.Ado.GetIntAsync(
  53. $"SELECT COUNT(1) FROM mdp_std_ipqc_inspection m WHERE {whereSql}", pars);
  54. var list = await _db.Ado.SqlQueryAsync<IpqcInspectionListRow>(
  55. $"""
  56. SELECT
  57. m.id AS Id,
  58. m.bill_no AS BillNo,
  59. m.product_model AS ProductModel,
  60. m.production_batch_no AS ProductionBatchNo,
  61. m.production_work_order AS ProductionWorkOrder,
  62. m.result_judgement AS ResultJudgement,
  63. m.attachment AS Attachment,
  64. m.remark AS Remark,
  65. m.inspector AS Inspector,
  66. m.process_code AS ProcessCode,
  67. m.process_name AS ProcessName,
  68. m.production_person AS ProductionPerson,
  69. m.sample_qty AS SampleQty,
  70. m.form_no AS FormNo,
  71. m.version_no AS VersionNo,
  72. m.effective_date AS EffectiveDate,
  73. m.material_code AS MaterialCode,
  74. m.material_name AS MaterialName,
  75. m.inspec_standard_version AS InspecStandardVersion,
  76. m.inspec_standard_code AS InspecStandardCode
  77. FROM mdp_std_ipqc_inspection m
  78. WHERE {whereSql}
  79. ORDER BY {BuildOrderBy(input.SortField, input.SortOrder)}
  80. LIMIT {pageSize} OFFSET {offset}
  81. """,
  82. pars);
  83. return new { total, page, pageSize, list };
  84. }
  85. /// <summary>
  86. /// 排序白名单:仅允许按已展示列排序,杜绝 SQL 注入。
  87. /// </summary>
  88. private static string BuildOrderBy(string? sortField, string? sortOrder)
  89. {
  90. var column = sortField switch
  91. {
  92. "billNo" => "m.bill_no",
  93. "effectiveDate" => "m.effective_date",
  94. _ => "m.effective_date",
  95. };
  96. var direction = string.Equals(sortOrder, "asc", StringComparison.OrdinalIgnoreCase) ? "ASC" : "DESC";
  97. return $"{column} {direction}, m.id DESC";
  98. }
  99. }