Coverage for apps/client_needs/schemas.py: 100%
61 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-04 14:06 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-04 14:06 +0000
1"""Ninja schemas for document references and client needs."""
3from ninja import ModelSchema, Schema
4from pydantic import Field, field_validator
6from apps.client_needs.models import ClientNeed, Document, DocumentClassification
7from domain.enums import ClientNeedType
10class DocumentOut(ModelSchema):
11 class Meta:
12 model = Document
13 exclude = ["loan"]
16class DocumentCreate(Schema):
17 classification: str
18 content_hash: str
19 external_doc_id: str | None = None
22class ClientNeedOut(ModelSchema):
23 borrower_ids: list[int] = []
25 class Meta:
26 model = ClientNeed
27 exclude = ["loan", "borrowers"]
29 @staticmethod
30 def resolve_borrower_ids(obj: ClientNeed) -> list[int]:
31 return list(obj.borrowers.values_list("id", flat=True))
34class ClientNeedCreate(Schema):
35 name: str = Field(..., min_length=1, max_length=255)
36 type: str = Field(..., min_length=1)
37 borrower_ids: list[int] = []
38 required: bool = True
39 description: str = ""
40 due_date: str | None = None
42 @field_validator("name")
43 @classmethod
44 def validate_name(cls, v: str) -> str:
45 s = v.strip()
46 if not s:
47 raise ValueError("Name cannot be blank.")
48 return s
50 @field_validator("type")
51 @classmethod
52 def validate_type(cls, v: str) -> str:
53 valid_types = {e.value for e in ClientNeedType}
54 if v not in valid_types:
55 raise ValueError(
56 f"Invalid need type '{v}'. Allowed types: {', '.join(sorted(valid_types))}"
57 )
58 return v
61class ClientNeedFulfill(Schema):
62 document_id: int
65class DocumentClassificationOut(ModelSchema):
66 class Meta:
67 model = DocumentClassification
68 fields = ["code", "name", "category", "system", "is_active"]
71class DocumentPatch(Schema):
72 classification: str | None = None
73 external_doc_id: str | None = None
76class GeneratedNeedsOut(Schema):
77 created: list[ClientNeedOut]
78 skipped: int
81class DocumentClassificationCreate(Schema):
82 code: str
83 name: str
84 category: str
87class DocumentClassificationPatch(Schema):
88 name: str | None = None
89 category: str | None = None
90 is_active: bool | None = None