PurchaseReceiptService.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using Admin.NET.Plugin.AiDOP.MaterialWarehouse.Dto;
  2. namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse;
  3. /// <summary>
  4. /// S5 采购收货单 只读 list 服务。
  5. ///
  6. /// 数据源:DOP 数据中台标准层 mdp_std_purchase_receipt(明细粒度 domain#receiver#line)。
  7. /// 由 PurchaseReceiptMdpSyncService 从 aidopdev.PurOrdRctDetail/PurOrdRctMaster RctType='rc' 同步标准化而来。
  8. ///
  9. /// 本服务仅 SELECT:无新增/编辑/删除/收货确认/入库写入/库存事务/状态流转;无 detail(扁平列表)。
  10. /// </summary>
  11. [ApiDescriptionSettings(Order = 305, Description = "采购收货单")]
  12. [Route("api/PurchaseReceipt")]
  13. [AllowAnonymous]
  14. [NonUnify]
  15. public class PurchaseReceiptService : IDynamicApiController, ITransient
  16. {
  17. private readonly ISqlSugarClient _db;
  18. public PurchaseReceiptService(ISqlSugarClient db)
  19. {
  20. _db = db;
  21. }
  22. /// <summary>
  23. /// 采购收货单列表(只读分页查询)。
  24. /// </summary>
  25. [DisplayName("采购收货单列表")]
  26. [HttpGet("list")]
  27. public async Task<object> GetList([FromQuery] PurchaseReceiptListInput input)
  28. {
  29. var page = input.Page <= 0 ? 1 : input.Page;
  30. var pageSize = input.PageSize <= 0 ? 10 : input.PageSize;
  31. var offset = (page - 1) * pageSize;
  32. var where = new List<string> { "1=1" };
  33. var pars = new List<SugarParameter>();
  34. if (input.TenantId is > 0)
  35. {
  36. where.Add("m.tenant_id = @TenantId");
  37. pars.Add(new SugarParameter("@TenantId", input.TenantId));
  38. }
  39. if (!string.IsNullOrWhiteSpace(input.Supp))
  40. {
  41. where.Add("(m.supp LIKE @Supp OR m.sort_name LIKE @Supp)");
  42. pars.Add(new SugarParameter("@Supp", $"%{input.Supp.Trim()}%"));
  43. }
  44. if (!string.IsNullOrWhiteSpace(input.ItemNum))
  45. {
  46. where.Add("m.item_num LIKE @ItemNum");
  47. pars.Add(new SugarParameter("@ItemNum", $"%{input.ItemNum.Trim()}%"));
  48. }
  49. if (!string.IsNullOrWhiteSpace(input.RctDateFrom))
  50. {
  51. where.Add("m.rct_date >= @RctDateFrom");
  52. pars.Add(new SugarParameter("@RctDateFrom", $"{input.RctDateFrom.Trim()} 00:00:00"));
  53. }
  54. if (!string.IsNullOrWhiteSpace(input.RctDateTo))
  55. {
  56. where.Add("m.rct_date <= @RctDateTo");
  57. pars.Add(new SugarParameter("@RctDateTo", $"{input.RctDateTo.Trim()} 23:59:59"));
  58. }
  59. if (!string.IsNullOrWhiteSpace(input.PurOrd))
  60. {
  61. where.Add("m.pur_ord LIKE @PurOrd");
  62. pars.Add(new SugarParameter("@PurOrd", $"%{input.PurOrd.Trim()}%"));
  63. }
  64. if (!string.IsNullOrWhiteSpace(input.Receiver))
  65. {
  66. where.Add("m.receiver LIKE @Receiver");
  67. pars.Add(new SugarParameter("@Receiver", $"%{input.Receiver.Trim()}%"));
  68. }
  69. if (!string.IsNullOrWhiteSpace(input.SalesJob))
  70. {
  71. where.Add("m.sales_job LIKE @SalesJob");
  72. pars.Add(new SugarParameter("@SalesJob", $"%{input.SalesJob.Trim()}%"));
  73. }
  74. if (!string.IsNullOrWhiteSpace(input.Req))
  75. {
  76. where.Add("m.req LIKE @Req");
  77. pars.Add(new SugarParameter("@Req", $"%{input.Req.Trim()}%"));
  78. }
  79. if (!string.IsNullOrWhiteSpace(input.DopReq))
  80. {
  81. where.Add("m.dop_req LIKE @DopReq");
  82. pars.Add(new SugarParameter("@DopReq", $"%{input.DopReq.Trim()}%"));
  83. }
  84. var whereSql = string.Join(" AND ", where);
  85. var total = await _db.Ado.GetIntAsync(
  86. $"SELECT COUNT(1) FROM mdp_std_purchase_receipt m WHERE {whereSql}", pars);
  87. var list = await _db.Ado.SqlQueryAsync<PurchaseReceiptListRow>(
  88. $"""
  89. SELECT
  90. m.id AS Id,
  91. m.receiver AS Receiver,
  92. m.line AS Line,
  93. m.rct_date AS RctDate,
  94. m.supp AS Supp,
  95. m.sort_name AS SortName,
  96. m.item_num AS ItemNum,
  97. m.item_name AS ItemName,
  98. m.item_spec AS ItemSpec,
  99. m.um AS Um,
  100. m.qty_ordered AS QtyOrdered,
  101. m.qty_received AS QtyReceived,
  102. m.lot_serial AS LotSerial,
  103. m.location AS Location,
  104. m.pur_ord AS PurOrd,
  105. m.sales_job AS SalesJob,
  106. m.address1 AS Address1,
  107. m.req AS Req,
  108. m.dop_req AS DopReq,
  109. m.ord_nbr AS OrdNbr
  110. FROM mdp_std_purchase_receipt m
  111. WHERE {whereSql}
  112. ORDER BY {BuildOrderBy(input.OrderBy, input.OrderDir)}
  113. LIMIT {pageSize} OFFSET {offset}
  114. """,
  115. pars);
  116. return new { total, page, pageSize, list };
  117. }
  118. /// <summary>
  119. /// 排序白名单:仅允许按已展示列排序,杜绝 SQL 注入。
  120. /// </summary>
  121. private static string BuildOrderBy(string? orderBy, string? orderDir)
  122. {
  123. var column = orderBy switch
  124. {
  125. "receiver" => "m.receiver",
  126. "rctDate" => "m.rct_date",
  127. "itemNum" => "m.item_num",
  128. "sortName" => "m.sort_name",
  129. "qtyOrdered" => "m.qty_ordered",
  130. "qtyReceived" => "m.qty_received",
  131. "purOrd" => "m.pur_ord",
  132. "salesJob" => "m.sales_job",
  133. _ => "m.rct_date",
  134. };
  135. var direction = string.Equals(orderDir, "asc", StringComparison.OrdinalIgnoreCase) ? "ASC" : "DESC";
  136. return $"{column} {direction}, m.id DESC";
  137. }
  138. }