# app/models/buy.py from app.extensions import db from datetime import datetime class StockBuy(db.Model): """ 采购入库库存表 对应数据库表: stock_buy """ __tablename__ = 'stock_buy' # 主键 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)) in_date = db.Column(db.Date) barcode = db.Column(db.String(100)) # 条码 serial_number = db.Column(db.String(100)) # 序列号 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)) # 在库/出库/损耗 inspection_status = db.Column(db.String(50)) # 未检/合格/不合格 warehouse_location = db.Column(db.String(100)) # --- 财务与商务 --- unit_price = db.Column(db.Numeric(19, 4), default=0) total_price = db.Column(db.Numeric(19, 4), default=0) currency = db.Column(db.String(20), default='CNY') exchange_rate = db.Column(db.Numeric(15, 6), default=1.0) supplier_name = db.Column(db.String(255)) # [关键映射区]:Python属性名 = DB列名 # 前端传 purchaser -> 存入 buyer_name buyer_name = db.Column(db.String(100)) # 前端传 purchaser_email -> 存入 buyer_email buyer_email = db.Column(db.String(100)) # 前端传 source_link -> 存入 original_link original_link = db.Column(db.Text) detail_link = db.Column(db.Text) arrival_photo = db.Column(db.Text) # [这就是报错缺失的字段],请确保执行了 ALTER TABLE remark = db.Column(db.Text) # 【关系定义】 # 建立与 MaterialBase 的关系,方便通过 stock.material 访问基础信息 material = db.relationship('MaterialBase', back_populates='stock_buys') def to_dict(self): """ 序列化:将模型转换为字典,主要用于单条查询或内部调用 列表查询主要依赖 Service 层的手动构建以提高性能 """ 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, 'inbound_date': self.in_date.strftime('%Y-%m-%d') if self.in_date else '', 'barcode': self.barcode, 'serial_number': self.serial_number, 'batch_number': self.batch_number, 'warehouse_loc': self.warehouse_location, 'status': self.status, 'inspection_status': self.inspection_status, 'remark': self.remark, # 数量 (转为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), # 兼容字段 # 财务 'unit_price': float(self.unit_price or 0), 'total_price': float(self.total_price or 0), 'currency': self.currency, 'exchange_rate': float(self.exchange_rate or 1.0), # 商务 (字段映射) 'supplier_name': self.supplier_name, 'purchaser': self.buyer_name, # 映射回前端 'purchaser_email': self.buyer_email, # 映射回前端 'source_link': self.original_link, # 映射回前端 'detail_link': self.detail_link, 'arrival_photo': self.arrival_photo }