CI / skip-ci-check (pull_request) Successful in 32s
CI / python-lint (pull_request) Successful in 36s
CI / docker-ci (pull_request) Successful in 36s
CI / secret-scan (pull_request) Successful in 47s
CI / admin-unit (pull_request) Successful in 1m27s
CI / viewer-unit (pull_request) Successful in 3m53s
CI / e2e (pull_request) Successful in 3m5s
POST /people/{keep_id}/merge reassigns faces, videos, and match
decisions, rebuilds encodings, then deletes sources so strict
Auto-Match thresholds stay recoverable.
110 lines
2.7 KiB
Python
110 lines
2.7 KiB
Python
"""People schemas for web API (Phase 3)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import date
|
|
from typing import Optional
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
|
|
|
|
class PersonResponse(BaseModel):
|
|
"""Person DTO returned from API."""
|
|
|
|
model_config = ConfigDict(from_attributes=True, protected_namespaces=())
|
|
|
|
id: int
|
|
first_name: str
|
|
last_name: str
|
|
middle_name: Optional[str] = None
|
|
maiden_name: Optional[str] = None
|
|
date_of_birth: Optional[date] = None
|
|
email: Optional[str] = None
|
|
phone: Optional[str] = None
|
|
|
|
|
|
class PersonCreateRequest(BaseModel):
|
|
"""Request payload to create a new person."""
|
|
|
|
model_config = ConfigDict(protected_namespaces=())
|
|
|
|
first_name: str = Field(..., min_length=1)
|
|
last_name: str = Field(..., min_length=1)
|
|
middle_name: Optional[str] = None
|
|
maiden_name: Optional[str] = None
|
|
date_of_birth: Optional[date] = None
|
|
email: Optional[str] = None
|
|
phone: Optional[str] = None
|
|
|
|
|
|
class PeopleListResponse(BaseModel):
|
|
"""List of people for selection dropdowns."""
|
|
|
|
model_config = ConfigDict(protected_namespaces=())
|
|
|
|
items: list[PersonResponse]
|
|
total: int
|
|
|
|
|
|
class PersonUpdateRequest(BaseModel):
|
|
"""Request payload to update a person."""
|
|
|
|
model_config = ConfigDict(protected_namespaces=())
|
|
|
|
first_name: str = Field(..., min_length=1)
|
|
last_name: str = Field(..., min_length=1)
|
|
middle_name: Optional[str] = None
|
|
maiden_name: Optional[str] = None
|
|
date_of_birth: Optional[date] = None
|
|
email: Optional[str] = None
|
|
phone: Optional[str] = None
|
|
|
|
|
|
class PersonWithFacesResponse(BaseModel):
|
|
"""Person with face count for modify identified workflow."""
|
|
|
|
model_config = ConfigDict(from_attributes=True, protected_namespaces=())
|
|
|
|
id: int
|
|
first_name: str
|
|
last_name: str
|
|
middle_name: Optional[str] = None
|
|
maiden_name: Optional[str] = None
|
|
date_of_birth: Optional[date] = None
|
|
email: Optional[str] = None
|
|
phone: Optional[str] = None
|
|
face_count: int
|
|
video_count: int
|
|
|
|
|
|
class PeopleWithFacesListResponse(BaseModel):
|
|
"""List of people with face counts."""
|
|
|
|
model_config = ConfigDict(protected_namespaces=())
|
|
|
|
items: list[PersonWithFacesResponse]
|
|
total: int
|
|
|
|
|
|
class PersonMergeRequest(BaseModel):
|
|
"""Merge other people into the keep person (Immich-style)."""
|
|
|
|
model_config = ConfigDict(protected_namespaces=())
|
|
|
|
merge_ids: list[int] = Field(..., min_length=1, description="Person IDs to merge into keep")
|
|
|
|
|
|
class PersonMergeResponse(BaseModel):
|
|
"""Result of merging people into keep."""
|
|
|
|
model_config = ConfigDict(protected_namespaces=())
|
|
|
|
person: PersonResponse
|
|
merged_ids: list[int]
|
|
faces_moved: int
|
|
videos_moved: int
|
|
encodings_rebuilt: int
|
|
|
|
|
|
|