OrderDeliveryService.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. namespace Admin.NET.Plugin.AiDOP.Order;
  2. /// <summary>
  3. /// 订单交付服务 📦
  4. /// 路由前缀:/api/Order/delivery/...
  5. /// </summary>
  6. [ApiDescriptionSettings(Order = 270, Description = "订单交付")]
  7. [Route("api/Order")]
  8. [AllowAnonymous]
  9. [NonUnify]
  10. public class OrderDeliveryService : IDynamicApiController, ITransient
  11. {
  12. private readonly ISqlSugarClient _db;
  13. public OrderDeliveryService(ISqlSugarClient db)
  14. {
  15. _db = db;
  16. }
  17. // ══════════════════════════════════════════════════════════════
  18. // 列表 GET /api/Order/delivery/list
  19. // ══════════════════════════════════════════════════════════════
  20. /// <summary>获取订单交付分页列表 📦</summary>
  21. [DisplayName("获取订单交付列表")]
  22. [HttpGet("delivery/list")]
  23. public async Task<object> GetDeliveryList([FromQuery] OrderDeliveryListInput input)
  24. {
  25. var pars = new List<SugarParameter>();
  26. var innerConditions = new List<string>
  27. {
  28. "entry.IsDeleted=0",
  29. "sorder.bill_no IS NOT NULL"
  30. };
  31. if (!string.IsNullOrWhiteSpace(input.BillNo))
  32. {
  33. innerConditions.Add("sorder.bill_no LIKE @BillNo");
  34. pars.Add(new SugarParameter("@BillNo", $"%{input.BillNo.Trim()}%"));
  35. }
  36. if (!string.IsNullOrWhiteSpace(input.CustomNo))
  37. {
  38. innerConditions.Add("sorder.custom_no LIKE @CustomNo");
  39. pars.Add(new SugarParameter("@CustomNo", $"%{input.CustomNo.Trim()}%"));
  40. }
  41. if (!string.IsNullOrWhiteSpace(input.ItemNumber))
  42. {
  43. innerConditions.Add("entry.item_number LIKE @ItemNumber");
  44. pars.Add(new SugarParameter("@ItemNumber", $"%{input.ItemNumber.Trim()}%"));
  45. }
  46. if (!string.IsNullOrWhiteSpace(input.PlanDateFrom))
  47. {
  48. innerConditions.Add("entry.plan_date >= @PlanDateFrom");
  49. pars.Add(new SugarParameter("@PlanDateFrom", input.PlanDateFrom.Trim()));
  50. }
  51. var innerWhere = string.Join(" AND ", innerConditions);
  52. var baseSql = BuildListBaseSql(innerWhere);
  53. // progress 是计算列,需包一层过滤
  54. var outerWhere = "";
  55. if (!string.IsNullOrWhiteSpace(input.Progress))
  56. {
  57. outerWhere = "WHERE t.progress = @Progress";
  58. pars.Add(new SugarParameter("@Progress", input.Progress.Trim()));
  59. }
  60. var offset = (input.Page - 1) * input.PageSize;
  61. var total = await _db.Ado.GetIntAsync(
  62. $"SELECT COUNT(*) FROM ({baseSql}) AS t {outerWhere}", pars);
  63. var list = await _db.Ado.SqlQueryAsync<OrderDeliveryListRow>(
  64. $"SELECT * FROM ({baseSql}) AS t {outerWhere} ORDER BY t.id DESC LIMIT {input.PageSize} OFFSET {offset}",
  65. pars);
  66. return new { total, page = input.Page, pageSize = input.PageSize, list };
  67. }
  68. private static string BuildListBaseSql(string innerWhere) => $"""
  69. SELECT
  70. entry.Id AS Id,
  71. sorder.bill_no AS BillNo,
  72. entry.rstate AS Rstate,
  73. entry.entry_seq AS EntrySeq,
  74. entry.item_number AS ItemNumber,
  75. entry.item_name AS ItemName,
  76. entry.specification AS Specification,
  77. entry.unit AS Unit,
  78. sorder.custom_no AS CustomNo,
  79. entry.custom_order_bill_no AS CustomOrderBillNo,
  80. entry.custom_order_itemno AS CustomOrderItemNo,
  81. sorder.custom_level AS CustomLevel,
  82. entry.qty AS Qty,
  83. entry.deliver_count AS DeliverCount,
  84. entry.bom_number AS BomNumber,
  85. sorder.emp_name AS EmpName,
  86. entry.planner_name AS PlannerName,
  87. entry.plan_date AS PlanDate,
  88. entry.sys_capacity_date AS SysCapacityDate,
  89. entry.date AS Date,
  90. entry.create_time AS CreateTime,
  91. entry.create_by_name AS CreateByName,
  92. sorder.auditor AS Auditor,
  93. CASE
  94. WHEN entry.progress = 0 THEN '0'
  95. WHEN nbo.nboNum > 0 THEN '7'
  96. WHEN compp.num > 0 THEN '6'
  97. WHEN cnb.num > 0 THEN '5'
  98. WHEN pr.num > 0 THEN '4'
  99. WHEN nb.num > 0 THEN '3'
  100. WHEN p.num > 0 THEN '2'
  101. WHEN entry.progress = 3 THEN '1'
  102. ELSE CAST(entry.progress AS CHAR)
  103. END AS Progress,
  104. yeard.ProdLine AS ProdLine,
  105. yeard.ProdRange AS ProdRange,
  106. asn.ShipDate AS ShipDate,
  107. CAST(sp.recid AS CHAR) AS Recid,
  108. IF(sp.recid IS NOT NULL, '是', '否') AS Spstatus,
  109. mo.moentry_mono AS MoentryMono
  110. FROM crm_seorderentry entry
  111. LEFT JOIN crm_seorder sorder ON entry.seorder_id = sorder.Id
  112. LEFT JOIN (
  113. SELECT a.id, a.soentry_id, b.product_code, a.moentry_mono
  114. FROM mes_moentry a
  115. JOIN mes_morder b ON a.moentry_mono = b.morder_no
  116. ) mo ON entry.id = mo.soentry_id AND entry.item_number = mo.product_code
  117. LEFT JOIN (
  118. SELECT WorkOrd, COUNT(*) AS num
  119. FROM NbrMaster WHERE type = 'SM' GROUP BY WorkOrd
  120. ) nb ON mo.moentry_mono = nb.WorkOrd
  121. LEFT JOIN (
  122. SELECT WorkOrds, COUNT(*) AS num
  123. FROM PeriodSequenceDet GROUP BY WorkOrds
  124. ) p ON mo.moentry_mono = p.WorkOrds
  125. LEFT JOIN (
  126. SELECT pr_mono, COUNT(*) AS num
  127. FROM srm_pr_main WHERE state > 1 GROUP BY pr_mono
  128. ) pr ON mo.moentry_mono = pr.pr_mono
  129. LEFT JOIN (
  130. SELECT WorkOrds, COUNT(*) AS num
  131. FROM PeriodSequenceDet WHERE CompQty > 0 GROUP BY WorkOrds
  132. ) compp ON mo.moentry_mono = compp.WorkOrds
  133. LEFT JOIN (
  134. SELECT WorkOrd, COUNT(*) AS num
  135. FROM NbrDetail WHERE type = 'SM' AND QtyFrom > 0 GROUP BY WorkOrd
  136. ) cnb ON mo.moentry_mono = cnb.WorkOrd
  137. LEFT JOIN (
  138. SELECT ProdLine, ProdRange, SAPItemNumber
  139. FROM YearDemandManagement GROUP BY ProdLine, ProdRange, SAPItemNumber
  140. ) yeard ON entry.item_number = yeard.SAPItemNumber
  141. LEFT JOIN (
  142. SELECT OrdNbr, ContainerItem, MAX(UpdateTime) AS ShipDate
  143. FROM ASNBOLShipperDetail GROUP BY OrdNbr, ContainerItem
  144. ) asn ON asn.OrdNbr = sorder.bill_no AND asn.ContainerItem = entry.item_number
  145. LEFT JOIN ShippingPlanDetail sp ON entry.id = sp.sentry_id
  146. LEFT JOIN LATERAL (
  147. SELECT COUNT(*) AS nboNum
  148. FROM ASNBOLShipperDetail
  149. WHERE OrdNbr = sorder.bill_no AND ContainerItem = entry.item_number
  150. ) AS nbo ON TRUE
  151. WHERE {innerWhere}
  152. """;
  153. // ══════════════════════════════════════════════════════════════
  154. // 价值流 GET /api/Order/delivery/flow/{entryId}
  155. // ══════════════════════════════════════════════════════════════
  156. /// <summary>获取订单价值流全量数据(8个Tab)📦</summary>
  157. [DisplayName("获取订单价值流")]
  158. [HttpGet("delivery/flow/{entryId}")]
  159. public async Task<object> GetDeliveryFlow(long entryId)
  160. {
  161. // ── 先取工单号 ──
  162. const string monoSql = """
  163. SELECT a.moentry_mono
  164. FROM mes_moentry a
  165. JOIN mes_morder b ON a.moentry_mono = b.morder_no
  166. WHERE a.soentry_id = @Id
  167. """;
  168. var mono = await _db.Ado.GetStringAsync(monoSql, new { Id = entryId });
  169. // ── 并发查询各 Tab ──
  170. var basicTask = QueryBasic(entryId);
  171. var orderInfoTask = QueryOrderInfo(entryId);
  172. var reviewTask = QueryReview(entryId, mono);
  173. var changesTask = QueryChanges(entryId);
  174. var scheduleTask = QuerySchedule(mono);
  175. var materialTask = QueryMaterials(entryId, mono);
  176. var poTask = QueryPo(mono);
  177. var prTask = QueryPr(mono);
  178. var deliveryScheduleTask = QueryDeliverySchedule(mono);
  179. var nbrTask = QueryNbr(mono);
  180. var prodReportTask = QueryProdReport(mono);
  181. var iqcTask = QueryIqc(mono);
  182. var fqcTask = QueryFqc(mono);
  183. var receiptTask = QueryReceipt(mono);
  184. var shipmentTask = QueryShipment(entryId);
  185. await Task.WhenAll(basicTask, orderInfoTask, reviewTask, changesTask,
  186. scheduleTask, materialTask, poTask, prTask, deliveryScheduleTask,
  187. nbrTask, prodReportTask, iqcTask, fqcTask, receiptTask, shipmentTask);
  188. return new
  189. {
  190. basic = basicTask.Result,
  191. tab1 = orderInfoTask.Result,
  192. tab2 = new { review = reviewTask.Result, changes = changesTask.Result },
  193. tab3 = scheduleTask.Result,
  194. tab4 = materialTask.Result,
  195. tab5 = new { po = poTask.Result, pr = prTask.Result, deliverySchedule = deliveryScheduleTask.Result },
  196. tab6 = nbrTask.Result,
  197. tab7 = new { prodReport = prodReportTask.Result, iqc = iqcTask.Result },
  198. tab8 = new { fqc = fqcTask.Result, receipt = receiptTask.Result, shipment = shipmentTask.Result },
  199. };
  200. }
  201. // ── 基础信息 ──
  202. private async Task<FlowBasicRow?> QueryBasic(long entryId)
  203. {
  204. const string sql = """
  205. SELECT
  206. entry.item_number AS ItemNumber,
  207. entry.item_name AS ItemName,
  208. entry.specification AS Specification,
  209. entry.qty AS Qty,
  210. sorder.bill_from AS BillFrom,
  211. entry.plan_date AS PlanDate,
  212. CAST(entry.progress AS CHAR) AS Progress,
  213. entry.update_time AS Mrptime
  214. FROM crm_seorderentry entry
  215. LEFT JOIN crm_seorder sorder ON entry.seorder_id = sorder.Id
  216. WHERE entry.Id = @Id AND entry.IsDeleted = 0
  217. """;
  218. return (await _db.Ado.SqlQueryAsync<FlowBasicRow>(sql, new { Id = entryId })).FirstOrDefault();
  219. }
  220. // ── Tab1 订单信息 ──
  221. private async Task<FlowOrderInfoRow?> QueryOrderInfo(long entryId)
  222. {
  223. const string sql = """
  224. SELECT
  225. sorder.bill_no AS BillNo,
  226. sorder.custom_name AS CustomName,
  227. sorder.custom_level AS CustomLevel,
  228. sorder.flowstate AS State,
  229. sorder.date AS Date,
  230. sorder.create_by_name AS CreateByName,
  231. sorder.order_type AS OrderType,
  232. entry.update_time AS AuditDate,
  233. sorder.auditor AS Auditor,
  234. sorder.bill_from AS BillFrom,
  235. sorder.emp_name AS EmpName,
  236. sorder.emp_no AS EmpNo
  237. FROM crm_seorderentry entry
  238. LEFT JOIN crm_seorder sorder ON entry.seorder_id = sorder.Id
  239. WHERE entry.Id = @Id AND entry.IsDeleted = 0
  240. """;
  241. return (await _db.Ado.SqlQueryAsync<FlowOrderInfoRow>(sql, new { Id = entryId })).FirstOrDefault();
  242. }
  243. // ── Tab2 订单评审 ──
  244. private async Task<FlowReviewRow?> QueryReview(long entryId, string? mono)
  245. {
  246. const string sql = """
  247. SELECT
  248. entry.sys_capacity_date AS SysCapacityDate,
  249. mo.moentry_mono AS MorderNo,
  250. entry.create_time AS CreateTime,
  251. mo.make_qty AS MakeQty,
  252. mo.use_qty AS UseQty,
  253. mo.mo_qty AS MoQty
  254. FROM crm_seorderentry entry
  255. LEFT JOIN (
  256. SELECT a.soentry_id, a.moentry_mono,
  257. b.make_qty, b.use_qty, b.mo_qty
  258. FROM mes_moentry a
  259. LEFT JOIN mes_morder b ON a.moentry_mono = b.morder_no
  260. ) mo ON entry.id = mo.soentry_id
  261. WHERE entry.Id = @Id AND entry.IsDeleted = 0
  262. """;
  263. return (await _db.Ado.SqlQueryAsync<FlowReviewRow>(sql, new { Id = entryId })).FirstOrDefault();
  264. }
  265. // ── Tab2 变更记录 ──
  266. private async Task<List<FlowChangeRow>> QueryChanges(long entryId)
  267. {
  268. const string sql = """
  269. SELECT
  270. ROW_NUMBER() OVER (ORDER BY c.update_time) AS Sno,
  271. c.bill_no AS BillNo,
  272. c.change_Type AS ChangeType,
  273. c.change_Reason AS ChangeReason,
  274. c.change_content AS ChangeContent,
  275. c.update_time AS UpdateTime
  276. FROM crm_seorder_change c
  277. JOIN crm_seorderentry entry ON c.bill_no = (
  278. SELECT s.bill_no FROM crm_seorder s WHERE s.Id = entry.seorder_id
  279. )
  280. WHERE entry.Id = @Id
  281. ORDER BY c.update_time
  282. """;
  283. return await _db.Ado.SqlQueryAsync<FlowChangeRow>(sql, new { Id = entryId });
  284. }
  285. // ── Tab3 计划排程 ──
  286. private async Task<List<FlowScheduleRow>> QuerySchedule(string? mono)
  287. {
  288. if (string.IsNullOrWhiteSpace(mono)) return new();
  289. const string sql = """
  290. SELECT
  291. ROW_NUMBER() OVER (ORDER BY WorkDate) AS Sno,
  292. WorkOrds, WorkDate, Line, Op, WorkQty,
  293. ItemNum, Descr, Descr1, CreateTime
  294. FROM PeriodSequenceDet
  295. WHERE WorkOrds = @Mono
  296. ORDER BY WorkDate
  297. """;
  298. return await _db.Ado.SqlQueryAsync<FlowScheduleRow>(sql, new SugarParameter("@Mono", mono));
  299. }
  300. // ── Tab4 物料需求 ──
  301. private async Task<List<FlowMaterialRow>> QueryMaterials(long entryId, string? mono)
  302. {
  303. if (string.IsNullOrWhiteSpace(mono)) return new();
  304. const string sql = """
  305. SELECT
  306. ROW_NUMBER() OVER (ORDER BY num) AS Sno,
  307. num, item_number AS ItemNumber, item_name AS ItemName,
  308. model AS Model, unit AS Unit, bom_number AS BomNumber,
  309. kitting_time AS KittingTime, erp_cls_name AS ErpClsName,
  310. backflush AS Backflush, qty AS Qty, scrap AS Scrap,
  311. wastage AS Wastage, needCount AS NeedCount,
  312. self_lack_qty AS SelfLackQty, sqty AS Sqty,
  313. use_qty AS UseQty, lack_qty AS LackQty,
  314. mo_qty AS MoQty, make_qty AS MakeQty,
  315. purchase_qty AS PurchaseQty,
  316. purchase_occupy_qty AS PurchaseOccupyQty,
  317. subcontracting_qty AS SubcontractingQty,
  318. satisfy_time AS SatisfyTime,
  319. type AS Type, haveicsubs AS HaveIcSubs,
  320. substitute_code AS SubstituteCode
  321. FROM b_kitting_detail
  322. WHERE mono = @Mono
  323. ORDER BY num
  324. """;
  325. return await _db.Ado.SqlQueryAsync<FlowMaterialRow>(sql, new SugarParameter("@Mono", mono));
  326. }
  327. // ── Tab5 采购订单 ──
  328. private async Task<List<FlowPoRow>> QueryPo(string? mono)
  329. {
  330. if (string.IsNullOrWhiteSpace(mono)) return new();
  331. const string sql = """
  332. SELECT
  333. ROW_NUMBER() OVER (ORDER BY po.create_time) AS Sno,
  334. po.po_billno AS PoBillNo,
  335. po.supplier_no AS SupplierNo,
  336. po.supplier_name AS SupplierName,
  337. po.po_total AS PoTotal,
  338. po.po_purchaser AS PoPurchaser,
  339. po.state AS State,
  340. po.po_ssend_date AS PoSsendDate,
  341. po.create_time AS CreateTime
  342. FROM srm_po_main po
  343. WHERE po.pr_mono = @Mono
  344. ORDER BY po.create_time
  345. """;
  346. return await _db.Ado.SqlQueryAsync<FlowPoRow>(sql, new SugarParameter("@Mono", mono));
  347. }
  348. // ── Tab5 采购申请 ──
  349. private async Task<List<FlowPrRow>> QueryPr(string? mono)
  350. {
  351. if (string.IsNullOrWhiteSpace(mono)) return new();
  352. const string sql = """
  353. SELECT
  354. ROW_NUMBER() OVER (ORDER BY pr.create_time) AS Sno,
  355. pr.pr_billno AS PrBillNo,
  356. pr.number AS Number,
  357. pr.icitem_name AS IcItemName,
  358. pr.model AS Model,
  359. pr.pr_purchasenumber AS PrPurchaseNumber,
  360. pr.pr_purchasename AS PrPurchaseName,
  361. pr.pr_aqty AS PrAQty,
  362. pr.pr_ssend_date AS PrSsendDate,
  363. pr.pr_sarrive_date AS PrSarriveDate,
  364. pr.pr_unit AS PrUnit,
  365. pr.pr_purchaser AS PrPurchaser
  366. FROM srm_pr_main pr
  367. WHERE pr.pr_mono = @Mono AND pr.state > 1
  368. ORDER BY pr.create_time
  369. """;
  370. return await _db.Ado.SqlQueryAsync<FlowPrRow>(sql, new SugarParameter("@Mono", mono));
  371. }
  372. // ── Tab5 物料交货单 ──
  373. private async Task<List<FlowDeliveryScheduleRow>> QueryDeliverySchedule(string? mono)
  374. {
  375. if (string.IsNullOrWhiteSpace(mono)) return new();
  376. const string sql = """
  377. SELECT
  378. ROW_NUMBER() OVER (ORDER BY d.requestdate) AS Sno,
  379. d.ponumber AS PoNumber,
  380. d.dsnum AS DsNum,
  381. d.itemnum AS ItemNum,
  382. d.Descr AS Descr,
  383. d.suppliercode AS SupplierCode,
  384. d.supplier AS Supplier,
  385. d.requestdate AS RequestDate,
  386. d.needdate AS NeedDate,
  387. d.schedqty AS SchedQty,
  388. d.sentqty AS SentQty,
  389. d.restqty AS RestQty
  390. FROM srm_delivery_det d
  391. WHERE d.mono = @Mono
  392. ORDER BY d.requestdate
  393. """;
  394. return await _db.Ado.SqlQueryAsync<FlowDeliveryScheduleRow>(sql, new SugarParameter("@Mono", mono));
  395. }
  396. // ── Tab6 生产备料 ──
  397. private async Task<List<FlowNbrRow>> QueryNbr(string? mono)
  398. {
  399. if (string.IsNullOrWhiteSpace(mono)) return new();
  400. const string sql = """
  401. SELECT
  402. CAST(d.Line AS CHAR) AS Line,
  403. n.Nbr, d.ItemNum, d.Descr, d.Descr1,
  404. d.LocationFrom, d.LocationTo,
  405. d.CurrQtyOpened, d.QtyOrd, d.QtyFrom, d.QtyRec,
  406. d.unit, d.UpdateTime
  407. FROM NbrMaster n
  408. JOIN NbrDetail d ON n.Nbr = d.Nbr
  409. WHERE n.WorkOrd = @Mono AND n.type = 'SM'
  410. ORDER BY d.Line
  411. """;
  412. return await _db.Ado.SqlQueryAsync<FlowNbrRow>(sql, new SugarParameter("@Mono", mono));
  413. }
  414. // ── Tab7 生产报工 ──
  415. private async Task<List<FlowProdReportRow>> QueryProdReport(string? mono)
  416. {
  417. if (string.IsNullOrWhiteSpace(mono)) return new();
  418. const string sql = """
  419. SELECT
  420. ROW_NUMBER() OVER (ORDER BY r.ProdDate) AS Sno,
  421. r.WorkOrd, r.ItemNum, r.Descr, r.Descr1, r.Um,
  422. r.QtyCompleted, r.QtyReject, r.QtyScrapped,
  423. r.ProdDate, r.Op, r.Name
  424. FROM mes_production_report r
  425. WHERE r.WorkOrd = @Mono
  426. ORDER BY r.ProdDate
  427. """;
  428. return await _db.Ado.SqlQueryAsync<FlowProdReportRow>(sql, new SugarParameter("@Mono", mono));
  429. }
  430. // ── Tab7 IQC信息 ──
  431. private async Task<List<FlowIqcRow>> QueryIqc(string? mono)
  432. {
  433. if (string.IsNullOrWhiteSpace(mono)) return new();
  434. const string sql = """
  435. SELECT
  436. ROW_NUMBER() OVER (ORDER BY i.FAPPLYTIME) AS Line,
  437. i.po_bill AS PoBill,
  438. i.po_billline AS PoBillLine,
  439. i.FBILLNO AS FBillNo,
  440. i.FMATERIALCFG AS FMaterialCfg,
  441. i.wlmc AS Wlmc,
  442. i.ggxh AS Ggxh,
  443. i.FRINSQTY AS FRinsQty,
  444. i.FAPPLYTIME AS FApplyTime,
  445. i.FINSPESTARTDATE AS FInspeStartDate,
  446. i.FINSPECTSTATUS AS FInspecStatus
  447. FROM mes_iqc_bill i
  448. WHERE i.mono = @Mono
  449. ORDER BY i.FAPPLYTIME
  450. """;
  451. return await _db.Ado.SqlQueryAsync<FlowIqcRow>(sql, new SugarParameter("@Mono", mono));
  452. }
  453. // ── Tab8 FQC信息 ──
  454. private async Task<List<FlowFqcRow>> QueryFqc(string? mono)
  455. {
  456. if (string.IsNullOrWhiteSpace(mono)) return new();
  457. const string sql = """
  458. SELECT
  459. ROW_NUMBER() OVER (ORDER BY f.FINSPEENDDATE) AS Sno,
  460. f.WorkOrd, f.sczld, f.FBILLNO,
  461. f.FMATERIALCFG AS FMaterialCfg,
  462. f.wlmc AS Wlmc,
  463. f.ggxh AS Ggxh,
  464. f.scph AS Scph,
  465. f.FRINSQTY AS FRinsQty,
  466. f.FINSPEENDDATE AS FInspeEndDate
  467. FROM mes_fqc_bill f
  468. WHERE f.WorkOrd = @Mono
  469. ORDER BY f.FINSPEENDDATE
  470. """;
  471. return await _db.Ado.SqlQueryAsync<FlowFqcRow>(sql, new SugarParameter("@Mono", mono));
  472. }
  473. // ── Tab8 生产入库 ──
  474. private async Task<List<FlowReceiptRow>> QueryReceipt(string? mono)
  475. {
  476. if (string.IsNullOrWhiteSpace(mono)) return new();
  477. const string sql = """
  478. SELECT
  479. ROW_NUMBER() OVER (ORDER BY r.CreateTime) AS Sno,
  480. r.Status, r.WorkOrd, r.itemnum AS ItemNum, r.descr AS Descr,
  481. r.UM, r.QtyOrded, r.CompQty,
  482. r.inspection_number AS InspectionNumber,
  483. r.qualified_number AS QualifiedNumber,
  484. r.QtyChangeAdvance,
  485. r.moentry_prdname AS MoentryPrdName,
  486. r.moentry_wrkcname AS MoentryWrkcName,
  487. r.OrdDate, r.DueDate, r.CreateTime
  488. FROM mes_production_receipt r
  489. WHERE r.WorkOrd = @Mono
  490. ORDER BY r.CreateTime
  491. """;
  492. return await _db.Ado.SqlQueryAsync<FlowReceiptRow>(sql, new SugarParameter("@Mono", mono));
  493. }
  494. // ── Tab8 成品发运 ──
  495. private async Task<List<FlowShipmentRow>> QueryShipment(long entryId)
  496. {
  497. const string sql = """
  498. SELECT
  499. ROW_NUMBER() OVER (ORDER BY d.ShipDate) AS Sno,
  500. d.Id, d.Location, d.ShipDate,
  501. d.QtyToShip, d.RealQty,
  502. d.Location AS LocationCode
  503. FROM ASNBOLShipperDetail d
  504. JOIN crm_seorderentry entry ON d.ContainerItem = entry.item_number
  505. JOIN crm_seorder sorder ON d.OrdNbr = sorder.bill_no
  506. AND sorder.Id = entry.seorder_id
  507. WHERE entry.Id = @Id AND d.IsActive = 1
  508. ORDER BY d.ShipDate
  509. """;
  510. return await _db.Ado.SqlQueryAsync<FlowShipmentRow>(sql, new { Id = entryId });
  511. }
  512. }