Fixed generic_webhook error and made the duplicate submission thing a bit cleaner
This commit is contained in:
@@ -26,6 +26,7 @@ from fastapi.security import (
|
||||
)
|
||||
from pydantic import BaseModel
|
||||
from slowapi.errors import RateLimitExceeded
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
|
||||
|
||||
from alpine_bits_python.schemas import ReservationData
|
||||
@@ -73,10 +74,7 @@ TOKEN_LOG_LENGTH = 10
|
||||
|
||||
|
||||
def get_advertising_account_ids(
|
||||
config: dict[str, Any],
|
||||
hotel_code: str,
|
||||
fbclid: str | None,
|
||||
gclid: str | None
|
||||
config: dict[str, Any], hotel_code: str, fbclid: str | None, gclid: str | None
|
||||
) -> tuple[str | None, str | None]:
|
||||
"""Get advertising account IDs based on hotel config and click IDs.
|
||||
|
||||
@@ -830,13 +828,22 @@ async def process_generic_webhook_submission(
|
||||
_LOGGER.warning("Invalid age value for child %d: %s", i, age_str)
|
||||
|
||||
# Extract tracking information
|
||||
utm_source = tracking_data.get("utm_source")
|
||||
utm_medium = tracking_data.get("utm_medium")
|
||||
utm_campaign = tracking_data.get("utm_campaign")
|
||||
utm_term = tracking_data.get("utm_term")
|
||||
utm_content = tracking_data.get("utm_content")
|
||||
fbclid = tracking_data.get("fbclid")
|
||||
gclid = tracking_data.get("gclid")
|
||||
utm_source = None
|
||||
utm_medium = None
|
||||
utm_campaign = None
|
||||
utm_term = None
|
||||
utm_content = None
|
||||
fbclid = None
|
||||
gclid = None
|
||||
|
||||
if tracking_data:
|
||||
utm_source = tracking_data.get("utm_source")
|
||||
utm_medium = tracking_data.get("utm_medium")
|
||||
utm_campaign = tracking_data.get("utm_campaign")
|
||||
utm_term = tracking_data.get("utm_term")
|
||||
utm_content = tracking_data.get("utm_content")
|
||||
fbclid = tracking_data.get("fbclid")
|
||||
gclid = tracking_data.get("gclid")
|
||||
|
||||
# Parse submission timestamp
|
||||
submission_time = data.get("timestamp")
|
||||
@@ -1009,11 +1016,21 @@ async def handle_wix_form(
|
||||
"""
|
||||
try:
|
||||
return await process_wix_form_submission(request, data, db_session)
|
||||
except IntegrityError as e:
|
||||
# Handle duplicate submissions gracefully - likely same form sent twice
|
||||
# or race condition between workers
|
||||
if "unique constraint" in str(e).lower() and "unique_id" in str(e).lower():
|
||||
_LOGGER.warning(
|
||||
"Duplicate submission detected (unique_id already exists). "
|
||||
"Returning success to prevent retry. Error: %s",
|
||||
str(e),
|
||||
)
|
||||
# Return success since the reservation already exists
|
||||
return {"status": "success", "message": "Reservation already processed"}
|
||||
# Re-raise if it's a different integrity error
|
||||
raise
|
||||
except Exception as e:
|
||||
_LOGGER.exception("Error in handle_wix_form: %s", e)
|
||||
|
||||
# Log error data to file asynchronously
|
||||
import traceback
|
||||
_LOGGER.exception("Error in handle_wix_form")
|
||||
|
||||
log_entry = {
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
@@ -1021,7 +1038,6 @@ async def handle_wix_form(
|
||||
"headers": dict(request.headers),
|
||||
"data": data,
|
||||
"error": str(e),
|
||||
"traceback": traceback.format_exc(),
|
||||
}
|
||||
|
||||
# Use asyncio to run file I/O in thread pool to avoid blocking
|
||||
@@ -1298,14 +1314,14 @@ async def handle_xml_upload(
|
||||
<status>success</status>
|
||||
<message>Conversion data processed successfully</message>
|
||||
<stats>
|
||||
<totalReservations>{processing_stats['total_reservations']}</totalReservations>
|
||||
<deletedReservations>{processing_stats['deleted_reservations']}</deletedReservations>
|
||||
<totalDailySales>{processing_stats['total_daily_sales']}</totalDailySales>
|
||||
<matchedToReservation>{processing_stats['matched_to_reservation']}</matchedToReservation>
|
||||
<matchedToCustomer>{processing_stats['matched_to_customer']}</matchedToCustomer>
|
||||
<matchedToHashedCustomer>{processing_stats['matched_to_hashed_customer']}</matchedToHashedCustomer>
|
||||
<unmatched>{processing_stats['unmatched']}</unmatched>
|
||||
<errors>{processing_stats['errors']}</errors>
|
||||
<totalReservations>{processing_stats["total_reservations"]}</totalReservations>
|
||||
<deletedReservations>{processing_stats["deleted_reservations"]}</deletedReservations>
|
||||
<totalDailySales>{processing_stats["total_daily_sales"]}</totalDailySales>
|
||||
<matchedToReservation>{processing_stats["matched_to_reservation"]}</matchedToReservation>
|
||||
<matchedToCustomer>{processing_stats["matched_to_customer"]}</matchedToCustomer>
|
||||
<matchedToHashedCustomer>{processing_stats["matched_to_hashed_customer"]}</matchedToHashedCustomer>
|
||||
<unmatched>{processing_stats["unmatched"]}</unmatched>
|
||||
<errors>{processing_stats["errors"]}</errors>
|
||||
</stats>
|
||||
</response>"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user