Added guestCounts to output.xml

This commit is contained in:
Jonas Linter
2025-09-29 09:24:19 +02:00
parent ff00edf35d
commit 4416397a69
5 changed files with 165 additions and 44 deletions

View File

@@ -8,3 +8,21 @@ When ASA wants to know our GuestRequests from the Landing page then they are the
Just for GuestRequests this should be fine however. Just for GuestRequests this should be fine however.
# Wix formular parsing Notizen
### Kontaktinformationen
#### Werbeparameter
field:angebot_auswaehlen -> Kommentar mit Angebot

View File

@@ -1,11 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<OTA_ResRetrieveRS xmlns="http://www.opentravel.org/OTA/2003/05" Version="7.000"> <OTA_ResRetrieveRS xmlns="http://www.opentravel.org/OTA/2003/05" Version="7.000">
<ReservationsList> <ReservationsList>
<HotelReservation CreateDateTime="2025-09-27T15:34:46.762660+00:00" ResStatus="Requested" RoomStayReservation="true"> <HotelReservation CreateDateTime="2025-09-29T07:21:12.768928+00:00" ResStatus="Requested" RoomStayReservation="true">
<UniqueID Type="14" ID="6b34fe24ac2ff811"/> <UniqueID Type="14" ID="6b34fe24ac2ff811"/>
<RoomStays> <RoomStays>
<RoomStay> <RoomStay>
<TimeSpan Start="2025-10-03" End="2025-10-05"/> <GuestCounts>
<GuestCount Count="2"/>
<GuestCount Count="1" Age="3"/>
<GuestCount Count="1" Age="0"/>
<GuestCount Count="1" Age="1"/>
</GuestCounts>
<TimeSpan Start="2025-10-31" End="2025-11-02"/>
</RoomStay> </RoomStay>
</RoomStays> </RoomStays>
<ResGuests> <ResGuests>
@@ -15,15 +21,12 @@
<Profile> <Profile>
<Customer Language="it"> <Customer Language="it">
<PersonName> <PersonName>
<NamePrefix>Familie</NamePrefix> <NamePrefix>Frau</NamePrefix>
<GivenName>Miriana</GivenName> <GivenName>Elena</GivenName>
<Surname>Darman</Surname> <Surname>Battiloro</Surname>
</PersonName> </PersonName>
<Telephone PhoneTechType="5" PhoneNumber="+39 348 443 0969"/> <Telephone PhoneTechType="5" PhoneNumber="+393337673262"/>
<Email Remark="newsletter:no">miriana.m9@gmail.com</Email> <Email Remark="newsletter:no">e.battiloro1@gmail.com</Email>
<Address Remark="catalog:no">
<CountryName Code="IT"/>
</Address>
</Customer> </Customer>
</Profile> </Profile>
</ProfileInfo> </ProfileInfo>
@@ -32,13 +35,13 @@
</ResGuests> </ResGuests>
<ResGlobalInfo> <ResGlobalInfo>
<Comments> <Comments>
<Comment Name="customer comment"> <Comment Name="additional info">
<ListItem ListItem="1" Language="it">Landing page comment</ListItem> <ListItem ListItem="1" Language="it">Herbstferien - Familienzeit mit Dolomitenblick</ListItem>
<Text>Wix form submission</Text> <Text>Angebot/Offerta</Text>
</Comment> </Comment>
</Comments> </Comments>
<HotelReservationIDs> <HotelReservationIDs>
<HotelReservationID ResID_Type="13" ResID_Value="PAZXh0bgNhZW0BMABhZGlkAasmYBTNE3QBp1jWuJ9zIpfEGRJMP63fMAMI405yvG5EtH-OT0PxSkAbBJaudFHR6cMtkdHu_aem_fopaFtECyVPNW9fmWfEkyA" ResID_SourceContext="99tales"/> <HotelReservationID ResID_Type="13" ResID_Value="PAZXh0bgNhZW0BMABhZGlkAasmYBhk4DQBp02L46Rl1jAuccxsOaeFSv7WSFnP-MQCsOrz9yDnKRH4hwZ7GEgxF9gy0_OF_aem_qSvrs6xsBkvTaI_Y9_hfnQ" ResID_SourceContext="99tales"/>
</HotelReservationIDs> </HotelReservationIDs>
<BasicPropertyInfo HotelCode="123" HotelName="Frangart Inn"/> <BasicPropertyInfo HotelCode="123" HotelName="Frangart Inn"/>
</ResGlobalInfo> </ResGlobalInfo>

View File

@@ -11,6 +11,7 @@ from .simplified_access import (
CommentsData, CommentsData,
CommentListItemData, CommentListItemData,
CustomerData, CustomerData,
GuestCountsFactory,
HotelReservationIdData, HotelReservationIdData,
PhoneTechType, PhoneTechType,
AlpineBitsFactory, AlpineBitsFactory,
@@ -53,23 +54,29 @@ def main():
db = SessionLocal() db = SessionLocal()
# Load data from JSON file # Load data from JSON file
json_path = os.path.join(os.path.dirname(__file__), '../../test_data/wix_test_data_20250927_070500.json') json_path = os.path.join(os.path.dirname(__file__), '../../test_data/wix_test_data_20250928_132611.json')
with open(json_path, 'r', encoding='utf-8') as f: with open(json_path, 'r', encoding='utf-8') as f:
wix_data = json.load(f) wix_data = json.load(f)
data = wix_data["data"]["data"] data = wix_data["data"]["data"]
# Extract relevant fields
given_name = data.get("field:first_name_abae") or data.get("contact", {}).get("name", {}).get("first")
surname = data.get("field:last_name_d97c") or data.get("contact", {}).get("name", {}).get("last") contact_info = data.get("contact", {})
first_name = contact_info.get("name", {}).get("first")
last_name = contact_info.get("name", {}).get("last")
email = contact_info.get("email")
phone_number = contact_info.get("phones", [{}])[0].get("e164Phone") # phone without formatting
locale = contact_info.get("locale", "de-de")
name_prefix = data.get("field:anrede") name_prefix = data.get("field:anrede")
email_address = data.get("field:email_5139") or data.get("contact", {}).get("email")
phone = data.get("field:phone_4c77") or (data.get("contact", {}).get("phones", [{}])[0].get("formattedPhone"))
email_newsletter = data.get("field:form_field_5a7b", "") != "Non selezionato" email_newsletter = data.get("field:form_field_5a7b", "") != "Non selezionato"
address_line = None address_line = None
city_name = None city_name = None
postal_code = None postal_code = None
country_code = data.get("contact", {}).get("phones", [{}])[0].get("countryCode", "") or "IT" country_code = None
gender = None gender = None
birth_date = None birth_date = None
language = data.get("contact", {}).get("locale", "en")[:2] language = data.get("contact", {}).get("locale", "en")[:2]
@@ -82,13 +89,22 @@ def main():
num_adults = int(data.get("field:number_7cf5") or 2) num_adults = int(data.get("field:number_7cf5") or 2)
num_children = int(data.get("field:anzahl_kinder") or 0) num_children = int(data.get("field:anzahl_kinder") or 0)
children_ages = [] children_ages = []
for k in data.keys():
if k.startswith("field:alter_kind_"): if num_children > 0:
try: for k in data.keys():
age = int(data[k]) if k.startswith("field:alter_kind_"):
children_ages.append(age) try:
except Exception: age = int(data[k])
pass children_ages.append(age)
except Exception:
pass
guest_counts = GuestCountsFactory().create_retrieve_guest_counts(num_adults, children_ages)
# print guests and kids info for debugging
print(f"Guests: {num_adults} adults, {num_children} children, ages: {children_ages}")
# UTM and offer # UTM and offer
utm_fields = [ utm_fields = [
@@ -108,11 +124,11 @@ def main():
# Save customer and reservation to DB # Save customer and reservation to DB
db_customer = DBCustomer( db_customer = DBCustomer(
given_name=given_name, given_name=first_name,
surname=surname, surname=last_name,
name_prefix=name_prefix, name_prefix=name_prefix,
email_address=email_address, email_address=email,
phone=phone, phone=phone_number,
email_newsletter=email_newsletter, email_newsletter=email_newsletter,
address_line=address_line, address_line=address_line,
city_name=city_name, city_name=city_name,
@@ -155,21 +171,24 @@ def main():
# RoomStay with TimeSpan # RoomStay with TimeSpan
room_stay = ( room_stay = (
ab.OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay( ab.OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay(
time_span=time_span time_span=time_span,
guest_counts=guest_counts,
) )
) )
room_stays = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays( room_stays = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays(
room_stay=[room_stay] room_stay=[room_stay],
) )
# CustomerData # CustomerData
phone_numbers = [(phone, PhoneTechType.MOBILE)] if phone else [] phone_numbers = [(phone_number, PhoneTechType.MOBILE)] if phone_number else []
customer_data = CustomerData( customer_data = CustomerData(
given_name=given_name, given_name=first_name,
surname=surname, surname=last_name,
name_prefix=name_prefix, name_prefix=name_prefix,
phone_numbers=phone_numbers, phone_numbers=phone_numbers,
email_address=email_address, email_address=email,
email_newsletter=email_newsletter, email_newsletter=email_newsletter,
address_line=address_line, address_line=address_line,
city_name=city_name, city_name=city_name,
@@ -203,18 +222,39 @@ def main():
hotel_code="123", hotel_name="Frangart Inn" hotel_code="123", hotel_name="Frangart Inn"
) )
# Comments from UTM fields and other info
comment = CommentData( user_comment_text = data.get("field:long_answer_3524", "")
name= ab.CommentName2.CUSTOMER_COMMENT,
text="Wix form submission",
comment = None
if user_comment_text:
# Comments from UTM fields and other info
comment = CommentData(
name= ab.CommentName2.CUSTOMER_COMMENT,
text=user_comment_text,
list_items=[CommentListItemData(
value="Landing page comment",
language=language,
list_item="1",
)],
)
offer_comment = CommentData(
name= ab.CommentName2.ADDITIONAL_INFO,
text="Angebot/Offerta",
list_items=[CommentListItemData( list_items=[CommentListItemData(
value="Landing page comment", value=offer,
language=language, language=language,
list_item="1", list_item="1",
)], )],
) )
comments_data = CommentsData(comments=[comment]) comments = [offer_comment, comment] if comment else [offer_comment]
comments_data = CommentsData(comments=comments)
comments = alpine_bits_factory.create(comments_data, OtaMessageType.RETRIEVE) comments = alpine_bits_factory.create(comments_data, OtaMessageType.RETRIEVE)
# ResGlobalInfo # ResGlobalInfo

View File

@@ -0,0 +1,7 @@
def parse_form(form: dict):
pass

View File

@@ -20,6 +20,11 @@ RetrieveComments = OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalI
NotifComment = OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Comments.Comment NotifComment = OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Comments.Comment
RetrieveComment = OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Comments.Comment RetrieveComment = OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Comments.Comment
# type aliases for GuestCounts
NotifGuestCounts = OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.GuestCounts
RetrieveGuestCounts = OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.GuestCounts
# phonetechtype enum 1,3,5 voice, fax, mobile # phonetechtype enum 1,3,5 voice, fax, mobile
class PhoneTechType(Enum): class PhoneTechType(Enum):
@@ -34,6 +39,12 @@ class OtaMessageType(Enum):
RETRIEVE = "retrieve" # For OtaResRetrieveRs RETRIEVE = "retrieve" # For OtaResRetrieveRs
@dataclass
class KidsAgeData:
"""Data class to hold information about children's ages."""
ages: list[int]
@dataclass @dataclass
class CustomerData: class CustomerData:
"""Simple data class to hold customer information without nested type constraints.""" """Simple data class to hold customer information without nested type constraints."""
@@ -65,6 +76,48 @@ class CustomerData:
self.phone_numbers = [] self.phone_numbers = []
class GuestCountsFactory:
@staticmethod
def create_notif_guest_counts(adults: int, kids: Optional[list[int]] = None) -> NotifGuestCounts:
"""
Create a GuestCounts object for OtaHotelResNotifRq.
:param adults: Number of adults
:param kids: List of ages for each kid (optional)
:return: GuestCounts instance
"""
return GuestCountsFactory._create_guest_counts(adults, kids, NotifGuestCounts)
@staticmethod
def create_retrieve_guest_counts(adults: int, kids: Optional[list[int]] = None) -> RetrieveGuestCounts:
"""
Create a GuestCounts object for OtaResRetrieveRs.
:param adults: Number of adults
:param kids: List of ages for each kid (optional)
:return: GuestCounts instance
"""
return GuestCountsFactory._create_guest_counts(adults, kids, RetrieveGuestCounts)
@staticmethod
def _create_guest_counts(adults: int, kids: Optional[list[int]], guest_counts_class: type) -> Any:
"""
Internal method to create a GuestCounts object of the specified type.
:param adults: Number of adults
:param kids: List of ages for each kid (optional)
:param guest_counts_class: The GuestCounts class to instantiate
:return: GuestCounts instance
"""
GuestCount = guest_counts_class.GuestCount
guest_count_list = []
if adults > 0:
guest_count_list.append(GuestCount(count=str(adults)))
if kids:
for age in kids:
guest_count_list.append(GuestCount(count="1", age=str(age)))
return guest_counts_class(guest_count=guest_count_list)
class CustomerFactory: class CustomerFactory:
"""Factory class to create Customer instances for both OtaHotelResNotifRq and OtaResRetrieveRs.""" """Factory class to create Customer instances for both OtaHotelResNotifRq and OtaResRetrieveRs."""