|
|
36e9f500aa
|
feat(borrow): 借库未归还直接报废功能(关联报废单流程)
后端:
- trans_service 新增 scrap_borrow 方法:未归还借用标记为 scrapped,
扣减总库存 stock_quantity(可用已在借出时冻结),生成 TransScrap 报废记录
- transactions.py 新增 POST /borrow/scrap 接口(复用 op_return:operation 权限,库管/主管可操作)
- scrap.py query_records 支持 trans_borrow 来源的物料名解析 + 行级隔离
前端:
- records.vue 未归还记录新增「报废」按钮(库管/主管可见)
- 报废弹窗:勾选明细 + 填报废原因 + 二次确认
- 状态显示新增「已报废」标签;整单所有明细报废时标记为 scrapped
|
2026-08-31 10:21:28 +08:00 |
|
|
|
2556b77530
|
perf: 系统级性能优化与并发安全修复
## 并发安全修复 (4处)
- scrap.py: 报废执行添加 SELECT FOR UPDATE 悲观锁,消除 TOCTOU 竞态
- stock.py (adjust_stock): 盘点调整添加 for_update=True 行锁
- outbound_service.py: 低库存预警 SMTP 调用移到 commit 之后,避免长事务
- trans_service.py: execute_dispatch 按 (source_table, id) 排序 items,消除死锁风险
## N+1 查询优化 (2处)
- inventory_task.py: _prefetch_inventory_map 单条 UNION ALL+GROUP BY 替代循环内逐条查询(N*4次→2次)
- stock.py (export_stocktake): get_borrowed_qty 批量 GROUP BY 替代逐条 TransBorrow 查询(~18000次→1次)
## BOM 列表性能重构
- bom_service.py: get_bom_list 单条 GROUP BY+string_agg+分页,消除 N+1 循环查询
- bom_service.py: 新增 get_bom_summary (轻量 GROUP BY category+COUNT)
- bom.py: 新增 /api/v1/bom/summary 路由,/list 支持 category 过滤
## Odoo 基础信息懒加载
- base_service.py: 新增 get_odoo_summary (GROUP BY category+COUNT)
- base.py: 新增 /api/v1/inbound/base/odoo-summary 路由
- buyOdoo.vue: 懒加载分组架构 (fetchOdooSummary + loadGroupItems)
- material_base.ts: 新增 getOdooSummary API
## 前端 Bug 修复
- BomManage.vue: 懒加载分组 (fetchBomSummary + loadGroupItems + collapse)
- BomManage.vue: 适配新 API 格式 (res.data.items 替代 res.data)
- buyOdoo.vue: 移除 "点击展开加载" 文字
- Selection.vue + borrow/apply/index.vue: openBomSelect 适配新 API 格式
|
2026-07-15 17:37:57 +08:00 |
|
|
|
e1417d740a
|
feat: 全模块公司隔离 + crossDomain权限码动态跨域控制
- get_current_company_filter: 新增_has_cross_domain_permission, 权限码替代硬编码
- 补全11个Service的get_current_company_filter调用(semi/product/service/outbound/bom/trans/scrap/summary)
- base/search修复: search_material此前无隔离, 已补全
- get_current_company_filter兜底: JWT缺company_name时返回__NO_COMPANY__防止放行
- permission.py: _get_operator_company补全返回值, 修复权限页保存逻辑
- 新增crossDomain迁移脚本, element_type=element挂system_mgmt下
|
2026-07-15 11:11:40 +08:00 |
|
|
|
1450e6c1de
|
fix(借还记录列表): 按 borrow_no 单号维度分页 + 修 SQLAlchemy Row 适配错误
- 分页基准从明细行改为单号:21 项单号不再被拆到 3 页
- 步骤 1a 构造 GROUP BY borrow_no 的 subquery(sort_key + status 聚合)
- 步骤 2 主查询 SELECT order_subq.c.borrow_no 一列,避免触发 PG GROUP BY 严格模式 (f405)
- 步骤 3 用 page_borrow_nos 拉明细,保留前端 groupMap 期望的 items 形态
- pagination.items 用 isinstance + hasattr(_mapping) 兜底提取纯字符串(修 psycopg2 can't adapt type 'Row')
- service 加 try-except,路由层识别 500 透传 traceback
- status 过滤改为单号聚合(borrowed=至少一条未还,returned=全部归还)
|
2026-06-16 14:53:42 +08:00 |
|
|
|
b79b0f99af
|
fix(借库扫码出库): 撤销 joinedload 修复 PG "FOR UPDATE cannot be applied to nullable side of outer join"
- 83b3db6 引入的 joinedload(ModelClass.base) 触发 LEFT OUTER JOIN,
而 with_for_update() 会被 SQLAlchemy 透传到 join 的 nullable 侧,
PG 直接抛 FeatureNotSupported,且连表加锁有死锁风险
- 退回最安全的单表 FOR UPDATE 模式,接受 N+1 lazy 加载的代价
- 在 防线3 上方加防回归注释,明确禁止未来再加 joinedload
- process_return 中的另两处 joinedload 不带 FOR UPDATE,不受 PG 限制,保留
|
2026-06-16 13:56:11 +08:00 |
|
|
|
83b3db693a
|
fix(借库扫码出库): 校验 key 从 (source_table, sku) 改为 (name, spec_model) + N+1 修复
- 借库申请按 (name, spec_model) 发起,审批明细无 sku 字段;
旧代码用 sku 做 key 会导致所有条目坍塌到同一桶,校验形同虚设
- 改为在扫码循环内即时累加、即时拦截:
防线4 锁定 stock 行后从 material_base 取真实 (name, spec_model),
与审批单按 strip 后的 (name, spec_model) 聚合比对
- 新增 joinedload(ModelClass.base) 一次 JOIN 加载 base,
避免循环内 stock.base 触发 N+1
- 修正 dispatch_borrow docstring 中"sku 用于超额交叉校验"的错误描述
|
2026-06-16 13:50:49 +08:00 |
|
|
|
7ef22a3830
|
feat(借库审批流): 完整前后端实现
|
2026-06-12 14:08:19 +08:00 |
|
|
|
9a5e3ee6b0
|
TransService.get_records: 追加 material_name 字段 + SKU 兜底查询解决数据孤岛问题
|
2026-06-12 11:06:34 +08:00 |
|
|
|
48651ffd01
|
perf: 消除出库列表和还库操作的 N+1 查询,改用批量 IN + joinedload
|
2026-05-19 09:49:30 +08:00 |
|
|
|
71e5f075d2
|
feat: implement composite debounced search with prepended select and wipe out duplicate root permission nodes
|
2026-03-20 10:26:45 +08:00 |
|
|
|
3bb3975022
|
fix: use .c to access SQLAlchemy subquery columns correctly
|
2026-03-20 10:15:11 +08:00 |
|
|
|
34629b432a
|
fix: correct SQLAlchemy join condition to resolve MaterialBase AttributeError
|
2026-03-20 10:06:22 +08:00 |
|
|
|
990399a408
|
feat: implement cross-table search and debounced dynamic search for borrow and return records
|
2026-03-20 09:58:42 +08:00 |
|
|
|
8db1015f99
|
fix: implement traffic-light color warning and correct ascending sort for overdue borrow records
|
2026-03-19 11:45:27 +08:00 |
|
|
|
b74464df6b
|
feat: add descending sort by return date and color-coded warning for impending returns
|
2026-03-19 11:40:38 +08:00 |
|
|
|
79d4a365e0
|
feat: add partial return support with returned_quantity tracking
|
2026-03-18 10:41:19 +08:00 |
|
|
|
b98f89bfe4
|
chore: add .material->.base refactor check comments
Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
|
2026-02-10 11:34:50 +08:00 |
|
|
|
04ee938cd1
|
借库逻辑实现
|
2026-02-06 17:11:47 +08:00 |
|
|
|
ee9f4aed3e
|
修正git管理关系
|
2026-01-26 13:47:53 +08:00 |
|