|
|
0daf50ac21
|
fix: 成品/半成品/维修列表第二层跨域判断补认 crossDomain(解决库管配跨域仍看不到双边)
|
2026-09-04 13:01:44 +08:00 |
|
|
|
1527d552d4
|
feat: 出库/借库记录记录并展示库位快照(DB加列+后端写入+记录页展示)
|
2026-09-04 11:42:44 +08:00 |
|
|
|
e5c49c5177
|
fix: 入库 search-base 物料选择加公司隔离,恢复半成品批号按本公司历史自动递增
|
2026-09-04 09:42:49 +08:00 |
|
|
|
1b760f351e
|
fix: 出库/借库扫码查库存与 BOM 子件物料选择加行级公司隔离(超管/跨域不受限)
|
2026-09-04 09:40:00 +08:00 |
|
|
|
c68ffdca0f
|
fix: 入库成品/半成品/采购编辑其它字段时不再误清空图片——仅显式携带图片字段才更新
|
2026-09-03 14:14:24 +08:00 |
|
|
|
7fe861b4a7
|
fix: 基础信息修改其它字段时不再误清空 product_image(图片消失)——仅显式携带 generalImage 才更新图片
|
2026-09-03 14:12:15 +08:00 |
|
|
|
bf7b2cc6d3
|
feat: BOM 库存接口支持按版本查询,修复同一编号多版本下拉回显错乱
|
2026-09-02 18:39:17 +08:00 |
|
|
|
ee22927660
|
fix: 解耦 Webhook 身份证与库存序列号,恢复批号入库纯净
- 前端:新增临时字段 form.track_id 存 16位身份证,Batch 时 form.serial_number 清空
- 前端:submitForm 不再把身份证补进 payload.serial_number,改为透传 payload.track_id
- 后端:StockSemi 仅存 serial_number(Batch 为空),notify_track 优先用 track_id
|
2026-09-01 16:44:48 +08:00 |
|
|
|
fbb4160787
|
feat: 采购申请新增库管'完结'功能(仿出库审批)
- 后端:approve 接口支持 action=close(已通过→已完结 status 1→4),模型 status_text 支持已完结
- 前端:采购申请状态tab加'已完结',已通过单显示'完结'按钮(库管)
|
2026-09-01 16:15:48 +08:00 |
|
|
|
2c092c4c01
|
feat: MOM 出库联动 Track 标记已出库
- 发货出库时反查库存表 serial_number(Track 身份证),commit 后通知 Track mom-outbound
- notify_track 支持指定 webhook url(TRACK_OUTBOUND_WEBHOOK_URL)
|
2026-09-01 13:53:00 +08:00 |
|
|
|
bee037f925
|
feat: MOM 扫码入库对接 Track 产品身份证自动填充
- 半成品/成品入库弹窗顶部新增'扫码入库'按钮,打开扫码面板(扫码枪/摄像头)
- 扫码 Track 身份证后自动填充物料信息与序列号,不再二次搜索
- 后端新增 track_query_service(httpx 调 Track lookup)、track-lookup 接口
- 入库成功后 notify_track 通知 Track 闭环
|
2026-09-01 13:52:56 +08:00 |
|
|
|
1000deda2f
|
feat(purchase): 采购单号改为 批次-批内序号 格式,显式体现同批
按用户原始逻辑还原并扩展:
- 单号格式: PUR-日期-时间-批次-批内序号
例: PUR-20260831-1021-0001-0001(今日第1次采购的第1条)
- generate_request_no 支持 batch_seq 参数生成批次+批内序号
- 新增 GET /purchase/next-batch-seq 返回今日下一个批次号
- 前端提交时获取批次号,同批所有行共享,循环提交生成连续批内序号
- 批次识别: 单号去掉末尾 -批内序号 即为批次前缀
- 保留旧格式兼容(无 batch_seq 时回退 PUR-日期-时间-流水)
|
2026-08-31 13:54:03 +08:00 |
|
|
|
f499346f74
|
refactor(purchase): 批次概念改为基于 request_no 前缀推导,撤销数据库字段
按用户反馈:不需要新增数据库字段,现有 request_no (PUR-20260831-1021-0001)
本身就能推导批次——去掉末尾4位流水号即为批次前缀。
- 撤销 purchase_request.batch_no 字段(模型/数据库)
- 撤销 create 接口的 batch_no 参数与 generate_batch_no
- 批次标识 = request_no 去掉末尾 -XXXX 段
getBatchKey('PUR-20260831-1021-0001') = 'PUR-20260831-1021'
- 按批次查询/批量审批接口改用 batch_key (request_no LIKE 前缀)
- 前端列表批次号列、整批弹窗、一键审批本批均基于前缀推导
- 零数据库迁移,历史数据立即可用
|
2026-08-31 13:49:11 +08:00 |
|
|
|
664127ee30
|
feat(purchase): 采购批次号支持,同一批提交的记录可分组查看/统计
背景: 循环提交把一批物品生成多条独立申请,无法识别'哪些是同一批采购'
后端:
- purchase_request 模型新增 batch_no 字段(同一批提交共享)
- create 接口接收 batch_no,无则自动生成 BATCH-yyyyMMdd-HHmm-随机
- 新增 GET /purchase/batch/<batch_no> 按批次查询所有记录
- 批量审批接口支持按 batch_no 一键审批整批
前端:
- 提交时生成 batch_no 共享给所有行
- 列表新增批次号列(可点击)
- 新增'整批查看'弹窗:显示同批次所有记录 + 一键批量通过本批
- 操作列新增'整批'按钮
数据库需执行: ALTER TABLE purchase_request ADD COLUMN batch_no VARCHAR(100);
|
2026-08-31 13:46:46 +08:00 |
|
|
|
3a07f1a272
|
fix(bom): BOM 详情查询改为 LEFT JOIN,子件物料被删后仍返回父件结构
- get_bom_detail 使用 outerjoin 替代 join
- 子件物料被删除后 child_name 显示 [已删除物料] 而非误报 BOM 不存在
- 修复按 BOM 出库时因子件删除导致 404 BOM 不存在
|
2026-08-31 10:28:22 +08:00 |
|
|
|
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 |
|
|
|
39f3f8af45
|
feat(outbound): 审批单手动完结/作废功能
- 后端: outbound_service 新增 close_request 方法(状态 1-已通过 → 4-已完结)
- 后端: 新增 POST /api/v1/outbound/request/<id>/close 接口
- 模型: status_text 数组增加「已完结」
- 前端: create.vue 审批单选择区新增「强制完结此单」按钮
完结后刷新列表,该单从已通过下拉中移除
- 权限: 超级管理员/审批人/拥有 outbound_create:operation 的用户可完结(库管可操作)
|
2026-08-31 10:15:33 +08:00 |
|
|
|
95057dedf5
|
refactor(import): 导入服务核心逻辑改造
- 预览阶段增加 Excel 内部重复检测 + 空规格去重 + 字段长度校验
- 执行阶段支持 skip 模式(跳过重复行继续导入)+ update 模式(覆盖更新已有记录)
- update 模式空值保护:Excel 空单元格不覆盖已有数据
- DB commit 异常防御:字段超长等异常优雅返回而非 500
- 去重规则改为仅依据 spec_model(货号唯一键)
- BOM 导入物料查找同步改为 spec-only
|
2026-08-03 15:53:10 +08:00 |
|
|
|
65aba4b313
|
fix: token 刷新时缺少 company_name 导致多租户过滤返回空数据
|
2026-08-03 09:22:50 +08:00 |
|
|
|
29de22b575
|
fix: crossDomain 重复收集 — 真实树中的 system_mgmt/crossDomain 与虚拟 global_privileges 冲突,从真实树中移除 crossDomain 避免双重收集
|
2026-07-17 16:22:59 +08:00 |
|
|
|
c45e7b5a52
|
debug: assign_permissions 加详细日志追踪 crossDomain 删除/插入/提交后状态
|
2026-07-17 16:18:05 +08:00 |
|
|
|
de2d13fa68
|
fix: 全局权限码 crossDomain/global:cross_company_op 强制存为 company_name='',防止按公司隔离失效
|
2026-07-17 15:50:06 +08:00 |
|
|
|
efe04c5d42
|
fix: assign_permissions 删除逻辑对齐 get_user_permissions 查询逻辑 — 公司定制+全局模板一起替换
|
2026-07-17 15:38:14 +08:00 |
|
|
|
f3c946d584
|
fix: 借库审批同样修复 — sys_element 补充 op_borrow_approval:operation,can_approve 增加 RBAC 权限判断
|
2026-07-17 15:22:54 +08:00 |
|
|
|
05832e913b
|
fix: can_approve 增加 outbound_approval:operation RBAC 权限判断,前端按钮权限与后端审批权限统一对齐
|
2026-07-17 15:17:26 +08:00 |
|
|
|
3c0954598c
|
perf: 综合安全加固 — RBAC严格映射+异步邮件+字段权限白名单+前端对齐+导入模板
本次提交包含本会话所有修改的最终统一提交
## 权限系统重构
- permission_service.py: 添加入库/采购操作元素 + ensure_default_permissions
- field_permissions.py: 严格1-to-1 Default Deny 字段映射(StockBuy/Semi/Product/MaterialBase)
- decorators.py: _expand_operation_perms 双向粒度桥接 + prevent_double_submit
- deploy_production.sql: 修复 sys_element 别名码(qty_inbound→in_quantity)
## 采购模块
- purchase.py: 权限驱动可见性 + inbound_purchase独立权限 + 价格字段过滤
- purchase_service.py: 异步邮件 + 三阶段批量模糊匹配防N+1
- purchase/index.vue: canApprove严格操作权限 + upload重复修复
## 导出/入
- base_service.py: export_excel 流式写入防OOM + get_latest_specs 优化
- import_service.py + import_api.py: Excel批量导入(模板+预览+执行)
- ImportDialog.vue: 三步骤导入弹窗
## 异步邮件
- email_service.py: send_email_async (守护线程)
- inventory_task.py: send_email→send_email_async
## 前端对齐
- product/semi/buy.vue: 列对齐in_quantity/stock_quantity/available_quantity + localStorage缓存V2
- buyOdoo.vue: 排序修复 + 导入按钮 + 移除点击展开加载
- BomManage.vue: 懒加载分组 + 导入按钮
- list.vue: 导入按钮
- Selection.vue + borrow/apply: BOM匹配修复 + 导入按钮
- outbound/create.vue: 出库类型必选
- AppMain.vue: 移除transition白屏修复
- material_base.ts, outbound.ts, bom.ts, stock.ts: 新增API函数
|
2026-07-17 13:07:12 +08:00 |
|
|
|
2e903cff2c
|
perf: 规格连号助手优化 — 流式查询+宽松regex+Redis缓存
## base_service.py get_latest_specs
- .all()全量→with_entities().limit(10000) 防OOM
- regex放宽: 支持 LICA-3000/M3x12 等格式(旧版仅匹配OPT12046)
- 移除OPT硬编码→SUB_CATEGORY_PREFIXES可配置集合
- Redis缓存(1h): 首次查询后缓存,后续命中直接返回
## base.py 缓存失效
- 新增 _invalidate_specs_cache() 辅助函数
- create/update/delete 成功后清除缓存
|
2026-07-16 18:15:43 +08:00 |
|
|
|
754c46bd59
|
feat: 采购申请字段级价格权限 — 库管看不到采购价格
## permission_service.py
- init_all_menus: 新增3个采购权限元素
inbound_purchase:unit_price, :total_price, :tax_rate
## purchase.py
- _filter_purchase_prices(): 无价格权限则pop价格字段
- GET /purchase (列表): 应用价格过滤
- GET /purchase/<id> (详情): 应用价格过滤
- approved-unstocked: 保留价格(入库数据源,前端按inbound_buy权限控制)
## purchase/index.vue
- 列表: 单价/总价/税率列 v-if hasPermission
- 详情: 单价/总价 v-if hasPermission
|
2026-07-16 17:34:24 +08:00 |
|
|
|
23fc10a25f
|
fix: Day2就绪 — 删除硬化+索引补全+全局异常处理
## base_service.py — MaterialBase删除硬化
- 新增 BomTable 引用检查(bom_usage_count)
- 物料被BOM引用时禁止删除,提示「请先解除BOM绑定」
## models/base.py + bom.py — 缺失索引补全
- material_base: company_name + is_enabled 添加 index=True
- bom_table: is_enabled 添加 index=True
## __init__.py — 全局异常处理
- @app.errorhandler(ValueError) → 400 + 自定义消息
- @app.errorhandler(404/405) → 标准错误
- @app.errorhandler(Exception) → 500 + 通用消息
堆栈仅记录服务器日志,不泄露到前端
|
2026-07-16 14:14:43 +08:00 |
|
|
|
5411cabd0a
|
feat: Excel批量导入后端 — 模板下载+预览验证+执行导入
## import_service.py (新增)
- generate_template(): 基础信息/BOM Excel模板生成(带样例数据)
- parse_boolean(): 是/否/True/False 稳健布尔解析
- preview_material/bom(): Dry-Run解析+验证(重复/存在性/必填)
- BOM ffill: 父件列自动向下填充(支持合并单元格UX)
- execute_material/bom_import(): 事务包裹批量写入
## import_api.py (新增)
- GET /api/v1/import/template?type=material|bom
- POST /api/v1/import/preview (文件→预览验证)
- POST /api/v1/import/execute (确认导入)
## __init__.py + requirements.txt
- 注册 import 蓝图; 新增 pandas>=1.5.0
|
2026-07-16 14:00:28 +08:00 |
|
|
|
3290f206c6
|
perf: 导出OOM修复(yield_per流式) + 采购模糊匹配安全防护
## base_service.py export_excel
- query.all()全量→yield_per(2000)分块流式读取
- all_rows[]内存收集→write_only=True直写Excel
- all_rows.sort()→ORDER BY数据库排序
- 删除~160行旧Excel样式/脱敏死代码
- 内存: 全量→2000行分块+输出流
## purchase_service.py
- 模糊匹配安全防护:
len(n.strip())>=2 过滤空格/单字符
.limit(500) 防全表返回
|
2026-07-16 13:08:45 +08:00 |
|
|
|
e313f575bf
|
perf: 系统级异步邮件 — 消除SMTP阻塞导致的10-15秒UI冻结
## email_service.py
- 新增 send_email_async(): threading.Thread(daemon=True) 包装 send_email()
无需 Flask app_context (send_email仅用os.getenv+smtplib)
- 6处 send_email→send_email_async 替换
## inventory_task.py
- 库存预警 send_email→send_email_async (2处)
|
2026-07-16 11:26:12 +08:00 |
|
|
|
128985af17
|
feat: 采购模块重构 — 权限驱动的可见性 + 严格操作权限
## purchase.py
- GET /purchase (列表): @jwt_required, 有权限看同公司全部/无权限只看自己
- POST /purchase (创建): @jwt_required, 任何登录用户可提交
- GET /purchase/<id> (详情): @jwt_required, 自己的或有权者可见
- PATCH /purchase/<id>/approve (审批): @permission_required('inbound_purchase:operation')
不再硬编码 SUPERVISOR 角色, 有操作权限即可审批
- GET /purchase/approvers, /auto-fill, /search-material: @jwt_required (开放给创建流程)
- 新增 _user_has_purchase_perm() 统一权限检查
- 移除所有硬编码 role in ('SUPERVISOR','SUPER_ADMIN')
## purchase_service.py
- send_email → send_email_async (采购审批邮件异步发送)
## purchase/index.vue
- canApprove: 仅检查 inbound_purchase:operation (菜单权限≠审批权限)
- customUpload: 修复 v-model:file-list 重复推入导致图片双份显示
- auth.py → purchase.py 权限前缀统一
|
2026-07-16 11:25:53 +08:00 |
|
|
|
0b75740ae0
|
feat: 权限系统重构 — 操作权限双向展开 + 启动时自动补全默认权限
## permission_service.py
- init_all_menus: menu_defs 新增 inbound_purchase(采购申请) 菜单项
- init_all_menus: 创建 inbound_purchase:operation 操作元素
- 新增 ensure_default_permissions(): 启动时从 sys_user 提取活跃角色,
对空权限角色自动补全默认菜单(按角色类型分级)
- 自动迁移: 已有 inbound_buy 权限的角色 → 自动获得 inbound_purchase
- SUPERVISOR 启动时自动获得 inbound_purchase 菜单权限
## decorators.py
- _expand_operation_perms 改为双向桥接:
正向(inbound_buy:operation←inbound_buy:write)→通过
反向(inbound_buy←inbound_buy:operation)→通过(可编辑隐含可读)
- 新增详细诊断日志,记录展开路径和失败原因
## __init__.py
- 启动时调用 PermissionService.ensure_default_permissions()
|
2026-07-16 11:25:41 +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 |
|
|
|
4934cd4d8f
|
feat: 采购管理税率+分开单价总价列 + 按单出/借库锁定扫描 + 含税法计算
- purchase: 新增tax_rate字段(model+service+frontend), 表格拆分为不含税单价/总价/税率三列
- buy.vue: 含税法计算(含税总价=数量×含税单价), 含税总价自动计算可手动覆盖
- create.vue: 按单出库模式下未选审批单时锁定摄像头和SKU输入
- borrow.vue: 未选审批单时锁定摄像头和SKU输入
- deploy_production.sql: 整合全部数据库变更(表结构+权限码+角色分配)
|
2026-07-15 16:07:59 +08:00 |
|
|
|
9988d1b7eb
|
fix: 补全审计/出库审批/采购管理/借库审批的权限保护+公司隔离
- audit.py: 补@permission_required(system_audit)+import, 审计日志通过split_part关联用户表过滤公司
- outbound.py: 出库审批5个端点全补@permission_required(outbound_list)
- purchase.py: 采购管理7个端点全补@permission_required(inbound_buy)
- borrow_service: 借库审批列表通过applicant_id关联用户表过滤公司
- outbound_service: 出库审批列表通过applicant_id关联用户表过滤公司
- purchase_service: 采购列表通过base_id+requester_id双路过滤公司
- base_service/search_material: 去除debug日志
- decorators: 去除debug日志
|
2026-07-15 11:49:53 +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 |
|
|
|
a2a7e0125c
|
fix: SUPERVISOR不能修改/删除SUPER_ADMIN账号, 不能删自己
|
2026-07-15 09:22:58 +08:00 |
|
|
|
a11b7972c3
|
feat: 打通采购申请与入库的按单入库链路
后端变更:
- PurchaseRequest 新增 base_id 硬关联 MaterialBase,StockBuy 新增 request_id 关联采购单
- handle_inbound 支持 request_id 入参,入库后自动反写采购单状态为已完成
- 新增 get_approved_requests 接口,返回已审批未入库采购单列表(含物料信息+历史数据回退匹配)
- create_purchase_request 新增 name+spec_model 自动匹配 MaterialBase
- 新增 SQL 和 Alembic 数据库迁移脚本
前端变更:
- 入库表单新增"从采购单导入"弹窗,支持搜索/选中已审批采购单并一键填充物料和商务信息
- 单价/总价交叉推算,缺项自动补全
- 选中行蓝色高亮+点击整行选中,行级交互优化
|
2026-07-14 15:25:00 +08:00 |
|
|
|
a2f9a3e754
|
V3.54
|
2026-07-13 17:33:16 +08:00 |
|
|
|
760f78e016
|
feat: 添加参考价格列 + 修复公司筛选跨域问题 + CLIP模型持久化
## 新增功能
- material_base 表新增 reference_price 列(NUMERIC(10,2))
- 基础信息 list.vue / buyOdoo.vue 页面增加「参考价格」列展示和编辑
- 新增 material_list:referencePrice 权限元素,支持按角色控制可见性
## Bug 修复
- 入库三页面(buy/product/semi)公司筛选:非超管用户 company=ALL 不再传给旧版后端
- 基础信息两页面(list/buyOdoo):buyOdoo 增加 v-if=isSuperAdmin 与 list.vue 行为统一
- company=ALL 默认值在各页面 getList/fetchData 中自动过滤,兼容旧版后端
## 运维优化
- docker-compose.prod.yml 增加 models_prod 卷挂载,CLIP模型持久化免重复上传
- deploy_code.sh 增加 models_prod 目录检查与模型文件存在性告警
|
2026-07-13 17:30:52 +08:00 |
|
|
|
4f5965db02
|
feat: JWT多租户数据权限隔离 & 主管系统管理权限 & 含税单价补齐
## 多租户公司数据隔离
- 新增 get_current_company_filter() 工具函数 (decorators.py)
SUPER_ADMIN: 可传company_name参数过滤或传ALL看全量
其他角色: 强制隔离到JWT中的company_name
- 重构 base_service.py / buy_service.py: 用集中式函数替换内联公司过滤
- SysRolePermission 表新增 company_name 字段,支持同角色不同公司权限
- get_user_permissions() 新增 company_name 参数,查公司定制+全局模板权限
- permission.py API 新增 @permission_required 拦截 + 公司过滤
- 19个API/service文件传递 company_name 到权限查询
## 主管系统管理权限
- delete_user() 允许SUPERVISOR删除同公司用户 (原仅SUPER_ADMIN)
- get_all_users() 新增 company_name 参数过滤
- 用户列表/权限分配 API 应用 get_current_company_filter()
- 前端 UserCreate.vue: 超管可见公司下拉框,主管隐藏部门字段
## 前端多租户适配
- material/list.vue / buy.vue: 公司下拉框仅超管可见,默认ALL
- UserCreate.vue: 新增搜索栏公司筛选,部门字段按角色显隐
- auth.ts: getUserList() 支持 params 参数
## Bug修复: 含税单价字段补齐
- buy.vue: 表格列/高级筛选/排序/权限映射新增 post_tax_unit_price
- buy_service.py: allowed_fields/sort_field_map 新增 post_tax_unit_price
|
2026-07-13 15:12:22 +08:00 |
|
|
|
ffafa635bb
|
feat: 将产品图/说明书备注字段从JSON数组中分离为独立数据库列
- 数据库新增 product_image_remark 和 manual_link_remark 两个TEXT列
- 备注文字不再与上传文件URL混存在 generalImage/generalManual JSON数组中
- 前端输入框改为textarea,绑定独立的备注字段
- 修复 handlePasteLink 忽略field参数的bug
- 新增 isInternalFile 辅助函数,用于区分上传文件与纯文本
- 同步修改 list.vue 和 buyOdoo.vue 两个页面
|
2026-07-10 10:52:23 +08:00 |
|
|
|
c1092407ad
|
V3.50
|
2026-06-25 15:21:43 +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 |
|
|
|
5c0c1632c3
|
fix(审批邮件): items_json序列化Bug修复 + 邮件方法出库/借库物理隔离
|
2026-06-12 15:04:57 +08:00 |
|
|
|
7ef22a3830
|
feat(借库审批流): 完整前后端实现
|
2026-06-12 14:08:19 +08:00 |
|