diff --git a/inventory-backend/app/services/trans_service.py b/inventory-backend/app/services/trans_service.py index 11549db..3d1e7c2 100644 --- a/inventory-backend/app/services/trans_service.py +++ b/inventory-backend/app/services/trans_service.py @@ -1089,7 +1089,10 @@ class TransService: # 无限期梯队内:单号内最早借出时间(呆滞借用盘点) func.min(TransBorrow.borrow_time).label('min_borrow_time'), # 单内是否含"有限期"明细:任一 expected_return_time 非空 → 1(有限期单排前) - func.max(case((TransBorrow.expected_return_time.isnot(None), 1), else_=0)).label('has_finite') + func.max(case((TransBorrow.expected_return_time.isnot(None), 1), else_=0)).label('has_finite'), + # 「已归还」页签的排序键:单号内**最晚**一次归还时间 + # (多明细分批归还时,整单结清的那一刻才是有意义的节点) + func.max(TransBorrow.return_time).label('max_return_time') ) .group_by(TransBorrow.borrow_no) .subquery() @@ -1434,18 +1437,31 @@ class TransService: ) ) - # ★ 默认排序(多级复合,符合"优先关注快到期/逾期"业务): - # 1) 有限期单(含 expected_return_time)排前,无限期单排后 - # 2) 有限期内按最早预计归还时间 ASC(越快到期/逾期越久越靠前) - # 3) 无限期内按最早借出时间 ASC(借出越久越靠前,暴露长期未还的呆滞借用) - 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)), - # ★ 无限期梯队内按借出时间**从近到远**(desc)。 - # 原实现是 asc「借出越久越靠前」,设计意图是暴露呆滞借用; - # 业务方明确要求改为从近到远,故反转。 - desc(order_subq.c.min_borrow_time) + # ★ 排序按页签分开: + # + # 「已归还」页签 —— 按**归还时间倒序**(从近到远)。 + # 这张列表此时回答的是「最近还了哪几笔」,而不是「哪笔快到期」, + # 所以不能沿用未归还那套「逾期优先」的排序,否则最近刚还的 + # 反而排在最后。取单号内**最晚**一次归还时间:多明细分批归还时, + # 整单结清的那一刻才是有意义的节点,也与主行「归还时间」列的 + # 展示口径一致(前端同样取 latest)。 + # + # 其余页签(全部 / 未归还)—— 沿用「优先关注快到期/逾期」: + # 1) 有限期单(含 expected_return_time)排前,无限期单排后 + # 2) 有限期内按最早预计归还时间 ASC(越快到期/逾期越久越靠前) + # 3) 无限期内按最早借出时间 DESC(从近到远) + _order_by = ( + [nullslast(desc(order_subq.c.max_return_time)), + desc(order_subq.c.borrow_no)] # 同一时刻的稳定兜底 + if status == 'returned' else + [case((order_subq.c.has_finite == 0, 1), else_=0).asc(), + nullslast(asc(order_subq.c.sort_key)), + # ★ 无限期梯队内按借出时间**从近到远**(desc)。 + # 原实现是 asc「借出越久越靠前」,设计意图是暴露呆滞借用; + # 业务方明确要求改为从近到远,故反转。 + desc(order_subq.c.min_borrow_time)] ) + borrow_no_q = borrow_no_q.order_by(*_order_by) # 分页(基准 = borrow_no 单号数) pagination = borrow_no_q.paginate(page=page, per_page=limit, error_out=False)