feat: 多工厂/厂间调拨/替代料/流水台账折叠 + 重写 README
- 多工厂(factory 表) + 顶栏工厂下拉过滤, 库存按厂聚合 - 厂间调拨(transfer): 源厂减+目标厂加, 总库存不变, 双向流水对账 - 替代料关系(substitute): 出库/BOM领料/生产领料缺料时提示可替代料 - 流水台账(ledger): 入出按日期合并折叠, 按日期导出同一 Excel - 生产订单增强: 编辑/删除(级联清关联流水)/调入数量/确认调入=厂间调拨 - 入库新增送货日期字段; 出库物料编码扫码定位 - 重写 README 补全全部模块; .gitignore 排除 dist_pkg/build_pkg/*.db - 停止跟踪 instance/app.db(运行时自动生成)
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
import os
|
||||
from datetime import datetime, date
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from sqlalchemy import UniqueConstraint
|
||||
|
||||
db = SQLAlchemy()
|
||||
|
||||
@@ -44,10 +45,12 @@ class Inbound(db.Model):
|
||||
__tablename__ = "inbound"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
material_id = db.Column(db.Integer, db.ForeignKey("material.id"), nullable=False, index=True)
|
||||
factory_id = db.Column(db.Integer, db.ForeignKey("factory.id"), nullable=True, index=True) # 所属工厂/仓库
|
||||
batch_no = db.Column(db.String(64), default="") # 批次号
|
||||
qty = db.Column(db.Float, nullable=False) # 入库数量(正)
|
||||
operator = db.Column(db.String(64), default="") # 经手人
|
||||
source = db.Column(db.String(255), default="") # 来源 / 供应商
|
||||
order_ref = db.Column(db.String(64), default="") # 关联生产单号 / 调拨单号
|
||||
occur_date = db.Column(db.Date, default=date.today)
|
||||
delivery_date = db.Column(db.Date, default=None) # 送货日期(供应商到货日, 可空)
|
||||
remark = db.Column(db.String(255), default="")
|
||||
@@ -58,6 +61,7 @@ class Outbound(db.Model):
|
||||
__tablename__ = "outbound"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
material_id = db.Column(db.Integer, db.ForeignKey("material.id"), nullable=False, index=True)
|
||||
factory_id = db.Column(db.Integer, db.ForeignKey("factory.id"), nullable=True, index=True) # 所属工厂/仓库
|
||||
batch_no = db.Column(db.String(64), default="") # 批次号
|
||||
qty = db.Column(db.Float, nullable=False) # 出库数量(正)
|
||||
operator = db.Column(db.String(64), default="") # 经手人
|
||||
@@ -91,6 +95,7 @@ class ProdOrder(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
order_no = db.Column(db.String(64), unique=True, nullable=False, index=True)
|
||||
bom_id = db.Column(db.Integer, db.ForeignKey("bom.id"), nullable=False, index=True)
|
||||
factory_id = db.Column(db.Integer, db.ForeignKey("factory.id"), nullable=True, index=True) # 生产工厂/车间
|
||||
qty = db.Column(db.Float, nullable=False, default=0) # 接单量(台/套)
|
||||
status = db.Column(db.String(32), default="planned") # planned / picked / closed
|
||||
operator = db.Column(db.String(64), default="")
|
||||
@@ -98,6 +103,37 @@ class ProdOrder(db.Model):
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
|
||||
|
||||
class ProdOrderAlloc(db.Model):
|
||||
"""生产订单「调入数量」手动录入: 每个物料的调入计划与已入账标记。
|
||||
|
||||
- alloc_qty: 该物料计划调入(转入)生产工厂的数量, 由用户在订单详情页手动填写。
|
||||
- posted: 是否已据此生成入库流水(调入工厂物料)。生成后该行只读, 避免重复入账。
|
||||
"""
|
||||
__tablename__ = "prod_order_alloc"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
order_id = db.Column(db.Integer, db.ForeignKey("prod_order.id"), nullable=False, index=True)
|
||||
material_id = db.Column(db.Integer, db.ForeignKey("material.id"), nullable=False, index=True)
|
||||
alloc_qty = db.Column(db.Float, default=0) # 调入数量(手动录入)
|
||||
posted = db.Column(db.Boolean, default=False) # 是否已生成入库流水
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
|
||||
|
||||
class Substitute(db.Model):
|
||||
"""替代料关系: 某主料(main)可由某替代料(sub)替代使用。
|
||||
|
||||
- 仅描述"谁可替代谁"的参考关系, 不直接参与库存计算。
|
||||
- 用于出库 / BOM 领料时, 若主料库存不足, 自动提示可用的替代料。
|
||||
- 唯一约束 (main_id, sub_id), 避免重复登记; main 与 sub 不可相同。
|
||||
"""
|
||||
__tablename__ = "substitute"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
main_id = db.Column(db.Integer, db.ForeignKey("material.id"), nullable=False, index=True)
|
||||
sub_id = db.Column(db.Integer, db.ForeignKey("material.id"), nullable=False, index=True)
|
||||
note = db.Column(db.String(255), default="")
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
__table_args__ = (UniqueConstraint("main_id", "sub_id", name="uq_sub_main_sub"),)
|
||||
|
||||
|
||||
# ---------------- M3: 操作日志 ----------------
|
||||
class OperationLog(db.Model):
|
||||
__tablename__ = "operation_log"
|
||||
@@ -107,3 +143,37 @@ class OperationLog(db.Model):
|
||||
target = db.Column(db.String(255), default="") # 对象
|
||||
detail = db.Column(db.String(512), default="") # 详情
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
|
||||
|
||||
# ---------------- M2-1: 多工厂 / 代工厂 ----------------
|
||||
class Factory(db.Model):
|
||||
__tablename__ = "factory"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
code = db.Column(db.String(32), unique=True, nullable=False, index=True) # 工厂编码, 如 SELF / SUB01
|
||||
name = db.Column(db.String(128), default="") # 工厂名称
|
||||
type = db.Column(db.String(16), default="self") # self 自厂 / subcontract 代工厂
|
||||
enabled = db.Column(db.Boolean, default=True) # 是否启用
|
||||
note = db.Column(db.String(255), default="")
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
|
||||
|
||||
# ---------------- M2-2: 厂间调拨 ----------------
|
||||
class Transfer(db.Model):
|
||||
"""厂间调拨: 从源工厂调出、调入目标工厂(同一颗物料)。
|
||||
|
||||
一条调拨记录对应两条流水:
|
||||
- Outbound(factory_id=from_factory_id) : 源厂库存扣减
|
||||
- Inbound (factory_id=to_factory_id) : 目标厂库存增加
|
||||
两张流水均带 source/purpose = 厂间调拨, 便于追溯和对账。
|
||||
"""
|
||||
__tablename__ = "transfer"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
no = db.Column(db.String(64), unique=True, nullable=False, index=True) # 调拨单号, 如 TR20260928xxx
|
||||
from_factory_id = db.Column(db.Integer, db.ForeignKey("factory.id"), nullable=False, index=True)
|
||||
to_factory_id = db.Column(db.Integer, db.ForeignKey("factory.id"), nullable=False, index=True)
|
||||
material_id = db.Column(db.Integer, db.ForeignKey("material.id"), nullable=False, index=True)
|
||||
qty = db.Column(db.Float, nullable=False) # 调拨数量(正)
|
||||
operator = db.Column(db.String(64), default="")
|
||||
occur_date = db.Column(db.Date, default=date.today)
|
||||
remark = db.Column(db.String(255), default="")
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
|
||||
Reference in New Issue
Block a user