87 lines
3.0 KiB
Python
87 lines
3.0 KiB
Python
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()
|