Changed how services work and updated csv_import
This commit is contained in:
@@ -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,7 +572,7 @@ 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:
|
||||
|
||||
@@ -564,4 +586,4 @@ class CSVImporter:
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
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,6 +154,7 @@ class CustomerService:
|
||||
hashed_customer.created_at = datetime.now(UTC)
|
||||
self.session.add(hashed_customer)
|
||||
|
||||
if auto_commit:
|
||||
await self.session.commit()
|
||||
await self.session.refresh(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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
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)
|
||||
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user