|
|
|
|
@@ -4,7 +4,7 @@ import asyncio
|
|
|
|
|
from datetime import date, datetime
|
|
|
|
|
from typing import Any, Protocol
|
|
|
|
|
|
|
|
|
|
from fastapi import HTTPException, Request
|
|
|
|
|
from fastapi import HTTPException
|
|
|
|
|
from sqlalchemy.exc import IntegrityError
|
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
|
|
|
|
|
|
@@ -14,7 +14,7 @@ from alpine_bits_python.customer_service import CustomerService
|
|
|
|
|
from alpine_bits_python.reservation_service import ReservationService
|
|
|
|
|
from alpine_bits_python.schemas import ReservationData
|
|
|
|
|
|
|
|
|
|
from .db import Hotel, WebhookRequest
|
|
|
|
|
from .db import WebhookRequest
|
|
|
|
|
from .logging_config import get_logger
|
|
|
|
|
|
|
|
|
|
_LOGGER = get_logger(__name__)
|
|
|
|
|
@@ -33,6 +33,7 @@ class WebhookProcessorProtocol(Protocol):
|
|
|
|
|
webhook_request: WebhookRequest,
|
|
|
|
|
db_session: AsyncSession,
|
|
|
|
|
config: dict[str, Any] | None = None,
|
|
|
|
|
event_dispatcher: Any | None = None,
|
|
|
|
|
) -> dict[str, Any]:
|
|
|
|
|
"""Process webhook payload.
|
|
|
|
|
|
|
|
|
|
@@ -40,6 +41,7 @@ class WebhookProcessorProtocol(Protocol):
|
|
|
|
|
webhook_request: WebhookRequest database record (contains payload_json and hotel_id)
|
|
|
|
|
db_session: Database session
|
|
|
|
|
config: Application configuration (optional)
|
|
|
|
|
event_dispatcher: Event dispatcher for push notifications (optional)
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Response dict with status, message, customer_id, reservation_id
|
|
|
|
|
@@ -82,20 +84,18 @@ class WebhookProcessorRegistry:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def process_wix_form_submission(
|
|
|
|
|
request: Request | None,
|
|
|
|
|
data: dict[str, Any],
|
|
|
|
|
db,
|
|
|
|
|
db_session: AsyncSession,
|
|
|
|
|
config: dict[str, Any] | None = None,
|
|
|
|
|
hotel_id: str | None = None,
|
|
|
|
|
event_dispatcher=None,
|
|
|
|
|
event_dispatcher: Any | None = None,
|
|
|
|
|
):
|
|
|
|
|
"""Shared business logic for handling Wix form submissions (test and production).
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
request: FastAPI Request object (can be None during startup reprocessing)
|
|
|
|
|
data: Webhook payload data
|
|
|
|
|
db: Database session
|
|
|
|
|
config: Application config (optional, extracted from request if not provided)
|
|
|
|
|
db_session: Database session
|
|
|
|
|
config: Application config (optional)
|
|
|
|
|
hotel_id: Hotel ID (optional, will use from data or config default if not provided)
|
|
|
|
|
event_dispatcher: Event dispatcher for push notifications (optional)
|
|
|
|
|
"""
|
|
|
|
|
@@ -103,12 +103,6 @@ async def process_wix_form_submission(
|
|
|
|
|
|
|
|
|
|
_LOGGER.info("Received Wix form data at %s", timestamp)
|
|
|
|
|
|
|
|
|
|
# Extract config and event_dispatcher from request if not provided
|
|
|
|
|
if config is None and request is not None:
|
|
|
|
|
config = request.app.state.config
|
|
|
|
|
if event_dispatcher is None and request is not None:
|
|
|
|
|
event_dispatcher = getattr(request.app.state, "event_dispatcher", None)
|
|
|
|
|
|
|
|
|
|
# Provide fallback config if still None
|
|
|
|
|
if config is None:
|
|
|
|
|
config = {}
|
|
|
|
|
@@ -188,7 +182,7 @@ async def process_wix_form_submission(
|
|
|
|
|
unique_id = data.get("submissionId", generate_unique_id())
|
|
|
|
|
|
|
|
|
|
# Use CustomerService to handle customer creation/update with hashing
|
|
|
|
|
customer_service = CustomerService(db)
|
|
|
|
|
customer_service = CustomerService(db_session)
|
|
|
|
|
|
|
|
|
|
customer_data = {
|
|
|
|
|
"given_name": first_name,
|
|
|
|
|
@@ -273,7 +267,7 @@ async def process_wix_form_submission(
|
|
|
|
|
raise HTTPException(status_code=400, detail="Failed to generate md5_unique_id")
|
|
|
|
|
|
|
|
|
|
# Use ReservationService to create reservation
|
|
|
|
|
reservation_service = ReservationService(db)
|
|
|
|
|
reservation_service = ReservationService(db_session)
|
|
|
|
|
try:
|
|
|
|
|
db_reservation = await reservation_service.create_reservation(
|
|
|
|
|
reservation, db_customer.id
|
|
|
|
|
@@ -327,6 +321,7 @@ class WixFormProcessor:
|
|
|
|
|
webhook_request: WebhookRequest,
|
|
|
|
|
db_session: AsyncSession,
|
|
|
|
|
config: dict[str, Any] | None = None,
|
|
|
|
|
event_dispatcher: Any | None = None,
|
|
|
|
|
) -> dict[str, Any]:
|
|
|
|
|
"""Process Wix form webhook payload.
|
|
|
|
|
|
|
|
|
|
@@ -334,6 +329,7 @@ class WixFormProcessor:
|
|
|
|
|
webhook_request: WebhookRequest database record
|
|
|
|
|
db_session: Database session
|
|
|
|
|
config: Application configuration (optional)
|
|
|
|
|
event_dispatcher: Event dispatcher for push notifications (optional)
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Response dict with status and details
|
|
|
|
|
@@ -341,32 +337,29 @@ class WixFormProcessor:
|
|
|
|
|
"""
|
|
|
|
|
# Call processing function with data from webhook_request
|
|
|
|
|
result = await process_wix_form_submission(
|
|
|
|
|
request=None, # No request context needed
|
|
|
|
|
data=webhook_request.payload_json,
|
|
|
|
|
db=db_session,
|
|
|
|
|
db_session=db_session,
|
|
|
|
|
config=config,
|
|
|
|
|
hotel_id=webhook_request.hotel_id,
|
|
|
|
|
event_dispatcher=None, # No push events during reprocessing
|
|
|
|
|
event_dispatcher=event_dispatcher,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def process_generic_webhook_submission(
|
|
|
|
|
request: Request | None,
|
|
|
|
|
data: dict[str, Any],
|
|
|
|
|
db,
|
|
|
|
|
db_session: AsyncSession,
|
|
|
|
|
config: dict[str, Any] | None = None,
|
|
|
|
|
hotel_id: str | None = None,
|
|
|
|
|
event_dispatcher=None,
|
|
|
|
|
event_dispatcher: Any | None = None,
|
|
|
|
|
):
|
|
|
|
|
"""Process generic webhook submissions with nested structure.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
request: FastAPI Request object (can be None during startup reprocessing)
|
|
|
|
|
data: Webhook payload data
|
|
|
|
|
db: Database session
|
|
|
|
|
config: Application config (optional, extracted from request if not provided)
|
|
|
|
|
db_session: Database session
|
|
|
|
|
config: Application config (optional)
|
|
|
|
|
hotel_id: Hotel ID (optional, will use from data or config default)
|
|
|
|
|
event_dispatcher: Event dispatcher for push notifications (optional)
|
|
|
|
|
|
|
|
|
|
@@ -402,12 +395,6 @@ async def process_generic_webhook_submission(
|
|
|
|
|
timestamp = datetime.now().isoformat()
|
|
|
|
|
_LOGGER.info("Processing generic webhook submission at %s", timestamp)
|
|
|
|
|
|
|
|
|
|
# Extract config and event_dispatcher from request if not provided
|
|
|
|
|
if config is None and request is not None:
|
|
|
|
|
config = request.app.state.config
|
|
|
|
|
if event_dispatcher is None and request is not None:
|
|
|
|
|
event_dispatcher = getattr(request.app.state, "event_dispatcher", None)
|
|
|
|
|
|
|
|
|
|
# Provide fallback config if still None
|
|
|
|
|
if config is None:
|
|
|
|
|
config = {}
|
|
|
|
|
@@ -531,7 +518,7 @@ async def process_generic_webhook_submission(
|
|
|
|
|
unique_id = generate_unique_id()
|
|
|
|
|
|
|
|
|
|
# Use CustomerService to handle customer creation/update with hashing
|
|
|
|
|
customer_service = CustomerService(db)
|
|
|
|
|
customer_service = CustomerService(db_session)
|
|
|
|
|
|
|
|
|
|
customer_data = {
|
|
|
|
|
"given_name": first_name,
|
|
|
|
|
@@ -593,7 +580,7 @@ async def process_generic_webhook_submission(
|
|
|
|
|
raise HTTPException(status_code=400, detail="Failed to generate md5_unique_id")
|
|
|
|
|
|
|
|
|
|
# Use ReservationService to create reservation
|
|
|
|
|
reservation_service = ReservationService(db)
|
|
|
|
|
reservation_service = ReservationService(db_session)
|
|
|
|
|
db_reservation = await reservation_service.create_reservation(
|
|
|
|
|
reservation, db_customer.id
|
|
|
|
|
)
|
|
|
|
|
@@ -646,6 +633,7 @@ class GenericWebhookProcessor:
|
|
|
|
|
webhook_request: WebhookRequest,
|
|
|
|
|
db_session: AsyncSession,
|
|
|
|
|
config: dict[str, Any] | None = None,
|
|
|
|
|
event_dispatcher: Any | None = None,
|
|
|
|
|
) -> dict[str, Any]:
|
|
|
|
|
"""Process generic webhook payload.
|
|
|
|
|
|
|
|
|
|
@@ -653,6 +641,7 @@ class GenericWebhookProcessor:
|
|
|
|
|
webhook_request: WebhookRequest database record
|
|
|
|
|
db_session: Database session
|
|
|
|
|
config: Application configuration (optional)
|
|
|
|
|
event_dispatcher: Event dispatcher for push notifications (optional)
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Response dict with status and details
|
|
|
|
|
@@ -660,12 +649,11 @@ class GenericWebhookProcessor:
|
|
|
|
|
"""
|
|
|
|
|
# Call processing function with data from webhook_request
|
|
|
|
|
result = await process_generic_webhook_submission(
|
|
|
|
|
request=None, # No request context needed
|
|
|
|
|
data=webhook_request.payload_json,
|
|
|
|
|
db=db_session,
|
|
|
|
|
db_session=db_session,
|
|
|
|
|
config=config,
|
|
|
|
|
hotel_id=webhook_request.hotel_id,
|
|
|
|
|
event_dispatcher=None, # No push events during reprocessing
|
|
|
|
|
event_dispatcher=event_dispatcher,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|