Validation_Suite/validation-suite/backend/mercury/app/services/domain_service.py

89 lines
3.4 KiB
Python

from __future__ import annotations
from typing import TypeVar
from uuid import UUID
from sqlalchemy.orm import Session
from fastapi import HTTPException, status
from app.models.contact import Contact
from app.models.customer import Customer
from app.models.device import Device
from app.models.equipment import Equipment
from app.models.location import Location
from app.models.user import User, UserRole
from app.models.validation import Validation
from app.repositories.base import Repository
from app.repositories.domain import (
ContactRepository,
CustomerRepository,
DeviceRepository,
EquipmentRepository,
LocationRepository,
UserRepository,
ValidationRepository,
)
ModelT = TypeVar("ModelT")
class CrudService:
def __init__(self, repository: Repository[ModelT]) -> None:
self.repository = repository
def list(self, page: int = 1, page_size: int = 20, search: str | None = None) -> dict:
safe_page = max(page, 1)
safe_page_size = min(max(page_size, 1), 100)
offset = (safe_page - 1) * safe_page_size
return {
"items": self.repository.list(safe_page_size, offset, search),
"total": self.repository.count(search),
"page": safe_page,
"page_size": safe_page_size,
}
def create(self, data: dict) -> ModelT:
data = self._normalize(data)
return self.repository.add(self.repository.model(**data))
def update(self, item_id: str, data: dict) -> ModelT:
data = self._normalize(data)
item = self.repository.get(item_id)
if item is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Resource not found")
if isinstance(item, Validation) and item.status in {"FREIGEGEBEN", "ABGESCHLOSSEN"}:
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Freigegebene oder abgeschlossene Validierungen sind schreibgeschuetzt")
for key, value in data.items():
setattr(item, key, value)
return item
def _normalize(self, data: dict) -> dict:
normalized = {}
for key, value in data.items():
if key.endswith("_id") and value == "":
normalized[key] = None
elif isinstance(value, UUID):
normalized[key] = str(value)
elif isinstance(value, list):
normalized[key] = [str(item) if isinstance(item, UUID) else item for item in value]
else:
normalized[key] = value
return normalized
def delete(self, item_id: str) -> None:
item = self.repository.get(item_id)
if item is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Resource not found")
self.repository.delete(item)
class DomainServices:
def __init__(self, session: Session) -> None:
self.users: CrudService[User] = CrudService(UserRepository(session))
self.customers: CrudService[Customer] = CrudService(CustomerRepository(session))
self.locations: CrudService[Location] = CrudService(LocationRepository(session))
self.contacts: CrudService[Contact] = CrudService(ContactRepository(session))
self.devices: CrudService[Device] = CrudService(DeviceRepository(session))
self.equipment: CrudService[Equipment] = CrudService(EquipmentRepository(session))
self.validations: CrudService[Validation] = CrudService(ValidationRepository(session))