DeliveryScheduleService.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. namespace Admin.NET.Plugin.AiDOP.Supply;
  2. /// <summary>
  3. /// 物料交货计划服务
  4. /// </summary>
  5. [ApiDescriptionSettings(Order = 306, Description = "物料交货计划")]
  6. [Route("api/Supply")]
  7. [AllowAnonymous]
  8. [NonUnify]
  9. public class DeliveryScheduleService : IDynamicApiController, ITransient
  10. {
  11. private readonly ISqlSugarClient _db;
  12. private readonly SqlSugarRepository<PolistDeliverySchedule> _rep;
  13. private readonly UserManager _userManager;
  14. public DeliveryScheduleService(
  15. ISqlSugarClient db,
  16. SqlSugarRepository<PolistDeliverySchedule> rep,
  17. UserManager userManager)
  18. {
  19. _db = db;
  20. _rep = rep;
  21. _userManager = userManager;
  22. }
  23. [DisplayName("物料交货计划列表")]
  24. [HttpGet("delivery-schedule/list")]
  25. public async Task<object> GetList([FromQuery] DeliveryScheduleListInput input)
  26. {
  27. var page = input.Page <= 0 ? 1 : input.Page;
  28. var pageSize = input.PageSize <= 0 ? 10 : input.PageSize;
  29. var offset = (page - 1) * pageSize;
  30. var pars = new List<SugarParameter>();
  31. var where = new List<string> { "ss.isactive = 1" };
  32. if (_userManager.TenantId > 0)
  33. {
  34. where.Add("ss.tenant_id = @TenantId");
  35. pars.Add(new SugarParameter("@TenantId", _userManager.TenantId));
  36. }
  37. if (!string.IsNullOrWhiteSpace(input.PoNumber))
  38. {
  39. where.Add("ss.ponumber LIKE @PoNumber");
  40. pars.Add(new SugarParameter("@PoNumber", $"%{input.PoNumber.Trim()}%"));
  41. }
  42. if (!string.IsNullOrWhiteSpace(input.DsNum))
  43. {
  44. where.Add("ss.dsnum LIKE @DsNum");
  45. pars.Add(new SugarParameter("@DsNum", $"%{input.DsNum.Trim()}%"));
  46. }
  47. if (!string.IsNullOrWhiteSpace(input.ItemNum))
  48. {
  49. where.Add("ss.itemnum LIKE @ItemNum");
  50. pars.Add(new SugarParameter("@ItemNum", $"%{input.ItemNum.Trim()}%"));
  51. }
  52. if (!string.IsNullOrWhiteSpace(input.Supplier))
  53. {
  54. where.Add("(ss.suppliercode LIKE @Supplier OR ss.supplier LIKE @Supplier)");
  55. pars.Add(new SugarParameter("@Supplier", $"%{input.Supplier.Trim()}%"));
  56. }
  57. if (!string.IsNullOrWhiteSpace(input.Status))
  58. {
  59. where.Add("ss.status = @Status");
  60. pars.Add(new SugarParameter("@Status", input.Status.Trim()));
  61. }
  62. var orderBy = BuildListOrderBy(input.SortField, input.SortOrder);
  63. var fromSql = $"""
  64. FROM srm_polist_ds ss
  65. LEFT JOIN ItemMaster im ON ss.domain = im.Domain AND ss.itemnum = im.ItemNum
  66. WHERE {string.Join(" AND ", where)}
  67. """;
  68. var total = await _db.Ado.GetIntAsync($"SELECT COUNT(1) {fromSql}", pars);
  69. var list = await _db.Ado.SqlQueryAsync<DeliveryScheduleListRow>(
  70. $"""
  71. SELECT
  72. ss.Id AS Id,
  73. ss.domain AS Domain,
  74. ss.icdsid AS IcdsId,
  75. ss.dsnum AS DsNum,
  76. ss.status AS Status,
  77. ss.itemnum AS ItemNum,
  78. im.Descr AS Descr,
  79. ss.um AS Um,
  80. ss.purgroup AS PurGroup,
  81. ss.suppliercode AS SupplierCode,
  82. ss.supplier AS Supplier,
  83. ss.submitdate AS SubmitDate,
  84. ss.requestdate AS RequestDate,
  85. ss.needdate AS NeedDate,
  86. ss.ponumber AS PoNumber,
  87. ss.poline AS PoLine,
  88. ss.schedqty AS SchedQty,
  89. ss.lastsentdate AS LastSentDate,
  90. ss.lastsentqty AS LastSentQty,
  91. ss.sentqty AS SentQty,
  92. ss.restqty AS RestQty
  93. {fromSql}
  94. ORDER BY {orderBy}
  95. LIMIT {pageSize} OFFSET {offset}
  96. """,
  97. pars);
  98. return new { total, page, pageSize, list };
  99. }
  100. [DisplayName("生成交货单")]
  101. [HttpPost("delivery-schedule/generate")]
  102. public async Task<object> Generate()
  103. {
  104. await ExecuteGenerateProcedure(string.Empty);
  105. return new { message = "生成交货单成功" };
  106. }
  107. [DisplayName("批量添加交货单")]
  108. [HttpPost("delivery-schedule/batch-generate")]
  109. public async Task<object> BatchGenerate([FromBody] DeliveryScheduleGenerateInput input)
  110. {
  111. if (string.IsNullOrWhiteSpace(input.PoNumber))
  112. throw Oops.Oh("采购单号不能为空");
  113. await ExecuteGenerateProcedure(input.PoNumber.Trim());
  114. return new { message = "批量添加成功" };
  115. }
  116. [DisplayName("发布交货单")]
  117. [HttpPost("delivery-schedule/publish")]
  118. public async Task<object> Publish([FromBody] DeliveryScheduleBatchIdsInput input)
  119. {
  120. var ids = ParseIds(input.Ids);
  121. if (!ids.Any()) throw Oops.Oh("请勾选要发布的数据");
  122. var account = _userManager.Account ?? "system";
  123. var affected = await _db.Updateable<PolistDeliverySchedule>()
  124. .SetColumns(x => new PolistDeliverySchedule
  125. {
  126. Status = "P",
  127. SubmitDate = DateTime.Now,
  128. UpdateUser = account,
  129. UpdateTime = DateTime.Now
  130. })
  131. .Where(x => ids.Contains(x.Id) && x.IsActive == 1 && x.Status == "N")
  132. .ExecuteCommandAsync();
  133. return new { affected, message = affected > 0 ? "发布成功" : "无可发布数据" };
  134. }
  135. [DisplayName("取消发布交货单")]
  136. [HttpPost("delivery-schedule/unpublish/{id:long}")]
  137. public async Task<object> UnPublish(long id)
  138. {
  139. var row = await _rep.GetFirstAsync(x => x.Id == id && x.IsActive == 1) ?? throw Oops.Oh("交货单不存在");
  140. row.Status = "N";
  141. row.UpdateUser = _userManager.Account;
  142. row.UpdateTime = DateTime.Now;
  143. await _rep.UpdateAsync(row);
  144. return new { message = "取消发布成功" };
  145. }
  146. [DisplayName("作废交货单")]
  147. [HttpPost("delivery-schedule/cancel/{id:long}")]
  148. public async Task<object> Cancel(long id)
  149. {
  150. var row = await _rep.GetFirstAsync(x => x.Id == id && x.IsActive == 1) ?? throw Oops.Oh("交货单不存在");
  151. row.Status = "C";
  152. row.UpdateUser = _userManager.Account;
  153. row.UpdateTime = DateTime.Now;
  154. await _rep.UpdateAsync(row);
  155. return new { message = "作废成功" };
  156. }
  157. [DisplayName("选择采购单分页")]
  158. [HttpGet("delivery-schedule/purchase-order/page")]
  159. public async Task<object> GetPurchaseOrderPage([FromQuery] PurchaseOrderSelectInput input)
  160. {
  161. var page = input.Page <= 0 ? 1 : input.Page;
  162. var pageSize = input.PageSize <= 0 ? 10 : input.PageSize;
  163. var offset = (page - 1) * pageSize;
  164. var pars = new List<SugarParameter>();
  165. var where = new List<string>
  166. {
  167. "IFNULL(m.Status,'') <> 'C'",
  168. "IFNULL(d.Status,'') <> 'C'",
  169. "(IFNULL(ds.dsnum, '') = '' OR (ds.status = 'C' AND d.QtyOrded - d.RctQty > 0))"
  170. };
  171. if (!string.IsNullOrWhiteSpace(input.PurOrd))
  172. {
  173. where.Add("m.PurOrd LIKE @PurOrd");
  174. pars.Add(new SugarParameter("@PurOrd", $"%{input.PurOrd.Trim()}%"));
  175. }
  176. if (!string.IsNullOrWhiteSpace(input.ItemNum))
  177. {
  178. where.Add("d.ItemNum LIKE @ItemNum");
  179. pars.Add(new SugarParameter("@ItemNum", $"%{input.ItemNum.Trim()}%"));
  180. }
  181. if (!string.IsNullOrWhiteSpace(input.Supp))
  182. {
  183. where.Add("(m.Supp LIKE @Supp OR s.Name LIKE @Supp)");
  184. pars.Add(new SugarParameter("@Supp", $"%{input.Supp.Trim()}%"));
  185. }
  186. var orderBy = BuildPurchaseOrderOrderBy(input.SortField, input.SortOrder);
  187. var fromSql = $"""
  188. FROM PurOrdMaster m
  189. INNER JOIN PurOrdDetail d ON m.RecID = d.PurOrdRecID
  190. LEFT JOIN srm_polist_ds ds ON d.PurOrd = ds.ponumber AND d.Line = ds.poline AND ds.isactive = 1
  191. LEFT JOIN ConsigneeAddressMaster s ON m.Domain = s.Domain AND m.Supp = s.Address AND s.Typed = 'Supp'
  192. WHERE {string.Join(" AND ", where)}
  193. """;
  194. var distinctSql = $"SELECT DISTINCT m.PurOrd, d.Line, d.ItemNum {fromSql}";
  195. var total = await _db.Ado.GetIntAsync($"SELECT COUNT(1) FROM ({distinctSql}) t", pars);
  196. var list = await _db.Ado.SqlQueryAsync<PurchaseOrderSelectRow>(
  197. $"""
  198. SELECT DISTINCT
  199. m.PurOrd AS PurOrd,
  200. d.Line AS Line,
  201. d.ItemNum AS ItemNum,
  202. d.UM AS Um,
  203. m.Supp AS Supp,
  204. s.Name AS Name,
  205. d.DueDate AS DueDate,
  206. d.QtyOrded AS QtyOrded,
  207. m.Buyer AS Buyer
  208. {fromSql}
  209. ORDER BY {orderBy}
  210. LIMIT {pageSize} OFFSET {offset}
  211. """,
  212. pars);
  213. return new { total, page, pageSize, list };
  214. }
  215. private async Task ExecuteGenerateProcedure(string poNumber)
  216. {
  217. var account = _userManager.Account ?? "system";
  218. var orgNo = _userManager.OrgId.ToString();
  219. await _db.Ado.ExecuteCommandAsync(
  220. "CALL pr_MES_GenerateJHD(@PoNumber, @OrgNo, @Account)",
  221. new SugarParameter("@PoNumber", poNumber),
  222. new SugarParameter("@OrgNo", orgNo),
  223. new SugarParameter("@Account", account));
  224. }
  225. private static List<long> ParseIds(string ids)
  226. {
  227. return ids.Split(',', StringSplitOptions.RemoveEmptyEntries)
  228. .Select(x => long.TryParse(x.Trim(), out var id) ? id : 0)
  229. .Where(x => x > 0)
  230. .Distinct()
  231. .ToList();
  232. }
  233. private static string BuildListOrderBy(string? sortField, string? sortOrder)
  234. {
  235. var dir = string.Equals(sortOrder, "asc", StringComparison.OrdinalIgnoreCase) ? "ASC" : "DESC";
  236. return sortField?.ToLowerInvariant() switch
  237. {
  238. "dsnum" => $"ss.dsnum {dir}",
  239. "status" => $"ss.status {dir}",
  240. "itemnum" => $"ss.itemnum {dir}",
  241. "requestdate" => $"ss.requestdate {dir}",
  242. "needdate" => $"ss.needdate {dir}",
  243. "schedqty" => $"ss.schedqty {dir}",
  244. "sentqty" => $"ss.sentqty {dir}",
  245. "restqty" => $"ss.restqty {dir}",
  246. "submitdate" => $"ss.submitdate {dir}",
  247. "ponumber" => $"ss.ponumber {dir}",
  248. _ => "ss.Id DESC"
  249. };
  250. }
  251. private static string BuildPurchaseOrderOrderBy(string? sortField, string? sortOrder)
  252. {
  253. var dir = string.Equals(sortOrder, "asc", StringComparison.OrdinalIgnoreCase) ? "ASC" : "DESC";
  254. return sortField?.ToLowerInvariant() switch
  255. {
  256. "purord" => $"m.PurOrd {dir}",
  257. "line" => $"d.Line {dir}",
  258. "itemnum" => $"d.ItemNum {dir}",
  259. "supp" => $"m.Supp {dir}",
  260. "name" => $"s.Name {dir}",
  261. "duedate" => $"d.DueDate {dir}",
  262. "qtyorded" => $"d.QtyOrded {dir}",
  263. "buyer" => $"m.Buyer {dir}",
  264. _ => "m.PurOrd DESC, d.Line ASC"
  265. };
  266. }
  267. private sealed class DeliveryScheduleListRow
  268. {
  269. public long Id { get; set; }
  270. public string? Domain { get; set; }
  271. public long? IcdsId { get; set; }
  272. public string? DsNum { get; set; }
  273. public string? Status { get; set; }
  274. public string? ItemNum { get; set; }
  275. public string? Descr { get; set; }
  276. public string? Um { get; set; }
  277. public string? PurGroup { get; set; }
  278. public string? SupplierCode { get; set; }
  279. public string? Supplier { get; set; }
  280. public DateTime? SubmitDate { get; set; }
  281. public DateTime? RequestDate { get; set; }
  282. public DateTime? NeedDate { get; set; }
  283. public string? PoNumber { get; set; }
  284. public int? PoLine { get; set; }
  285. public decimal? SchedQty { get; set; }
  286. public DateTime? LastSentDate { get; set; }
  287. public decimal? LastSentQty { get; set; }
  288. public decimal? SentQty { get; set; }
  289. public decimal? RestQty { get; set; }
  290. }
  291. private sealed class PurchaseOrderSelectRow
  292. {
  293. public string? PurOrd { get; set; }
  294. public int? Line { get; set; }
  295. public string? ItemNum { get; set; }
  296. public string? Um { get; set; }
  297. public string? Supp { get; set; }
  298. public string? Name { get; set; }
  299. public DateTime? DueDate { get; set; }
  300. public decimal? QtyOrded { get; set; }
  301. public string? Buyer { get; set; }
  302. }
  303. }