From eafdf992c7d6da5b6c30be7dab61c90a0a94293b Mon Sep 17 00:00:00 2001 From: yueli Date: Fri, 18 Sep 2026 09:43:25 +0800 Subject: [PATCH] =?UTF-8?q?fix(borrow):=20=E5=80=9F=E8=BF=98=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E3=80=8C=E5=BD=92=E8=BF=98=E4=BA=BA=E3=80=8D=E5=88=97?= =?UTF-8?q?=E9=94=99=E6=A0=87=E6=88=90=E4=BA=86=E7=BB=8F=E6=89=8B=E5=BA=93?= =?UTF-8?q?=E7=AE=A1=EF=BC=8C=E6=8B=86=E6=88=90=E4=B8=A4=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题 ---- 列表里那一列标着「归还人」,读的却是 trans_borrow.return_operator —— 而该字段 存的是**办理还库的库管**,不是来还东西的人。两者本就是不同的人: · returner_id(trans_borrow_return)—— 把东西交回窗口的人,已校验 == 当时持有人 · return_operator —— 经手办理的库管 实测(借用行 120):return_operator = 杜邢宸/duxingchen(库管), 而实际归还人是 returner_id = 21(测试)—— 页面却显示成了「杜邢宸」。 改动 ---- 一、后端 get_records 增补 returners:从 trans_borrow_return 取 returner_id 并 反查 sys_user 得到姓名(去重按明细挂回)。批量查一次,不做 N+1。 二、前端拆成两列,各自名副其实: 「归还人」 ← returners(后端新增) 「经手库管」 ← return_operators(原列改为正确标签) 三、顺带修展示口径:return_operator 存的是**完整 username**(高闯/gaochuang), 未按全站口径截断。_display_borrow_operator 现统一归一到展示名 (数字 id 反查 / 姓名、斜杠前段 / 已是展示名 原样),并修正其 docstring —— 它原本也把该字段称作「归还人」,是同一个误解的源头。 ★ 历史数据的现实 实际归还人流水是二期才建的,**历史归还没有这个记录**。这部分行的「归还人」 显示为空并挂 tooltip 说明「该笔归还发生在实际归还人记录上线之前」—— 刻意不拿库管的名字顶上,那正是本次要修的错。 验证 BOR-20260918-0001 → 归还人=['测试']、经手库管='杜邢宸' ✓ 两者分开 BOR-20260914-0001 → 归还人=[](历史)、经手库管='高闯' ✓ 归一化:'高闯/gaochuang'→'高闯'、'21'→'测试' ✓ 前端 vite build 通过;本次无需 DB 迁移。 --- inventory-backend/app/models/transaction.py | 22 ++++++++++---- .../app/services/trans_service.py | 29 +++++++++++++++++++ .../src/views/transaction/records.vue | 26 +++++++++++++++-- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/inventory-backend/app/models/transaction.py b/inventory-backend/app/models/transaction.py index dd36d49..741e925 100644 --- a/inventory-backend/app/models/transaction.py +++ b/inventory-backend/app/models/transaction.py @@ -16,11 +16,23 @@ def _borrow_user_name(uid): def _display_borrow_operator(op): - """归还人展示映射:历史存的是数字 user id → 映射为用户名;新数据存姓名则原样返回""" - if op and str(op).strip().isdigit(): - mapped = _borrow_user_name(int(op)) - return mapped if mapped else op - return op + """ + **经手库管**的展示映射(注意:不是「归还人」—— 两者是不同的人)。 + + 该字段历史上存过三种口径,统一归一到「展示名」: + · 数字 user id(更早期) → 反查 sys_user 取姓名; + · 完整 username「姓名/拼音」 → 取斜杠前段(与全站展示口径一致); + · 已经是展示名 → 原样返回。 + """ + if not op: + return op + s = str(op).strip() + if s.isdigit(): + mapped = _borrow_user_name(int(s)) + if mapped: + return mapped.split('/')[0] if '/' in mapped else mapped + return op + return s.split('/')[0] if '/' in s else op class TransBorrow(db.Model): diff --git a/inventory-backend/app/services/trans_service.py b/inventory-backend/app/services/trans_service.py index 3d1e7c2..e6d5c0d 100644 --- a/inventory-backend/app/services/trans_service.py +++ b/inventory-backend/app/services/trans_service.py @@ -1586,6 +1586,35 @@ class TransService: TransBorrowTransfer.status == TRANSFER_STATUS_PENDING, ).all() if _ids else [] _pending_map = {t.borrow_id: t.to_dict() for t in _pending} + # ============================================================ + # ★ 实际归还人(trans_borrow_return.returner_id) + # + # 与主表的 return_operator(**经手库管**)是**两个不同的人**: + # · returner_id —— 把东西交回窗口的人(已校验 == 当时持有人) + # · return_operator —— 办理还库的库管 + # 列表原先把后者标成「归还人」展示,属标签错误;此处补上真正 + # 的归还人,供前端分列展示。 + # ⚠ 本表是二期才建的,**历史归还没有这个记录** —— 那部分行的 + # returners 为空,前端显示为空并提示「历史数据未记录」, + # 而不是拿库管的名字顶上(那正是本次要修的错)。 + # ============================================================ + _ret_rows = TransBorrowReturn.query.filter( + TransBorrowReturn.borrow_id.in_(_ids) + ).all() if _ids else [] + _ret_uids = {t.returner_id for t in _ret_rows if t.returner_id} + _ret_names = {} + if _ret_uids: + from app.models.system import SysUser + for _u in SysUser.query.filter(SysUser.id.in_(_ret_uids)).all(): + _ret_names[_u.id] = user_display_name(_u) + _ret_map = {} + for _t in _ret_rows: + _nm = _ret_names.get(_t.returner_id) + if _nm: + _ret_map.setdefault(_t.borrow_id, set()).add(_nm) + for d in items_with_names: + d['returners'] = sorted(_ret_map.get(d.get('id'), set())) + for d in items_with_names: _pt = _pending_map.get(d.get('id')) if _pt is not None: diff --git a/inventory-web/src/views/transaction/records.vue b/inventory-web/src/views/transaction/records.vue index 39376e2..029e747 100644 --- a/inventory-web/src/views/transaction/records.vue +++ b/inventory-web/src/views/transaction/records.vue @@ -209,9 +209,29 @@ {{ row.children ? row.children.length : 0 }} 项 - - + + + + + +