@@ -1,891 +0,0 @@
# models/database.py
from sqlalchemy import Column , Integer , String , Text , DateTime , Date , JSON , LargeBinary , Boolean , Float , ForeignKey , UniqueConstraint , Numeric , CheckConstraint
from sqlalchemy . ext . declarative import declarative_base
from sqlalchemy . sql import func
from sqlalchemy . orm import relationship
from datetime import datetime , date
Base = declarative_base ( )
class User ( Base ) :
""" 用户表 """
__tablename__ = " users "
__excluded_fields__ = { ' hashed_password ' }
id = Column ( Integer , primary_key = True , index = True )
username = Column ( String ( 50 ) , unique = True , index = True , nullable = False )
email = Column ( String ( 255 ) , unique = True , index = True , nullable = False )
hashed_password = Column ( String ( 255 ) , nullable = False )
full_name = Column ( String ( 100 ) )
is_active = Column ( Boolean , default = True )
created_at = Column ( DateTime , default = func . now ( ) )
last_login = Column ( DateTime , nullable = True )
stp_files = relationship ( " STPFile " , back_populates = " user " )
user_roles = relationship ( " UserRole " , back_populates = " user " , cascade = " all, delete-orphan " )
@property
def roles ( self ) :
return [ ur . role for ur in self . user_roles ]
@property
def is_superuser ( self ) :
return any ( r . code == ' admin ' for r in self . roles )
def has_permission ( self , permission_code : str ) - > bool :
if self . is_superuser :
return True
for role in self . roles :
for perm in role . permissions :
if perm . code == permission_code :
return True
return False
def safe_dict ( self ) :
return { k : v for k , v in self . __dict__ . items ( )
if not k . startswith ( ' _ ' ) and k not in self . __excluded_fields__ }
def __repr__ ( self ) :
return f " <User(id= { self . id } , username= ' { self . username } ' )> "
class Role ( Base ) :
""" 角色表 """
__tablename__ = " roles "
id = Column ( Integer , primary_key = True , index = True )
code = Column ( String ( 50 ) , unique = True , index = True , nullable = False )
name = Column ( String ( 100 ) , nullable = False )
description = Column ( Text , nullable = True )
is_system = Column ( Boolean , default = False )
created_at = Column ( DateTime , default = func . now ( ) )
user_roles = relationship ( " UserRole " , back_populates = " role " , cascade = " all, delete-orphan " )
role_permissions = relationship ( " RolePermission " , back_populates = " role " , cascade = " all, delete-orphan " )
@property
def permissions ( self ) :
return [ rp . permission for rp in self . role_permissions ]
def __repr__ ( self ) :
return f " <Role(code= ' { self . code } ' , name= ' { self . name } ' )> "
class Permission ( Base ) :
""" 权限表 """
__tablename__ = " permissions "
id = Column ( Integer , primary_key = True , index = True )
code = Column ( String ( 100 ) , unique = True , index = True , nullable = False )
name = Column ( String ( 100 ) , nullable = False )
module = Column ( String ( 50 ) , nullable = True )
description = Column ( Text , nullable = True )
created_at = Column ( DateTime , default = func . now ( ) )
role_permissions = relationship ( " RolePermission " , back_populates = " permission " , cascade = " all, delete-orphan " )
def __repr__ ( self ) :
return f " <Permission(code= ' { self . code } ' , name= ' { self . name } ' )> "
class UserRole ( Base ) :
""" 用户角色关联表 """
__tablename__ = " user_roles "
id = Column ( Integer , primary_key = True , index = True )
user_id = Column ( Integer , ForeignKey ( " users.id " ) , nullable = False , index = True )
role_id = Column ( Integer , ForeignKey ( " roles.id " ) , nullable = False , index = True )
created_at = Column ( DateTime , default = func . now ( ) )
user = relationship ( " User " , back_populates = " user_roles " )
role = relationship ( " Role " , back_populates = " user_roles " )
def __repr__ ( self ) :
return f " <UserRole(user_id= { self . user_id } , role_id= { self . role_id } )> "
class RolePermission ( Base ) :
""" 角色权限关联表 """
__tablename__ = " role_permissions "
id = Column ( Integer , primary_key = True , index = True )
role_id = Column ( Integer , ForeignKey ( " roles.id " ) , nullable = False , index = True )
permission_id = Column ( Integer , ForeignKey ( " permissions.id " ) , nullable = False , index = True )
created_at = Column ( DateTime , default = func . now ( ) )
role = relationship ( " Role " , back_populates = " role_permissions " )
permission = relationship ( " Permission " , back_populates = " role_permissions " )
def __repr__ ( self ) :
return f " <RolePermission(role_id= { self . role_id } , permission_id= { self . permission_id } )> "
class STPFile ( Base ) :
""" STP源文件元数据表 - 支持同一文件多次上传 """
__tablename__ = " stp_files "
id = Column ( Integer , primary_key = True , index = True )
user_id = Column ( Integer , ForeignKey ( " users.id " ) , nullable = True , index = True )
# 关联进销存成品(P2-1:分析结果可一键创建为成品并回写)
product_id = Column ( Integer , ForeignKey ( " products.id " ) , nullable = True , index = True )
# 对象存储信息
object_key = Column ( String ( 500 ) , nullable = False , index = True ) # MinIO对象键
storage_bucket = Column ( String ( 100 ) , nullable = False ) # 存储桶名称
object_url = Column ( String ( 1000 ) , nullable = True ) # 预签名URL(可选)
# 文件信息
original_filename = Column ( String ( 255 ) , nullable = False , index = True ) # 添加索引支持按文件名查询
file_size = Column ( Integer , nullable = False )
file_hash = Column ( String ( 64 ) , index = True ) # 移除unique约束,允许同一文件多次上传
mime_type = Column ( String ( 50 ) , default = " application/octet-stream " )
# 上传批次标识 - 用于区分同一文件的多次上传
upload_batch = Column ( String ( 36 ) , index = True ) # UUID批次号
# 时间戳
upload_time = Column ( DateTime , default = func . now ( ) )
processed_time = Column ( DateTime , nullable = True )
# 状态
status = Column ( String ( 20 ) , default = " pending " , index = True ) # pending, processing, completed, failed
error_message = Column ( Text , nullable = True )
# 分析摘要 - 快速查询字段
volume = Column ( Float , nullable = True ) # 体积 mm³
surface_area = Column ( Float , nullable = True ) # 表面积 mm²
product_weight = Column ( Float , nullable = True ) # 产品重量 g
# 保留旧字段以兼容
file_path = Column ( String ( 500 ) , nullable = True ) # 本地路径(已弃用)
file_content = Column ( LargeBinary , nullable = True ) # 本地存储(已弃用)
filename = Column ( String ( 255 ) , nullable = True ) # 已弃用
# 关联关系
user = relationship ( " User " , back_populates = " stp_files " )
product = relationship ( " Product " ) # P2-1: 关联的进销存成品
geometry_data = relationship ( " GeometryData " , back_populates = " stp_file " , uselist = False )
mesh_data = relationship ( " MeshData " , back_populates = " stp_file " , uselist = False )
mold_cavity_data = relationship ( " MoldCavityData " , back_populates = " stp_file " , uselist = False )
html_file = relationship ( " HTMLFile " , back_populates = " stp_file " , uselist = False )
analysis_metrics = relationship ( " AnalysisMetrics " , back_populates = " stp_file " , uselist = False )
feature_detections = relationship ( " FeatureDetection " , back_populates = " stp_file " )
design_recommendations = relationship ( " DesignRecommendation " , back_populates = " stp_file " )
processing_tasks = relationship ( " ProcessingTask " , back_populates = " stp_file " )
def __repr__ ( self ) :
return f " <STPFile(id= { self . id } , original_filename= ' { self . original_filename } ' , status= ' { self . status } ' )> "
class GeometryData ( Base ) :
""" 几何数据JSON元数据表 """
__tablename__ = " geometry_data "
id = Column ( Integer , primary_key = True , index = True )
stp_file_id = Column ( Integer , ForeignKey ( " stp_files.id " ) , nullable = False , index = True )
# 对象存储信息
object_key = Column ( String ( 500 ) , nullable = False )
storage_bucket = Column ( String ( 100 ) , nullable = False )
object_url = Column ( String ( 1000 ) , nullable = True )
# 分析方法
analysis_method = Column ( String ( 50 ) , default = " pythonocc " ) # pythonocc, simulated
# 时间戳
created_time = Column ( DateTime , default = func . now ( ) )
# 几何属性摘要(便于快速查询)
volume = Column ( Float , nullable = True )
surface_area = Column ( Float , nullable = True )
bounding_box_min = Column ( JSON , nullable = True )
bounding_box_max = Column ( JSON , nullable = True )
center_of_mass = Column ( JSON , nullable = True )
# 拓扑信息
topology_faces = Column ( Integer , nullable = True )
topology_edges = Column ( Integer , nullable = True )
topology_vertices = Column ( Integer , nullable = True )
# 关联关系
stp_file = relationship ( " STPFile " , back_populates = " geometry_data " )
def __repr__ ( self ) :
return f " <GeometryData(id= { self . id } , stp_file_id= { self . stp_file_id } )> "
class MeshData ( Base ) :
""" 网格数据JSON元数据表(详细网格存 RustFS, PostgreSQL 存摘要) """
__tablename__ = " mesh_data "
id = Column ( Integer , primary_key = True , index = True )
stp_file_id = Column ( Integer , ForeignKey ( " stp_files.id " ) , nullable = False , index = True )
# 对象存储信息
object_key = Column ( String ( 500 ) , nullable = False )
storage_bucket = Column ( String ( 100 ) , nullable = False )
object_url = Column ( String ( 1000 ) , nullable = True )
# 生成设置
quality = Column ( String ( 20 ) , default = " medium " ) # low / medium / high
# 网格规模信息
vertex_count = Column ( Integer , nullable = True )
face_count = Column ( Integer , nullable = True )
point_count = Column ( Integer , nullable = True ) # 采样点云数量
# 网格边界框(便于快速查询)
bounding_box_min = Column ( JSON , nullable = True )
bounding_box_max = Column ( JSON , nullable = True )
# 时间戳
created_time = Column ( DateTime , default = func . now ( ) )
# 关联关系
stp_file = relationship ( " STPFile " , back_populates = " mesh_data " )
def __repr__ ( self ) :
return f " <MeshData(id= { self . id } , stp_file_id= { self . stp_file_id } , quality= ' { self . quality } ' )> "
class HTMLFile ( Base ) :
""" 网页文件元数据表 """
__tablename__ = " html_files "
id = Column ( Integer , primary_key = True , index = True )
stp_file_id = Column ( Integer , ForeignKey ( " stp_files.id " ) , nullable = False , index = True )
# 对象存储信息
object_key = Column ( String ( 500 ) , nullable = False )
storage_bucket = Column ( String ( 100 ) , nullable = False )
object_url = Column ( String ( 1000 ) , nullable = True )
# 文件信息
filename = Column ( String ( 255 ) , nullable = False )
generated_time = Column ( DateTime , default = func . now ( ) )
# 可视化相关元数据
visualization_type = Column ( String ( 50 ) , default = " 3d_viewer " )
has_interactive_elements = Column ( Boolean , default = True )
# 保留旧字段以兼容
file_path = Column ( String ( 500 ) , nullable = True )
html_content = Column ( Text , nullable = True )
# 关联关系
stp_file = relationship ( " STPFile " , back_populates = " html_file " )
def __repr__ ( self ) :
return f " <HTMLFile(id= { self . id } , stp_file_id= { self . stp_file_id } , object_key= ' { self . object_key } ' )> "
class ProcessingTask ( Base ) :
""" 处理任务记录表 """
__tablename__ = " processing_tasks "
id = Column ( Integer , primary_key = True , index = True )
task_id = Column ( String ( 36 ) , unique = True , index = True , nullable = False )
stp_file_id = Column ( Integer , ForeignKey ( " stp_files.id " ) , nullable = False , index = True )
# 批量上传聚合 ID(批次 2:批量元数据入库——PG 为单一事实源,
# 同批任务经此列聚合查询,不再依赖 Redis/进程内存存批量元数据)
batch_id = Column ( String ( 36 ) , nullable = True , index = True )
# 任务类型和状态
task_type = Column ( String ( 50 ) , default = " stp_parsing " ) # stp_parsing, geometry_analysis, mold_generation
status = Column ( String ( 20 ) , default = " pending " ) # pending, processing, completed, failed
# 时间戳
created_time = Column ( DateTime , default = func . now ( ) )
started_time = Column ( DateTime , nullable = True )
completed_time = Column ( DateTime , nullable = True )
# 处理进度
progress = Column ( Integer , default = 0 ) # 0-100
current_step = Column ( String ( 100 ) , nullable = True )
# 错误信息
error_message = Column ( Text , nullable = True )
error_stack = Column ( Text , nullable = True )
# 处理参数
parameters = Column ( JSON , nullable = True ) # 任务参数
# 关联关系
stp_file = relationship ( " STPFile " , back_populates = " processing_tasks " )
def __repr__ ( self ) :
return f " <ProcessingTask(id= { self . id } , task_id= ' { self . task_id } ' , status= ' { self . status } ' )> "
class MoldCavityData ( Base ) :
""" 模具型腔数据元数据表 """
__tablename__ = " mold_cavity_data "
id = Column ( Integer , primary_key = True , index = True )
stp_file_id = Column ( Integer , ForeignKey ( " stp_files.id " ) , nullable = False , index = True )
# 对象存储信息
detailed_object_key = Column ( String ( 500 ) , nullable = False ) # 完整三维数据
storage_bucket = Column ( String ( 100 ) , nullable = False )
# 模具类型和材料
mold_material = Column ( String ( 100 ) , default = " Aluminum Alloy 7075 " )
mold_type = Column ( String ( 50 ) , default = " single_cavity " ) # single_cavity, multi_cavity
# 工艺参数
shrinkage_rate = Column ( Float , nullable = False )
draft_angle = Column ( Float , nullable = False )
parting_line_length = Column ( Float , nullable = True )
# 生成时间
generated_time = Column ( DateTime , default = func . now ( ) )
# 关键信息摘要(快速查询字段)
cavity_key_info = Column ( JSON , nullable = True ) # 完整关键信息
# 提取的字段(便于查询和排序)
mold_size_length = Column ( Float , nullable = True )
mold_size_width = Column ( Float , nullable = True )
mold_size_height = Column ( Float , nullable = True )
estimated_clamping_force = Column ( String ( 50 ) , nullable = True )
product_weight = Column ( String ( 50 ) , nullable = True )
product_volume = Column ( Float , nullable = True )
wall_thickness_range = Column ( String ( 50 ) , nullable = True )
complexity_score = Column ( Float , nullable = True )
# 质量评估
weld_line_risk = Column ( String ( 50 ) , nullable = True ) # 熔接痕风险
sink_mark_risk = Column ( String ( 50 ) , nullable = True ) # 缩痕风险
warpage_risk = Column ( String ( 50 ) , nullable = True ) # 翘曲风险
# 多方案可信化摘要(第1周阶段1)
best_scheme_id = Column ( String ( 64 ) , nullable = True , index = True )
confidence_score = Column ( Float , nullable = True )
is_fallback = Column ( Boolean , nullable = True , index = True )
fallback_reason = Column ( Text , nullable = True )
# 关联关系
stp_file = relationship ( " STPFile " , back_populates = " mold_cavity_data " )
def __repr__ ( self ) :
return f " <MoldCavityData(stp_file_id= { self . stp_file_id } , mold_material= ' { self . mold_material } ' )> "
class FeatureDetection ( Base ) :
""" 特征检测结果表 """
__tablename__ = " feature_detections "
id = Column ( Integer , primary_key = True , index = True )
stp_file_id = Column ( Integer , ForeignKey ( " stp_files.id " ) , nullable = False , index = True )
# 特征信息
feature_type = Column ( String ( 50 ) , nullable = False , index = True ) # thin_wall, thick_wall, wall_non_uniform, rib, boss, draft_angle, high_curvature, fillet
confidence = Column ( Float , nullable = False ) # 0.0 - 1.0
# 位置和尺寸
location = Column ( JSON , nullable = True ) # [x, y, z]
dimensions = Column ( JSON , nullable = True ) # [length, width, height]
# 特征参数
parameters = Column ( JSON , nullable = True ) # 自定义参数
# 检测时间
detected_at = Column ( DateTime , default = func . now ( ) )
# 关联的几何数据
geometry_data_id = Column ( Integer , ForeignKey ( " geometry_data.id " ) , nullable = True )
# 关联关系
stp_file = relationship ( " STPFile " , back_populates = " feature_detections " )
def __repr__ ( self ) :
return f " <FeatureDetection(id= { self . id } , feature_type= ' { self . feature_type } ' , confidence= { self . confidence } )> "
class DesignRecommendation ( Base ) :
""" 设计建议表 """
__tablename__ = " design_recommendations "
id = Column ( Integer , primary_key = True , index = True )
stp_file_id = Column ( Integer , ForeignKey ( " stp_files.id " ) , nullable = False , index = True )
# 建议信息
rec_type = Column ( String ( 50 ) , nullable = False ) # wall_thickness, draft_angle, etc.
priority = Column ( String ( 20 ) , nullable = False ) # high, medium, low
description = Column ( String ( 500 ) , nullable = False )
reason = Column ( Text , nullable = True )
# 建议参数
parameters = Column ( JSON , nullable = True )
# 状态
status = Column ( String ( 20 ) , default = " pending " ) # pending, accepted, rejected
user_notes = Column ( Text , nullable = True )
# 时间戳
created_at = Column ( DateTime , default = func . now ( ) )
updated_at = Column ( DateTime , nullable = True )
# 关联关系
stp_file = relationship ( " STPFile " , back_populates = " design_recommendations " )
def __repr__ ( self ) :
return f " <DesignRecommendation(id= { self . id } , rec_type= ' { self . rec_type } ' , priority= ' { self . priority } ' )> "
class UserActivity ( Base ) :
""" 用户活动日志表 """
__tablename__ = " user_activities "
id = Column ( Integer , primary_key = True , index = True )
user_id = Column ( Integer , ForeignKey ( " users.id " ) , nullable = False , index = True )
# 活动信息
activity_type = Column ( String ( 50 ) , nullable = False , index = True ) # upload, view, download, delete, export
resource_type = Column ( String ( 50 ) , nullable = True ) # stp_file, geometry_data, mold_cavity
resource_id = Column ( Integer , nullable = True )
# 活动详情
description = Column ( Text , nullable = True )
meta_data = Column ( JSON , nullable = True )
# 时间戳
created_at = Column ( DateTime , default = func . now ( ) , index = True )
# IP和设备信息
ip_address = Column ( String ( 45 ) , nullable = True )
user_agent = Column ( String ( 500 ) , nullable = True )
def __repr__ ( self ) :
return f " <UserActivity(id= { self . id } , user_id= { self . user_id } , activity_type= ' { self . activity_type } ' )> "
class SystemLog ( Base ) :
""" 系统日志表(重要操作和错误) """
__tablename__ = " system_logs "
id = Column ( Integer , primary_key = True , index = True )
# 日志级别
level = Column ( String ( 20 ) , nullable = False , index = True ) # INFO, WARNING, ERROR, CRITICAL
# 日志信息
message = Column ( Text , nullable = False )
module = Column ( String ( 100 ) , nullable = True ) # 模块名
function_name = Column ( String ( 100 ) , nullable = True )
# 时间戳
created_at = Column ( DateTime , default = func . now ( ) , index = True )
# 用户信息(如果有关联用户)
user_id = Column ( Integer , ForeignKey ( " users.id " ) , nullable = True )
# 额外信息
request_id = Column ( String ( 100 ) , nullable = True ) # 关联的请求ID
execution_time_ms = Column ( Integer , nullable = True ) # 执行时间
# 关联数据
resource_type = Column ( String ( 50 ) , nullable = True )
resource_id = Column ( Integer , nullable = True )
def __repr__ ( self ) :
return f " <SystemLog(id= { self . id } , level= ' { self . level } ' , module= ' { self . module } ' )> "
class Product ( Base ) :
""" 产品表 """
__tablename__ = " products "
id = Column ( Integer , primary_key = True , index = True )
sku = Column ( String ( 50 ) , unique = True , index = True , nullable = False )
name = Column ( String ( 200 ) , nullable = False )
description = Column ( Text , nullable = True )
category = Column ( String ( 100 ) , nullable = True )
unit = Column ( String ( 20 ) , default = " 件 " )
item_type = Column ( String ( 20 ) , default = " finished " , index = True )
cost_price = Column ( Numeric ( 12 , 2 ) , default = 0 )
sale_price = Column ( Numeric ( 12 , 2 ) , default = 0 )
min_stock = Column ( Integer , default = 0 )
max_stock = Column ( Integer , default = 1000 )
is_active = Column ( Boolean , default = True )
created_at = Column ( DateTime , default = func . now ( ) )
updated_at = Column ( DateTime , default = func . now ( ) , onupdate = func . now ( ) )
inventory = relationship ( " Inventory " , back_populates = " product " , uselist = False )
stock_movements = relationship ( " StockMovement " , back_populates = " product " )
bom_materials = relationship (
" ProductMaterial " ,
foreign_keys = " ProductMaterial.finished_product_id " ,
back_populates = " finished_product " ,
cascade = " all, delete-orphan "
)
used_in_products = relationship (
" ProductMaterial " ,
foreign_keys = " ProductMaterial.material_product_id " ,
back_populates = " material_product "
)
def __repr__ ( self ) :
return f " <Product(id= { self . id } , sku= ' { self . sku } ' , name= ' { self . name } ' )> "
class ProductMaterial ( Base ) :
__tablename__ = " product_materials "
__table_args__ = (
UniqueConstraint ( " finished_product_id " , " material_product_id " , name = " uq_product_material_unique " ) ,
)
id = Column ( Integer , primary_key = True , index = True )
finished_product_id = Column ( Integer , ForeignKey ( " products.id " ) , nullable = False , index = True )
material_product_id = Column ( Integer , ForeignKey ( " products.id " ) , nullable = False , index = True )
quantity = Column ( Numeric ( 12 , 4 ) , nullable = False )
loss_rate = Column ( Numeric ( 5 , 4 ) , default = 0 )
created_at = Column ( DateTime , default = func . now ( ) )
updated_at = Column ( DateTime , default = func . now ( ) , onupdate = func . now ( ) )
finished_product = relationship (
" Product " ,
foreign_keys = [ finished_product_id ] ,
back_populates = " bom_materials "
)
material_product = relationship (
" Product " ,
foreign_keys = [ material_product_id ] ,
back_populates = " used_in_products "
)
def __repr__ ( self ) :
return f " <ProductMaterial(finished_product_id= { self . finished_product_id } , material_product_id= { self . material_product_id } )> "
class MaterialPriceHistory ( Base ) :
""" 物料价格历史表 """
__tablename__ = " material_price_history "
id = Column ( Integer , primary_key = True , index = True )
product_id = Column ( Integer , ForeignKey ( " products.id " ) , nullable = False , index = True )
price = Column ( Numeric ( 12 , 2 ) , nullable = False )
effective_date = Column ( DateTime , default = func . now ( ) , index = True )
supplier_id = Column ( Integer , ForeignKey ( " suppliers.id " ) , nullable = True , index = True )
remark = Column ( Text , nullable = True )
created_at = Column ( DateTime , default = func . now ( ) )
product = relationship ( " Product " , backref = " price_history " )
supplier = relationship ( " Supplier " , backref = " price_history " )
def __repr__ ( self ) :
return f " <MaterialPriceHistory(product_id= { self . product_id } , price= { self . price } , date= { self . effective_date } )> "
class MaterialSupplier ( Base ) :
""" 物料供应商关联表 """
__tablename__ = " material_suppliers "
id = Column ( Integer , primary_key = True , index = True )
product_id = Column ( Integer , ForeignKey ( " products.id " ) , nullable = False , index = True )
supplier_id = Column ( Integer , ForeignKey ( " suppliers.id " ) , nullable = False , index = True )
is_primary = Column ( Boolean , default = False )
contact_person = Column ( String ( 100 ) , nullable = True )
contact_phone = Column ( String ( 50 ) , nullable = True )
lead_time = Column ( Integer , nullable = True ) # 交货周期(天)
min_order_quantity = Column ( Integer , nullable = True )
created_at = Column ( DateTime , default = func . now ( ) )
updated_at = Column ( DateTime , default = func . now ( ) , onupdate = func . now ( ) )
product = relationship ( " Product " , backref = " suppliers " )
supplier = relationship ( " Supplier " , backref = " materials " )
def __repr__ ( self ) :
return f " <MaterialSupplier(product_id= { self . product_id } , supplier_id= { self . supplier_id } , primary= { self . is_primary } )> "
class Supplier ( Base ) :
""" 供应商表 """
__tablename__ = " suppliers "
id = Column ( Integer , primary_key = True , index = True )
code = Column ( String ( 50 ) , unique = True , index = True )
name = Column ( String ( 200 ) , nullable = False )
contact_person = Column ( String ( 100 ) , nullable = True )
phone = Column ( String ( 50 ) , nullable = True )
email = Column ( String ( 100 ) , nullable = True )
address = Column ( Text , nullable = True )
bank_name = Column ( String ( 100 ) , nullable = True )
bank_account = Column ( String ( 50 ) , nullable = True )
tax_number = Column ( String ( 50 ) , nullable = True )
is_active = Column ( Boolean , default = True )
created_at = Column ( DateTime , default = func . now ( ) )
updated_at = Column ( DateTime , default = func . now ( ) , onupdate = func . now ( ) )
purchase_orders = relationship ( " PurchaseOrder " , back_populates = " supplier " )
def __repr__ ( self ) :
return f " <Supplier(id= { self . id } , name= ' { self . name } ' )> "
class Customer ( Base ) :
""" 客户表 """
__tablename__ = " customers "
id = Column ( Integer , primary_key = True , index = True )
code = Column ( String ( 50 ) , unique = True , index = True )
name = Column ( String ( 200 ) , nullable = False )
contact_person = Column ( String ( 100 ) , nullable = True )
phone = Column ( String ( 50 ) , nullable = True )
email = Column ( String ( 100 ) , nullable = True )
address = Column ( Text , nullable = True )
bank_name = Column ( String ( 100 ) , nullable = True )
bank_account = Column ( String ( 50 ) , nullable = True )
tax_number = Column ( String ( 50 ) , nullable = True )
credit_limit = Column ( Numeric ( 12 , 2 ) , default = 0 )
is_active = Column ( Boolean , default = True )
created_at = Column ( DateTime , default = func . now ( ) )
updated_at = Column ( DateTime , default = func . now ( ) , onupdate = func . now ( ) )
sales_orders = relationship ( " SalesOrder " , back_populates = " customer " )
def __repr__ ( self ) :
return f " <Customer(id= { self . id } , name= ' { self . name } ' )> "
class Warehouse ( Base ) :
""" 仓库表 """
__tablename__ = " warehouses "
id = Column ( Integer , primary_key = True , index = True )
code = Column ( String ( 50 ) , unique = True , index = True )
name = Column ( String ( 200 ) , nullable = False )
address = Column ( Text , nullable = True )
manager = Column ( String ( 100 ) , nullable = True )
phone = Column ( String ( 50 ) , nullable = True )
is_active = Column ( Boolean , default = True )
is_default = Column ( Boolean , default = False )
created_at = Column ( DateTime , default = func . now ( ) )
inventories = relationship ( " Inventory " , back_populates = " warehouse " )
def __repr__ ( self ) :
return f " <Warehouse(id= { self . id } , name= ' { self . name } ' )> "
class Inventory ( Base ) :
""" 库存表 """
__tablename__ = " inventory "
__table_args__ = (
UniqueConstraint ( " product_id " , " warehouse_id " , name = " uq_inventory_product_warehouse " ) ,
CheckConstraint ( " quantity >= 0 AND locked_quantity >= 0 AND locked_quantity <= quantity " , name = " ck_inventory_qty_nonnegative " ) ,
)
id = Column ( Integer , primary_key = True , index = True )
product_id = Column ( Integer , ForeignKey ( " products.id " ) , nullable = False , index = True )
warehouse_id = Column ( Integer , ForeignKey ( " warehouses.id " ) , nullable = False , index = True )
quantity = Column ( Numeric ( 12 , 4 ) , default = 0 )
locked_quantity = Column ( Numeric ( 12 , 4 ) , default = 0 )
batch_number = Column ( String ( 50 ) , nullable = True )
location = Column ( String ( 100 ) , nullable = True )
updated_at = Column ( DateTime , default = func . now ( ) , onupdate = func . now ( ) )
product = relationship ( " Product " , back_populates = " inventory " )
warehouse = relationship ( " Warehouse " , back_populates = " inventories " )
def __repr__ ( self ) :
return f " <Inventory(product_id= { self . product_id } , quantity= { self . quantity } )> "
@property
def available_quantity ( self ) :
return self . quantity - self . locked_quantity
class StockMovement ( Base ) :
""" 库存变动记录表 """
__tablename__ = " stock_movements "
id = Column ( Integer , primary_key = True , index = True )
product_id = Column ( Integer , ForeignKey ( " products.id " ) , nullable = False , index = True )
warehouse_id = Column ( Integer , ForeignKey ( " warehouses.id " ) , nullable = False )
movement_type = Column ( String ( 20 ) , nullable = False )
quantity = Column ( Numeric ( 12 , 4 ) , nullable = False )
before_quantity = Column ( Numeric ( 12 , 4 ) , default = 0 )
after_quantity = Column ( Numeric ( 12 , 4 ) , default = 0 )
reference_type = Column ( String ( 50 ) , nullable = True )
reference_id = Column ( Integer , nullable = True )
reference_no = Column ( String ( 50 ) , nullable = True )
unit_price = Column ( Numeric ( 12 , 2 ) , nullable = True )
total_amount = Column ( Numeric ( 12 , 2 ) , nullable = True )
remark = Column ( Text , nullable = True )
operator_id = Column ( Integer , ForeignKey ( " users.id " ) , nullable = True )
created_at = Column ( DateTime , default = func . now ( ) , index = True )
product = relationship ( " Product " , back_populates = " stock_movements " )
def __repr__ ( self ) :
return f " <StockMovement(id= { self . id } , type= ' { self . movement_type } ' , qty= { self . quantity } )> "
class PurchaseOrder ( Base ) :
""" 采购订单表 """
__tablename__ = " purchase_orders "
id = Column ( Integer , primary_key = True , index = True )
order_no = Column ( String ( 50 ) , unique = True , index = True , nullable = False )
supplier_id = Column ( Integer , ForeignKey ( " suppliers.id " ) , nullable = False , index = True )
order_date = Column ( DateTime , default = func . now ( ) )
expected_date = Column ( Date , nullable = True )
status = Column ( String ( 20 ) , default = " draft " )
total_amount = Column ( Numeric ( 12 , 2 ) , default = 0 )
paid_amount = Column ( Numeric ( 12 , 2 ) , default = 0 )
remark = Column ( Text , nullable = True )
operator_id = Column ( Integer , ForeignKey ( " users.id " ) , nullable = True )
created_at = Column ( DateTime , default = func . now ( ) )
updated_at = Column ( DateTime , default = func . now ( ) , onupdate = func . now ( ) )
# 状态变更时间
received_date = Column ( DateTime , nullable = True ) # 已收货时间
paid_date = Column ( DateTime , nullable = True ) # 已付款时间
supplier = relationship ( " Supplier " , back_populates = " purchase_orders " )
items = relationship ( " PurchaseOrderItem " , back_populates = " order " , cascade = " all, delete-orphan " )
def __repr__ ( self ) :
return f " <PurchaseOrder(order_no= ' { self . order_no } ' , status= ' { self . status } ' )> "
class PurchaseOrderItem ( Base ) :
""" 采购订单明细表 """
__tablename__ = " purchase_order_items "
__table_args__ = (
CheckConstraint ( " quantity > 0 AND received_quantity >= 0 AND received_quantity <= quantity " , name = " ck_purchase_order_items_qty " ) ,
)
id = Column ( Integer , primary_key = True , index = True )
order_id = Column ( Integer , ForeignKey ( " purchase_orders.id " ) , nullable = False )
product_id = Column ( Integer , ForeignKey ( " products.id " ) , nullable = False )
quantity = Column ( Integer , nullable = False )
received_quantity = Column ( Integer , default = 0 )
unit_price = Column ( Numeric ( 12 , 2 ) , nullable = False )
amount = Column ( Numeric ( 12 , 2 ) , nullable = False )
remark = Column ( Text , nullable = True )
order = relationship ( " PurchaseOrder " , back_populates = " items " )
def __repr__ ( self ) :
return f " <PurchaseOrderItem(order_id= { self . order_id } , product_id= { self . product_id } )> "
class SalesOrder ( Base ) :
""" 销售订单表 """
__tablename__ = " sales_orders "
id = Column ( Integer , primary_key = True , index = True )
order_no = Column ( String ( 50 ) , unique = True , index = True , nullable = False )
customer_id = Column ( Integer , ForeignKey ( " customers.id " ) , nullable = False , index = True )
order_date = Column ( DateTime , default = func . now ( ) )
delivery_date = Column ( Date , nullable = True )
manufacturing_date = Column ( DateTime , nullable = True )
actual_delivery_date = Column ( DateTime , nullable = True )
actual_payment_date = Column ( DateTime , nullable = True )
status = Column ( String ( 20 ) , default = " draft " )
production_status = Column ( String ( 20 ) , default = " not_started " , index = True )
production_no = Column ( String ( 50 ) , nullable = True , index = True )
planned_material_cost = Column ( Numeric ( 12 , 2 ) , default = 0 )
actual_material_cost = Column ( Numeric ( 12 , 2 ) , default = 0 )
total_amount = Column ( Numeric ( 12 , 2 ) , default = 0 )
received_amount = Column ( Numeric ( 12 , 2 ) , default = 0 )
remark = Column ( Text , nullable = True )
operator_id = Column ( Integer , ForeignKey ( " users.id " ) , nullable = True )
created_at = Column ( DateTime , default = func . now ( ) )
updated_at = Column ( DateTime , default = func . now ( ) , onupdate = func . now ( ) )
customer = relationship ( " Customer " , back_populates = " sales_orders " )
items = relationship ( " SalesOrderItem " , back_populates = " order " , cascade = " all, delete-orphan " )
def __repr__ ( self ) :
return f " <SalesOrder(order_no= ' { self . order_no } ' , status= ' { self . status } ' )> "
class FinanceTransaction ( Base ) :
__tablename__ = " finance_transactions "
id = Column ( Integer , primary_key = True , index = True )
txn_no = Column ( String ( 50 ) , unique = True , index = True , nullable = False )
txn_type = Column ( String ( 20 ) , nullable = False , index = True )
partner_type = Column ( String ( 20 ) , nullable = False , index = True )
partner_id = Column ( Integer , nullable = False , index = True )
amount = Column ( Numeric ( 12 , 2 ) , nullable = False )
txn_date = Column ( DateTime , default = func . now ( ) , index = True )
method = Column ( String ( 30 ) , default = " bank " )
account_name = Column ( String ( 100 ) , nullable = True )
status = Column ( String ( 20 ) , default = " confirmed " , index = True )
remark = Column ( Text , nullable = True )
operator_id = Column ( Integer , ForeignKey ( " users.id " ) , nullable = True )
created_at = Column ( DateTime , default = func . now ( ) , index = True )
allocations = relationship ( " FinanceAllocation " , back_populates = " transaction " , cascade = " all, delete-orphan " )
def __repr__ ( self ) :
return f " <FinanceTransaction(txn_no= ' { self . txn_no } ' , txn_type= ' { self . txn_type } ' , amount= { self . amount } )> "
class FinanceAllocation ( Base ) :
__tablename__ = " finance_allocations "
id = Column ( Integer , primary_key = True , index = True )
transaction_id = Column ( Integer , ForeignKey ( " finance_transactions.id " ) , nullable = False , index = True )
order_type = Column ( String ( 20 ) , nullable = False , index = True )
order_id = Column ( Integer , nullable = False , index = True )
allocated_amount = Column ( Numeric ( 12 , 2 ) , nullable = False )
created_at = Column ( DateTime , default = func . now ( ) , index = True )
transaction = relationship ( " FinanceTransaction " , back_populates = " allocations " )
def __repr__ ( self ) :
return f " <FinanceAllocation(transaction_id= { self . transaction_id } , order_type= ' { self . order_type } ' , amount= { self . allocated_amount } )> "
class AnalysisMetrics ( Base ) :
""" 分析指标表 """
__tablename__ = " analysis_metrics "
id = Column ( Integer , primary_key = True , index = True )
stp_file_id = Column ( Integer , ForeignKey ( " stp_files.id " ) , nullable = False , index = True )
# 质量指标
volume_utilization = Column ( Float , default = 0 ) # 体积利用率
topology_complexity = Column ( Float , default = 0 ) # 拓扑复杂度
wall_uniformity = Column ( Float , default = 0 ) # 壁厚均匀性
# 分析摘要
analysis_summary = Column ( Text , nullable = True )
# FreeCAD 验证结果
verification_status = Column ( String ( 20 ) , nullable = True ) # passed, failed, pending, error
verification_volume_diff = Column ( Float , nullable = True ) # 体积差异百分比
verification_area_diff = Column ( Float , nullable = True ) # 表面积差异百分比
verification_details = Column ( JSON , nullable = True ) # 完整验证结果
# 时间戳
created_at = Column ( DateTime , default = func . now ( ) )
# 关联关系
stp_file = relationship ( " STPFile " , back_populates = " analysis_metrics " )
def __repr__ ( self ) :
return f " <AnalysisMetrics(stp_file_id= { self . stp_file_id } , volume_utilization= { self . volume_utilization } )> "
class SalesOrderItem ( Base ) :
""" 销售订单明细表 """
__tablename__ = " sales_order_items "
__table_args__ = (
CheckConstraint ( " quantity > 0 AND delivered_quantity >= 0 AND delivered_quantity <= quantity " , name = " ck_sales_order_items_qty " ) ,
)
id = Column ( Integer , primary_key = True , index = True )
order_id = Column ( Integer , ForeignKey ( " sales_orders.id " ) , nullable = False )
product_id = Column ( Integer , ForeignKey ( " products.id " ) , nullable = False )
quantity = Column ( Integer , nullable = False )
delivered_quantity = Column ( Integer , default = 0 )
unit_price = Column ( Numeric ( 12 , 2 ) , nullable = False )
amount = Column ( Numeric ( 12 , 2 ) , nullable = False )
remark = Column ( Text , nullable = True )
order = relationship ( " SalesOrder " , back_populates = " items " )
def __repr__ ( self ) :
return f " <SalesOrderItem(order_id= { self . order_id } , product_id= { self . product_id } )> "