Before simplifying the factory

This commit is contained in:
Jonas Linter
2025-09-24 15:28:55 +02:00
parent b0bd77b3c6
commit 79ceb72d12
4 changed files with 374 additions and 103 deletions

View File

@@ -6,8 +6,14 @@ from datetime import datetime, timezone
import re import re
from xsdata_pydantic.bindings import XmlSerializer from xsdata_pydantic.bindings import XmlSerializer
from simplified_access import CustomerData, CustomerFactory, PhoneTechType, ResGuestFactory from simplified_access import (
CustomerData,
CustomerFactory,
HotelReservationIdData,
HotelReservationIdFactory,
PhoneTechType,
ResGuestFactory,
)
def main(): def main():
@@ -45,7 +51,7 @@ def main():
name_prefix="Mr.", name_prefix="Mr.",
phone_numbers=[ phone_numbers=[
("+1234567890", PhoneTechType.MOBILE), # Phone number with type ("+1234567890", PhoneTechType.MOBILE), # Phone number with type
("+0987654321", None) # Phone number without type ("+0987654321", None), # Phone number without type
], ],
email_address="john.doe@example.com", email_address="john.doe@example.com",
email_newsletter=True, email_newsletter=True,
@@ -56,23 +62,25 @@ def main():
address_catalog=False, address_catalog=False,
gender="Male", gender="Male",
birth_date="1980-01-01", birth_date="1980-01-01",
language="en" language="en",
) )
res_guests = ResGuestFactory.create_retrieve_res_guests(customer_data) res_guests = ResGuestFactory.create_retrieve_res_guests(customer_data)
hotel_res_id_data = HotelReservationIdData(
res_id_type="13",
res_id_value=None,
res_id_source=None,
res_id_source_context="99tales",
)
# Create HotelReservationId using the factory
hotel_res_id = HotelReservationIdFactory.create_retrieve_hotel_reservation_id(
hotel_res_id_data
)
# Use the actual nested HotelReservationIds class # Use the actual nested HotelReservationIds class
hotel_res_ids = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.HotelReservationIds( hotel_res_ids = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.HotelReservationIds(
hotel_reservation_id = [ hotel_reservation_id=[hotel_res_id]
ab.OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.HotelReservationIds.HotelReservationId(
res_id_type="13", res_id_source_context="99tales"
)
]
) )
# Basic property info # Basic property info
@@ -146,7 +154,6 @@ def main():
parsed_result = parser.from_string(xml_content, ab.OtaResRetrieveRs) parsed_result = parser.from_string(xml_content, ab.OtaResRetrieveRs)
print("✅ Round-trip validation successful!") print("✅ Round-trip validation successful!")
print( print(
f"Parsed reservation status: {parsed_result.reservations_list.hotel_reservation[0].res_status}" f"Parsed reservation status: {parsed_result.reservations_list.hotel_reservation[0].res_status}"

View File

@@ -1,7 +1,7 @@
<?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-24T13:06:48.996519+00:00" ResStatus="Requested" RoomStayReservation="true"> <HotelReservation CreateDateTime="2025-09-24T13:22:30.892827+00:00" ResStatus="Requested" RoomStayReservation="true">
<UniqueID Type="14" ID="6b34fe24ac2ff811"/> <UniqueID Type="14" ID="6b34fe24ac2ff811"/>
<RoomStays> <RoomStays>
<RoomStay> <RoomStay>

View File

@@ -10,6 +10,10 @@ from generated.alpinebits import OtaHotelResNotifRq, OtaResRetrieveRs
NotifCustomer = OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer NotifCustomer = OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer
RetrieveCustomer = OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer RetrieveCustomer = OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer
# Define type aliases for HotelReservationId types
NotifHotelReservationId = OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.HotelReservationIds.HotelReservationId
RetrieveHotelReservationId = OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.HotelReservationIds.HotelReservationId
# phonetechtype enum 1,3,5 voice, fax, mobile # phonetechtype enum 1,3,5 voice, fax, mobile
class PhoneTechType(Enum): class PhoneTechType(Enum):
@@ -18,23 +22,28 @@ class PhoneTechType(Enum):
MOBILE = "5" MOBILE = "5"
@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."""
given_name: str given_name: str
surname: str surname: str
name_prefix: None | str = None name_prefix: None | str = None
name_title: None | str = None name_title: None | str = None
phone_numbers: list[tuple[str, None | PhoneTechType]] = None # (phone_number, phone_tech_type) phone_numbers: list[tuple[str, None | PhoneTechType]] = (
None # (phone_number, phone_tech_type)
)
email_address: None | str = None email_address: None | str = None
email_newsletter: None | bool = None # True for "yes", False for "no", None for not specified email_newsletter: None | bool = (
None # True for "yes", False for "no", None for not specified
)
address_line: None | str = None address_line: None | str = None
city_name: None | str = None city_name: None | str = None
postal_code: None | str = None postal_code: None | str = None
country_code: None | str = None # Two-letter country code country_code: None | str = None # Two-letter country code
address_catalog: None | bool = None # True for "yes", False for "no", None for not specified address_catalog: None | bool = (
None # True for "yes", False for "no", None for not specified
)
gender: None | str = None # "Unknown", "Male", "Female" gender: None | str = None # "Unknown", "Male", "Female"
birth_date: None | str = None birth_date: None | str = None
language: None | str = None # Two-letter language code language: None | str = None # Two-letter language code
@@ -46,69 +55,70 @@ class CustomerData:
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."""
@staticmethod @staticmethod
def create_notif_customer(data: CustomerData) -> NotifCustomer: def create_notif_customer(data: CustomerData) -> NotifCustomer:
"""Create a Customer for OtaHotelResNotifRq.""" """Create a Customer for OtaHotelResNotifRq."""
return CustomerFactory._create_customer(NotifCustomer, data) return CustomerFactory._create_customer(NotifCustomer, data)
@staticmethod @staticmethod
def create_retrieve_customer(data: CustomerData) -> RetrieveCustomer: def create_retrieve_customer(data: CustomerData) -> RetrieveCustomer:
"""Create a Customer for OtaResRetrieveRs.""" """Create a Customer for OtaResRetrieveRs."""
return CustomerFactory._create_customer(RetrieveCustomer, data) return CustomerFactory._create_customer(RetrieveCustomer, data)
@staticmethod @staticmethod
def _create_customer(customer_class: type, data: CustomerData) -> Any: def _create_customer(customer_class: type, data: CustomerData) -> Any:
"""Internal method to create a customer of the specified type.""" """Internal method to create a customer of the specified type."""
# Create PersonName # Create PersonName
person_name = customer_class.PersonName( person_name = customer_class.PersonName(
given_name=data.given_name, given_name=data.given_name,
surname=data.surname, surname=data.surname,
name_prefix=data.name_prefix, name_prefix=data.name_prefix,
name_title=data.name_title name_title=data.name_title,
) )
# Create telephone list # Create telephone list
telephones = [] telephones = []
for phone_number, phone_tech_type in data.phone_numbers: for phone_number, phone_tech_type in data.phone_numbers:
telephone = customer_class.Telephone( telephone = customer_class.Telephone(
phone_number=phone_number, phone_number=phone_number,
phone_tech_type=phone_tech_type.value if phone_tech_type else None phone_tech_type=phone_tech_type.value if phone_tech_type else None,
) )
telephones.append(telephone) telephones.append(telephone)
# Create email if provided # Create email if provided
email = None email = None
if data.email_address: if data.email_address:
remark = None remark = None
if data.email_newsletter is not None: if data.email_newsletter is not None:
remark = f"newsletter:{'yes' if data.email_newsletter else 'no'}" remark = f"newsletter:{'yes' if data.email_newsletter else 'no'}"
email = customer_class.Email( email = customer_class.Email(value=data.email_address, remark=remark)
value=data.email_address,
remark=remark
)
# Create address if any address fields are provided # Create address if any address fields are provided
address = None address = None
if any([data.address_line, data.city_name, data.postal_code, data.country_code]): if any(
[data.address_line, data.city_name, data.postal_code, data.country_code]
):
country_name = None country_name = None
if data.country_code: if data.country_code:
country_name = customer_class.Address.CountryName(code=data.country_code) country_name = customer_class.Address.CountryName(
code=data.country_code
)
address_remark = None address_remark = None
if data.address_catalog is not None: if data.address_catalog is not None:
address_remark = f"catalog:{'yes' if data.address_catalog else 'no'}" address_remark = f"catalog:{'yes' if data.address_catalog else 'no'}"
address = customer_class.Address( address = customer_class.Address(
address_line=data.address_line, address_line=data.address_line,
city_name=data.city_name, city_name=data.city_name,
postal_code=data.postal_code, postal_code=data.postal_code,
country_name=country_name, country_name=country_name,
remark=address_remark remark=address_remark,
) )
# Create the customer # Create the customer
return customer_class( return customer_class(
person_name=person_name, person_name=person_name,
@@ -117,29 +127,36 @@ class CustomerFactory:
address=address, address=address,
gender=data.gender, gender=data.gender,
birth_date=data.birth_date, birth_date=data.birth_date,
language=data.language language=data.language,
) )
@staticmethod @staticmethod
def from_notif_customer(customer: NotifCustomer) -> CustomerData: def from_notif_customer(customer: NotifCustomer) -> CustomerData:
"""Convert a NotifCustomer back to CustomerData.""" """Convert a NotifCustomer back to CustomerData."""
return CustomerFactory._customer_to_data(customer) return CustomerFactory._customer_to_data(customer)
@staticmethod @staticmethod
def from_retrieve_customer(customer: RetrieveCustomer) -> CustomerData: def from_retrieve_customer(customer: RetrieveCustomer) -> CustomerData:
"""Convert a RetrieveCustomer back to CustomerData.""" """Convert a RetrieveCustomer back to CustomerData."""
return CustomerFactory._customer_to_data(customer) return CustomerFactory._customer_to_data(customer)
@staticmethod @staticmethod
def _customer_to_data(customer: Any) -> CustomerData: def _customer_to_data(customer: Any) -> CustomerData:
"""Internal method to convert any customer type to CustomerData.""" """Internal method to convert any customer type to CustomerData."""
# Extract phone numbers # Extract phone numbers
phone_numbers = [] phone_numbers = []
if customer.telephone: if customer.telephone:
for tel in customer.telephone: for tel in customer.telephone:
phone_numbers.append((tel.phone_number, PhoneTechType(tel.phone_tech_type) if tel.phone_tech_type else None)) phone_numbers.append(
(
tel.phone_number,
PhoneTechType(tel.phone_tech_type)
if tel.phone_tech_type
else None,
)
)
# Extract email info # Extract email info
email_address = None email_address = None
email_newsletter = None email_newsletter = None
@@ -150,28 +167,28 @@ class CustomerFactory:
email_newsletter = True email_newsletter = True
elif "newsletter:no" in customer.email.remark: elif "newsletter:no" in customer.email.remark:
email_newsletter = False email_newsletter = False
# Extract address info # Extract address info
address_line = None address_line = None
city_name = None city_name = None
postal_code = None postal_code = None
country_code = None country_code = None
address_catalog = None address_catalog = None
if customer.address: if customer.address:
address_line = customer.address.address_line address_line = customer.address.address_line
city_name = customer.address.city_name city_name = customer.address.city_name
postal_code = customer.address.postal_code postal_code = customer.address.postal_code
if customer.address.country_name: if customer.address.country_name:
country_code = customer.address.country_name.code country_code = customer.address.country_name.code
if customer.address.remark: if customer.address.remark:
if "catalog:yes" in customer.address.remark: if "catalog:yes" in customer.address.remark:
address_catalog = True address_catalog = True
elif "catalog:no" in customer.address.remark: elif "catalog:no" in customer.address.remark:
address_catalog = False address_catalog = False
return CustomerData( return CustomerData(
given_name=customer.person_name.given_name, given_name=customer.person_name.given_name,
surname=customer.person_name.surname, surname=customer.person_name.surname,
@@ -187,7 +204,81 @@ class CustomerFactory:
address_catalog=address_catalog, address_catalog=address_catalog,
gender=customer.gender, gender=customer.gender,
birth_date=customer.birth_date, birth_date=customer.birth_date,
language=customer.language language=customer.language,
)
@dataclass
class HotelReservationIdData:
"""Simple data class to hold hotel reservation ID information without nested type constraints."""
res_id_type: str # Required field - pattern: [0-9]+
res_id_value: None | str = None # Max 64 characters
res_id_source: None | str = None # Max 64 characters
res_id_source_context: None | str = None # Max 64 characters
class HotelReservationIdFactory:
"""Factory class to create HotelReservationId instances for both OtaHotelResNotifRq and OtaResRetrieveRs."""
@staticmethod
def create_notif_hotel_reservation_id(
data: HotelReservationIdData,
) -> NotifHotelReservationId:
"""Create a HotelReservationId for OtaHotelResNotifRq."""
return HotelReservationIdFactory._create_hotel_reservation_id(
NotifHotelReservationId, data
)
@staticmethod
def create_retrieve_hotel_reservation_id(
data: HotelReservationIdData,
) -> RetrieveHotelReservationId:
"""Create a HotelReservationId for OtaResRetrieveRs."""
return HotelReservationIdFactory._create_hotel_reservation_id(
RetrieveHotelReservationId, data
)
@staticmethod
def _create_hotel_reservation_id(
hotel_reservation_id_class: type, data: HotelReservationIdData
) -> Any:
"""Internal method to create a hotel reservation id of the specified type."""
return hotel_reservation_id_class(
res_id_type=data.res_id_type,
res_id_value=data.res_id_value,
res_id_source=data.res_id_source,
res_id_source_context=data.res_id_source_context,
)
@staticmethod
def from_notif_hotel_reservation_id(
hotel_reservation_id: NotifHotelReservationId,
) -> HotelReservationIdData:
"""Convert a NotifHotelReservationId back to HotelReservationIdData."""
return HotelReservationIdFactory._hotel_reservation_id_to_data(
hotel_reservation_id
)
@staticmethod
def from_retrieve_hotel_reservation_id(
hotel_reservation_id: RetrieveHotelReservationId,
) -> HotelReservationIdData:
"""Convert a RetrieveHotelReservationId back to HotelReservationIdData."""
return HotelReservationIdFactory._hotel_reservation_id_to_data(
hotel_reservation_id
)
@staticmethod
def _hotel_reservation_id_to_data(
hotel_reservation_id: Any,
) -> HotelReservationIdData:
"""Internal method to convert any hotel reservation id type to HotelReservationIdData."""
return HotelReservationIdData(
res_id_type=hotel_reservation_id.res_id_type,
res_id_value=hotel_reservation_id.res_id_value,
res_id_source=hotel_reservation_id.res_id_source,
res_id_source_context=hotel_reservation_id.res_id_source_context,
) )
@@ -198,64 +289,56 @@ RetrieveResGuests = OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests
class ResGuestFactory: class ResGuestFactory:
"""Factory class to create complete ResGuests structures with a primary customer.""" """Factory class to create complete ResGuests structures with a primary customer."""
@staticmethod @staticmethod
def create_notif_res_guests(customer_data: CustomerData) -> NotifResGuests: def create_notif_res_guests(customer_data: CustomerData) -> NotifResGuests:
"""Create a complete ResGuests structure for OtaHotelResNotifRq with primary customer.""" """Create a complete ResGuests structure for OtaHotelResNotifRq with primary customer."""
return ResGuestFactory._create_res_guests( return ResGuestFactory._create_res_guests(
NotifResGuests, NotifResGuests, NotifCustomer, customer_data
NotifCustomer,
customer_data
) )
@staticmethod @staticmethod
def create_retrieve_res_guests(customer_data: CustomerData) -> RetrieveResGuests: def create_retrieve_res_guests(customer_data: CustomerData) -> RetrieveResGuests:
"""Create a complete ResGuests structure for OtaResRetrieveRs with primary customer.""" """Create a complete ResGuests structure for OtaResRetrieveRs with primary customer."""
return ResGuestFactory._create_res_guests( return ResGuestFactory._create_res_guests(
RetrieveResGuests, RetrieveResGuests, RetrieveCustomer, customer_data
RetrieveCustomer,
customer_data
) )
@staticmethod @staticmethod
def _create_res_guests(res_guests_class: type, customer_class: type, customer_data: CustomerData) -> Any: def _create_res_guests(
res_guests_class: type, customer_class: type, customer_data: CustomerData
) -> Any:
"""Internal method to create complete ResGuests structure.""" """Internal method to create complete ResGuests structure."""
# Create the customer using the existing CustomerFactory # Create the customer using the existing CustomerFactory
customer = CustomerFactory._create_customer(customer_class, customer_data) customer = CustomerFactory._create_customer(customer_class, customer_data)
# Create Profile with the customer # Create Profile with the customer
profile = res_guests_class.ResGuest.Profiles.ProfileInfo.Profile( profile = res_guests_class.ResGuest.Profiles.ProfileInfo.Profile(
customer=customer customer=customer
) )
# Create ProfileInfo with the profile # Create ProfileInfo with the profile
profile_info = res_guests_class.ResGuest.Profiles.ProfileInfo( profile_info = res_guests_class.ResGuest.Profiles.ProfileInfo(profile=profile)
profile=profile
)
# Create Profiles with the profile_info # Create Profiles with the profile_info
profiles = res_guests_class.ResGuest.Profiles( profiles = res_guests_class.ResGuest.Profiles(profile_info=profile_info)
profile_info=profile_info
)
# Create ResGuest with the profiles # Create ResGuest with the profiles
res_guest = res_guests_class.ResGuest( res_guest = res_guests_class.ResGuest(profiles=profiles)
profiles=profiles
)
# Create ResGuests with the res_guest # Create ResGuests with the res_guest
return res_guests_class( return res_guests_class(res_guest=res_guest)
res_guest=res_guest
)
@staticmethod @staticmethod
def extract_primary_customer(res_guests: Union[NotifResGuests, RetrieveResGuests]) -> CustomerData: def extract_primary_customer(
res_guests: Union[NotifResGuests, RetrieveResGuests],
) -> CustomerData:
"""Extract the primary customer data from a ResGuests structure.""" """Extract the primary customer data from a ResGuests structure."""
# Navigate down the nested structure to get the customer # Navigate down the nested structure to get the customer
customer = res_guests.res_guest.profiles.profile_info.profile.customer customer = res_guests.res_guest.profiles.profile_info.profile.customer
# Use the existing CustomerFactory conversion method # Use the existing CustomerFactory conversion method
if isinstance(res_guests, NotifResGuests): if isinstance(res_guests, NotifResGuests):
return CustomerFactory.from_notif_customer(customer) return CustomerFactory.from_notif_customer(customer)
@@ -272,7 +355,7 @@ if __name__ == "__main__":
name_prefix="Mr.", name_prefix="Mr.",
phone_numbers=[ phone_numbers=[
("+1234567890", PhoneTechType.MOBILE), # Phone number with type ("+1234567890", PhoneTechType.MOBILE), # Phone number with type
("+0987654321", None) # Phone number without type ("+0987654321", None), # Phone number without type
], ],
email_address="john.doe@example.com", email_address="john.doe@example.com",
email_newsletter=True, email_newsletter=True,
@@ -283,39 +366,96 @@ if __name__ == "__main__":
address_catalog=False, address_catalog=False,
gender="Male", gender="Male",
birth_date="1980-01-01", birth_date="1980-01-01",
language="en" language="en",
) )
# Create customer for OtaHotelResNotifRq # Create customer for OtaHotelResNotifRq
notif_customer = CustomerFactory.create_notif_customer(customer_data) notif_customer = CustomerFactory.create_notif_customer(customer_data)
print("Created NotifCustomer:", notif_customer.person_name.given_name, notif_customer.person_name.surname) print(
"Created NotifCustomer:",
notif_customer.person_name.given_name,
notif_customer.person_name.surname,
)
# Create customer for OtaResRetrieveRs # Create customer for OtaResRetrieveRs
retrieve_customer = CustomerFactory.create_retrieve_customer(customer_data) retrieve_customer = CustomerFactory.create_retrieve_customer(customer_data)
print("Created RetrieveCustomer:", retrieve_customer.person_name.given_name, retrieve_customer.person_name.surname) print(
"Created RetrieveCustomer:",
retrieve_customer.person_name.given_name,
retrieve_customer.person_name.surname,
)
# Convert back to data class # Convert back to data class
converted_data = CustomerFactory.from_notif_customer(notif_customer) converted_data = CustomerFactory.from_notif_customer(notif_customer)
print("Converted back to data:", converted_data.given_name, converted_data.surname) print("Converted back to data:", converted_data.given_name, converted_data.surname)
# Verify they contain the same information # Verify they contain the same information
print("Original and converted data match:", customer_data == converted_data) print("Original and converted data match:", customer_data == converted_data)
print("\n--- HotelReservationIdFactory Examples ---")
# Create hotel reservation ID data
reservation_id_data = HotelReservationIdData(
res_id_type="123",
res_id_value="RESERVATION-456",
res_id_source="HOTEL_SYSTEM",
res_id_source_context="BOOKING_ENGINE",
)
# Create HotelReservationId for both types
notif_res_id = HotelReservationIdFactory.create_notif_hotel_reservation_id(
reservation_id_data
)
retrieve_res_id = HotelReservationIdFactory.create_retrieve_hotel_reservation_id(
reservation_id_data
)
print(
"Created NotifHotelReservationId:",
notif_res_id.res_id_type,
notif_res_id.res_id_value,
)
print(
"Created RetrieveHotelReservationId:",
retrieve_res_id.res_id_type,
retrieve_res_id.res_id_value,
)
# Convert back to data class
converted_res_id_data = HotelReservationIdFactory.from_notif_hotel_reservation_id(
notif_res_id
)
print(
"Converted back to reservation ID data:",
converted_res_id_data.res_id_type,
converted_res_id_data.res_id_value,
)
# Verify they contain the same information
print(
"Original and converted reservation ID data match:",
reservation_id_data == converted_res_id_data,
)
print("\n--- ResGuestFactory Examples ---") print("\n--- ResGuestFactory Examples ---")
# Create complete ResGuests structure for OtaHotelResNotifRq - much simpler! # Create complete ResGuests structure for OtaHotelResNotifRq - much simpler!
notif_res_guests = ResGuestFactory.create_notif_res_guests(customer_data) notif_res_guests = ResGuestFactory.create_notif_res_guests(customer_data)
print("Created NotifResGuests with customer:", print(
notif_res_guests.res_guest.profiles.profile_info.profile.customer.person_name.given_name) "Created NotifResGuests with customer:",
notif_res_guests.res_guest.profiles.profile_info.profile.customer.person_name.given_name,
)
# Create complete ResGuests structure for OtaResRetrieveRs - much simpler! # Create complete ResGuests structure for OtaResRetrieveRs - much simpler!
retrieve_res_guests = ResGuestFactory.create_retrieve_res_guests(customer_data) retrieve_res_guests = ResGuestFactory.create_retrieve_res_guests(customer_data)
print("Created RetrieveResGuests with customer:", print(
retrieve_res_guests.res_guest.profiles.profile_info.profile.customer.person_name.given_name) "Created RetrieveResGuests with customer:",
retrieve_res_guests.res_guest.profiles.profile_info.profile.customer.person_name.given_name,
)
# Extract primary customer data back from ResGuests structure # Extract primary customer data back from ResGuests structure
extracted_data = ResGuestFactory.extract_primary_customer(retrieve_res_guests) extracted_data = ResGuestFactory.extract_primary_customer(retrieve_res_guests)
print("Extracted customer data:", extracted_data.given_name, extracted_data.surname) print("Extracted customer data:", extracted_data.given_name, extracted_data.surname)
# Verify roundtrip conversion # Verify roundtrip conversion
print("Roundtrip conversion successful:", customer_data == extracted_data) print("Roundtrip conversion successful:", customer_data == extracted_data)

View File

@@ -10,11 +10,15 @@ from simplified_access import (
CustomerData, CustomerData,
CustomerFactory, CustomerFactory,
ResGuestFactory, ResGuestFactory,
HotelReservationIdData,
HotelReservationIdFactory,
PhoneTechType, PhoneTechType,
NotifCustomer, NotifCustomer,
RetrieveCustomer, RetrieveCustomer,
NotifResGuests, NotifResGuests,
RetrieveResGuests RetrieveResGuests,
NotifHotelReservationId,
RetrieveHotelReservationId
) )
@@ -53,6 +57,25 @@ def minimal_customer_data():
) )
@pytest.fixture
def sample_hotel_reservation_id_data():
"""Fixture providing sample hotel reservation ID data for testing."""
return HotelReservationIdData(
res_id_type="123",
res_id_value="RESERVATION-456",
res_id_source="HOTEL_SYSTEM",
res_id_source_context="BOOKING_ENGINE"
)
@pytest.fixture
def minimal_hotel_reservation_id_data():
"""Fixture providing minimal hotel reservation ID data (only required fields)."""
return HotelReservationIdData(
res_id_type="999"
)
class TestCustomerData: class TestCustomerData:
"""Test the CustomerData dataclass.""" """Test the CustomerData dataclass."""
@@ -213,6 +236,73 @@ class TestCustomerFactory:
assert customer.telephone[2].phone_tech_type == "5" # MOBILE assert customer.telephone[2].phone_tech_type == "5" # MOBILE
class TestHotelReservationIdData:
"""Test the HotelReservationIdData dataclass."""
def test_hotel_reservation_id_data_creation_full(self, sample_hotel_reservation_id_data):
"""Test creating HotelReservationIdData with all fields."""
assert sample_hotel_reservation_id_data.res_id_type == "123"
assert sample_hotel_reservation_id_data.res_id_value == "RESERVATION-456"
assert sample_hotel_reservation_id_data.res_id_source == "HOTEL_SYSTEM"
assert sample_hotel_reservation_id_data.res_id_source_context == "BOOKING_ENGINE"
def test_hotel_reservation_id_data_creation_minimal(self, minimal_hotel_reservation_id_data):
"""Test creating HotelReservationIdData with only required fields."""
assert minimal_hotel_reservation_id_data.res_id_type == "999"
assert minimal_hotel_reservation_id_data.res_id_value is None
assert minimal_hotel_reservation_id_data.res_id_source is None
assert minimal_hotel_reservation_id_data.res_id_source_context is None
class TestHotelReservationIdFactory:
"""Test the HotelReservationIdFactory class."""
def test_create_notif_hotel_reservation_id_full(self, sample_hotel_reservation_id_data):
"""Test creating a NotifHotelReservationId with full data."""
reservation_id = HotelReservationIdFactory.create_notif_hotel_reservation_id(sample_hotel_reservation_id_data)
assert isinstance(reservation_id, NotifHotelReservationId)
assert reservation_id.res_id_type == "123"
assert reservation_id.res_id_value == "RESERVATION-456"
assert reservation_id.res_id_source == "HOTEL_SYSTEM"
assert reservation_id.res_id_source_context == "BOOKING_ENGINE"
def test_create_retrieve_hotel_reservation_id_full(self, sample_hotel_reservation_id_data):
"""Test creating a RetrieveHotelReservationId with full data."""
reservation_id = HotelReservationIdFactory.create_retrieve_hotel_reservation_id(sample_hotel_reservation_id_data)
assert isinstance(reservation_id, RetrieveHotelReservationId)
assert reservation_id.res_id_type == "123"
assert reservation_id.res_id_value == "RESERVATION-456"
assert reservation_id.res_id_source == "HOTEL_SYSTEM"
assert reservation_id.res_id_source_context == "BOOKING_ENGINE"
def test_create_hotel_reservation_id_minimal(self, minimal_hotel_reservation_id_data):
"""Test creating hotel reservation IDs with minimal data."""
notif_reservation_id = HotelReservationIdFactory.create_notif_hotel_reservation_id(minimal_hotel_reservation_id_data)
retrieve_reservation_id = HotelReservationIdFactory.create_retrieve_hotel_reservation_id(minimal_hotel_reservation_id_data)
for reservation_id in [notif_reservation_id, retrieve_reservation_id]:
assert reservation_id.res_id_type == "999"
assert reservation_id.res_id_value is None
assert reservation_id.res_id_source is None
assert reservation_id.res_id_source_context is None
def test_from_notif_hotel_reservation_id_roundtrip(self, sample_hotel_reservation_id_data):
"""Test converting NotifHotelReservationId back to HotelReservationIdData."""
reservation_id = HotelReservationIdFactory.create_notif_hotel_reservation_id(sample_hotel_reservation_id_data)
converted_data = HotelReservationIdFactory.from_notif_hotel_reservation_id(reservation_id)
assert converted_data == sample_hotel_reservation_id_data
def test_from_retrieve_hotel_reservation_id_roundtrip(self, sample_hotel_reservation_id_data):
"""Test converting RetrieveHotelReservationId back to HotelReservationIdData."""
reservation_id = HotelReservationIdFactory.create_retrieve_hotel_reservation_id(sample_hotel_reservation_id_data)
converted_data = HotelReservationIdFactory.from_retrieve_hotel_reservation_id(reservation_id)
assert converted_data == sample_hotel_reservation_id_data
class TestResGuestFactory: class TestResGuestFactory:
"""Test the ResGuestFactory class.""" """Test the ResGuestFactory class."""
@@ -313,6 +403,17 @@ class TestIntegration:
assert retrieve_customer.person_name.given_name == retrieve_from_res_guests.person_name.given_name assert retrieve_customer.person_name.given_name == retrieve_from_res_guests.person_name.given_name
assert retrieve_customer.person_name.surname == retrieve_from_res_guests.person_name.surname assert retrieve_customer.person_name.surname == retrieve_from_res_guests.person_name.surname
def test_hotel_reservation_id_factories_produce_same_data(self, sample_hotel_reservation_id_data):
"""Test that both HotelReservationId factories produce equivalent results."""
notif_reservation_id = HotelReservationIdFactory.create_notif_hotel_reservation_id(sample_hotel_reservation_id_data)
retrieve_reservation_id = HotelReservationIdFactory.create_retrieve_hotel_reservation_id(sample_hotel_reservation_id_data)
# Both should have the same field values
assert notif_reservation_id.res_id_type == retrieve_reservation_id.res_id_type
assert notif_reservation_id.res_id_value == retrieve_reservation_id.res_id_value
assert notif_reservation_id.res_id_source == retrieve_reservation_id.res_id_source
assert notif_reservation_id.res_id_source_context == retrieve_reservation_id.res_id_source_context
def test_complex_customer_workflow(self): def test_complex_customer_workflow(self):
"""Test a complex workflow with multiple operations.""" """Test a complex workflow with multiple operations."""
# Create original data # Create original data
@@ -342,6 +443,29 @@ class TestIntegration:
notif_extracted = ResGuestFactory.extract_primary_customer(notif_res_guests) notif_extracted = ResGuestFactory.extract_primary_customer(notif_res_guests)
retrieve_extracted = ResGuestFactory.extract_primary_customer(retrieve_res_guests) retrieve_extracted = ResGuestFactory.extract_primary_customer(retrieve_res_guests)
# All should be equal
assert original_data == notif_extracted
assert original_data == retrieve_extracted
assert notif_extracted == retrieve_extracted
def test_complex_hotel_reservation_id_workflow(self):
"""Test a complex workflow with HotelReservationId operations."""
# Create original reservation ID data
original_data = HotelReservationIdData(
res_id_type="456",
res_id_value="COMPLEX-RESERVATION-789",
res_id_source="INTEGRATION_SYSTEM",
res_id_source_context="API_CALL"
)
# Create HotelReservationId for both types
notif_reservation_id = HotelReservationIdFactory.create_notif_hotel_reservation_id(original_data)
retrieve_reservation_id = HotelReservationIdFactory.create_retrieve_hotel_reservation_id(original_data)
# Extract data back from both
notif_extracted = HotelReservationIdFactory.from_notif_hotel_reservation_id(notif_reservation_id)
retrieve_extracted = HotelReservationIdFactory.from_retrieve_hotel_reservation_id(retrieve_reservation_id)
# All should be equal # All should be equal
assert original_data == notif_extracted assert original_data == notif_extracted
assert original_data == retrieve_extracted assert original_data == retrieve_extracted