|
""" |
|
SQLAlchemy 資料庫模型 - 基於進銷存系統 |
|
""" |
|
|
|
from sqlalchemy import Column, Integer, String, Text, DECIMAL, Boolean, DateTime, ForeignKey, JSON, Date, Float, Enum |
|
from sqlalchemy.sql import func |
|
from sqlalchemy.orm import relationship |
|
from backend.database.connection import Base |
|
import enum |
|
|
|
|
|
class UserRole(str, enum.Enum): |
|
ADMIN = "ADMIN" |
|
USER = "USER" |
|
|
|
class TransactionType(str, enum.Enum): |
|
PURCHASE = "PURCHASE" |
|
SELL = "SELL" |
|
|
|
class TransactionStatus(str, enum.Enum): |
|
PENDING = "PENDING" |
|
PROCESSING = "PROCESSING" |
|
COMPLETED = "COMPLETED" |
|
CANCELLED = "CANCELLED" |
|
|
|
class PurchaseOrderStatus(str, enum.Enum): |
|
DRAFT = "DRAFT" |
|
PENDING = "PENDING" |
|
CONFIRMED = "CONFIRMED" |
|
RECEIVED = "RECEIVED" |
|
CANCELLED = "CANCELLED" |
|
|
|
class SalesOrderStatus(str, enum.Enum): |
|
DRAFT = "DRAFT" |
|
CONFIRMED = "CONFIRMED" |
|
SHIPPED = "SHIPPED" |
|
DELIVERED = "DELIVERED" |
|
CANCELLED = "CANCELLED" |
|
|
|
class PaymentStatus(str, enum.Enum): |
|
UNPAID = "UNPAID" |
|
PARTIAL = "PARTIAL" |
|
PAID = "PAID" |
|
|
|
|
|
class User(Base): |
|
"""用戶模型""" |
|
__tablename__ = "users" |
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True) |
|
name = Column(String(255)) |
|
email = Column(String(255), unique=True, nullable=False) |
|
phoneNumber = Column(String(50)) |
|
role = Column(Enum(UserRole), default=UserRole.USER) |
|
createdAt = Column(DateTime(timezone=True), server_default=func.now()) |
|
|
|
|
|
purchase_orders = relationship("PurchaseOrder", back_populates="purchaser") |
|
sales_orders = relationship("SalesOrder", back_populates="salesperson") |
|
|
|
class Category(Base): |
|
"""商品類別模型""" |
|
__tablename__ = "categories" |
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True) |
|
name = Column(String(255), nullable=False) |
|
|
|
|
|
products = relationship("Product", back_populates="category") |
|
|
|
class Product(Base): |
|
"""商品模型""" |
|
__tablename__ = "products" |
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True) |
|
productCode = Column(String(100), unique=True, nullable=False) |
|
productName = Column(String(255), nullable=False) |
|
unit = Column(String(50), nullable=False) |
|
warehouse = Column(String(100)) |
|
unitWeight = Column(Float) |
|
barcode = Column(String(100)) |
|
category_id = Column(Integer, ForeignKey("categories.id")) |
|
stock = Column(Integer, default=0) |
|
is_deleted = Column(Boolean, default=False) |
|
deleted_at = Column(DateTime(timezone=True)) |
|
deleted_by = Column(Integer) |
|
createdAt = Column(DateTime(timezone=True), server_default=func.now()) |
|
updatedAt = Column(DateTime(timezone=True), onupdate=func.now()) |
|
|
|
|
|
category = relationship("Category", back_populates="products") |
|
purchase_order_items = relationship("PurchaseOrderItem", back_populates="product") |
|
sales_order_items = relationship("SalesOrderItem", back_populates="product") |
|
|
|
class Supplier(Base): |
|
"""供應商模型""" |
|
__tablename__ = "suppliers" |
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True) |
|
name = Column(String(255), nullable=False) |
|
contactInfo = Column(Text) |
|
address = Column(Text) |
|
|
|
|
|
purchase_orders = relationship("PurchaseOrder", back_populates="supplier") |
|
|
|
class Customer(Base): |
|
"""客戶模型""" |
|
__tablename__ = "customers" |
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True) |
|
customerType = Column(String(100)) |
|
salesPersonId = Column(String(100)) |
|
salesPersonName = Column(String(255)) |
|
customerCode = Column(String(100), unique=True, nullable=False) |
|
customerName = Column(String(255), nullable=False) |
|
contactPerson = Column(String(255)) |
|
invoiceTitle = Column(String(255)) |
|
taxId = Column(String(50)) |
|
phoneNumber = Column(String(50)) |
|
faxNumber = Column(String(50)) |
|
deliveryAddress = Column(Text) |
|
businessHours = Column(String(255)) |
|
paymentMethod = Column(String(100)) |
|
paymentCategory = Column(String(100)) |
|
creditLimit = Column(Float, default=0.0) |
|
createdDate = Column(DateTime(timezone=True), server_default=func.now()) |
|
updatedAt = Column(DateTime(timezone=True), onupdate=func.now()) |
|
|
|
|
|
sales_orders = relationship("SalesOrder", back_populates="customer") |
|
|
|
class PurchaseOrder(Base): |
|
"""採購單模型""" |
|
__tablename__ = "purchase_orders" |
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True) |
|
po_number = Column(String(100), unique=True, nullable=False) |
|
purchase_date = Column(Date, nullable=False) |
|
expected_delivery_date = Column(Date) |
|
supplier_id = Column(Integer, ForeignKey("suppliers.id")) |
|
purchaser_id = Column(Integer, ForeignKey("users.id")) |
|
status = Column(Enum(PurchaseOrderStatus), default=PurchaseOrderStatus.DRAFT) |
|
subtotal = Column(Float, default=0.0) |
|
tax_amount = Column(Float, default=0.0) |
|
total_amount = Column(Float, default=0.0) |
|
payment_status = Column(Enum(PaymentStatus), default=PaymentStatus.UNPAID) |
|
notes = Column(Text) |
|
created_at = Column(DateTime(timezone=True), server_default=func.now()) |
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now()) |
|
|
|
|
|
supplier = relationship("Supplier", back_populates="purchase_orders") |
|
purchaser = relationship("User", back_populates="purchase_orders") |
|
items = relationship("PurchaseOrderItem", back_populates="purchase_order") |
|
|
|
class PurchaseOrderItem(Base): |
|
"""採購單明細模型""" |
|
__tablename__ = "purchase_order_items" |
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True) |
|
purchase_order_id = Column(Integer, ForeignKey("purchase_orders.id")) |
|
product_id = Column(Integer, ForeignKey("products.id")) |
|
quantity = Column(Integer, nullable=False) |
|
unit_price = Column(Float, nullable=False) |
|
line_total = Column(Float, nullable=False) |
|
notes = Column(Text) |
|
created_at = Column(DateTime(timezone=True), server_default=func.now()) |
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now()) |
|
|
|
|
|
purchase_order = relationship("PurchaseOrder", back_populates="items") |
|
product = relationship("Product", back_populates="purchase_order_items") |
|
|
|
class SalesOrder(Base): |
|
"""銷售單模型""" |
|
__tablename__ = "sales_orders" |
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True) |
|
so_number = Column(String(100), unique=True, nullable=False) |
|
sales_date = Column(Date, nullable=False) |
|
customer_id = Column(Integer, ForeignKey("customers.id")) |
|
salesperson_id = Column(Integer, ForeignKey("users.id")) |
|
status = Column(Enum(SalesOrderStatus), default=SalesOrderStatus.DRAFT) |
|
subtotal = Column(Float, default=0.0) |
|
tax_amount = Column(Float, default=0.0) |
|
discount_amount = Column(Float, default=0.0) |
|
total_amount = Column(Float, default=0.0) |
|
notes = Column(Text) |
|
created_at = Column(DateTime(timezone=True), server_default=func.now()) |
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now()) |
|
|
|
|
|
customer = relationship("Customer", back_populates="sales_orders") |
|
salesperson = relationship("User", back_populates="sales_orders") |
|
items = relationship("SalesOrderItem", back_populates="sales_order") |
|
|
|
class SalesOrderItem(Base): |
|
"""銷售單明細模型""" |
|
__tablename__ = "sales_order_items" |
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True) |
|
sales_order_id = Column(Integer, ForeignKey("sales_orders.id")) |
|
product_id = Column(Integer, ForeignKey("products.id")) |
|
quantity = Column(Integer, nullable=False) |
|
unit_price = Column(Float, nullable=False) |
|
line_total = Column(Float, nullable=False) |
|
notes = Column(Text) |
|
created_at = Column(DateTime(timezone=True), server_default=func.now()) |
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now()) |
|
|
|
|
|
sales_order = relationship("SalesOrder", back_populates="items") |
|
product = relationship("Product", back_populates="sales_order_items") |
|
|
|
|
|
class LineMessage(Base): |
|
"""LINE 訊息記錄模型""" |
|
__tablename__ = "line_messages" |
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True) |
|
user_id = Column(String(255)) |
|
message = Column(Text, nullable=False) |
|
message_type = Column(String(50), default="text") |
|
timestamp = Column(DateTime(timezone=True), server_default=func.now()) |
|
processed = Column(Boolean, default=False) |