This commit is contained in:
Iliyan Angelov
2025-11-17 18:26:30 +02:00
parent 48353cde9c
commit 0c59fe1173
2535 changed files with 278997 additions and 2480 deletions

View File

@@ -16,6 +16,8 @@ from .favorite import Favorite
from .audit_log import AuditLog
from .cookie_policy import CookiePolicy
from .cookie_integration_config import CookieIntegrationConfig
from .system_settings import SystemSettings
from .invoice import Invoice, InvoiceItem
__all__ = [
"Role",
@@ -36,5 +38,8 @@ __all__ = [
"AuditLog",
"CookiePolicy",
"CookieIntegrationConfig",
"SystemSettings",
"Invoice",
"InvoiceItem",
]

Binary file not shown.

View File

@@ -35,6 +35,7 @@ class Booking(Base):
user = relationship("User", back_populates="bookings")
room = relationship("Room", back_populates="bookings")
payments = relationship("Payment", back_populates="booking", cascade="all, delete-orphan")
invoices = relationship("Invoice", back_populates="booking", cascade="all, delete-orphan")
service_usages = relationship("ServiceUsage", back_populates="booking", cascade="all, delete-orphan")
checkin_checkout = relationship("CheckInCheckOut", back_populates="booking", uselist=False)

View File

@@ -0,0 +1,100 @@
from sqlalchemy import Column, Integer, String, DateTime, Numeric, Text, Enum, ForeignKey, Boolean
from sqlalchemy.orm import relationship
from datetime import datetime
import enum
from ..config.database import Base
class InvoiceStatus(str, enum.Enum):
draft = "draft"
sent = "sent"
paid = "paid"
overdue = "overdue"
cancelled = "cancelled"
class Invoice(Base):
__tablename__ = "invoices"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
invoice_number = Column(String(50), unique=True, nullable=False, index=True)
booking_id = Column(Integer, ForeignKey("bookings.id"), nullable=False)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
# Invoice details
issue_date = Column(DateTime, default=datetime.utcnow, nullable=False)
due_date = Column(DateTime, nullable=False)
paid_date = Column(DateTime, nullable=True)
# Amounts
subtotal = Column(Numeric(10, 2), nullable=False, default=0.00)
tax_rate = Column(Numeric(5, 2), nullable=False, default=0.00) # Tax percentage
tax_amount = Column(Numeric(10, 2), nullable=False, default=0.00)
discount_amount = Column(Numeric(10, 2), nullable=False, default=0.00)
total_amount = Column(Numeric(10, 2), nullable=False)
amount_paid = Column(Numeric(10, 2), nullable=False, default=0.00)
balance_due = Column(Numeric(10, 2), nullable=False)
# Status
status = Column(Enum(InvoiceStatus), nullable=False, default=InvoiceStatus.draft)
# Company/Organization information (for admin to manage)
company_name = Column(String(200), nullable=True)
company_address = Column(Text, nullable=True)
company_phone = Column(String(50), nullable=True)
company_email = Column(String(100), nullable=True)
company_tax_id = Column(String(100), nullable=True)
company_logo_url = Column(String(500), nullable=True)
# Customer information (snapshot at invoice creation)
customer_name = Column(String(200), nullable=False)
customer_email = Column(String(100), nullable=False)
customer_address = Column(Text, nullable=True)
customer_phone = Column(String(50), nullable=True)
customer_tax_id = Column(String(100), nullable=True)
# Additional information
notes = Column(Text, nullable=True)
terms_and_conditions = Column(Text, nullable=True)
payment_instructions = Column(Text, nullable=True)
# Metadata
created_by_id = Column(Integer, ForeignKey("users.id"), nullable=True)
updated_by_id = Column(Integer, ForeignKey("users.id"), nullable=True)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
# Relationships
booking = relationship("Booking", back_populates="invoices")
user = relationship("User", foreign_keys=[user_id], backref="invoices")
created_by = relationship("User", foreign_keys=[created_by_id])
updated_by = relationship("User", foreign_keys=[updated_by_id])
items = relationship("InvoiceItem", back_populates="invoice", cascade="all, delete-orphan")
class InvoiceItem(Base):
__tablename__ = "invoice_items"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
invoice_id = Column(Integer, ForeignKey("invoices.id"), nullable=False)
# Item details
description = Column(String(500), nullable=False)
quantity = Column(Numeric(10, 2), nullable=False, default=1.00)
unit_price = Column(Numeric(10, 2), nullable=False)
tax_rate = Column(Numeric(5, 2), nullable=False, default=0.00)
discount_amount = Column(Numeric(10, 2), nullable=False, default=0.00)
line_total = Column(Numeric(10, 2), nullable=False)
# Optional reference to booking items
room_id = Column(Integer, ForeignKey("rooms.id"), nullable=True)
service_id = Column(Integer, ForeignKey("services.id"), nullable=True)
# Metadata
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
# Relationships
invoice = relationship("Invoice", back_populates="items")
room = relationship("Room")
service = relationship("Service")

View File

@@ -11,6 +11,7 @@ class PaymentMethod(str, enum.Enum):
debit_card = "debit_card"
bank_transfer = "bank_transfer"
e_wallet = "e_wallet"
stripe = "stripe"
class PaymentType(str, enum.Enum):

View File

@@ -22,6 +22,9 @@ class Room(Base):
status = Column(Enum(RoomStatus), nullable=False, default=RoomStatus.available)
price = Column(Numeric(10, 2), nullable=False)
featured = Column(Boolean, nullable=False, default=False)
capacity = Column(Integer, nullable=True) # Room-specific capacity, overrides room_type capacity
room_size = Column(String(50), nullable=True) # e.g., "1 Room", "2 Rooms", "50 sqm"
view = Column(String(100), nullable=True) # e.g., "City View", "Ocean View", etc.
images = Column(JSON, nullable=True)
amenities = Column(JSON, nullable=True)
description = Column(Text, nullable=True)

View File

@@ -0,0 +1,21 @@
from sqlalchemy import Column, Integer, String, DateTime, Text, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
from ..config.database import Base
class SystemSettings(Base):
"""
System-wide settings controlled by administrators.
Stores key-value pairs for platform configuration like currency, etc.
"""
__tablename__ = "system_settings"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
key = Column(String(100), unique=True, nullable=False, index=True)
value = Column(Text, nullable=False)
description = Column(Text, nullable=True)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
updated_by_id = Column(Integer, ForeignKey("users.id"), nullable=True)
updated_by = relationship("User", lazy="joined")

View File

@@ -15,6 +15,7 @@ class User(Base):
phone = Column(String(20), nullable=True)
address = Column(Text, nullable=True)
avatar = Column(String(255), nullable=True)
currency = Column(String(3), nullable=False, default='VND') # ISO 4217 currency code
is_active = Column(Boolean, nullable=False, default=True)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)