StocktakeResultService.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. using Admin.NET.Plugin.AiDOP.MaterialWarehouse.Dto;
  2. namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse;
  3. /// <summary>
  4. /// S5 盘点结果查询 只读 list 服务。
  5. ///
  6. /// 数据源:aidopdev.MissedPrint(盘点标签 IsTag=1),忠实复刻证据 sql.txt:
  7. /// LEFT JOIN ItemMaster(名称/规格/单位),过滤 m.Domain=@Domain AND m.IsTag=1。
  8. /// 盘点口径由 SQL 内定义(非脑补):
  9. /// 账面(标签数量)=Qty;实盘数量=CompQty;差异数量=CompQty-Qty;
  10. /// 盘点状态=CompQty≠Qty?'有差异':'正常';状态=Status='Q'?'冻结':'';实际库位=FirmString2;实际货架=FirmString4。
  11. /// Domain 由 GeneralizedCodeMaster(SystemConfig/CompanyCode) 解析,默认 8010。排序 UpdateTime DESC, RecID DESC。
  12. ///
  13. /// 本服务仅 SELECT:无新增/编辑/删除/库存事务/状态流转;MissedPrint 无 tenant_id,不做租户过滤。
  14. /// </summary>
  15. [ApiDescriptionSettings(Order = 304, Description = "盘点结果查询")]
  16. [Route("api/S5StocktakeResult")]
  17. [AllowAnonymous]
  18. [NonUnify]
  19. public class StocktakeResultService : IDynamicApiController, ITransient
  20. {
  21. private readonly ISqlSugarClient _db;
  22. public StocktakeResultService(ISqlSugarClient db)
  23. {
  24. _db = db;
  25. }
  26. /// <summary>解析公司域(GeneralizedCodeMaster SystemConfig/CompanyCode,默认 8010)。</summary>
  27. private async Task<string> ResolveDomainAsync()
  28. {
  29. var list = await _db.Ado.SqlQueryAsync<string>(
  30. "SELECT Domain FROM GeneralizedCodeMaster WHERE FldName='SystemConfig' AND Val='CompanyCode' ORDER BY RecID LIMIT 1");
  31. var domain = list.FirstOrDefault();
  32. return string.IsNullOrWhiteSpace(domain) ? "8010" : domain;
  33. }
  34. /// <summary>
  35. /// 盘点结果查询列表(只读分页查询)。
  36. /// </summary>
  37. [DisplayName("盘点结果查询列表")]
  38. [HttpGet("list")]
  39. public async Task<object> GetList([FromQuery] StocktakeResultListInput input)
  40. {
  41. var page = input.Page <= 0 ? 1 : input.Page;
  42. var pageSize = input.PageSize <= 0 ? 10 : input.PageSize;
  43. var offset = (page - 1) * pageSize;
  44. var domain = await ResolveDomainAsync();
  45. var where = new List<string> { "m.Domain = @Domain", "m.IsTag = 1" };
  46. var pars = new List<SugarParameter> { new("@Domain", domain) };
  47. if (!string.IsNullOrWhiteSpace(input.MaterialCode))
  48. {
  49. where.Add("m.ItemNum LIKE @MaterialCode");
  50. pars.Add(new SugarParameter("@MaterialCode", $"%{input.MaterialCode.Trim()}%"));
  51. }
  52. if (!string.IsNullOrWhiteSpace(input.InvStatus))
  53. {
  54. var s = input.InvStatus.Trim();
  55. if (s == "有差异")
  56. where.Add("m.CompQty <> m.Qty");
  57. else if (s == "正常")
  58. where.Add("m.CompQty = m.Qty");
  59. }
  60. var whereSql = string.Join(" AND ", where);
  61. var total = await _db.Ado.GetIntAsync($"SELECT COUNT(1) FROM MissedPrint m WHERE {whereSql}", pars);
  62. var list = await _db.Ado.SqlQueryAsync<StocktakeResultListRow>(
  63. $"""
  64. SELECT
  65. m.ItemNum AS MaterialCode,
  66. i.Descr AS MaterialName,
  67. i.Descr1 AS Spec,
  68. m.Location AS Location,
  69. m.Shelf AS Shelf,
  70. m.FirmString2 AS ActLocation,
  71. m.FirmString4 AS ActShelf,
  72. m.LotSerial AS BatchNo,
  73. i.UM AS Unit,
  74. m.Qty AS TagQty,
  75. m.CompQty AS CountQty,
  76. (m.CompQty - m.Qty) AS QtyDiff,
  77. (CASE WHEN m.Status = 'Q' THEN '冻结' ELSE '' END) AS Status,
  78. (CASE WHEN m.CompQty <> m.Qty THEN '有差异' ELSE '正常' END) AS InvStatus,
  79. m.UpdateUser AS CountUser,
  80. m.UpdateTime AS CountTime
  81. FROM MissedPrint m
  82. LEFT JOIN ItemMaster i ON m.Domain = i.Domain AND m.ItemNum = i.ItemNum
  83. WHERE {whereSql}
  84. ORDER BY m.UpdateTime DESC, m.RecID DESC
  85. LIMIT {pageSize} OFFSET {offset}
  86. """,
  87. pars);
  88. return new { total, page, pageSize, list };
  89. }
  90. }