添加半成品页面进行数据
This commit is contained in:
@ -1,2 +1,13 @@
|
||||
# app/models/__init__.py
|
||||
|
||||
# 1. 基础物料
|
||||
from app.models.material import MaterialBase
|
||||
from app.models.stock import StockBuy
|
||||
|
||||
# 2. 采购入库 (指向新路径)
|
||||
from app.models.inbound.buy import StockBuy
|
||||
|
||||
# 3. 半成品入库 (指向新路径)
|
||||
from app.models.inbound.semi import StockSemi
|
||||
|
||||
# 如果有其他模型 (比如 sys_user 等),保留它们
|
||||
# from app.models.sys_user import SysUser
|
||||
0
inventory-backend/app/models/inbound/__init__.py
Normal file
0
inventory-backend/app/models/inbound/__init__.py
Normal file
@ -1,4 +1,4 @@
|
||||
# app/models/stock.py
|
||||
# app/models/buy.py
|
||||
from app.extensions import db
|
||||
from datetime import datetime
|
||||
|
||||
143
inventory-backend/app/models/inbound/semi.py
Normal file
143
inventory-backend/app/models/inbound/semi.py
Normal file
@ -0,0 +1,143 @@
|
||||
# app/models/inbound/semi.py
|
||||
from app.extensions import db
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class StockSemi(db.Model):
|
||||
"""
|
||||
半成品入库库存表
|
||||
对应数据库表: stock_semi
|
||||
"""
|
||||
__tablename__ = 'stock_semi'
|
||||
|
||||
# =========================================================
|
||||
# 1. 基础字段 (Strictly matching SQL Schema)
|
||||
# =========================================================
|
||||
|
||||
# 主键
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
||||
# 外键关联 material_base 表
|
||||
base_id = db.Column(db.Integer, db.ForeignKey('material_base.id'), nullable=False)
|
||||
|
||||
# 身份标识
|
||||
sku = db.Column(db.String(100))
|
||||
|
||||
# SQL字段名为 production_date, 对应前端的 "入库日期/生产日期"
|
||||
production_date = db.Column(db.Date)
|
||||
|
||||
barcode = db.Column(db.String(100)) # 条码
|
||||
serial_number = db.Column(db.String(100)) # 序列号
|
||||
|
||||
# 注意:提供的 SQL 中 stock_semi 没有 batch_number 字段,这里不定义,以免报错。
|
||||
# 如果后续数据库加上了该字段,请取消下方注释:
|
||||
# batch_number = db.Column(db.String(100))
|
||||
|
||||
# --- 数量 ---
|
||||
in_quantity = db.Column(db.Numeric(19, 4), default=0)
|
||||
stock_quantity = db.Column(db.Numeric(19, 4), default=0)
|
||||
available_quantity = db.Column(db.Numeric(19, 4), default=0)
|
||||
|
||||
# --- 状态与位置 ---
|
||||
status = db.Column(db.String(50)) # 在库/出库/损耗
|
||||
warehouse_location = db.Column(db.String(100)) # 仓库位
|
||||
|
||||
# =========================================================
|
||||
# 2. 半成品特有字段 (SQL 字段映射)
|
||||
# =========================================================
|
||||
|
||||
# BOM 相关
|
||||
# 数据库列名: bom_id, Python属性: bom_code (为了适配前端习惯)
|
||||
bom_code = db.Column('bom_id', db.String(100))
|
||||
bom_version = db.Column(db.String(50))
|
||||
|
||||
# 工单 相关
|
||||
# 数据库列名: work_order_id, Python属性: work_order_code
|
||||
work_order_code = db.Column('work_order_id', db.String(100))
|
||||
|
||||
# 成本 相关
|
||||
raw_material_cost = db.Column(db.Numeric(19, 4), default=0) # 原材料成本
|
||||
manual_cost = db.Column(db.Numeric(19, 4), default=0) # 手动/人工成本
|
||||
|
||||
# 生产信息
|
||||
# 数据库列名: producer_name, Python属性: production_manager
|
||||
production_manager = db.Column('producer_name', db.String(100))
|
||||
|
||||
# 生产起止时间 (SQL定义为 VARCHAR(255))
|
||||
production_time_range = db.Column(db.String(255))
|
||||
|
||||
# 质量与链接
|
||||
quality_status = db.Column(db.String(50)) # 质量状态
|
||||
quality_report_link = db.Column(db.Text) # 质量报告链接
|
||||
detail_link = db.Column(db.Text) # 详细信息链接
|
||||
|
||||
# =========================================================
|
||||
# 3. 关系定义
|
||||
# =========================================================
|
||||
# 建立与 MaterialBase 的关系
|
||||
# 注意:确保 MaterialBase 模型中定义了 back_populates='stock_semis'
|
||||
material = db.relationship('MaterialBase', back_populates='stock_semis')
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
序列化:将模型转换为字典,供API返回JSON使用
|
||||
在这里处理字段名称转换,确保前端能正确显示数据
|
||||
"""
|
||||
# 计算单件总成本 (原料 + 人工)
|
||||
raw_val = float(self.raw_material_cost or 0)
|
||||
man_val = float(self.manual_cost or 0)
|
||||
unit_total = raw_val + man_val
|
||||
|
||||
return {
|
||||
'id': self.id,
|
||||
'base_id': self.base_id,
|
||||
|
||||
# --- 级联基础信息 (防止 None 报错) ---
|
||||
'material_name': self.material.name if self.material else '',
|
||||
'spec_model': self.material.spec_model if self.material else '',
|
||||
'category': self.material.category if self.material else '',
|
||||
'unit': self.material.unit if self.material else '',
|
||||
'material_type': self.material.material_type if self.material else '',
|
||||
|
||||
# --- 实体信息 ---
|
||||
'sku': self.sku,
|
||||
# 将 production_date 映射回前端通用的 inbound_date
|
||||
'inbound_date': self.production_date.strftime('%Y-%m-%d') if self.production_date else '',
|
||||
'barcode': self.barcode,
|
||||
'serial_number': self.serial_number,
|
||||
# 'batch_number': self.batch_number, # SQL无此字段,暂不返回
|
||||
'warehouse_loc': self.warehouse_location,
|
||||
'status': self.status,
|
||||
|
||||
# --- 数量 (转为float防止json序列化报错) ---
|
||||
'in_quantity': float(self.in_quantity or 0),
|
||||
'qty_inbound': float(self.in_quantity or 0), # 兼容字段
|
||||
'stock_quantity': float(self.stock_quantity or 0),
|
||||
'qty_stock': float(self.stock_quantity or 0), # 兼容字段
|
||||
'available_quantity': float(self.available_quantity or 0),
|
||||
'qty_available': float(self.available_quantity or 0), # 兼容字段
|
||||
|
||||
# --- 半成品特有数据 ---
|
||||
'bom_code': self.bom_code,
|
||||
'bom_version': self.bom_version,
|
||||
'work_order_code': self.work_order_code,
|
||||
|
||||
'raw_material_cost': raw_val,
|
||||
'manual_cost': man_val,
|
||||
'unit_total_cost': unit_total, # 前端展示总成本用
|
||||
|
||||
'production_manager': self.production_manager,
|
||||
|
||||
# 时间范围 (SQL存的是字符串,直接返回即可,或者根据需要拆分)
|
||||
# 如果 service 层存的是 "Start ~ End",这里直接返回
|
||||
'production_time_range': self.production_time_range,
|
||||
# 为了兼容前端分开的时间字段(如果有):
|
||||
'production_start_time': self.production_time_range.split(' ~ ')[
|
||||
0] if self.production_time_range and ' ~ ' in self.production_time_range else '',
|
||||
'production_end_time': self.production_time_range.split(' ~ ')[
|
||||
1] if self.production_time_range and ' ~ ' in self.production_time_range else '',
|
||||
|
||||
'quality_status': self.quality_status,
|
||||
'quality_report_link': self.quality_report_link,
|
||||
'detail_link': self.detail_link
|
||||
}
|
||||
@ -10,7 +10,7 @@ class MaterialBase(db.Model):
|
||||
"""
|
||||
__tablename__ = 'material_base'
|
||||
|
||||
# 1. 基础字段 (必须与 SQL 建表语句完全一致)
|
||||
# 1. 基础字段 (保持不变)
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(255), nullable=False, comment='基础信息名称')
|
||||
|
||||
@ -32,26 +32,31 @@ class MaterialBase(db.Model):
|
||||
manual_link = db.Column(db.Text, comment='通用说明书链接')
|
||||
product_image = db.Column(db.Text, comment='通用产品图链接')
|
||||
|
||||
# 启用状态 (注意:SQL中是 boolean)
|
||||
# 启用状态
|
||||
is_enabled = db.Column(db.Boolean, default=True, comment='是否启用')
|
||||
|
||||
# ============================================================
|
||||
# ⚠️ 注意:你之前提供的 SQL 建表语句中【没有】下面这两个时间字段。
|
||||
# 如果数据库里没有这两列,代码运行到这里会报错 (UndefinedColumn)。
|
||||
# 我先将其注释掉。如果你确认数据库已经 Alter Table 加了这两列,请取消注释。
|
||||
# 时间字段 (保持你原本的注释状态,以免报错)
|
||||
# ============================================================
|
||||
# create_time = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
# update_time = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
# 【核心关联】
|
||||
# 关联采购库存表 (StockBuy),lazy='dynamic' 允许后续做 .count() 统计
|
||||
# 确保 app/models/stock.py 中有 back_populates='material'
|
||||
# ============================================================
|
||||
# 关联关系区域 (修改重点)
|
||||
# ============================================================
|
||||
|
||||
# 1. 关联采购库存 (StockBuy) - 保持不变
|
||||
# 注意:确保 app/models/inbound/buy.py 中的 StockBuy 定义了 back_populates='material'
|
||||
stock_buys = db.relationship('StockBuy', back_populates='material', lazy='dynamic')
|
||||
|
||||
# 2. 【新增】关联半成品库存 (StockSemi)
|
||||
# 注意:确保 app/models/inbound/semi.py 中的 StockSemi 定义了 back_populates='material'
|
||||
# 这样以后可以通过 material.stock_semis 来访问该物料下的所有半成品库存记录
|
||||
stock_semis = db.relationship('StockSemi', back_populates='material', lazy='dynamic')
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
序列化方法:将模型转换为字典,供API返回JSON使用
|
||||
这里是解决【前端表格空白】最关键的地方
|
||||
"""
|
||||
return {
|
||||
'id': self.id,
|
||||
@ -59,7 +64,7 @@ class MaterialBase(db.Model):
|
||||
'category': self.category,
|
||||
|
||||
# =========================================
|
||||
# 关键映射区 (解决前后端字段名不一致问题)
|
||||
# 关键映射区 (保持不变)
|
||||
# =========================================
|
||||
# 数据库叫 material_type -> 前端叫 type
|
||||
'type': self.material_type,
|
||||
@ -74,11 +79,9 @@ class MaterialBase(db.Model):
|
||||
'generalManual': self.manual_link,
|
||||
'generalImage': self.product_image,
|
||||
|
||||
# 状态处理:前端 Switch 通常接受 boolean 或 1/0
|
||||
# 数据库里的 true -> 返回 1 (启用)
|
||||
# 数据库里的 false/None -> 返回 0 (禁用)
|
||||
# 状态处理
|
||||
'isEnabled': 1 if self.is_enabled else 0,
|
||||
|
||||
# 如果上方注释了 create_time,这里也要注释,否则会报错
|
||||
# 时间字段保持注释
|
||||
# 'createTime': self.create_time.strftime('%Y-%m-%d %H:%M:%S') if hasattr(self, 'create_time') and self.create_time else None
|
||||
}
|
||||
Reference in New Issue
Block a user