Changed how services work and updated csv_import

This commit is contained in:
Jonas Linter
2025-11-18 16:40:09 +01:00
parent 2c61d13d7a
commit a34fc6e28a
3 changed files with 67 additions and 28 deletions

View File

@@ -184,7 +184,7 @@ class CSVImporter:
return None
async def import_csv_file(
self, csv_file_path: str, hotel_code: Optional[str] = None, dryrun: bool = False
self, csv_file_path: str, hotel_code: Optional[str] = None, dryrun: bool = False, pre_acknowledge: bool = False, client_id: Optional[str] = None, username: Optional[str] = None
) -> dict[str, Any]:
"""Import reservations from a CSV file.
@@ -192,6 +192,9 @@ class CSVImporter:
csv_file_path: Path to CSV file
hotel_code: Optional hotel code to override CSV values
dryrun: If True, parse and print first 10 rows as JSON without importing
pre_acknowledge: If True, pre-acknowledges all imported reservations
client_id: Client ID for pre-acknowledgement (required if pre_acknowledge=True)
username: Username for pre-acknowledgement (optional, but recommended)
Returns:
Dictionary with import statistics or parsed data (if dryrun=True)
@@ -200,6 +203,9 @@ class CSVImporter:
if not path.exists():
raise FileNotFoundError(f"CSV file not found: {csv_file_path}")
if pre_acknowledge and not client_id:
raise ValueError("client_id is required when pre_acknowledge=True")
# Start a transaction - will rollback on any exception
await self.db_session.begin()
@@ -272,6 +278,7 @@ class CSVImporter:
"existing_customers": 0,
"created_reservations": 0,
"skipped_duplicates": 0,
"pre_acknowledged": 0,
"errors": [],
}
@@ -353,10 +360,10 @@ class CSVImporter:
"name_title": None,
}
# Get or create customer
customer = await self._find_or_create_customer(customer_data)
# Get or create customer (without committing)
customer = await self._find_or_create_customer(customer_data, auto_commit=False)
if customer.id is None:
await self.db_session.refresh(customer)
await self.db_session.flush() # Flush to get customer.id
stats["created_customers"] += 1
else:
stats["existing_customers"] += 1
@@ -463,13 +470,28 @@ class CSVImporter:
room_classification_code=room_class_code,
)
# Create reservation if customer exists
# Create reservation if customer exists (without committing)
if customer.id:
await self.reservation_service.create_reservation(
reservation, customer.id
db_reservation = await self.reservation_service.create_reservation(
reservation, customer.id, auto_commit=False
)
stats["created_reservations"] += 1
_LOGGER.info("Created reservation for %s %s", first_name, last_name)
# Pre-acknowledge if requested
if pre_acknowledge and db_reservation.md5_unique_id:
await self.reservation_service.record_acknowledgement(
client_id=client_id,
unique_id=db_reservation.md5_unique_id,
username=username,
auto_commit=False
)
stats["pre_acknowledged"] += 1
_LOGGER.debug(
"Pre-acknowledged reservation %s for client %s",
db_reservation.md5_unique_id,
username or client_id
)
else:
raise ValueError("Failed to get or create customer")
@@ -505,7 +527,7 @@ class CSVImporter:
else:
return None
async def _find_or_create_customer(self, customer_data: dict) -> Customer:
async def _find_or_create_customer(self, customer_data: dict, auto_commit: bool = True) -> Customer:
"""Find existing customer or create new one.
Args:
@@ -550,18 +572,18 @@ class CSVImporter:
# Update customer data if needed
try:
existing_customer = await self.customer_service.update_customer(
existing, customer_data
existing, customer_data, auto_commit=auto_commit
)
except Exception as e:
print(customer_data)
print("---")
print(existing)
raise
return existing_customer
# Create new customer
return await self.customer_service.create_customer(customer_data)
return await self.customer_service.create_customer(customer_data, auto_commit=auto_commit)

View File

@@ -23,11 +23,12 @@ class CustomerService:
def __init__(self, session: AsyncSession):
self.session = session
async def create_customer(self, customer_data: dict) -> Customer:
async def create_customer(self, customer_data: dict, auto_commit: bool = True) -> Customer:
"""Create a new customer and automatically create its hashed version.
Args:
customer_data: Dictionary containing customer fields
auto_commit: If True, commits the transaction. If False, caller must commit.
Returns:
The created Customer instance (with hashed_version relationship populated)
@@ -60,17 +61,19 @@ class CustomerService:
hashed_customer.created_at = datetime.now(UTC)
self.session.add(hashed_customer)
await self.session.commit()
await self.session.refresh(customer)
if auto_commit:
await self.session.commit()
await self.session.refresh(customer)
return customer
async def update_customer(self, customer: Customer, update_data: dict) -> Customer:
async def update_customer(self, customer: Customer, update_data: dict, auto_commit: bool = True) -> Customer:
"""Update an existing customer and sync its hashed version.
Args:
customer: The customer to update
update_data: Dictionary of fields to update
auto_commit: If True, commits the transaction. If False, caller must commit.
Returns:
The updated Customer instance
@@ -151,8 +154,9 @@ class CustomerService:
hashed_customer.created_at = datetime.now(UTC)
self.session.add(hashed_customer)
await self.session.commit()
await self.session.refresh(customer)
if auto_commit:
await self.session.commit()
await self.session.refresh(customer)
return customer
@@ -171,7 +175,7 @@ class CustomerService:
)
return result.scalar_one_or_none()
async def get_or_create_customer(self, customer_data: dict) -> Customer:
async def get_or_create_customer(self, customer_data: dict, auto_commit: bool = True) -> Customer:
"""Get existing customer or create new one if not found.
Uses contact_id to identify existing customers if provided.
@@ -179,6 +183,7 @@ class CustomerService:
Args:
customer_data: Dictionary containing customer fields
(contact_id is optional)
auto_commit: If True, commits the transaction. If False, caller must commit.
Returns:
Existing or newly created Customer instance
@@ -190,10 +195,10 @@ class CustomerService:
existing = await self.get_customer_by_contact_id(contact_id)
if existing:
# Update existing customer
return await self.update_customer(existing, customer_data)
return await self.update_customer(existing, customer_data, auto_commit=auto_commit)
# Create new customer (either no contact_id or customer doesn't exist)
return await self.create_customer(customer_data)
return await self.create_customer(customer_data, auto_commit=auto_commit)
async def get_hashed_customer(self, customer_id: int) -> HashedCustomer | None:
"""Get the hashed version of a customer.

View File

@@ -48,13 +48,14 @@ class ReservationService:
return Reservation(**data)
async def create_reservation(
self, reservation_data: ReservationData, customer_id: int
self, reservation_data: ReservationData, customer_id: int, auto_commit: bool = True
) -> Reservation:
"""Create a new reservation.
Args:
reservation_data: ReservationData containing reservation details
customer_id: ID of the customer making the reservation
auto_commit: If True, commits the transaction. If False, caller must commit.
Returns:
Created Reservation instance
@@ -63,8 +64,13 @@ class ReservationService:
reservation_data, customer_id
)
self.session.add(reservation)
await self.session.commit()
await self.session.refresh(reservation)
if auto_commit:
await self.session.commit()
await self.session.refresh(reservation)
else:
await self.session.flush() # Flush to get the reservation.id
return reservation
async def get_reservation_by_unique_id(
@@ -220,7 +226,7 @@ class ReservationService:
]
async def record_acknowledgement(
self, client_id: str, unique_id: str, username: Optional[str] = None
self, client_id: str, unique_id: str, username: Optional[str] = None, auto_commit: bool = True
) -> AckedRequest:
"""Record that a client has acknowledged a reservation.
@@ -228,6 +234,7 @@ class ReservationService:
client_id: The client ID
unique_id: The unique_id of the reservation (md5_unique_id)
username: The username of the client making the request (optional)
auto_commit: If True, commits the transaction. If False, caller must commit.
Returns:
Created AckedRequest instance
@@ -239,8 +246,13 @@ class ReservationService:
timestamp=datetime.now(UTC),
)
self.session.add(acked)
await self.session.commit()
await self.session.refresh(acked)
if auto_commit:
await self.session.commit()
await self.session.refresh(acked)
else:
await self.session.flush() # Flush to get the acked.id
return acked
async def is_acknowledged(self, unique_id: str, username: Optional[str] = None, client_id: Optional[str] = None) -> bool: