Merge branch 'db_fixes_plus_free_rooms' of https://gitea.99tales.net/jonas/alpinebits_python into db_fixes_plus_free_rooms
This commit is contained in:
@@ -28,7 +28,7 @@ from fastapi.security import (
|
||||
from pydantic import BaseModel
|
||||
from slowapi.errors import RateLimitExceeded
|
||||
from sqlalchemy import and_, select, update
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker, AsyncSession
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
from alpine_bits_python.hotel_service import HotelService
|
||||
@@ -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:
|
||||
@@ -719,7 +719,7 @@ async def validate_basic_auth(
|
||||
async def handle_webhook_unified(
|
||||
request: Request,
|
||||
webhook_secret: str,
|
||||
db_session=Depends(get_async_session),
|
||||
db_session: AsyncSession = Depends(get_async_session),
|
||||
):
|
||||
"""Unified webhook handler with deduplication and routing.
|
||||
|
||||
@@ -846,6 +846,9 @@ async def handle_webhook_unified(
|
||||
if not webhook_endpoint:
|
||||
raise HTTPException(status_code=404, detail="Webhook not found")
|
||||
|
||||
webhook_endpoint_id = webhook_endpoint.id
|
||||
webhook_hotel_id = webhook_endpoint.hotel_id
|
||||
|
||||
# Verify hotel is active
|
||||
if not webhook_endpoint.hotel.is_active:
|
||||
raise HTTPException(status_code=404, detail="Hotel is not active")
|
||||
@@ -860,8 +863,8 @@ async def handle_webhook_unified(
|
||||
|
||||
webhook_request_data = WebhookRequestData(
|
||||
payload_json=payload,
|
||||
webhook_endpoint_id=webhook_endpoint.id,
|
||||
hotel_id=webhook_endpoint.hotel_id,
|
||||
webhook_endpoint_id=webhook_endpoint_id,
|
||||
hotel_id=webhook_hotel_id,
|
||||
status=WebhookStatus.PROCESSING,
|
||||
processing_started_at=timestamp,
|
||||
created_at=timestamp,
|
||||
@@ -923,12 +926,17 @@ async def handle_webhook_unified(
|
||||
db_session.add(webhook_request)
|
||||
await db_session.flush()
|
||||
|
||||
webhook_request_id = webhook_request.id
|
||||
|
||||
try:
|
||||
# 6. Get processor for webhook_type
|
||||
processor = webhook_registry.get_processor(webhook_endpoint.webhook_type)
|
||||
if not processor:
|
||||
raise ValueError(f"No processor for type: {webhook_endpoint.webhook_type}")
|
||||
|
||||
# Persist the webhook row before handing off to processors
|
||||
await db_session.commit()
|
||||
|
||||
# 7. Process webhook with simplified interface
|
||||
result = await processor.process(
|
||||
webhook_request=webhook_request,
|
||||
@@ -937,34 +945,50 @@ async def handle_webhook_unified(
|
||||
event_dispatcher=request.app.state.event_dispatcher,
|
||||
)
|
||||
|
||||
# 8. Update status and link created entities when available
|
||||
webhook_request.status = WebhookStatus.COMPLETED
|
||||
webhook_request.processing_completed_at = datetime.now(UTC)
|
||||
if not db_session.in_transaction():
|
||||
await db_session.begin()
|
||||
|
||||
created_customer_id = result.get("customer_id") if isinstance(result, dict) else None
|
||||
created_reservation_id = (
|
||||
result.get("reservation_id") if isinstance(result, dict) else None
|
||||
completion_values = {
|
||||
"status": WebhookStatus.COMPLETED,
|
||||
"processing_completed_at": datetime.now(UTC),
|
||||
}
|
||||
|
||||
if isinstance(result, dict):
|
||||
created_customer_id = result.get("customer_id")
|
||||
created_reservation_id = result.get("reservation_id")
|
||||
if created_customer_id:
|
||||
completion_values["created_customer_id"] = created_customer_id
|
||||
if created_reservation_id:
|
||||
completion_values["created_reservation_id"] = created_reservation_id
|
||||
|
||||
await db_session.execute(
|
||||
update(WebhookRequest)
|
||||
.where(WebhookRequest.id == webhook_request_id)
|
||||
.values(**completion_values)
|
||||
)
|
||||
|
||||
if created_customer_id:
|
||||
webhook_request.created_customer_id = created_customer_id
|
||||
if created_reservation_id:
|
||||
webhook_request.created_reservation_id = created_reservation_id
|
||||
|
||||
await db_session.commit()
|
||||
|
||||
return {
|
||||
**result,
|
||||
"webhook_id": webhook_request.id,
|
||||
"hotel_id": webhook_endpoint.hotel_id,
|
||||
"webhook_id": webhook_request_id,
|
||||
"hotel_id": webhook_hotel_id,
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
_LOGGER.exception("Error processing webhook: %s", e)
|
||||
|
||||
webhook_request.status = WebhookStatus.FAILED
|
||||
webhook_request.last_error = str(e)[:2000]
|
||||
webhook_request.processing_completed_at = datetime.now(UTC)
|
||||
await db_session.rollback()
|
||||
if not db_session.in_transaction():
|
||||
await db_session.begin()
|
||||
await db_session.execute(
|
||||
update(WebhookRequest)
|
||||
.where(WebhookRequest.id == webhook_request_id)
|
||||
.values(
|
||||
status=WebhookStatus.FAILED,
|
||||
last_error=str(e)[:2000],
|
||||
processing_completed_at=datetime.now(UTC),
|
||||
)
|
||||
)
|
||||
await db_session.commit()
|
||||
|
||||
raise HTTPException(status_code=500, detail="Error processing webhook")
|
||||
@@ -1188,7 +1212,9 @@ async def _process_conversion_xml_background(
|
||||
# Now process the conversion XML
|
||||
_LOGGER.info("Starting database processing of %s", filename)
|
||||
conversion_service = ConversionService(session_maker, hotel.hotel_id)
|
||||
processing_stats = await conversion_service.process_conversion_xml(xml_content)
|
||||
processing_stats = await conversion_service.process_conversion_xml(xml_content, run_full_guest_matching=True)
|
||||
|
||||
await conversion_service.classify_regular_guests(24)
|
||||
|
||||
_LOGGER.info(
|
||||
"Conversion processing complete for %s: %s", filename, processing_stats
|
||||
|
||||
Reference in New Issue
Block a user