import uuid from datetime import datetime, timezone from repositories.pocketbase_client import pb_client from repositories.repo_config import USE_MOCK_REPOSITORIES COLLECTION = 'tenant_seats' class SeatRepository: """ Data access for the `tenant_seats` collection. Pure CRUD only — seat limit enforcement and allow/reject decisions live in licence_service, not here, per the no-business-logic-in-repositories rule. """ def get_active(self, tenant_id, email): """Returns the active seat record for (tenant_id, email), or None.""" safe_email = email.replace('"', '\\"') return pb_client.get_first( COLLECTION, f'tenant_id = "{tenant_id}" && email = "{safe_email}" && active = true' ) def count_active(self, tenant_id): """Returns the count of active seats for a tenant.""" return len(pb_client.list( COLLECTION, filter_str=f'tenant_id = "{tenant_id}" && active = true', per_page=200 )) def list_for_tenant(self, tenant_id): """Returns all seats (active and inactive) for a tenant.""" return pb_client.list(COLLECTION, filter_str=f'tenant_id = "{tenant_id}"', per_page=200) def create(self, data): """Creates a seat record and returns it.""" return pb_client.create(COLLECTION, data) def update_last_accessed(self, seat_id): """Stamps last_accessed = now on an existing seat record.""" return pb_client.update(COLLECTION, seat_id, { 'last_accessed': datetime.now(timezone.utc).isoformat() }) def delete(self, seat_id): """Deletes a seat record. Returns True on success.""" return pb_client.delete(COLLECTION, seat_id) class MockSeatRepository: """In-memory stand-in for SeatRepository.""" def __init__(self): self._records = {} def get_active(self, tenant_id, email): return next(( r for r in self._records.values() if r.get('tenant_id') == tenant_id and r.get('email') == email and r.get('active') ), None) def count_active(self, tenant_id): return len([ r for r in self._records.values() if r.get('tenant_id') == tenant_id and r.get('active') ]) def list_for_tenant(self, tenant_id): return [r for r in self._records.values() if r.get('tenant_id') == tenant_id] def create(self, data): record_id = data.get('id') or str(uuid.uuid4()) record = {'id': record_id, 'active': True, **data} self._records[record_id] = record return record def update_last_accessed(self, seat_id): if seat_id not in self._records: return None self._records[seat_id]['last_accessed'] = datetime.now(timezone.utc).isoformat() return self._records[seat_id] def delete(self, seat_id): return self._records.pop(seat_id, None) is not None seat_repository = MockSeatRepository() if USE_MOCK_REPOSITORIES else SeatRepository()