91 lines
3.5 KiB
Python
91 lines
3.5 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
|
|
total = self.repository.count(search)
|
|
return {
|
|
"items": self.repository.list(safe_page_size, offset, search),
|
|
"total": total,
|
|
"page": safe_page,
|
|
"page_size": safe_page_size,
|
|
"pages": max((total + safe_page_size - 1) // safe_page_size, 1),
|
|
}
|
|
|
|
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))
|