Works but form_id is not unique. Need to find something else

This commit is contained in:
Jonas Linter
2025-09-29 16:09:42 +02:00
parent 54c002ac96
commit 7f25fb2b02
3 changed files with 337 additions and 1 deletions

View File

@@ -1,10 +1,19 @@
from datetime import datetime, timezone
from typing import Union, Optional, Any, TypeVar
from pydantic import BaseModel, ConfigDict, Field
from dataclasses import dataclass
from enum import Enum
from typing import Tuple
from alpine_bits_python.db import Customer, Reservation
# Import the generated classes
from .generated.alpinebits import OtaHotelResNotifRq, OtaResRetrieveRs, CommentName2
from .generated.alpinebits import HotelReservationResStatus, OtaHotelResNotifRq, OtaResRetrieveRs, CommentName2, UniqueIdType2
import logging
_LOGGER = logging.getLogger(__name__)
_LOGGER.setLevel(logging.INFO)
# Define type aliases for the two Customer types
NotifCustomer = OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer
@@ -650,7 +659,146 @@ class AlpineBitsFactory:
raise ValueError(f"Unsupported object type: {type(obj)}")
def create_xml_from_db(list: list[Tuple[Reservation, Customer]]):
""" Create RetrievedReservation XML from database entries.
list of pairs (Reservation, Customer)
"""
reservations_list = []
for reservation, customer in list:
_LOGGER.info(f"Creating XML for reservation {reservation.form_id} and customer {customer.given_name}")
phone_numbers = [(customer.phone, PhoneTechType.MOBILE)] if customer.phone is not None else []
customer_data = CustomerData(
given_name=customer.given_name,
surname=customer.surname,
name_prefix=customer.name_prefix,
name_title=customer.name_title,
phone_numbers=phone_numbers,
email_address=customer.email_address,
email_newsletter=customer.email_newsletter,
address_line=customer.address_line,
city_name=customer.city_name,
postal_code=customer.postal_code,
country_code=customer.country_code,
address_catalog=customer.address_catalog,
gender=customer.gender,
birth_date=customer.birth_date,
language=customer.language,
)
alpine_bits_factory = AlpineBitsFactory()
res_guests = alpine_bits_factory.create_res_guests(
customer_data, OtaMessageType.RETRIEVE
)
# Guest counts
children_ages = [int(a) for a in reservation.children_ages.split(",") if a]
guest_counts = GuestCountsFactory.create_retrieve_guest_counts(
reservation.num_adults, children_ages
)
# UniqueID
unique_id = OtaResRetrieveRs.ReservationsList.HotelReservation.UniqueId(
type_value=UniqueIdType2.VALUE_14, id=reservation.form_id
)
# TimeSpan
time_span = OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.TimeSpan(
start=reservation.start_date.isoformat() if reservation.start_date else None,
end=reservation.end_date.isoformat() if reservation.end_date else None,
)
room_stay = (
OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay(
time_span=time_span,
guest_counts=guest_counts,
)
)
room_stays = OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays(
room_stay=[room_stay],
)
hotel_res_id_data = HotelReservationIdData(
res_id_type="13",
res_id_value=reservation.fbclid or reservation.gclid,
res_id_source=None,
res_id_source_context="99tales",
)
hotel_res_id = alpine_bits_factory.create(
hotel_res_id_data, OtaMessageType.RETRIEVE
)
hotel_res_ids = OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.HotelReservationIds(
hotel_reservation_id=[hotel_res_id]
)
basic_property_info = OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.BasicPropertyInfo(
hotel_code=reservation.hotel_code,
hotel_name=reservation.hotel_name,
)
# Comments
offer_comment = CommentData(
name=CommentName2.ADDITIONAL_INFO,
text="Angebot/Offerta",
list_items=[
CommentListItemData(
value=reservation.offer,
language=customer.language,
list_item="1",
)
],
)
comment = None
if reservation.user_comment:
comment = CommentData(
name=CommentName2.CUSTOMER_COMMENT,
text=reservation.user_comment,
list_items=[
CommentListItemData(
value="Landing page comment",
language=customer.language,
list_item="1",
)
],
)
comments = [offer_comment, comment] if comment else [offer_comment]
comments_data = CommentsData(comments=comments)
comments_xml = alpine_bits_factory.create(comments_data, OtaMessageType.RETRIEVE)
res_global_info = (
OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo(
hotel_reservation_ids=hotel_res_ids,
basic_property_info=basic_property_info,
comments=comments_xml,
)
)
hotel_reservation = OtaResRetrieveRs.ReservationsList.HotelReservation(
create_date_time=datetime.now(timezone.utc).isoformat(),
res_status=HotelReservationResStatus.REQUESTED,
room_stay_reservation="true",
unique_id=unique_id,
room_stays=room_stays,
res_guests=res_guests,
res_global_info=res_global_info,
)
reservations_list.append(hotel_reservation)
retrieved_reservations = OtaResRetrieveRs.ReservationsList(
hotel_reservation=reservations_list
)
ota_res_retrieve_rs = OtaResRetrieveRs(
version="7.000", success=None, reservations_list=retrieved_reservations
)
try:
ota_res_retrieve_rs.model_validate(ota_res_retrieve_rs.model_dump())
except Exception as e:
_LOGGER.error(f"Validation error: {e}")
raise
return ota_res_retrieve_rs

View File

@@ -17,6 +17,10 @@ from xml.etree import ElementTree as ET
from dataclasses import dataclass
from enum import Enum, IntEnum
from alpine_bits_python.alpine_bits_helpers import PhoneTechType, create_xml_from_db
from .generated.alpinebits import OtaPingRq, OtaPingRs, WarningStatus, OtaReadRq
from xsdata_pydantic.bindings import XmlSerializer
from xsdata.formats.dataclass.serializers.config import SerializerConfig
@@ -407,6 +411,8 @@ def validate_hotel_authentication(username: str, password: str, hotelid: str, co
class ReadAction(AlpineBitsAction):
"""Implementation for OTA_Read action."""
@@ -478,7 +484,19 @@ class ReadAction(AlpineBitsAction):
for reservation, customer in reservation_customer_pairs:
_LOGGER.info(f"Reservation: {reservation.id}, Customer: {customer.given_name}")
res_retrive_rs = create_xml_from_db(reservation_customer_pairs)
config = SerializerConfig(
pretty_print=True, xml_declaration=True, encoding="UTF-8"
)
serializer = XmlSerializer(config=config)
response_xml = serializer.render(
res_retrive_rs, ns_map={None: "http://www.opentravel.org/OTA/2003/05"}
)
return AlpineBitsResponse(response_xml, HttpStatusCode.OK)