import uuid from repositories.pocketbase_client import pb_client from repositories.repo_config import USE_MOCK_REPOSITORIES COLLECTION = 'tenants' class TenantRepository: """ Data access for the `tenants` collection. No business logic — callers (services) decide what a missing tenant or inactive status means. """ def get_by_domain(self, domain): """ Returns the tenant record matching domain, or None. Data flow: domain → PocketBase filter `domain = "{domain}"` → first matching record returned, or None """ safe_domain = domain.replace('"', '\\"') return pb_client.get_first(COLLECTION, f'domain = "{safe_domain}"') def get_by_id(self, tenant_id): """Returns a tenant record by id, or None.""" return pb_client.get_one(COLLECTION, tenant_id) def get_by_stripe_customer_id(self, stripe_customer_id): """Returns the tenant matching a Stripe customer id — used by the Stripe webhook handler.""" safe_id = stripe_customer_id.replace('"', '\\"') return pb_client.get_first(COLLECTION, f'stripe_customer_id = "{safe_id}"') def create(self, data): """Creates a tenant record and returns it.""" return pb_client.create(COLLECTION, data) def update(self, tenant_id, data): """Patches a tenant record and returns the updated record.""" return pb_client.update(COLLECTION, tenant_id, data) def delete(self, tenant_id): """Hard-deletes a tenant record — GDPR Article 17 erasure only, never used in normal operation.""" return pb_client.delete(COLLECTION, tenant_id) class MockTenantRepository: """In-memory stand-in for TenantRepository — same interface, no PocketBase dependency.""" def __init__(self): self._records = {} def get_by_domain(self, domain): return next((r for r in self._records.values() if r.get('domain') == domain), None) def get_by_id(self, tenant_id): return self._records.get(tenant_id) def get_by_stripe_customer_id(self, stripe_customer_id): return next((r for r in self._records.values() if r.get('stripe_customer_id') == stripe_customer_id), None) def create(self, data): record_id = data.get('id') or str(uuid.uuid4()) record = {'id': record_id, **data} self._records[record_id] = record return record def update(self, tenant_id, data): if tenant_id not in self._records: return None self._records[tenant_id] = {**self._records[tenant_id], **data} return self._records[tenant_id] def delete(self, tenant_id): return self._records.pop(tenant_id, None) is not None tenant_repository = MockTenantRepository() if USE_MOCK_REPOSITORIES else TenantRepository()