Commit Graph

27 Commits

Author SHA1 Message Date
fe54d01391 fix(outbound): 序列号物料出库被误判超出计划数量
现象:申请单里同一个物料有 2 个,扫第 2 个时报
「超出计划数量(计划: 1,已扫: 1,本次: 1)」。

根因:计划侧与已扫侧用了**不同的聚合方式**。
  已扫侧 .filter().reduce()  → 把【所有】匹配行加总
  计划侧 .find()             → 只取【第一条】匹配行
序列号物料在申请单里是「一物一行、每行 quantity=1」(因为每个序列号对应
一条独立库存行),于是 planQty 只拿到 1,而 alreadyScanned 是全部之和,
1 + 1 > 1 直接判超发。普通数量制物料计划单只有一行,两边一致,所以一直
没暴露 —— 只有序列号物料会踩中。

同一缺陷还有第二处:unscannedList 逐行比较 planQty 与「累计已扫」,
导致两行各自都被同一笔扫码"满足",扫 1 个就把整个物料判为扫完、未扫清单漏报。

修复:
- validateAgainstPlan:计划侧改为 .filter().reduce() 汇总所有匹配行
- unscannedList:先按「名称+规格」合并计划行,再与同口径汇总的已扫数比较

用申请单 410(Opt1025 两行各 1 个)的真实数据模拟验证:
  修复前 扫第2个 → 超出计划数量(计划:1,已扫:1,本次:1)  ← 与现场报错逐字一致
  修复后 扫第2个 → 通过
  修复后 扫第3个 → 仍被拦(计划:2,已扫:2,本次:1),超发保护未失效
2026-09-15 13:21:36 +08:00
b313fefdfa fix(web): 扫码页与备选库位带单据ID,按有效可用量限流
配合后端预占回加:扫码/借库/审批页面调用 /outbound/scan 与 /outbound/alternatives
时带上本单 id 与 biz_type,拿到的 available_quantity 即为「实时可用量 + 本单
预占」,本单锁定的行不会再因实时可用量为 0 而被拦住或从列表消失。

后端已在响应边界完成归一化,故前端模板与校验逻辑(:max、库存列展示、超量
警告、草稿存取)一律不动,只多传参数 —— 避免把同一语义散落到多个读写点。

- api/outbound.ts:getStockByBarcode / getStockAlternatives 加 requestId 与
  bizType 参数,导出 ScanBizType,ScanResult 补 reserved_quantity 等字段
- api/transaction.ts:同名的历史副本同步签名(当前无调用方,加注释指向唯一来源)
- views/outbound/create.vue、views/transaction/borrow.vue:各 3 处调用点带上
  单据 id;refreshStockFromDraft 改为显式透传 id,不依赖 computed 已解析
- views/borrow/approval/index.vue:审批页也带上本单 id,否则待审批单
  (预占已生效)锁定的行会因实时可用量为 0 而从备选列表消失

借库侧 request_id 是 BorrowApproval.id,靠 biz_type='borrow' 与出库单区分 ——
两张表 ID 空间独立,不可省。
2026-09-11 10:34:23 +08:00
ce767e39ac feat(scan): 扫码时检测单据失效,避免白扫一场
场景
----
库管正在扫码,这张单被撤回/驳回/执行了。若不检测,库管会一直扫到
提交时才发现单据已作废(后端会拒绝),前面的工作白做。

实现
----
新增 checkRequestStillValid():重新拉一次「已通过(status=1)」列表,
看当前单据是否还在其中。不在 → 已被撤回/驳回/执行,立即弹窗告知并
清空界面(草稿后端也已同步清除)。复用现有列表接口,无需新增端点。

触发时机(覆盖两类场景):
  · 页面重新可见时(visibilitychange)—— PDA 熄屏唤醒、切回标签页
  · 每 60 秒一次 —— 库管一直在页面上扫、没切走

三点取舍:
  · 仅购物车非空时检测(正在作业才打扰),空清单不发请求;
  · 60 秒轮询而非实时推送 —— 引入 WebSocket 长连接成本过高,
    此处最多浪费 1 分钟扫码,相比"扫完几十分钟才发现"已足够;
  · 检测失败不阻断作业(仅 console.warn)—— 后端提交时仍会做最终校验,
    前端检测是为了早发现,不是安全防线。

出库 create.vue 与借库 borrow.vue 两页同款实现。
2026-09-11 09:06:51 +08:00
a4a9afb6db feat(scan): 出库/借库扫码页接入草稿,切换单据不清空
交互
----
无需「暂停」按钮 —— 在下拉框切换单据这个动作本身就是暂停:
  切走 → 自动存当前单据的进度
  切回 → 自动恢复,并提示「已恢复上次的扫码进度(N 项)」
下拉框对扫到一半的单据显示橙色「已扫 N」徽标,不必逐个点开试。
提交成功后自动清除该单据的草稿。

修复的三个 bug
--------------
1) 切换时把 A 的内容存到了 B 名下
   v-model="selectedRequestId" 的 computed setter 会**先于** @change 把
   selectedRequest 改成新单,故 handleRequestChange 里读到的是新单。
   新增 activeRequestId ref 记录「界面上真正显示的是哪张单」,
   保存时显式传入离开的那张单的 ID。

2) 切回时把目标单的旧草稿删了
   原先写了「购物车为空则清除草稿」,但切换瞬间购物车必然为空,
   于是切回 A 时触发了清除。现改为空清单只跳过保存、不清除;
   清理由「提交成功」或「用户点清空列表」显式触发。

3) 恢复后名称/规格为空、出库数显示 NaN
   draftPayload 只存了 4 个字段(stock_id/source_table/sku/quantity),
   而购物车表格绑定的是 name/spec_model/available_quantity/out_quantity
   —— 全都没存。现保存完整快照,并在恢复时归一化
   (out_quantity ?? quantity)以兼容已存在的旧草稿。

补充:恢复后刷新实时库存
------------------------
草稿里的 available_quantity 是扫描那一刻的快照,跨时间恢复可能已过期
(期间别人出库/借出会消耗可用量)。恢复后复用 /alternatives 端点拉一次
实时可用量:数量超了会明确提示「N 项物料的实际库存已少于你扫的数量」,
避免工人扫满后到提交时才被后端拒绝。失败不阻断,沿用草稿快照。

另:离开页面(路由跳转)时存草稿并弹确认;beforeunload 用 sendBeacon
尽力保存(该路径无法带 Authorization 头,可能失败,但防抖保存已覆盖
绝大部分内容)。
2026-09-10 17:21:24 +08:00
ea52c78f9e feat(outbound): 计划出库清单数量前置,移除类型列
问题
----
计划出库清单的「计划数量」列排在表格最右侧(名称/规格/库位之后)。
表格共 6 列且名称规格会撑宽,最右列容易被容器裁掉,工人反馈"看不见数量"。

改动
----
· 「计划数量」从最右移到「序号」之后,橙色加粗 + 字号放大到 15px;
· 移除「类型」列(material_type);
· 库位列宽 150 → 170。

注:该列一直存在且数据正常(items_json 的 quantity 字段),
此前是可见性问题而非数据缺失。
2026-09-10 15:57:20 +08:00
209b29c10f feat(outbound): 备选库位可见性,让「物理覆盖」不再盲扫
问题
----
预占会把货锁定在某个库位,但工人到现场可能进不去/找不到该库位,
需要改扫同物料的其它批次。后端执行端已支持按 base_id 校验、允许换批次,
但系统从不告诉他「还有哪些库位有货」—— 工人只能凭记忆或挨个翻。

后端:新增 GET /api/v1/outbound/alternatives
--------------------------------------------
  入参 base_id(必填)、source_table/stock_id(可选,用于标注推荐行)
  返回该物料全部可用库存行 + 合计可用量,推荐行置顶、其余按可用量降序。

为什么不复用 stock/list 或 bom-match-stock 的查询模式:
那两处按 stock_quantity > 0 过滤,会把「有货但已被别单全部预占」的库位
也列出来,工人跑过去才发现拿不到。实测库中有 14 行处于该状态。
本接口按 available_quantity > 0 过滤,只给真正能拿的库位。

前端:计划清单库位列加图标 + popover
------------------------------------
  [推荐] Y1/2/1  可用 5      ← 本单锁定行(来自 items_json 的 stock_id)
  [备选] Y2/3/4  可用 10
  [备选] Z1/1/1  可用 2

三处取舍:
  · trigger="click" 而非 hover —— 车间用扫码枪/触摸屏,hover 在触屏不可用
  · @show 时才发请求 —— 计划清单可能几十行,渲染即请求会打出一片并发
  · 附提示文案「现场取不到推荐库位时可直接扫备选库位条码出库」

注:历史单据的 items_json 无 stock_id,此时所有库位显示为「备选」
(不影响可用性,仅少了推荐标记);预占改造后新提交的单可正确标注。

实测:造 3 批次 Y1/2/1(5) Y2/3/4(10) Z1/1/1(2),预占首个后其 available=0,
接口正确排除该库位,返回两个备选、合计可用 12。
2026-09-10 14:59:17 +08:00
478b90fe50 feat: 出库类型贯穿申请→扫码出库——申请单加 outbound_type,申请时选类型、扫码出库自动带出 2026-09-07 14:01:13 +08:00
eaafeaf24e feat: 出库类型新增「维修出库(REPAIR)」下拉选项与记录类型/标签映射 2026-09-07 13:51:38 +08:00
f5aa2f481b feat(scan): 出库/借库扫码增加未扫清单弹窗
- 扫码进度条旁新增「未扫清单 (N)」按钮(有未扫满物料时显示)
- 弹窗列出计划中未扫满的物料:名称/规格/计划数量/已扫数量/待扫数量
- 提供「去扫码」快捷跳转,方便补扫漏掉的物料
- 未扫满 = 计划数量 > 已扫数量(含完全未扫和扫了一部分的情况)
2026-08-31 14:53:20 +08:00
e026c00a85 refactor(outbound): 移除扫码出库页的强制完结按钮
- 删除 create.vue 中「强制完结此单」按钮及对应逻辑
- 完结功能保留在出库审批列表页(approval/index.vue)
- 出库执行页聚焦扫码作业
2026-08-31 14:38:51 +08:00
e492000c3e feat(scan): 出库/借库扫码进度显示 + 重复扫码确认
- 出库 create.vue + 借库 borrow.vue 均增加扫码进度条
  显示: 已扫/总数 种 + 已扫/总数 件 + 进度百分比
- 重复扫码时不再直接 +1,改为弹窗确认「确认 +1 / 取消」
  防止手滑重复扫或误操作
- 扫码进度条选中审批单后显示
2026-08-31 14:35:26 +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
b6ec45a8b8 feat(outbound): 出库流程强化(缺料防漏 + 完全移除直接出库)
① BOM 清单 SKU 改为规格型号(getBomWithStock 返回 children 无 sku,只有 child_spec)
② 缺货清单自动写入出库申请备注(借鸡生蛋:历史欠料永久留存在申请单)
③ 打印单底部增加欠料待补签收区(补料人签字/日期)
④ 有缺料时阻断式二次确认,防手快漏看
⑤ 完全移除直接出库模式,所有出库必须按单出库
   - create.vue 删除 radio 切换、direct 相关逻辑
   - 提交前强制校验已选择审批申请单
2026-08-31 09:37:14 +08:00
9c0414b802 fix(outbound): 出库备注改为必填,按单出库自动填充申请原因
- 备注字段新增 required 校验规则
- placeholder 从「可选填」改为「请填写出库原因」
- 按单出库模式选择申请单后,自动将申请原因填入备注
2026-08-07 15:58:59 +08:00
5b1cd4d8d0 fix: 扫码出库类型改为必选,移除默认值SALES
- outbound_type 默认值: SALES → '' (空)
- el-select 新增 clearable
- rules 新增 outbound_type required 校验
2026-07-16 13:13:08 +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
DXC
62c0e3738e fix(outbound+trans): 修复POST接口错误数据清洗导致的sku/quantity字段被清除Bug,并新增出库审批工作流全链路 2026-04-28 16:02:34 +08:00
DXC
faea0379da refactor: replace transfer outbound type with production outbound across frontend and backend 2026-03-19 17:13:24 +08:00
dxc
29ab7432a3 修正,让调拨出库改为生产出库 2026-03-19 17:04:15 +08:00
DXC
6cc3d1b6e0 feat: upgrade adjustment workflow to require explicit inbound SKU or outbound tracking number and fix UTC timezone issue 2026-03-19 15:26:40 +08:00
dxc
3714dd180b feat: apply RBAC read/write separation to outbound_create module
Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
2026-02-27 13:54:06 +08:00
dxc
fdf22b9973 修改条形码为二维码,同时对于扫码展示部分进行修改 2026-02-09 14:48:09 +08:00
dxc
489e62e55b 摄像头逻辑进行修改,更改分辨率进行快速的读取识别 2026-02-06 11:28:48 +08:00
dxc
c1ddb8093f 出库进行修改,确保可以进行多个样例的出库以及出库的记录展示 2026-02-05 16:54:11 +08:00
dxc
3f6ab3e607 修改出库签名逻辑,对签字进行单独屏幕 2026-02-05 15:51:19 +08:00
dxc
f3b60dfc54 出库操作逻辑上面实现,成功跑通 2026-02-05 10:20:52 +08:00
dxc
797b611530 出库逻辑添加,扫码识别编码成功,后续对应逻辑没有完成 2026-02-04 17:22:20 +08:00