Fixed unique_id issue in reservation table
This commit is contained in:
@@ -681,7 +681,7 @@ def create_xml_from_db(list: list[Tuple[Reservation, Customer]]):
|
|||||||
|
|
||||||
for reservation, customer in list:
|
for reservation, customer in list:
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
f"Creating XML for reservation {reservation.form_id} and customer {customer.given_name}"
|
f"Creating XML for reservation {reservation.unique_id} and customer {customer.given_name}"
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -718,10 +718,7 @@ def create_xml_from_db(list: list[Tuple[Reservation, Customer]]):
|
|||||||
reservation.num_adults, children_ages
|
reservation.num_adults, children_ages
|
||||||
)
|
)
|
||||||
|
|
||||||
unique_id_string = reservation.form_id
|
unique_id_string = reservation.unique_id
|
||||||
|
|
||||||
if len(unique_id_string) > 32:
|
|
||||||
unique_id_string = unique_id_string[:32] # Truncate to 32 characters
|
|
||||||
|
|
||||||
# UniqueID
|
# UniqueID
|
||||||
unique_id = OtaResRetrieveRs.ReservationsList.HotelReservation.UniqueId(
|
unique_id = OtaResRetrieveRs.ReservationsList.HotelReservation.UniqueId(
|
||||||
@@ -828,7 +825,7 @@ def create_xml_from_db(list: list[Tuple[Reservation, Customer]]):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
f"Error creating XML for reservation {reservation.form_id} and customer {customer.given_name}: {e}"
|
f"Error creating XML for reservation {reservation.unique_id} and customer {customer.given_name}: {e}"
|
||||||
)
|
)
|
||||||
|
|
||||||
retrieved_reservations = OtaResRetrieveRs.ReservationsList(
|
retrieved_reservations = OtaResRetrieveRs.ReservationsList(
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ from xsdata.formats.dataclass.serializers.config import SerializerConfig
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from xsdata_pydantic.bindings import XmlParser
|
from xsdata_pydantic.bindings import XmlParser
|
||||||
import logging
|
import logging
|
||||||
from .db import Reservation, Customer
|
from .db import AckedRequest, Reservation, Customer
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
|
|
||||||
@@ -493,6 +493,8 @@ class ReadAction(AlpineBitsAction):
|
|||||||
|
|
||||||
# query all reservations for this hotel from the database, where start_date is greater than or equal to the given start_date
|
# query all reservations for this hotel from the database, where start_date is greater than or equal to the given start_date
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
stmt = (
|
stmt = (
|
||||||
select(Reservation, Customer)
|
select(Reservation, Customer)
|
||||||
.join(Customer, Reservation.customer_id == Customer.id)
|
.join(Customer, Reservation.customer_id == Customer.id)
|
||||||
@@ -500,6 +502,20 @@ class ReadAction(AlpineBitsAction):
|
|||||||
)
|
)
|
||||||
if start_date:
|
if start_date:
|
||||||
stmt = stmt.filter(Reservation.start_date >= start_date)
|
stmt = stmt.filter(Reservation.start_date >= start_date)
|
||||||
|
else:
|
||||||
|
# remove reservations that have been acknowledged via client_id
|
||||||
|
if client_info.client_id:
|
||||||
|
subquery = (
|
||||||
|
select(Reservation.id)
|
||||||
|
.join(
|
||||||
|
AckedRequest,
|
||||||
|
AckedRequest.unique_id == Reservation.unique_id,
|
||||||
|
)
|
||||||
|
.filter(AckedRequest.client_id == client_info.client_id)
|
||||||
|
)
|
||||||
|
stmt = stmt.filter(~Reservation.id.in_(subquery))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
result = await dbsession.execute(stmt)
|
result = await dbsession.execute(stmt)
|
||||||
reservation_customer_pairs: list[tuple[Reservation, Customer]] = (
|
reservation_customer_pairs: list[tuple[Reservation, Customer]] = (
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from .config_loader import load_config
|
|||||||
from fastapi.responses import HTMLResponse, PlainTextResponse, Response
|
from fastapi.responses import HTMLResponse, PlainTextResponse, Response
|
||||||
from .models import WixFormSubmission
|
from .models import WixFormSubmission
|
||||||
from datetime import datetime, date, timezone
|
from datetime import datetime, date, timezone
|
||||||
from .auth import validate_api_key, validate_wix_signature, generate_api_key
|
from .auth import generate_unique_id, validate_api_key, validate_wix_signature, generate_api_key
|
||||||
from .rate_limit import (
|
from .rate_limit import (
|
||||||
limiter,
|
limiter,
|
||||||
webhook_limiter,
|
webhook_limiter,
|
||||||
@@ -280,12 +280,16 @@ async def process_wix_form_submission(request: Request, data: Dict[str, Any], db
|
|||||||
("utm_Term", "utm_term"),
|
("utm_Term", "utm_term"),
|
||||||
("utm_Content", "utm_content"),
|
("utm_Content", "utm_content"),
|
||||||
]
|
]
|
||||||
utm_comment_text = []
|
|
||||||
for label, field in utm_fields:
|
# get submissionId and ensure max length 35. Generate one if not present
|
||||||
val = data.get(f"field:{field}") or data.get(label)
|
|
||||||
if val:
|
unique_id = data.get("submissionId", generate_unique_id())
|
||||||
utm_comment_text.append(f"{label}: {val}")
|
|
||||||
utm_comment = ",".join(utm_comment_text) if utm_comment_text else None
|
if len(unique_id) > 35:
|
||||||
|
# strip to first 35 chars
|
||||||
|
unique_id = unique_id[:35]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# use database session
|
# use database session
|
||||||
|
|
||||||
@@ -309,19 +313,19 @@ async def process_wix_form_submission(request: Request, data: Dict[str, Any], db
|
|||||||
name_title=None,
|
name_title=None,
|
||||||
)
|
)
|
||||||
db.add(db_customer)
|
db.add(db_customer)
|
||||||
await db.commit()
|
await db.flush() # This assigns db_customer.id without committing
|
||||||
await db.refresh(db_customer)
|
#await db.refresh(db_customer)
|
||||||
|
|
||||||
|
|
||||||
db_reservation = DBReservation(
|
db_reservation = DBReservation(
|
||||||
customer_id=db_customer.id,
|
customer_id=db_customer.id,
|
||||||
form_id=data.get("submissionId"),
|
unique_id=unique_id,
|
||||||
start_date=date.fromisoformat(start_date) if start_date else None,
|
start_date=date.fromisoformat(start_date) if start_date else None,
|
||||||
end_date=date.fromisoformat(end_date) if end_date else None,
|
end_date=date.fromisoformat(end_date) if end_date else None,
|
||||||
num_adults=num_adults,
|
num_adults=num_adults,
|
||||||
num_children=num_children,
|
num_children=num_children,
|
||||||
children_ages=",".join(str(a) for a in children_ages),
|
children_ages=",".join(str(a) for a in children_ages),
|
||||||
offer=offer,
|
offer=offer,
|
||||||
utm_comment=utm_comment,
|
|
||||||
created_at=datetime.now(timezone.utc),
|
created_at=datetime.now(timezone.utc),
|
||||||
utm_source=data.get("field:utm_source"),
|
utm_source=data.get("field:utm_source"),
|
||||||
utm_medium=data.get("field:utm_medium"),
|
utm_medium=data.get("field:utm_medium"),
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ if os.getenv("WIX_API_KEY"):
|
|||||||
if os.getenv("ADMIN_API_KEY"):
|
if os.getenv("ADMIN_API_KEY"):
|
||||||
API_KEYS["admin-key"] = os.getenv("ADMIN_API_KEY")
|
API_KEYS["admin-key"] = os.getenv("ADMIN_API_KEY")
|
||||||
|
|
||||||
|
def generate_unique_id() -> str:
|
||||||
|
"""Generate a unique ID with max length 35 characters"""
|
||||||
|
return secrets.token_urlsafe(26)[:35] # 26 bytes -> 35 chars in base64url
|
||||||
|
|
||||||
|
|
||||||
def generate_api_key() -> str:
|
def generate_api_key() -> str:
|
||||||
"""Generate a secure API key"""
|
"""Generate a secure API key"""
|
||||||
|
|||||||
@@ -44,14 +44,13 @@ class Reservation(Base):
|
|||||||
__tablename__ = "reservations"
|
__tablename__ = "reservations"
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
customer_id = Column(Integer, ForeignKey("customers.id"))
|
customer_id = Column(Integer, ForeignKey("customers.id"))
|
||||||
form_id = Column(String, unique=True)
|
unique_id = Column(String(35), unique=True) # max length 35
|
||||||
start_date = Column(Date)
|
start_date = Column(Date)
|
||||||
end_date = Column(Date)
|
end_date = Column(Date)
|
||||||
num_adults = Column(Integer)
|
num_adults = Column(Integer)
|
||||||
num_children = Column(Integer)
|
num_children = Column(Integer)
|
||||||
children_ages = Column(String) # comma-separated
|
children_ages = Column(String) # comma-separated
|
||||||
offer = Column(String)
|
offer = Column(String)
|
||||||
utm_comment = Column(String)
|
|
||||||
created_at = Column(DateTime)
|
created_at = Column(DateTime)
|
||||||
# Add all UTM fields and user comment for XML
|
# Add all UTM fields and user comment for XML
|
||||||
utm_source = Column(String)
|
utm_source = Column(String)
|
||||||
@@ -68,11 +67,11 @@ class Reservation(Base):
|
|||||||
customer = relationship("Customer", back_populates="reservations")
|
customer = relationship("Customer", back_populates="reservations")
|
||||||
|
|
||||||
|
|
||||||
class HashedCustomer(Base):
|
|
||||||
__tablename__ = "hashed_customers"
|
# Table for tracking acknowledged requests by client
|
||||||
|
class AckedRequest(Base):
|
||||||
|
__tablename__ = 'acked_requests'
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
customer_id = Column(Integer)
|
client_id = Column(String, index=True)
|
||||||
hashed_email = Column(String)
|
unique_id = Column(String, index=True) # Should match Reservation.form_id or another unique field
|
||||||
hashed_phone = Column(String)
|
timestamp = Column(DateTime)
|
||||||
hashed_name = Column(String)
|
|
||||||
redacted_at = Column(DateTime)
|
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ def create_xml_from_db(customer: DBCustomer, reservation: DBReservation):
|
|||||||
|
|
||||||
# UniqueID
|
# UniqueID
|
||||||
unique_id = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.UniqueId(
|
unique_id = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.UniqueId(
|
||||||
type_value=ab.UniqueIdType2.VALUE_14, id=reservation.form_id
|
type_value=ab.UniqueIdType2.VALUE_14, id=reservation.unique_id
|
||||||
)
|
)
|
||||||
|
|
||||||
# TimeSpan
|
# TimeSpan
|
||||||
|
|||||||
Reference in New Issue
Block a user