feat: add repair parts tracking
This commit is contained in:
1 parent
6e550c1c13
commit
eab9646960
23 files changed
+2386
-4
No files matched your search
@@ -0,0 +1,75 @@
|
||||
"""Business rules for the minimal component registry."""
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
from app.components.exceptions import (
|
||||
ComponentActorRequired,
|
||||
ComponentNotFound,
|
||||
ComponentValidationError,
|
||||
DuplicateComponentAssetID,
|
||||
)
|
||||
from app.components.models import ComponentCreateRequest, ComponentDetail
|
||||
from app.components.repository import ComponentRepository
|
||||
|
||||
|
||||
class ComponentService:
|
||||
"""Minimal component workflows independent of FastAPI."""
|
||||
|
||||
def __init__(self, repository: ComponentRepository):
|
||||
self.repository = repository
|
||||
|
||||
@staticmethod
|
||||
def _normalize_optional_text(value: str | None, field_name: str) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
normalized = str(value).strip()
|
||||
if not normalized:
|
||||
raise ComponentValidationError(
|
||||
f"{field_name} must not be blank when supplied"
|
||||
)
|
||||
if len(normalized) > 255:
|
||||
raise ComponentValidationError(
|
||||
f"{field_name} must not exceed 255 characters"
|
||||
)
|
||||
return normalized
|
||||
|
||||
@staticmethod
|
||||
def _map_component(component: dict) -> ComponentDetail:
|
||||
return ComponentDetail(**component)
|
||||
|
||||
def create_component(
|
||||
self,
|
||||
request: ComponentCreateRequest,
|
||||
*,
|
||||
actor_user_id: UUID | None,
|
||||
) -> ComponentDetail:
|
||||
if actor_user_id is None:
|
||||
raise ComponentActorRequired()
|
||||
|
||||
asset_id = self._normalize_optional_text(request.asset_id, "asset_id")
|
||||
values = {
|
||||
"manufacturer": self._normalize_optional_text(
|
||||
request.manufacturer, "manufacturer"
|
||||
),
|
||||
"model": self._normalize_optional_text(request.model, "model"),
|
||||
"manufacturer_serial": self._normalize_optional_text(
|
||||
request.manufacturer_serial, "manufacturer_serial"
|
||||
),
|
||||
}
|
||||
try:
|
||||
with self.repository.transaction() as repository:
|
||||
component = repository.create_component(
|
||||
component_type=request.component_type,
|
||||
asset_id=asset_id,
|
||||
created_by=actor_user_id,
|
||||
**values,
|
||||
)
|
||||
except DuplicateComponentAssetID as exc:
|
||||
raise DuplicateComponentAssetID(asset_id or "") from exc
|
||||
return self._map_component(component)
|
||||
|
||||
def get_component(self, component_id: UUID) -> ComponentDetail:
|
||||
component = self.repository.get_component(component_id)
|
||||
if component is None:
|
||||
raise ComponentNotFound(component_id)
|
||||
return self._map_component(component)
|
||||
Reference in new issue
Block a user