AlpineBitsfactory. Not necessarily a great idea though
This commit is contained in:
13
src/main.py
13
src/main.py
@@ -8,11 +8,10 @@ from xsdata_pydantic.bindings import XmlSerializer
|
|||||||
|
|
||||||
from simplified_access import (
|
from simplified_access import (
|
||||||
CustomerData,
|
CustomerData,
|
||||||
CustomerFactory,
|
|
||||||
HotelReservationIdData,
|
HotelReservationIdData,
|
||||||
HotelReservationIdFactory,
|
|
||||||
PhoneTechType,
|
PhoneTechType,
|
||||||
ResGuestFactory,
|
AlpineBitsFactory,
|
||||||
|
OtaMessageType
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -65,7 +64,9 @@ def main():
|
|||||||
language="en",
|
language="en",
|
||||||
)
|
)
|
||||||
|
|
||||||
res_guests = ResGuestFactory.create_retrieve_res_guests(customer_data)
|
alpine_bits_factory = AlpineBitsFactory()
|
||||||
|
|
||||||
|
res_guests = alpine_bits_factory.create_res_guests(customer_data, OtaMessageType.RETRIEVE)
|
||||||
|
|
||||||
hotel_res_id_data = HotelReservationIdData(
|
hotel_res_id_data = HotelReservationIdData(
|
||||||
res_id_type="13",
|
res_id_type="13",
|
||||||
@@ -74,9 +75,7 @@ def main():
|
|||||||
res_id_source_context="99tales",
|
res_id_source_context="99tales",
|
||||||
)
|
)
|
||||||
# Create HotelReservationId using the factory
|
# Create HotelReservationId using the factory
|
||||||
hotel_res_id = HotelReservationIdFactory.create_retrieve_hotel_reservation_id(
|
hotel_res_id = alpine_bits_factory.create(hotel_res_id_data, OtaMessageType.RETRIEVE)
|
||||||
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(
|
||||||
|
|||||||
@@ -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:22:30.892827+00:00" ResStatus="Requested" RoomStayReservation="true">
|
<HotelReservation CreateDateTime="2025-09-24T13:36:42.168402+00:00" ResStatus="Requested" RoomStayReservation="true">
|
||||||
<UniqueID Type="14" ID="6b34fe24ac2ff811"/>
|
<UniqueID Type="14" ID="6b34fe24ac2ff811"/>
|
||||||
<RoomStays>
|
<RoomStays>
|
||||||
<RoomStay>
|
<RoomStay>
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ class PhoneTechType(Enum):
|
|||||||
MOBILE = "5"
|
MOBILE = "5"
|
||||||
|
|
||||||
|
|
||||||
|
# Enum to specify which OTA message type to use
|
||||||
|
class OtaMessageType(Enum):
|
||||||
|
NOTIF = "notification" # For OtaHotelResNotifRq
|
||||||
|
RETRIEVE = "retrieve" # For OtaResRetrieveRs
|
||||||
|
|
||||||
|
|
||||||
@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."""
|
||||||
@@ -346,6 +352,86 @@ class ResGuestFactory:
|
|||||||
return CustomerFactory.from_retrieve_customer(customer)
|
return CustomerFactory.from_retrieve_customer(customer)
|
||||||
|
|
||||||
|
|
||||||
|
class AlpineBitsFactory:
|
||||||
|
"""Unified factory class for creating AlpineBits objects with a simple interface."""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create(data: Union[CustomerData, HotelReservationIdData], message_type: OtaMessageType) -> Any:
|
||||||
|
"""
|
||||||
|
Create an AlpineBits object based on the data type and message type.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data: The data object (CustomerData, HotelReservationIdData, etc.)
|
||||||
|
message_type: Whether to create for NOTIF or RETRIEVE message types
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The appropriate AlpineBits object based on the data type and message type
|
||||||
|
"""
|
||||||
|
if isinstance(data, CustomerData):
|
||||||
|
if message_type == OtaMessageType.NOTIF:
|
||||||
|
return CustomerFactory.create_notif_customer(data)
|
||||||
|
else:
|
||||||
|
return CustomerFactory.create_retrieve_customer(data)
|
||||||
|
|
||||||
|
elif isinstance(data, HotelReservationIdData):
|
||||||
|
if message_type == OtaMessageType.NOTIF:
|
||||||
|
return HotelReservationIdFactory.create_notif_hotel_reservation_id(data)
|
||||||
|
else:
|
||||||
|
return HotelReservationIdFactory.create_retrieve_hotel_reservation_id(data)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported data type: {type(data)}")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_res_guests(customer_data: CustomerData, message_type: OtaMessageType) -> Union[NotifResGuests, RetrieveResGuests]:
|
||||||
|
"""
|
||||||
|
Create a complete ResGuests structure with a primary customer.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
customer_data: The customer data
|
||||||
|
message_type: Whether to create for NOTIF or RETRIEVE message types
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The appropriate ResGuests object
|
||||||
|
"""
|
||||||
|
if message_type == OtaMessageType.NOTIF:
|
||||||
|
return ResGuestFactory.create_notif_res_guests(customer_data)
|
||||||
|
else:
|
||||||
|
return ResGuestFactory.create_retrieve_res_guests(customer_data)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def extract_data(obj: Any) -> Union[CustomerData, HotelReservationIdData]:
|
||||||
|
"""
|
||||||
|
Extract data from an AlpineBits object back to a simple data class.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj: The AlpineBits object to extract data from
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The appropriate data object
|
||||||
|
"""
|
||||||
|
# Check if it's a Customer object
|
||||||
|
if hasattr(obj, 'person_name') and hasattr(obj.person_name, 'given_name'):
|
||||||
|
if isinstance(obj, NotifCustomer):
|
||||||
|
return CustomerFactory.from_notif_customer(obj)
|
||||||
|
elif isinstance(obj, RetrieveCustomer):
|
||||||
|
return CustomerFactory.from_retrieve_customer(obj)
|
||||||
|
|
||||||
|
# Check if it's a HotelReservationId object
|
||||||
|
elif hasattr(obj, 'res_id_type'):
|
||||||
|
if isinstance(obj, NotifHotelReservationId):
|
||||||
|
return HotelReservationIdFactory.from_notif_hotel_reservation_id(obj)
|
||||||
|
elif isinstance(obj, RetrieveHotelReservationId):
|
||||||
|
return HotelReservationIdFactory.from_retrieve_hotel_reservation_id(obj)
|
||||||
|
|
||||||
|
# Check if it's a ResGuests object
|
||||||
|
elif hasattr(obj, 'res_guest'):
|
||||||
|
return ResGuestFactory.extract_primary_customer(obj)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported object type: {type(obj)}")
|
||||||
|
|
||||||
|
|
||||||
# Usage examples
|
# Usage examples
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Create customer data using simple data class
|
# Create customer data using simple data class
|
||||||
@@ -459,3 +545,41 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
# Verify roundtrip conversion
|
# Verify roundtrip conversion
|
||||||
print("Roundtrip conversion successful:", customer_data == extracted_data)
|
print("Roundtrip conversion successful:", customer_data == extracted_data)
|
||||||
|
|
||||||
|
print("\n--- Unified AlpineBitsFactory Examples ---")
|
||||||
|
|
||||||
|
# Much simpler approach - single factory with enum parameter!
|
||||||
|
print("=== Customer Creation ===")
|
||||||
|
notif_customer = AlpineBitsFactory.create(customer_data, OtaMessageType.NOTIF)
|
||||||
|
retrieve_customer = AlpineBitsFactory.create(customer_data, OtaMessageType.RETRIEVE)
|
||||||
|
print("Created customers using unified factory")
|
||||||
|
|
||||||
|
print("=== HotelReservationId Creation ===")
|
||||||
|
reservation_id_data = HotelReservationIdData(
|
||||||
|
res_id_type="123",
|
||||||
|
res_id_value="RESERVATION-456",
|
||||||
|
res_id_source="HOTEL_SYSTEM"
|
||||||
|
)
|
||||||
|
notif_res_id = AlpineBitsFactory.create(reservation_id_data, OtaMessageType.NOTIF)
|
||||||
|
retrieve_res_id = AlpineBitsFactory.create(reservation_id_data, OtaMessageType.RETRIEVE)
|
||||||
|
print("Created reservation IDs using unified factory")
|
||||||
|
|
||||||
|
print("=== ResGuests Creation ===")
|
||||||
|
notif_res_guests = AlpineBitsFactory.create_res_guests(customer_data, OtaMessageType.NOTIF)
|
||||||
|
retrieve_res_guests = AlpineBitsFactory.create_res_guests(customer_data, OtaMessageType.RETRIEVE)
|
||||||
|
print("Created ResGuests using unified factory")
|
||||||
|
|
||||||
|
print("=== Data Extraction ===")
|
||||||
|
# Extract data back using unified interface
|
||||||
|
extracted_customer_data = AlpineBitsFactory.extract_data(notif_customer)
|
||||||
|
extracted_res_id_data = AlpineBitsFactory.extract_data(notif_res_id)
|
||||||
|
extracted_from_res_guests = AlpineBitsFactory.extract_data(retrieve_res_guests)
|
||||||
|
|
||||||
|
print("Data extraction successful:")
|
||||||
|
print("- Customer roundtrip:", customer_data == extracted_customer_data)
|
||||||
|
print("- ReservationId roundtrip:", reservation_id_data == extracted_res_id_data)
|
||||||
|
print("- ResGuests roundtrip:", customer_data == extracted_from_res_guests)
|
||||||
|
|
||||||
|
print("\n--- Comparison with old approach ---")
|
||||||
|
print("Old way required multiple imports and knowing specific factory methods")
|
||||||
|
print("New way: single import, single factory, enum parameter to specify type!")
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ from simplified_access import (
|
|||||||
ResGuestFactory,
|
ResGuestFactory,
|
||||||
HotelReservationIdData,
|
HotelReservationIdData,
|
||||||
HotelReservationIdFactory,
|
HotelReservationIdFactory,
|
||||||
|
AlpineBitsFactory,
|
||||||
PhoneTechType,
|
PhoneTechType,
|
||||||
|
OtaMessageType,
|
||||||
NotifCustomer,
|
NotifCustomer,
|
||||||
RetrieveCustomer,
|
RetrieveCustomer,
|
||||||
NotifResGuests,
|
NotifResGuests,
|
||||||
@@ -381,6 +383,141 @@ class TestPhoneTechType:
|
|||||||
assert PhoneTechType.MOBILE.value == "5"
|
assert PhoneTechType.MOBILE.value == "5"
|
||||||
|
|
||||||
|
|
||||||
|
class TestAlpineBitsFactory:
|
||||||
|
"""Test the unified AlpineBitsFactory class."""
|
||||||
|
|
||||||
|
def test_create_customer_notif(self, sample_customer_data):
|
||||||
|
"""Test creating customer using unified factory for NOTIF."""
|
||||||
|
customer = AlpineBitsFactory.create(sample_customer_data, OtaMessageType.NOTIF)
|
||||||
|
assert isinstance(customer, NotifCustomer)
|
||||||
|
assert customer.person_name.given_name == "John"
|
||||||
|
assert customer.person_name.surname == "Doe"
|
||||||
|
|
||||||
|
def test_create_customer_retrieve(self, sample_customer_data):
|
||||||
|
"""Test creating customer using unified factory for RETRIEVE."""
|
||||||
|
customer = AlpineBitsFactory.create(sample_customer_data, OtaMessageType.RETRIEVE)
|
||||||
|
assert isinstance(customer, RetrieveCustomer)
|
||||||
|
assert customer.person_name.given_name == "John"
|
||||||
|
assert customer.person_name.surname == "Doe"
|
||||||
|
|
||||||
|
def test_create_hotel_reservation_id_notif(self, sample_hotel_reservation_id_data):
|
||||||
|
"""Test creating hotel reservation ID using unified factory for NOTIF."""
|
||||||
|
reservation_id = AlpineBitsFactory.create(sample_hotel_reservation_id_data, OtaMessageType.NOTIF)
|
||||||
|
assert isinstance(reservation_id, NotifHotelReservationId)
|
||||||
|
assert reservation_id.res_id_type == "123"
|
||||||
|
assert reservation_id.res_id_value == "RESERVATION-456"
|
||||||
|
|
||||||
|
def test_create_hotel_reservation_id_retrieve(self, sample_hotel_reservation_id_data):
|
||||||
|
"""Test creating hotel reservation ID using unified factory for RETRIEVE."""
|
||||||
|
reservation_id = AlpineBitsFactory.create(sample_hotel_reservation_id_data, OtaMessageType.RETRIEVE)
|
||||||
|
assert isinstance(reservation_id, RetrieveHotelReservationId)
|
||||||
|
assert reservation_id.res_id_type == "123"
|
||||||
|
assert reservation_id.res_id_value == "RESERVATION-456"
|
||||||
|
|
||||||
|
def test_create_res_guests_notif(self, sample_customer_data):
|
||||||
|
"""Test creating ResGuests using unified factory for NOTIF."""
|
||||||
|
res_guests = AlpineBitsFactory.create_res_guests(sample_customer_data, OtaMessageType.NOTIF)
|
||||||
|
assert isinstance(res_guests, NotifResGuests)
|
||||||
|
customer = res_guests.res_guest.profiles.profile_info.profile.customer
|
||||||
|
assert customer.person_name.given_name == "John"
|
||||||
|
|
||||||
|
def test_create_res_guests_retrieve(self, sample_customer_data):
|
||||||
|
"""Test creating ResGuests using unified factory for RETRIEVE."""
|
||||||
|
res_guests = AlpineBitsFactory.create_res_guests(sample_customer_data, OtaMessageType.RETRIEVE)
|
||||||
|
assert isinstance(res_guests, RetrieveResGuests)
|
||||||
|
customer = res_guests.res_guest.profiles.profile_info.profile.customer
|
||||||
|
assert customer.person_name.given_name == "John"
|
||||||
|
|
||||||
|
def test_extract_data_from_customer(self, sample_customer_data):
|
||||||
|
"""Test extracting data from customer objects."""
|
||||||
|
# Create both types and extract data back
|
||||||
|
notif_customer = AlpineBitsFactory.create(sample_customer_data, OtaMessageType.NOTIF)
|
||||||
|
retrieve_customer = AlpineBitsFactory.create(sample_customer_data, OtaMessageType.RETRIEVE)
|
||||||
|
|
||||||
|
notif_extracted = AlpineBitsFactory.extract_data(notif_customer)
|
||||||
|
retrieve_extracted = AlpineBitsFactory.extract_data(retrieve_customer)
|
||||||
|
|
||||||
|
assert notif_extracted == sample_customer_data
|
||||||
|
assert retrieve_extracted == sample_customer_data
|
||||||
|
|
||||||
|
def test_extract_data_from_hotel_reservation_id(self, sample_hotel_reservation_id_data):
|
||||||
|
"""Test extracting data from hotel reservation ID objects."""
|
||||||
|
# Create both types and extract data back
|
||||||
|
notif_res_id = AlpineBitsFactory.create(sample_hotel_reservation_id_data, OtaMessageType.NOTIF)
|
||||||
|
retrieve_res_id = AlpineBitsFactory.create(sample_hotel_reservation_id_data, OtaMessageType.RETRIEVE)
|
||||||
|
|
||||||
|
notif_extracted = AlpineBitsFactory.extract_data(notif_res_id)
|
||||||
|
retrieve_extracted = AlpineBitsFactory.extract_data(retrieve_res_id)
|
||||||
|
|
||||||
|
assert notif_extracted == sample_hotel_reservation_id_data
|
||||||
|
assert retrieve_extracted == sample_hotel_reservation_id_data
|
||||||
|
|
||||||
|
def test_extract_data_from_res_guests(self, sample_customer_data):
|
||||||
|
"""Test extracting data from ResGuests objects."""
|
||||||
|
# Create both types and extract data back
|
||||||
|
notif_res_guests = AlpineBitsFactory.create_res_guests(sample_customer_data, OtaMessageType.NOTIF)
|
||||||
|
retrieve_res_guests = AlpineBitsFactory.create_res_guests(sample_customer_data, OtaMessageType.RETRIEVE)
|
||||||
|
|
||||||
|
notif_extracted = AlpineBitsFactory.extract_data(notif_res_guests)
|
||||||
|
retrieve_extracted = AlpineBitsFactory.extract_data(retrieve_res_guests)
|
||||||
|
|
||||||
|
assert notif_extracted == sample_customer_data
|
||||||
|
assert retrieve_extracted == sample_customer_data
|
||||||
|
|
||||||
|
def test_unsupported_data_type_error(self):
|
||||||
|
"""Test that unsupported data types raise ValueError."""
|
||||||
|
with pytest.raises(ValueError, match="Unsupported data type"):
|
||||||
|
AlpineBitsFactory.create("invalid_data", OtaMessageType.NOTIF)
|
||||||
|
|
||||||
|
def test_unsupported_object_type_error(self):
|
||||||
|
"""Test that unsupported object types raise ValueError in extract_data."""
|
||||||
|
with pytest.raises(ValueError, match="Unsupported object type"):
|
||||||
|
AlpineBitsFactory.extract_data("invalid_object")
|
||||||
|
|
||||||
|
def test_complete_workflow_with_unified_factory(self):
|
||||||
|
"""Test a complete workflow using only the unified factory."""
|
||||||
|
# Original data
|
||||||
|
customer_data = CustomerData(
|
||||||
|
given_name="Unified",
|
||||||
|
surname="Factory",
|
||||||
|
email_address="unified@factory.com",
|
||||||
|
phone_numbers=[("+1234567890", PhoneTechType.MOBILE)]
|
||||||
|
)
|
||||||
|
|
||||||
|
reservation_data = HotelReservationIdData(
|
||||||
|
res_id_type="999",
|
||||||
|
res_id_value="UNIFIED-TEST"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create using unified factory
|
||||||
|
customer_notif = AlpineBitsFactory.create(customer_data, OtaMessageType.NOTIF)
|
||||||
|
customer_retrieve = AlpineBitsFactory.create(customer_data, OtaMessageType.RETRIEVE)
|
||||||
|
|
||||||
|
res_id_notif = AlpineBitsFactory.create(reservation_data, OtaMessageType.NOTIF)
|
||||||
|
res_id_retrieve = AlpineBitsFactory.create(reservation_data, OtaMessageType.RETRIEVE)
|
||||||
|
|
||||||
|
res_guests_notif = AlpineBitsFactory.create_res_guests(customer_data, OtaMessageType.NOTIF)
|
||||||
|
res_guests_retrieve = AlpineBitsFactory.create_res_guests(customer_data, OtaMessageType.RETRIEVE)
|
||||||
|
|
||||||
|
# Extract everything back
|
||||||
|
extracted_customer_from_notif = AlpineBitsFactory.extract_data(customer_notif)
|
||||||
|
extracted_customer_from_retrieve = AlpineBitsFactory.extract_data(customer_retrieve)
|
||||||
|
|
||||||
|
extracted_res_id_from_notif = AlpineBitsFactory.extract_data(res_id_notif)
|
||||||
|
extracted_res_id_from_retrieve = AlpineBitsFactory.extract_data(res_id_retrieve)
|
||||||
|
|
||||||
|
extracted_from_res_guests_notif = AlpineBitsFactory.extract_data(res_guests_notif)
|
||||||
|
extracted_from_res_guests_retrieve = AlpineBitsFactory.extract_data(res_guests_retrieve)
|
||||||
|
|
||||||
|
# Verify everything matches
|
||||||
|
assert extracted_customer_from_notif == customer_data
|
||||||
|
assert extracted_customer_from_retrieve == customer_data
|
||||||
|
assert extracted_res_id_from_notif == reservation_data
|
||||||
|
assert extracted_res_id_from_retrieve == reservation_data
|
||||||
|
assert extracted_from_res_guests_notif == customer_data
|
||||||
|
assert extracted_from_res_guests_retrieve == customer_data
|
||||||
|
|
||||||
|
|
||||||
class TestIntegration:
|
class TestIntegration:
|
||||||
"""Integration tests combining both factories."""
|
"""Integration tests combining both factories."""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user