143 lines
6.0 KiB
Python
143 lines
6.0 KiB
Python
# 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
|
||
} |