From 15d0c6b97a3af8622358001fe3b1307710b14a6b Mon Sep 17 00:00:00 2001 From: yueli Date: Thu, 17 Sep 2026 09:53:26 +0800 Subject: [PATCH] =?UTF-8?q?fix(borrow):=20=E4=BF=AE=E5=A4=8D=E5=80=9F?= =?UTF-8?q?=E8=BF=98=E8=AE=B0=E5=BD=95=E6=8E=92=E5=BA=8F=E8=A2=AB=E9=9D=99?= =?UTF-8?q?=E9=BB=98=E4=B8=A2=E5=BC=83=EF=BC=8C=E6=97=A0=E9=99=90=E6=9C=9F?= =?UTF-8?q?=E6=94=B9=E6=8C=89=E5=80=9F=E5=87=BA=E6=97=B6=E9=97=B4=E4=BB=8E?= =?UTF-8?q?=E8=BF=91=E5=88=B0=E8=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现象 ---- 借还记录列表的排序看起来毫无规律:无限期单排在有限期前面,有限期内 10-01 排在 11-01 之后。业务方反馈「不是逾期的、剩余天数最近的排前面吗?」 根因 ---- 三级复合排序(trans_service get_records 步骤 2)算得完全正确,但**结果被 后面一步覆盖**: # 步骤 2:算出分页用的 page_borrow_nos(顺序正确) # 步骤 3:再按集合把明细拉回来 —— detail_records = TransBorrow.query.filter(borrow_no.in_(page_borrow_nos)) .order_by(TransBorrow.borrow_no.asc(), ...) 单号形如 BOR-YYYYMMDD-NNNN,**它的字母序恰好等于借出日期序**。于是这 10 条 明细被重排成「按借出日期升序」,那份精心设计的排序被整套丢弃。 实测(修复前,未归还页签第 1 页): 1 BOR-20260413-0001 无限期 04-13 ← 无限期在最前 4 BOR-20260611-0001 无限期 06-11 5 BOR-20260903-0010 逾期 09-10 ← 逾期单反而最后 8 BOR-20260904-0005 10-01 ← 10-01 排在 11-01 之后 ★ 该功能自上线起从未生效: 1450e6c (06-16) 引入按 borrow_no 重排的明细拉取 73510d3 (09-04) 才加入三级复合排序 —— 加在了被覆盖的路径上, 提交信息「借还记录默认排序重构」名存实亡。 修复 ---- 按 page_borrow_nos 的顺序还原输出(明细内部仍按 id 升序,即扫码顺序)。 同时按业务方要求调整第二梯队方向: ① 有限期单在前(有任何明细含预计归还时间) ② 有限期内按单内最早预计归还时间**升序** —— 逾期优先,其后剩余天数由近到远 ③ 无限期内按单内最早借出时间**降序**(从近到远) ★ 原为升序「借出越久越靠前,暴露呆滞借用」,业务方明确要求反转 修复后实测(未归还页签): 有限期 09-10(逾期7天) → 09-11(逾期6天) → 09-15(逾期2天) → 10-01 → 11-01 → 11-27 无限期 09-17 → 09-14 → 09-11 → 09-10 → … → 04-13(跨页连续) 验证:borrowed / returned 两个页签各 3 页顺序全部核对通过;关键词、物料名、 高级筛选、日期范围、空结果六条过滤路径冒烟通过;同单号明细未被跨单号打散。 --- .../app/services/trans_service.py | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/inventory-backend/app/services/trans_service.py b/inventory-backend/app/services/trans_service.py index 3859a09..f09720c 100644 --- a/inventory-backend/app/services/trans_service.py +++ b/inventory-backend/app/services/trans_service.py @@ -1216,7 +1216,10 @@ class TransService: borrow_no_q = borrow_no_q.order_by( case((order_subq.c.has_finite == 0, 1), else_=0).asc(), nullslast(asc(order_subq.c.sort_key)), - asc(order_subq.c.min_borrow_time) + # ★ 无限期梯队内按借出时间**从近到远**(desc)。 + # 原实现是 asc「借出越久越靠前」,设计意图是暴露呆滞借用; + # 业务方明确要求改为从近到远,故反转。 + desc(order_subq.c.min_borrow_time) ) # 分页(基准 = borrow_no 单号数) @@ -1311,6 +1314,23 @@ class TransService: item_dict['material_name'] = material_name items_with_names.append(item_dict) + # ==================================================================== + # ★ 恢复业务排序(此前被静默丢弃) + # + # detail_records 是按 `borrow_no ASC` 重新拉取的,而单号形如 + # BOR-YYYYMMDD-NNNN —— 它的**字母序恰好等于借出日期序**。 + # 于是上面步骤 2 辛苦算出的「逾期优先」分页顺序(page_borrow_nos) + # 被这次重排**整套覆盖**:无限期单排到了最前,有限期里 10-01 排在 + # 11-01 之后,看起来完全随机。那份 ORDER BY 一直是死代码。 + # + # 这里按 page_borrow_nos 的顺序还原输出。明细内部仍按 id 升序 + # (同一次发货写入的明细,id 序即扫码顺序,便于阅读)。 + # ==================================================================== + _order_idx = {bn: i for i, bn in enumerate(page_borrow_nos)} + items_with_names.sort( + key=lambda d: (_order_idx.get(d.get('borrow_no'), len(_order_idx)), d.get('id') or 0) + ) + return { 'items': items_with_names, 'total': total_orders,