Holy db migrations batman
This commit is contained in:
@@ -768,9 +768,9 @@ def _process_single_reservation(
|
||||
hotel_reservation_id=[hotel_res_id]
|
||||
)
|
||||
|
||||
if reservation.hotel_code is None:
|
||||
if reservation.hotel_id is None:
|
||||
raise ValueError("Reservation hotel_code is None")
|
||||
hotel_code = str(reservation.hotel_code)
|
||||
hotel_code = str(reservation.hotel_id)
|
||||
hotel_name = None if reservation.hotel_name is None else str(reservation.hotel_name)
|
||||
|
||||
basic_property_info = HotelReservation.ResGlobalInfo.BasicPropertyInfo(
|
||||
|
||||
@@ -138,7 +138,7 @@ async def push_listener(customer: DBCustomer, reservation: DBReservation, hotel)
|
||||
|
||||
server: AlpineBitsServer = app.state.alpine_bits_server
|
||||
hotel_id = hotel["hotel_id"]
|
||||
reservation_hotel_id = reservation.hotel_code
|
||||
reservation_hotel_id = reservation.hotel_id
|
||||
|
||||
# Double-check hotel matching (should be guaranteed by dispatcher)
|
||||
if hotel_id != reservation_hotel_id:
|
||||
|
||||
@@ -642,7 +642,7 @@ class ConversionService:
|
||||
|
||||
# Organize by hotel_code for efficient lookup
|
||||
for reservation in reservations:
|
||||
hotel_code = reservation.hotel_code
|
||||
hotel_code = reservation.hotel_id
|
||||
if hotel_code not in self._reservation_cache:
|
||||
self._reservation_cache[hotel_code] = []
|
||||
# Cache the hashed customer - prefer direct relationship, fall back to customer relationship
|
||||
@@ -1095,7 +1095,7 @@ class ConversionService:
|
||||
|
||||
# Add hotel filter if available
|
||||
if hotel_id:
|
||||
query = query.where(Reservation.hotel_code == hotel_id)
|
||||
query = query.where(Reservation.hotel_id == hotel_id)
|
||||
|
||||
# Execute query
|
||||
db_result = await session.execute(query)
|
||||
|
||||
@@ -472,7 +472,7 @@ class CSVImporter:
|
||||
num_adults=num_adults,
|
||||
num_children=num_children,
|
||||
children_ages=children_ages,
|
||||
hotel_code=final_hotel_code,
|
||||
hotel_id=final_hotel_code,
|
||||
hotel_name=final_hotel_name,
|
||||
offer=str(row.get("room_offer", "")).strip() or None,
|
||||
user_comment=str(row.get("message", "")).strip() or None,
|
||||
|
||||
@@ -27,7 +27,7 @@ from sqlalchemy.ext.asyncio import (
|
||||
async_sessionmaker,
|
||||
create_async_engine,
|
||||
)
|
||||
from sqlalchemy.orm import backref, declarative_base, relationship
|
||||
from sqlalchemy.orm import backref, declarative_base, foreign, relationship
|
||||
|
||||
from .const import WebhookStatus
|
||||
from .logging_config import get_logger
|
||||
@@ -435,7 +435,13 @@ class ConversionGuest(Base):
|
||||
last_seen = Column(DateTime(timezone=True))
|
||||
|
||||
# Relationships
|
||||
conversions = relationship("Conversion", back_populates="guest")
|
||||
conversions = relationship(
|
||||
"Conversion",
|
||||
back_populates="guest",
|
||||
foreign_keys="[Conversion.hotel_id, Conversion.guest_id]",
|
||||
primaryjoin="and_(ConversionGuest.hotel_id == foreign(Conversion.hotel_id), "
|
||||
"ConversionGuest.guest_id == foreign(Conversion.guest_id))",
|
||||
)
|
||||
hashed_customer = relationship("HashedCustomer", backref="conversion_guests")
|
||||
|
||||
@staticmethod
|
||||
@@ -541,8 +547,8 @@ class Reservation(Base):
|
||||
# Advertising account IDs (stored conditionally based on fbclid/gclid presence)
|
||||
meta_account_id = Column(String)
|
||||
google_account_id = Column(String)
|
||||
# Add hotel_code and hotel_name for XML
|
||||
hotel_code = Column(String)
|
||||
# Add hotel_id and hotel_name for XML
|
||||
hotel_id = Column(String, ForeignKey("hotels.hotel_id", ondelete="CASCADE"))
|
||||
hotel_name = Column(String)
|
||||
# RoomTypes fields (optional)
|
||||
room_type_code = Column(String)
|
||||
@@ -569,7 +575,7 @@ class AckedRequest(Base):
|
||||
) # Username of the client making the request
|
||||
unique_id = Column(
|
||||
String, index=True
|
||||
) # Should match Reservation.form_id or another unique field
|
||||
) # Matches the md5_unique_id in Reservation
|
||||
timestamp = Column(DateTime(timezone=True))
|
||||
|
||||
|
||||
@@ -646,13 +652,10 @@ class Conversion(Base):
|
||||
created_at = Column(DateTime(timezone=True)) # When this record was imported
|
||||
updated_at = Column(DateTime(timezone=True)) # When this record was last updated
|
||||
|
||||
# Composite foreign key constraint for ConversionGuest (hotel_id, guest_id)
|
||||
# Table constraints
|
||||
# Note: The relationship to ConversionGuest is handled via SQLAlchemy ORM
|
||||
# by matching (hotel_id, guest_id) pairs, no DB-level FK constraint needed
|
||||
__table_args__ = (
|
||||
ForeignKeyConstraint(
|
||||
["hotel_id", "guest_id"],
|
||||
["conversion_guests.hotel_id", "conversion_guests.guest_id"],
|
||||
ondelete="SET NULL",
|
||||
),
|
||||
UniqueConstraint(
|
||||
"hotel_id", "pms_reservation_id", name="uq_conversion_hotel_reservation"
|
||||
),
|
||||
@@ -662,7 +665,13 @@ class Conversion(Base):
|
||||
reservation = relationship("Reservation", backref="conversions")
|
||||
customer = relationship("Customer", backref="conversions")
|
||||
hashed_customer = relationship("HashedCustomer", backref="conversions")
|
||||
guest = relationship("ConversionGuest", back_populates="conversions")
|
||||
guest = relationship(
|
||||
"ConversionGuest",
|
||||
back_populates="conversions",
|
||||
foreign_keys="[Conversion.hotel_id, Conversion.guest_id]",
|
||||
primaryjoin="and_(Conversion.hotel_id == ConversionGuest.hotel_id, "
|
||||
"Conversion.guest_id == ConversionGuest.guest_id)",
|
||||
)
|
||||
conversion_rooms = relationship(
|
||||
"ConversionRoom", back_populates="conversion", cascade="all, delete-orphan"
|
||||
)
|
||||
|
||||
@@ -115,7 +115,7 @@ async def backfill_advertising_account_ids(
|
||||
sql = text(
|
||||
"UPDATE reservations "
|
||||
"SET meta_account_id = :meta_account "
|
||||
"WHERE hotel_code = :hotel_id "
|
||||
"WHERE hotel_id = :hotel_id "
|
||||
"AND fbclid IS NOT NULL "
|
||||
"AND fbclid != '' "
|
||||
"AND (meta_account_id IS NULL OR meta_account_id = '')"
|
||||
@@ -141,7 +141,7 @@ async def backfill_advertising_account_ids(
|
||||
sql = text(
|
||||
"UPDATE reservations "
|
||||
"SET google_account_id = :google_account "
|
||||
"WHERE hotel_code = :hotel_id "
|
||||
"WHERE hotel_id = :hotel_id "
|
||||
"AND gclid IS NOT NULL "
|
||||
"AND gclid != '' "
|
||||
"AND (google_account_id IS NULL OR google_account_id = '')"
|
||||
@@ -215,7 +215,7 @@ async def backfill_acked_requests_username(
|
||||
UPDATE acked_requests
|
||||
SET username = :username
|
||||
WHERE unique_id IN (
|
||||
SELECT md5_unique_id FROM reservations WHERE hotel_code = :hotel_id
|
||||
SELECT md5_unique_id FROM reservations WHERE hotel_id = :hotel_id
|
||||
)
|
||||
AND username IS NULL
|
||||
"""
|
||||
|
||||
@@ -523,10 +523,10 @@ class ReservationStatsCollector:
|
||||
async with self.async_sessionmaker() as session:
|
||||
# Query reservations created in the reporting period
|
||||
result = await session.execute(
|
||||
select(Reservation.hotel_code, func.count(Reservation.id))
|
||||
select(Reservation.hotel_id, func.count(Reservation.id))
|
||||
.where(Reservation.created_at >= period_start)
|
||||
.where(Reservation.created_at < period_end)
|
||||
.group_by(Reservation.hotel_code)
|
||||
.group_by(Reservation.hotel_id)
|
||||
)
|
||||
|
||||
hotel_counts = dict(result.all())
|
||||
|
||||
@@ -181,7 +181,7 @@ class ReservationService:
|
||||
if end_date:
|
||||
filters.append(Reservation.created_at <= end_date)
|
||||
if hotel_code:
|
||||
filters.append(Reservation.hotel_code == hotel_code)
|
||||
filters.append(Reservation.hotel_id == hotel_code)
|
||||
|
||||
if filters:
|
||||
query = query.where(and_(*filters))
|
||||
|
||||
@@ -131,7 +131,7 @@ class ReservationData(BaseModel):
|
||||
num_adults: int = Field(..., ge=1)
|
||||
num_children: int = Field(0, ge=0, le=10)
|
||||
children_ages: list[int] = Field(default_factory=list)
|
||||
hotel_code: str = Field(..., min_length=1, max_length=50)
|
||||
hotel_id: str = Field(..., min_length=1, max_length=50)
|
||||
hotel_name: str | None = Field(None, max_length=200)
|
||||
offer: str | None = Field(None, max_length=500)
|
||||
user_comment: str | None = Field(None, max_length=2000)
|
||||
|
||||
@@ -306,7 +306,7 @@ async def migrate_data(
|
||||
user_comment=reservation.user_comment,
|
||||
fbclid=reservation.fbclid,
|
||||
gclid=reservation.gclid,
|
||||
hotel_code=reservation.hotel_code,
|
||||
hotel_code=reservation.hotel_id,
|
||||
hotel_name=reservation.hotel_name,
|
||||
room_type_code=reservation.room_type_code,
|
||||
room_classification_code=reservation.room_classification_code,
|
||||
|
||||
@@ -247,7 +247,7 @@ async def process_wix_form_submission(
|
||||
num_adults=num_adults,
|
||||
num_children=num_children,
|
||||
children_ages=children_ages,
|
||||
hotel_code=hotel_code,
|
||||
hotel_id=hotel_code,
|
||||
hotel_name=hotel_name,
|
||||
offer=offer,
|
||||
created_at=submissionTime,
|
||||
@@ -575,7 +575,7 @@ async def process_generic_webhook_submission(
|
||||
"num_adults": num_adults,
|
||||
"num_children": num_children,
|
||||
"children_ages": children_ages,
|
||||
"hotel_code": hotel_code,
|
||||
"hotel_id": hotel_code,
|
||||
"hotel_name": hotel_name,
|
||||
"offer": selected_offers_str,
|
||||
"utm_source": utm_source,
|
||||
|
||||
Reference in New Issue
Block a user