ed351f96ec
refactor(scrap): 按单执行校验改用 SKU 主键匹配
...
架构要求以 SKU 为唯一校验键,原实现按 (source_table, stock_id) 匹配。
已核验数据前提:SKU 在同一库存表内唯一(0 重复),且不存在跨表重名
(stock_buy / stock_semi / stock_product 交叉 0 冲突),故 SKU 可安全
作为跨来源标识。
改动:
· 新增 _match_key():SKU 非空时以 'sku:<SKU>' 为键;个别历史库存行
SKU 为空,回退 'row:<table>#<id>',前缀区分确保绝不串键;
· _build_approved_index() 按 SKU 聚合,累加批准量并保留各行的
source_table + stock_id(rows 列表);
· 校验拆为两步并给出明确文案:SKU 是否在批准明细内、同 SKU 累计量
是否超批准量;
· ★ 扣减改为按批准单配对的 source_table + stock_id 定位库存行加锁,
不再信任前端传来的 stock_id —— 实测前端传伪造 stock_id=99999 时,
仍从批准单指定的库存行扣减,台账同样记录批准单的 stock_id;
· 同一 SKU 在批准单占多行时,按批准顺序依次分配扣减量。
实测 7 项校验用例 + 多行分配 / 批准行已删除 / 可用不足 均符合预期。
2026-09-10 10:21:50 +08:00
7719943779
feat(scrap): 报废执行改为按单扫码校验,废弃盲执行
...
execute() 原先只吃 request_id,按申请单快照全量扣减,用户反馈「扫码与报废脱节」。
现改为接收实扫明细 scanned_items:
· 强制按单:未提交实扫明细一律拒绝执行;
· 键为 (source_table, stock_id),与申请单 items_json 同口径,
同一物品多次扫码自动累加,兼容「逐件扫」与「输数量」两种操作;
· 校验实扫项必须落在批准明细内,且累计量不得超批准量,否则整单拒绝;
· 允许合法子集(少扫 = 本次不报废该行);
· 扣减以实扫量为准,同时扣 available_quantity 与 stock_quantity
(报废即实物销毁,上一版只扣可用库存会让总库存虚挂)。
接口 POST /scrap/request/<id>/execute 由无 body 改为接收 {items:[...]}。
2026-09-10 10:14:40 +08:00
b4b79c68a9
fix(borrow): 借库转报废实物不足时报错回滚,不再夹断到 0
...
原逻辑在 stock_quantity 减为负数时直接置 0。但借出时已扣减过
available_quantity,夹断会使 available_quantity > stock_quantity,
凭空多出可用库存,后续出库/借库可继续占用这批并不存在的实物。
改为不足即抛 ValueError,与同一事务内其余校验一致,整单回滚。
2026-09-10 10:14:36 +08:00
8755837fe8
fix(timezone): 审批单据时间统一为 naive 北京时间,消除 8 小时偏差
...
成因:approved_at / executed_at 列是 timestamp without time zone,而赋值用了
带时区的 datetime.now(timezone(timedelta(hours=8)))。psycopg2 对 naive 列不会
剥掉 tzinfo,而是转成 naive UTC 再写入,结果比同为北京时间的 created_at 早 8 小时。
(代码里并无 datetime.utcnow(),真实成因是 aware 值被驱动的隐式 UTC 转换。)
改动:
· outbound_service / borrow_service 的审批分支
datetime.now(beijing_tz).replace(tzinfo=None) → beijing_time()
(免审批分支已在上一轮改为 beijing_time,此处补齐审批分支);
· purchase_service 审批/完结分支同源缺陷一并修复;
· scrap_approval / scrap_approval_service 的 _beijing()、_beijing_now() 由
tz-aware 改为 naive —— 配合上述迁移把列类型改为 naive,
若仍返回 aware 值,timestamptz→timestamp 后会反向早 8 小时。
实测四表(scrap/outbound/borrow/purchase)created_at 与 approved_at 差值
均在同一秒内(-1ms ~ -12ms)。
2026-09-10 10:14:31 +08:00
8b61cdb67d
fix(approval): 需审批判定改为 base_id → SKU → 名称+规格 三级降级
...
原判定仅有 base_id 与「名称+规格字符串」两级,出库申请明细只有 name/spec、
无 base_id,只能走脆弱的字符串匹配,同名或同规格不同料极易误判。
新增 SKU 优先级:material_base 表本身没有 sku 列,SKU 只存在于
stock_buy / stock_semi / stock_product,故经明细自带 source_table 反查
sku → base_id 再回查物料,查不到才依次降级其余两张库存表。
查到物料即定论,不再往下走字符串兜底,杜绝误杀。
2026-09-10 10:14:17 +08:00
98e657e289
fix(scrap): TransScrap 补 scrap_request_no 列映射
...
报废执行写台账时以关键字传入 scrap_request_no,但该列只存在于 DB
(db_migrations/add_scrap_approval.sql)而未在 ORM 声明,执行报废必然抛
TypeError: 'scrap_request_no' is an invalid keyword argument for TransScrap,
被 500 捕获后连同库存扣减一起回滚,整条按单报废链路不可用。
2026-09-10 10:14:14 +08:00
1dbf74b7bc
feat(borrow): 借库审批补「完结」能力(对齐出库 status=4)
...
- mark_completed 改为 1→4 已完结(真正扫码借出完成仍为 status=3)
- 前端审批页新增「已完结」筛选项与状态映射;审批信息列对 3/4 显示审批人
2026-09-10 09:47:07 +08:00
ffbb2199f0
feat(scrap): 报废申请审批流 + 按单报废(后端)
...
- ScrapApproval 模型 + ScrapApprovalService:提交/列表/审批/执行(锁库存扣 available_quantity 写 TransScrap)
- 新路由 POST /scrap/request、/request/check-approval、GET /request、PATCH /request/<id>/approve、POST /request/<id>/execute;权限码 scrap_apply/scrap_approval/scrap_execute(无角色硬编码)
- 旧 /scrap 直接报废入口保持不变
- /inbound/stock/list 每项返回 source_table,供按单流程精准选库存
2026-09-10 09:46:57 +08:00
044e6dbd98
feat(borrow,outbound): 库管(WAREHOUSE_MGR)代建申请强制审批
...
- submit/create 新增 force_approval:库管建单无视物料是否需审批,一律走审批
- 路由按当前角色为 WAREHOUSE_MGR 传 true;未选审批人返回明确业务错误
2026-09-09 16:19:38 +08:00
cd600f9fc2
fix(auth): 审批人列表按公司收窄——本公司主管 + 所有超管
...
- get_approvers:普通/主管仅见 department=本人公司 的 SUPERVISOR 与全部 SUPER_ADMIN;超管本人不受限
2026-09-09 15:23:51 +08:00
2a9e2e4560
fix(bom): BOM 三态互斥 + active_only排除归档 + 详情主备注
...
- get_bom_list active_only 补 is_archived==False,出库/借库“按BOM套餐”不再泄漏归档版本
- get_bom_detail 返回顶层 remark,详情弹窗主备注可回显
- 状态互斥:update_enabled 切启/停即清归档;update_archived 归档→废弃(enabled=False)、取消归档→启用;停用视图排除归档
2026-09-09 13:00:41 +08:00
eff9b62224
fix(borrow,outbound): 普通用户记录只看本人——按领用人/借用人姓名(不含账号前缀)匹配
...
- 出库记录/借还记录:非管理者视角时按 领用人(consumer_name)/借用人(borrower_name) 过滤
- 匹配取登录名 username.split(/)[0] 的姓名;兼容库里存“姓名/xiaolongxia”全名(姓名+/前缀)
- 修复:管理员替员工创建、领用人=员工 的单,员工登录可见
2026-09-09 11:19:15 +08:00
67d3113fe1
fix(permission): 记录管理者视角仅超管/主管/仓库管理员,去掉入库员/出库员
...
- PRIVILEGED_VIEWER_ROLES 收敛为 SUPER_ADMIN/SUPERVISOR/WAREHOUSE_MGR
- 入库员(INBOUND)、出库员(OUTBOUND)按普通处理:借还/出库记录只看自己
2026-09-09 11:19:09 +08:00
aa9322bcbc
feat(borrow): 借库申请后端必填校验——申请原因、预计归还日期(长期借用除外)
...
- submit_approval 校验:申请原因非空;未勾长期借用时必须有 expected_return_time,否则 ValueError 拦截
2026-09-09 10:53:12 +08:00
4146f35010
feat(permission): “出库/借库需审批”开关权限化——仅主管/超管可见可改
...
- 新增权限码 material_list:isApprovalRequired,授予仅 SUPER_ADMIN/SUPERVISOR(收回其它角色)
- 物料列表该列仅持码角色可见;后端批量端点与字段脱敏均改按新码校验,其余角色看不到值也无法改
2026-09-09 10:47:36 +08:00
6bdc8a82f2
feat(borrow,outbound): 申请预检按需显示审批人——默认不显示,命中需审批才出现并必选
...
- 后端新增 /borrow/request/check-approval 与 /outbound/request/check-approval 预检接口
- 申请弹窗默认隐藏审批人;提交前预检:命中需审批→显示审批人并红字列物料、未选拦截;未命中→隐藏并直接提交(approver=null)
- 申请 items 补传 base_id 供后端 ID 精确判定
2026-09-09 10:47:29 +08:00
d06ce45a72
feat(borrow,outbound): 需审批判定收敛——ID优先 + 名称精确AND核心规格(斜杠前段)
...
- approval_control 重写:带 base_id 按主键绝对判定;无 id 才名称100%一致 AND 核心规格(_code_of)一致兜底,杜绝同名不同规误杀
- 借/出库服务命中需审批但未选审批人时,报错列出需审批物料名/规格
2026-09-09 10:47:24 +08:00
4cd3eefdf4
feat(borrow,outbound): 默认免审批改造——命中物料需审批才走原流程
...
- models/base.py 加 is_approval_required 列及 isApprovalRequired 序列化;field_permissions 登记
- 新增 POST /inbound/base/batch-approval(批量设需审批,仿批量质检)
- borrow_service.submit_approval / outbound_service.create_request:明细含需审批物料→须选审批人走原审批;否则创建即 status=1(待库管执行)、不发审批邮件
- 判定按 (name,spec_model) 反查启用物料
2026-09-09 09:31:18 +08:00
9622baf76e
fix(borrow,outbound): 记录查看按角色收窄——普通只看自己,库管/主管/超管/跨域看全部
...
- decorators 新增 is_privileged_viewer(SUPER_ADMIN/SUPERVISOR/WAREHOUSE_MGR 或 crossDomain)
- 借库记录列表:非管理者强制 applicant_id=当前用户
- 出库记录列表+详情:非管理者强制只看自己/无权访问他人单(403)
2026-09-09 09:31:01 +08:00
2b0e335790
fix(inbound/buy): 批号自增改为按物料精准取最近一条
...
- 新增 get_latest_batch_record_by_base_id:SQL 直接 filter(base_id)+order by in_date/id desc first(),O(1) 不分页
- 新增 GET /inbound/buy/latest-record
- 修复原“拉全表前1000条再前端过滤”导致的历史被截断→批号退回000001/重复入库被拦(如 CCAB0029)
2026-09-08 18:16:04 +08:00
66b3e4897f
fix(bom): get_bom_summary 关键词与 list 对齐 + 状态更新方法健壮化
...
- get_bom_summary 关键词过滤改为与 get_bom_list 同款子查询(同时匹配 bom_no、父件名/规格、子件名/规格),任意关键词下 summary 计数与 list 明细严格一致,消除“标题有数、表格为空”
- update_enabled/update_archived 对 bom_no/version 做 strip 规范化,并细化“BOM不存在”报错(带上实际参数便于排查)
2026-09-08 13:58:43 +08:00
02f74278df
feat(bom): 归档业务闭环——状态筛选+归档/取消归档入口
...
- get_bom_list/get_bom_summary 状态过滤支持 archived,enabled 语义改为“启用且未归档”
- get_bom_list 输出补 is_archived;新增 update_archived 与 POST /bom/archive(整组切换归档、清缓存、审计)
- “未指定版本自动取最新”硬化为仅认启用且未归档(get_bom_detail / get_bom_no_by_parent)
- 前端:状态按钮组加“归档”;列表状态列区分归档;操作列加“归档/取消归档”按钮
2026-09-08 11:13:38 +08:00
91fb6c1a03
feat(bom): 自制件子件选版本落库/强校验 + 独立启停 + 状态筛选
...
- save_bom 落库 child_bom_no/child_bom_version;自制件必选且须属于启用未归档配方集,外购件置空;跨版本查重纳入引用版本
- get_bom_detail 改为读存储列,空则回退最新启用配方;候选/校验/回退读取均排除 is_archived
- 新增 GET /bom/self-bom-versions(子件候选版本);新增 POST /bom/status 独立启停(update_enabled 清缓存)
- 草稿链路 save_draft/get_draft_detail/publish 持久化引用版本
- get_bom_list/get_bom_summary 支持 status(enabled/disabled) 过滤
2026-09-08 10:14:44 +08:00
3dd8458de0
feat: BOM 子件展示自制件 BOM 版本号——子件列表与出库/借库 BOM 清单打印均显示
2026-09-07 18:01:16 +08:00
220f73acbd
feat: 首页全局搜索支持按 SKU 查库位——采购/半成品/成品库存纳入搜索并显示库位
2026-09-07 15:47:25 +08:00
478b90fe50
feat: 出库类型贯穿申请→扫码出库——申请单加 outbound_type,申请时选类型、扫码出库自动带出
2026-09-07 14:01:13 +08:00
73510d3a71
feat: 借还记录默认排序重构——有限期单按预计归还时间升序靠前,无限期单按借出时间升序靠后(优先关注快到期/逾期)
2026-09-04 16:17:42 +08:00
b274ed1ed1
feat: TransBorrow 归还人 to_dict 自动把数字 user id 映射为用户名(历史记录不再显示数字,lru_cache 防 N+1)
2026-09-04 16:12:36 +08:00
02f36b383c
fix: 借库归还/报废/借库执行操作人由 JWT 数字 ID 改为用户名(归还人不再显示数字)
2026-09-04 16:10:00 +08:00
808e491fe8
fix: BOM 匹配库存(bom_match_stock)加行级公司隔离(三表按 base 公司过滤,超管/跨域不受限)
2026-09-04 15:57:14 +08:00
b40aa3ab90
fix: 出库选单手动添加库存(/v1/inbound/stock/list)加行级公司隔离(三表按 base 公司过滤,超管/跨域不受限)
2026-09-04 15:55:24 +08:00
2f6027b43c
fix: 采购列表字段过滤后补回 base_id,恢复前端批号自动叠加(与 semi 列表一致,修 LICA 同物料二次入库拦截)
2026-09-04 15:33:17 +08:00
b6ecde11dd
refactor: warehouse/tree 移除临时打点日志,保留 O(N) build_tree 优化
2026-09-04 15:19:00 +08:00
7e3fc11bf5
chore: warehouse/tree 接口加 3 阶段耗时打点日志(查库/build_tree/序列化)
2026-09-04 15:16:20 +08:00
bc6e97ae97
perf: warehouse build_tree 改为 Map 分组内存组装,消除 O(N²) 递归全扫(tree TTFB 1.7s→0.08s)
2026-09-04 15:10:38 +08:00
3bd19c1ab5
feat: 借库审批支持手动完结——已通过(status=1)单可强制完结,库管/主管/超管可见
2026-09-04 14:52:31 +08:00
0daf50ac21
fix: 成品/半成品/维修列表第二层跨域判断补认 crossDomain(解决库管配跨域仍看不到双边)
2026-09-04 13:01:44 +08:00
1527d552d4
feat: 出库/借库记录记录并展示库位快照(DB加列+后端写入+记录页展示)
2026-09-04 11:42:44 +08:00
7cdc0bc3a1
perf: 库位选择器改为按需懒加载——新增 /warehouse/children 接口,WarehouseSelector 移除全量树依赖
2026-09-04 10:51:49 +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
3cb9b0da98
chore: 添加 httpx 依赖(Track Webhook 通知);gitignore 忽略根目录 .env 防密钥入库
2026-09-02 18:39:17 +08:00
bf7b2cc6d3
feat: BOM 库存接口支持按版本查询,修复同一编号多版本下拉回显错乱
2026-09-02 18:39:17 +08:00
85130db6ea
perf: Docker 构建使用清华镜像源并启用 BuildKit pip 缓存挂载,大幅加速重复构建
2026-09-02 18:39:09 +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
4e09860b36
feat: 采购申请完结功能移到批次主行,与出库审批一致
...
- 移除展开行内的单条完结按钮(需点开),改为主行'完结本批'直接可见
- 后端 batch-approve 支持 action=close(批次内已通过→已完结)
- 超管/库管在主行操作列即可看到并完结
2026-09-01 16:21:48 +08:00
fbb4160787
feat: 采购申请新增库管'完结'功能(仿出库审批)
...
- 后端:approve 接口支持 action=close(已通过→已完结 status 1→4),模型 status_text 支持已完结
- 前端:采购申请状态tab加'已完结',已通过单显示'完结'按钮(库管)
2026-09-01 16:15:48 +08:00
a2d3a2c43a
fix: 半成品列表字段权限过滤后补回 base_id,修复批号自增失效
...
- get_list 的 apply_strict_rbac 剥离 base_id,导致前端 checkHistoryAndSetMode 无法按物料匹配历史
- 过滤后补回 base_id,扫码/选物料联动时批号能按历史正确自增(如 000002 → 000003)
2026-09-01 16:08:27 +08:00