feat: 库存管理系统 MaterialWMS 初始版本
- Flask + SQLAlchemy 物料/入库/出库/BOM/生产订单全模块管理 - PyInstaller 打包为单文件 EXE (双击运行, 自动建库) - 物料维度: 入库总数量 / 消耗总数量 / 逐次入库流水(含时间) - BOM 详情展示组成物料的规格型号与单套用量 - 支持 Altium / 嘉立创 BOM 批量导入(文本与 Excel 双通道) - 内置端到端验证脚本(tools/_exe_util.py 等, 清理进程树防残留)
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
"""物料入库/出库系统 - 数据模型 (SQLAlchemy 2.0)
|
||||
|
||||
实体:
|
||||
User 账号(admin / manager / operator)
|
||||
Material 物料主数据
|
||||
Inbound 入库流水(含"期初"来源的首笔)
|
||||
Outbound 出库流水(含生产领用)
|
||||
Bom BOM 清单(产品型号)
|
||||
BomItem BOM 组成(某物料单套用量)
|
||||
ProdOrder 生产订单(接单量) -> 按 BOM 展开领料需求
|
||||
OperationLog 操作日志(谁/何时/做了什么)
|
||||
|
||||
库存口径: 在库 = SUM(入库) - SUM(出库), 由 app 实时聚合, 不冗余存储。
|
||||
"""
|
||||
import os
|
||||
from datetime import datetime, date
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
db = SQLAlchemy()
|
||||
|
||||
|
||||
class User(db.Model):
|
||||
__tablename__ = "user"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
username = db.Column(db.String(64), unique=True, nullable=False, index=True)
|
||||
password = db.Column(db.String(128), nullable=False) # sha256 hex
|
||||
role = db.Column(db.String(32), default="operator") # admin / manager / operator
|
||||
display_name = db.Column(db.String(64), default="")
|
||||
active = db.Column(db.Boolean, default=True)
|
||||
|
||||
|
||||
class Material(db.Model):
|
||||
__tablename__ = "material"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
part_number = db.Column(db.String(64), unique=True, nullable=False, index=True)
|
||||
manufacturer = db.Column(db.String(255), default="") # 型号 / 规格
|
||||
unit = db.Column(db.String(16), default="个")
|
||||
safety_stock = db.Column(db.Float, default=0) # 安全库存
|
||||
note = db.Column(db.String(255), default="")
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
|
||||
|
||||
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)
|
||||
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="") # 来源 / 供应商
|
||||
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)
|
||||
|
||||
|
||||
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)
|
||||
batch_no = db.Column(db.String(64), default="") # 批次号
|
||||
qty = db.Column(db.Float, nullable=False) # 出库数量(正)
|
||||
operator = db.Column(db.String(64), default="") # 经手人
|
||||
purpose = db.Column(db.String(255), default="") # 用途
|
||||
order_ref = 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)
|
||||
|
||||
|
||||
# ---------------- M2: BOM 与生产订单 ----------------
|
||||
class Bom(db.Model):
|
||||
__tablename__ = "bom"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
code = db.Column(db.String(64), unique=True, nullable=False, index=True) # BOM 型号简码
|
||||
name = db.Column(db.String(255), default="")
|
||||
note = db.Column(db.String(255), default="")
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
|
||||
|
||||
class BomItem(db.Model):
|
||||
__tablename__ = "bom_item"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
bom_id = db.Column(db.Integer, db.ForeignKey("bom.id"), nullable=False, index=True)
|
||||
material_id = db.Column(db.Integer, db.ForeignKey("material.id"), nullable=False, index=True)
|
||||
qty_per_unit = db.Column(db.Float, nullable=False, default=0) # 单套用量
|
||||
|
||||
|
||||
class ProdOrder(db.Model):
|
||||
__tablename__ = "prod_order"
|
||||
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)
|
||||
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="")
|
||||
remark = db.Column(db.String(255), default="")
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
|
||||
|
||||
# ---------------- M3: 操作日志 ----------------
|
||||
class OperationLog(db.Model):
|
||||
__tablename__ = "operation_log"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
operator = db.Column(db.String(64), default="")
|
||||
action = db.Column(db.String(64), default="") # 动作分类
|
||||
target = db.Column(db.String(255), default="") # 对象
|
||||
detail = db.Column(db.String(512), default="") # 详情
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
Reference in New Issue
Block a user