API: Standardized JSON list responses with Pydantic schemas and Pagination; add sort_by/sort_dir validation with whitelists; consistent JSON 401 for /api/*; structured logging for sorting/pagination; add pydantic dep; add Docker smoke script and README docs.
This commit is contained in:
101
app/schemas.py
Normal file
101
app/schemas.py
Normal file
@@ -0,0 +1,101 @@
|
||||
"""
|
||||
Pydantic schemas for API responses.
|
||||
|
||||
Defines output models for Clients, Phones, Cases, and Transactions, along with
|
||||
shared pagination envelopes for list endpoints.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class PhoneOut(BaseModel):
|
||||
id: int
|
||||
phone_type: Optional[str] = None
|
||||
phone_number: Optional[str] = None
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class ClientOut(BaseModel):
|
||||
id: int
|
||||
rolodex_id: Optional[str] = None
|
||||
first_name: Optional[str] = None
|
||||
last_name: Optional[str] = None
|
||||
company: Optional[str] = None
|
||||
address: Optional[str] = None
|
||||
city: Optional[str] = None
|
||||
state: Optional[str] = None
|
||||
zip_code: Optional[str] = None
|
||||
phones: Optional[List[PhoneOut]] = None
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class CaseClientOut(BaseModel):
|
||||
id: int
|
||||
rolodex_id: Optional[str] = None
|
||||
first_name: Optional[str] = None
|
||||
last_name: Optional[str] = None
|
||||
company: Optional[str] = None
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class CaseOut(BaseModel):
|
||||
id: int
|
||||
file_no: str
|
||||
status: Optional[str] = None
|
||||
case_type: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
open_date: Optional[datetime] = None
|
||||
close_date: Optional[datetime] = None
|
||||
client: Optional[CaseClientOut] = None
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class TransactionOut(BaseModel):
|
||||
id: int
|
||||
case_id: int
|
||||
case_file_no: Optional[str] = None
|
||||
transaction_date: Optional[datetime] = None
|
||||
item_no: Optional[int] = None
|
||||
amount: Optional[float] = None
|
||||
billed: Optional[str] = None
|
||||
t_code: Optional[str] = None
|
||||
t_type_l: Optional[str] = None
|
||||
quantity: Optional[float] = None
|
||||
rate: Optional[float] = None
|
||||
description: Optional[str] = None
|
||||
employee_number: Optional[str] = None
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class Pagination(BaseModel):
|
||||
page: int
|
||||
page_size: int
|
||||
total: int
|
||||
total_pages: int
|
||||
|
||||
|
||||
class RolodexListResponse(BaseModel):
|
||||
items: List[ClientOut]
|
||||
pagination: Pagination
|
||||
|
||||
|
||||
class FilesListResponse(BaseModel):
|
||||
items: List[CaseOut]
|
||||
pagination: Pagination
|
||||
|
||||
|
||||
class LedgerListResponse(BaseModel):
|
||||
items: List[TransactionOut]
|
||||
pagination: Pagination
|
||||
|
||||
|
||||
Reference in New Issue
Block a user