update to python fastpi

This commit is contained in:
Iliyan Angelov
2025-11-16 15:59:05 +02:00
parent 93d4c1df80
commit 98ccd5b6ff
4464 changed files with 773233 additions and 13740 deletions

View File

@@ -0,0 +1,34 @@
from .role import Role
from .user import User
from .refresh_token import RefreshToken
from .password_reset_token import PasswordResetToken
from .room_type import RoomType
from .room import Room
from .booking import Booking
from .payment import Payment
from .service import Service
from .service_usage import ServiceUsage
from .promotion import Promotion
from .checkin_checkout import CheckInCheckOut
from .banner import Banner
from .review import Review
from .favorite import Favorite
__all__ = [
"Role",
"User",
"RefreshToken",
"PasswordResetToken",
"RoomType",
"Room",
"Booking",
"Payment",
"Service",
"ServiceUsage",
"Promotion",
"CheckInCheckOut",
"Banner",
"Review",
"Favorite",
]

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,31 @@
from sqlalchemy import Column, Integer, String, DateTime, Boolean, Text
from sqlalchemy.orm import relationship
from datetime import datetime
from ..config.database import Base
class Banner(Base):
__tablename__ = "banners"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
title = Column(String(100), nullable=False)
description = Column(Text, nullable=True)
image_url = Column(String(255), nullable=False)
link_url = Column(String(255), nullable=True)
position = Column(String(50), nullable=False, default="home")
display_order = Column(Integer, nullable=False, default=0)
is_active = Column(Boolean, nullable=False, default=True)
start_date = Column(DateTime, nullable=True)
end_date = Column(DateTime, nullable=True)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
def is_active_now(self):
from datetime import datetime
now = datetime.utcnow()
if not self.is_active:
return False
if not self.start_date or not self.end_date:
return self.is_active
return self.start_date <= now <= self.end_date

View File

@@ -0,0 +1,40 @@
from sqlalchemy import Column, Integer, String, DateTime, Numeric, Boolean, Text, Enum, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
import enum
from ..config.database import Base
class BookingStatus(str, enum.Enum):
pending = "pending"
confirmed = "confirmed"
checked_in = "checked_in"
checked_out = "checked_out"
cancelled = "cancelled"
class Booking(Base):
__tablename__ = "bookings"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
booking_number = Column(String(50), unique=True, nullable=False, index=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
room_id = Column(Integer, ForeignKey("rooms.id"), nullable=False)
check_in_date = Column(DateTime, nullable=False)
check_out_date = Column(DateTime, nullable=False)
num_guests = Column(Integer, nullable=False, default=1)
total_price = Column(Numeric(10, 2), nullable=False)
status = Column(Enum(BookingStatus), nullable=False, default=BookingStatus.pending)
deposit_paid = Column(Boolean, nullable=False, default=False)
requires_deposit = Column(Boolean, nullable=False, default=False)
special_requests = Column(Text, nullable=True)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
# Relationships
user = relationship("User", back_populates="bookings")
room = relationship("Room", back_populates="bookings")
payments = relationship("Payment", 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,27 @@
from sqlalchemy import Column, Integer, DateTime, Numeric, Text, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
from ..config.database import Base
class CheckInCheckOut(Base):
__tablename__ = "checkin_checkout"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
booking_id = Column(Integer, ForeignKey("bookings.id"), nullable=False, unique=True)
checkin_time = Column(DateTime, nullable=True)
checkout_time = Column(DateTime, nullable=True)
checkin_by = Column(Integer, ForeignKey("users.id"), nullable=True)
checkout_by = Column(Integer, ForeignKey("users.id"), nullable=True)
room_condition_checkin = Column(Text, nullable=True)
room_condition_checkout = Column(Text, nullable=True)
additional_charges = Column(Numeric(10, 2), nullable=False, default=0.0)
notes = Column(Text, 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="checkin_checkout")
checked_in_by = relationship("User", foreign_keys=[checkin_by], back_populates="checkins_processed")
checked_out_by = relationship("User", foreign_keys=[checkout_by], back_populates="checkouts_processed")

View File

@@ -0,0 +1,19 @@
from sqlalchemy import Column, Integer, ForeignKey, DateTime
from sqlalchemy.orm import relationship
from datetime import datetime
from ..config.database import Base
class Favorite(Base):
__tablename__ = "favorites"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
room_id = Column(Integer, ForeignKey("rooms.id"), nullable=False)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
# Relationships
user = relationship("User", back_populates="favorites")
room = relationship("Room", back_populates="favorites")

View File

@@ -0,0 +1,20 @@
from sqlalchemy import Column, Integer, String, DateTime, Boolean, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
from ..config.database import Base
class PasswordResetToken(Base):
__tablename__ = "password_reset_tokens"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
token = Column(String(255), unique=True, nullable=False, index=True)
expires_at = Column(DateTime, nullable=False)
used = Column(Boolean, default=False, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
# Relationships
user = relationship("User")

View File

@@ -0,0 +1,49 @@
from sqlalchemy import Column, Integer, String, DateTime, Numeric, Text, Enum, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
import enum
from ..config.database import Base
class PaymentMethod(str, enum.Enum):
cash = "cash"
credit_card = "credit_card"
debit_card = "debit_card"
bank_transfer = "bank_transfer"
e_wallet = "e_wallet"
class PaymentType(str, enum.Enum):
full = "full"
deposit = "deposit"
remaining = "remaining"
class PaymentStatus(str, enum.Enum):
pending = "pending"
completed = "completed"
failed = "failed"
refunded = "refunded"
class Payment(Base):
__tablename__ = "payments"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
booking_id = Column(Integer, ForeignKey("bookings.id"), nullable=False)
amount = Column(Numeric(10, 2), nullable=False)
payment_method = Column(Enum(PaymentMethod), nullable=False)
payment_type = Column(Enum(PaymentType), nullable=False, default=PaymentType.full)
deposit_percentage = Column(Integer, nullable=True)
related_payment_id = Column(Integer, ForeignKey("payments.id"), nullable=True)
payment_status = Column(Enum(PaymentStatus), nullable=False, default=PaymentStatus.pending)
transaction_id = Column(String(100), nullable=True)
payment_date = Column(DateTime, nullable=True)
notes = Column(Text, 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="payments")
related_payment = relationship("Payment", remote_side=[id], backref="related_payments")

View File

@@ -0,0 +1,60 @@
from sqlalchemy import Column, Integer, String, DateTime, Numeric, Boolean, Text, Enum
from sqlalchemy.orm import relationship
from datetime import datetime
import enum
from ..config.database import Base
class DiscountType(str, enum.Enum):
percentage = "percentage"
fixed_amount = "fixed_amount"
class Promotion(Base):
__tablename__ = "promotions"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
code = Column(String(50), unique=True, nullable=False, index=True)
name = Column(String(100), nullable=False)
description = Column(Text, nullable=True)
discount_type = Column(Enum(DiscountType), nullable=False)
discount_value = Column(Numeric(10, 2), nullable=False)
min_booking_amount = Column(Numeric(10, 2), nullable=True)
max_discount_amount = Column(Numeric(10, 2), nullable=True)
start_date = Column(DateTime, nullable=False)
end_date = Column(DateTime, nullable=False)
usage_limit = Column(Integer, nullable=True)
used_count = Column(Integer, nullable=False, default=0)
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)
def is_valid(self):
from datetime import datetime
now = datetime.utcnow()
if not self.is_active:
return False
if now < self.start_date or now > self.end_date:
return False
if self.usage_limit is not None and self.used_count >= self.usage_limit:
return False
return True
def calculate_discount(self, booking_amount):
if not self.is_valid():
return 0.0
if self.min_booking_amount and booking_amount < float(self.min_booking_amount):
return 0.0
discount = 0.0
if self.discount_type == DiscountType.percentage:
discount = float(booking_amount) * float(self.discount_value) / 100.0
elif self.discount_type == DiscountType.fixed_amount:
discount = float(self.discount_value)
if self.max_discount_amount and discount > float(self.max_discount_amount):
discount = float(self.max_discount_amount)
return discount

View File

@@ -0,0 +1,18 @@
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
from ..config.database import Base
class RefreshToken(Base):
__tablename__ = "refresh_tokens"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
token = Column(String(500), unique=True, nullable=False, index=True)
expires_at = Column(DateTime, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
# Relationships
user = relationship("User", back_populates="refresh_tokens")

View File

@@ -0,0 +1,29 @@
from sqlalchemy import Column, Integer, Text, Enum, ForeignKey, DateTime
from sqlalchemy.orm import relationship
from datetime import datetime
import enum
from ..config.database import Base
class ReviewStatus(str, enum.Enum):
pending = "pending"
approved = "approved"
rejected = "rejected"
class Review(Base):
__tablename__ = "reviews"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
room_id = Column(Integer, ForeignKey("rooms.id"), nullable=False)
rating = Column(Integer, nullable=False)
comment = Column(Text, nullable=False)
status = Column(Enum(ReviewStatus), nullable=False, default=ReviewStatus.pending)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
# Relationships
user = relationship("User", back_populates="reviews")
room = relationship("Room", back_populates="reviews")

View File

@@ -0,0 +1,18 @@
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.orm import relationship
from datetime import datetime
from ..config.database import Base
class Role(Base):
__tablename__ = "roles"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
name = Column(String(50), unique=True, nullable=False, index=True)
description = Column(String(255), nullable=True)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
# Relationships
users = relationship("User", back_populates="role")

View File

@@ -0,0 +1,36 @@
from sqlalchemy import Column, Integer, String, Numeric, Boolean, Text, JSON, Enum, ForeignKey, DateTime
from sqlalchemy.orm import relationship
from datetime import datetime
import enum
from ..config.database import Base
class RoomStatus(str, enum.Enum):
available = "available"
occupied = "occupied"
maintenance = "maintenance"
cleaning = "cleaning"
class Room(Base):
__tablename__ = "rooms"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
room_type_id = Column(Integer, ForeignKey("room_types.id"), nullable=False)
room_number = Column(String(20), unique=True, nullable=False, index=True)
floor = Column(Integer, nullable=False)
status = Column(Enum(RoomStatus), nullable=False, default=RoomStatus.available)
price = Column(Numeric(10, 2), nullable=False)
featured = Column(Boolean, nullable=False, default=False)
images = Column(JSON, nullable=True)
amenities = Column(JSON, nullable=True)
description = Column(Text, nullable=True)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
# Relationships
room_type = relationship("RoomType", back_populates="rooms")
bookings = relationship("Booking", back_populates="room")
reviews = relationship("Review", back_populates="room")
favorites = relationship("Favorite", back_populates="room", cascade="all, delete-orphan")

View File

@@ -0,0 +1,21 @@
from sqlalchemy import Column, Integer, String, Numeric, Text, JSON, DateTime
from sqlalchemy.orm import relationship
from datetime import datetime
from ..config.database import Base
class RoomType(Base):
__tablename__ = "room_types"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
name = Column(String(100), unique=True, nullable=False)
description = Column(Text, nullable=True)
base_price = Column(Numeric(10, 2), nullable=False)
capacity = Column(Integer, nullable=False)
amenities = Column(JSON, nullable=True)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
# Relationships
rooms = relationship("Room", back_populates="room_type")

View File

@@ -0,0 +1,21 @@
from sqlalchemy import Column, Integer, String, Numeric, Boolean, Text, DateTime
from sqlalchemy.orm import relationship
from datetime import datetime
from ..config.database import Base
class Service(Base):
__tablename__ = "services"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
name = Column(String(100), nullable=False)
description = Column(Text, nullable=True)
price = Column(Numeric(10, 2), nullable=False)
category = Column(String(50), nullable=True)
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)
# Relationships
service_usages = relationship("ServiceUsage", back_populates="service")

View File

@@ -0,0 +1,24 @@
from sqlalchemy import Column, Integer, DateTime, Numeric, Text, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
from ..config.database import Base
class ServiceUsage(Base):
__tablename__ = "service_usages"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
booking_id = Column(Integer, ForeignKey("bookings.id"), nullable=False)
service_id = Column(Integer, ForeignKey("services.id"), nullable=False)
quantity = Column(Integer, nullable=False, default=1)
unit_price = Column(Numeric(10, 2), nullable=False)
total_price = Column(Numeric(10, 2), nullable=False)
usage_date = Column(DateTime, nullable=False, default=datetime.utcnow)
notes = Column(Text, 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="service_usages")
service = relationship("Service", back_populates="service_usages")

View File

@@ -0,0 +1,30 @@
from sqlalchemy import Column, Integer, String, Boolean, Text, ForeignKey, DateTime
from sqlalchemy.orm import relationship
from datetime import datetime
from ..config.database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
role_id = Column(Integer, ForeignKey("roles.id"), nullable=False)
email = Column(String(100), unique=True, nullable=False, index=True)
password = Column(String(255), nullable=False)
full_name = Column(String(100), nullable=False)
phone = Column(String(20), nullable=True)
address = Column(Text, nullable=True)
avatar = Column(String(255), nullable=True)
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)
# Relationships
role = relationship("Role", back_populates="users")
bookings = relationship("Booking", back_populates="user")
refresh_tokens = relationship("RefreshToken", back_populates="user", cascade="all, delete-orphan")
checkins_processed = relationship("CheckInCheckOut", foreign_keys="CheckInCheckOut.checkin_by", back_populates="checked_in_by")
checkouts_processed = relationship("CheckInCheckOut", foreign_keys="CheckInCheckOut.checkout_by", back_populates="checked_out_by")
reviews = relationship("Review", back_populates="user")
favorites = relationship("Favorite", back_populates="user", cascade="all, delete-orphan")