feat(return): 逆向物流数据模型与迁移
新增原单退回与不良品在管的持久化结构。
- TransOutbound 增 returned_quantity(numeric(19,4),非 float):该值参与
「return_qty <= quantity - returned_quantity」判等,浮点误差会让反复部分
退回后出现「已退满却判定未退满」的错判
- 新增 TransReturn:退回流水,每次退回写一条而非覆盖式更新。刻意与
trans_borrow 划清界限——后者部分归还时会覆盖 return_time/operator,
导致归还历史永久丢失
- 新增 TransDefectiveGoods:不良品在管台账。坏件全程不入库存表,因为
status 是行级属性而质量是件级属性,把坏件加回原行只能整行打不良
(实测 stock_buy 单行最大 4789 件、中位 8 件,整行打不良会凭空损失良品)
- 状态机:待处理 → 处理中 → {已回库|已报废|已闭环}。终态由累计去向推导
而非「最后一次动作」——一批坏件可能既回库过又报废过,按最后动作定状态
会产生误导
- restocked_qty/scrapped_qty 两列:二期用 quantity-remaining_qty 反推回库量,
三期加入报废出口后该反推失效
- 审计白名单与模型预加载同步登记(监听器绑定 18 → 20 个模型)
迁移脚本均为纯追加式 DDL,含预检、回滚段与执行后核对。首个脚本用
COALESCE 包裹数量列——库存表允许数量为 NULL,而「NULL 大于 0」求值为
NULL 而非真,裸写会让脏行在预览与诊断两次查询里凭空消失。
This commit is contained in:
@ -139,16 +139,28 @@ class TransOutbound(db.Model):
|
||||
# [新增] 出库时的库位快照(从源库存记录带出,便于历史追溯)
|
||||
warehouse_location = db.Column(db.String(100))
|
||||
|
||||
# [新增] 累计已退回数量(良品 + 不良品口径合并),用于原单退回的额度校验。
|
||||
# ★ 用 numeric(19,4) 而非 float:本系统所有数量列一律 numeric(19,4),
|
||||
# 且该值要参与 `return_qty <= quantity - returned_quantity` 的判等比较,
|
||||
# 浮点误差会让反复部分退回后出现「已退满却判定未退满」的错判。
|
||||
# DDL 见 db_migrations/phase2_return_and_defective_goods.sql
|
||||
returned_quantity = db.Column(db.Numeric(19, 4), nullable=False, default=0)
|
||||
|
||||
remark = db.Column(db.Text)
|
||||
|
||||
def to_dict(self):
|
||||
qty = float(self.quantity) if self.quantity else 0
|
||||
returned = float(self.returned_quantity) if self.returned_quantity is not None else 0
|
||||
return {
|
||||
'id': self.id,
|
||||
'outbound_no': self.outbound_no,
|
||||
'sku': self.sku,
|
||||
'source_table': self.source_table,
|
||||
'outbound_type': self.outbound_type,
|
||||
'quantity': float(self.quantity) if self.quantity else 0,
|
||||
'quantity': qty,
|
||||
# [新增] 退回额度三件套,供前端判断该明细还能退多少
|
||||
'returned_quantity': returned,
|
||||
'returnable_quantity': qty - returned,
|
||||
'unit_price': float(self.unit_price) if self.unit_price else 0,
|
||||
'consumer_name': self.consumer_name,
|
||||
'signature_path': self.signature_path,
|
||||
|
||||
Reference in New Issue
Block a user