""" 商品相关模型 """ from datetime import datetime from config.database import db import json class Category(db.Model): """商品分类模型""" __tablename__ = 'categories' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), nullable=False) parent_id = db.Column(db.Integer, default=0) level = db.Column(db.Integer, default=1) sort_order = db.Column(db.Integer, default=0) icon_url = db.Column(db.String(255)) is_active = db.Column(db.Integer, default=1) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) def to_dict(self): return { 'id': self.id, 'name': self.name, 'parent_id': self.parent_id, 'level': self.level, 'sort_order': self.sort_order, 'icon_url': self.icon_url, 'is_active': self.is_active, 'created_at': self.created_at.isoformat() if self.created_at else None } def __repr__(self): return f'' class SpecName(db.Model): """规格名称模型""" __tablename__ = 'spec_names' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), nullable=False) sort_order = db.Column(db.Integer, default=0) created_at = db.Column(db.DateTime, default=datetime.utcnow) def to_dict(self): return { 'id': self.id, 'name': self.name, 'sort_order': self.sort_order } def __repr__(self): return f'' class SpecValue(db.Model): """规格值模型""" __tablename__ = 'spec_values' id = db.Column(db.Integer, primary_key=True) spec_name_id = db.Column(db.Integer, db.ForeignKey('spec_names.id'), nullable=False) value = db.Column(db.String(100), nullable=False) sort_order = db.Column(db.Integer, default=0) created_at = db.Column(db.DateTime, default=datetime.utcnow) spec_name = db.relationship('SpecName', backref='values') def to_dict(self): return { 'id': self.id, 'spec_name_id': self.spec_name_id, 'value': self.value, 'sort_order': self.sort_order } def __repr__(self): return f'' class Product(db.Model): """商品模型""" __tablename__ = 'products' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(200), nullable=False) category_id = db.Column(db.Integer, db.ForeignKey('categories.id'), nullable=False) brand = db.Column(db.String(100)) price = db.Column(db.Numeric(10, 2), nullable=False) original_price = db.Column(db.Numeric(10, 2)) description = db.Column(db.Text) main_image = db.Column(db.String(255)) status = db.Column(db.Integer, default=1) # 0-下架 1-上架 has_specs = db.Column(db.Integer, default=0) # 0-无规格 1-有规格 sales_count = db.Column(db.Integer, default=0) view_count = db.Column(db.Integer, default=0) weight = db.Column(db.Numeric(8, 2)) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) category = db.relationship('Category', backref='products') def to_dict(self): return { 'id': self.id, 'name': self.name, 'category_id': self.category_id, 'category_name': self.category.name if self.category else '', 'brand': self.brand, 'price': float(self.price) if self.price else 0, 'original_price': float(self.original_price) if self.original_price else None, 'description': self.description, 'main_image': self.main_image, 'status': self.status, 'has_specs': self.has_specs, 'sales_count': self.sales_count, 'view_count': self.view_count, 'weight': float(self.weight) if self.weight else None, 'created_at': self.created_at.isoformat() if self.created_at else None, 'updated_at': self.updated_at.isoformat() if self.updated_at else None } def __repr__(self): return f'' class ProductImage(db.Model): """商品图片模型""" __tablename__ = 'product_images' id = db.Column(db.Integer, primary_key=True) product_id = db.Column(db.Integer, db.ForeignKey('products.id'), nullable=False) image_url = db.Column(db.String(255), nullable=False) sort_order = db.Column(db.Integer, default=0) is_main = db.Column(db.Integer, default=0) # 0-否 1-是 created_at = db.Column(db.DateTime, default=datetime.utcnow) product = db.relationship('Product', backref='images') def to_dict(self): return { 'id': self.id, 'product_id': self.product_id, 'image_url': self.image_url, 'sort_order': self.sort_order, 'is_main': self.is_main, 'created_at': self.created_at.isoformat() if self.created_at else None } def __repr__(self): return f'' class ProductSpecRelation(db.Model): """商品规格关联模型""" __tablename__ = 'product_spec_relations' id = db.Column(db.Integer, primary_key=True) product_id = db.Column(db.Integer, db.ForeignKey('products.id'), nullable=False) spec_name_id = db.Column(db.Integer, db.ForeignKey('spec_names.id'), nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) product = db.relationship('Product', backref='spec_relations') spec_name = db.relationship('SpecName') def __repr__(self): return f'' class ProductInventory(db.Model): """商品库存模型(SKU)""" __tablename__ = 'product_inventory' id = db.Column(db.Integer, primary_key=True) product_id = db.Column(db.Integer, db.ForeignKey('products.id'), nullable=False) sku_code = db.Column(db.String(100), unique=True, nullable=False) spec_combination = db.Column(db.JSON) price_adjustment = db.Column(db.Numeric(10, 2), default=0) stock = db.Column(db.Integer, nullable=False, default=0) warning_stock = db.Column(db.Integer, default=10) is_default = db.Column(db.Integer, default=0) status = db.Column(db.Integer, default=1) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) product = db.relationship('Product', backref='inventory') def get_final_price(self): """获取最终价格""" base_price = float(self.product.price) if self.product and self.product.price else 0 adjustment = float(self.price_adjustment) if self.price_adjustment else 0 return base_price + adjustment def to_dict(self): return { 'id': self.id, 'product_id': self.product_id, 'sku_code': self.sku_code, 'spec_combination': self.spec_combination, 'price_adjustment': float(self.price_adjustment) if self.price_adjustment else 0, 'final_price': self.get_final_price(), 'stock': self.stock, 'warning_stock': self.warning_stock, 'is_default': self.is_default, 'status': self.status, 'created_at': self.created_at.isoformat() if self.created_at else None } def __repr__(self): return f'' class InventoryLog(db.Model): """库存变更日志模型""" __tablename__ = 'inventory_logs' id = db.Column(db.Integer, primary_key=True) product_id = db.Column(db.Integer, db.ForeignKey('products.id'), nullable=False) sku_code = db.Column(db.String(100), nullable=False) change_type = db.Column(db.Integer, nullable=False) # 1-入库 2-出库 3-调整 change_quantity = db.Column(db.Integer, nullable=False) before_stock = db.Column(db.Integer, nullable=False) after_stock = db.Column(db.Integer, nullable=False) related_order_id = db.Column(db.Integer) remark = db.Column(db.String(255)) created_at = db.Column(db.DateTime, default=datetime.utcnow) product = db.relationship('Product') @classmethod def create_log(cls, product_id, sku_code, change_type, change_quantity, before_stock, after_stock, related_order_id=None, remark=None): """创建库存变更日志""" log = cls( product_id=product_id, sku_code=sku_code, change_type=change_type, change_quantity=change_quantity, before_stock=before_stock, after_stock=after_stock, related_order_id=related_order_id, remark=remark ) db.session.add(log) db.session.commit() return log def to_dict(self): return { 'id': self.id, 'product_id': self.product_id, 'sku_code': self.sku_code, 'change_type': self.change_type, 'change_quantity': self.change_quantity, 'before_stock': self.before_stock, 'after_stock': self.after_stock, 'related_order_id': self.related_order_id, 'remark': self.remark, 'created_at': self.created_at.isoformat() if self.created_at else None } def __repr__(self): return f''