"""B01_Dashboard 요청 스키마.""" from datetime import date from pydantic import BaseModel, Field class UpdateUserRequest(BaseModel): name: str = Field(min_length=1, max_length=100) position: str | None = Field(default=None, max_length=100) department: str | None = Field(default=None, max_length=100) phone: str | None = Field(default=None, max_length=50) class UiPrefsRequest(BaseModel): """화면 취향 묶음 — 배치·표시 값만. 키는 브라우저 등록표(`b_page_state.ts`)가 정본이다. 값은 문자열 하나(높이는 `"438"`, 접힘은 `"true"`)라 저장소에 넣던 모양 그대로다. 설계값이 섞여 들어오지 않게 **문자열만** 받는다. """ prefs: dict[str, str] = Field(default_factory=dict) class CreateCompanyRequest(BaseModel): name: str = Field(min_length=1, max_length=255) business_registration_number: str = Field(min_length=1, max_length=20) business_address: str | None = Field(default=None, max_length=500) business_owner: str | None = Field(default=None, max_length=100) class JoinCompanyRequest(BaseModel): company_id: int = Field(gt=0) class AddMemberRequest(BaseModel): # 팀원 등록은 「이미 가입한 사람을 고르는」 일이다 (2026-09-06 사용자 확정) — # 계정을 대신 만들지 않는다. 소속이 없는 가입자만 고를 수 있다. user_id: int = Field(gt=0) class InviteMemberRequest(BaseModel): """아직 가입하지 않은 사람에게 보내는 가입 안내 메일.""" email: str = Field(min_length=3, max_length=255) name: str | None = Field(default=None, max_length=100) class UpdateCompanyLogoRequest(BaseModel): # 회사 대표 로고 (company_assets.id, kind=LOGO). None 이면 지정을 지운다. logo_asset_id: int | None = Field(default=None, gt=0) class ProcessJoinRequest(BaseModel): action: str = Field(pattern="^(APPROVE|REJECT)$") reason: str | None = Field(default=None, max_length=500) class ChangeUserRoleRequest(BaseModel): role: str = Field(pattern="^(SYSTEM_ADMIN|ADMIN|USER)$") class AssignCompanyRequest(BaseModel): company_id: int | None = Field(default=None, gt=0) class UpdateProjectRequest(BaseModel): name: str = Field(min_length=1, max_length=255) # 참여자 (2026-09-06 사용자 확정) — 도면 표제란 3역할과 별개로, 설계에 손대는 사람들. # 참여자면 일반 사용자도 그 프로젝트를 수정할 수 있다. 비우면 지금 값을 그대로 둔다. member_user_ids: list[int] | None = Field(default=None) region: str | None = Field(default=None, max_length=100) road_type: str | None = Field(default=None, max_length=100) project_year: int | None = Field(default=None, ge=1900, le=2100) estimated_length_m: float | None = Field(default=None, ge=0) # 계획노선 사용 범위 (2026-09-04 사용자 지시) — 비우면 전 구간. route_start_m: float | None = Field(default=None, ge=0) route_end_m: float | None = Field(default=None, ge=0) memo: str | None = Field(default=None, max_length=5000) status: str | None = Field(default=None, max_length=50) # 도면 표제란·표지에 실리는 값 (2026-09-02). 프로그램이 지어낼 수 없어 사람이 넣는다. client_org: str | None = Field(default=None, max_length=255) project_number: str | None = Field(default=None, max_length=100) work_amount: str | None = Field(default=None, max_length=100) # 설계일자는 확정일 자동이 아니라 사용자 지정이다 (2026-09-02 사용자 확정). design_date: date | None = None # 담당자는 회사 구성원(users) 중에서, 로고·서명은 회사 공유 자산(company_assets) 중에서 # 고른다 — 같은 회사 것인지는 라우터가 확인한다. pm_user_id: int | None = Field(default=None, gt=0) field_lead_user_id: int | None = Field(default=None, gt=0) designer_user_id: int | None = Field(default=None, gt=0) logo_asset_id: int | None = Field(default=None, gt=0) signature_asset_id: int | None = Field(default=None, gt=0) class AdminUpdateUserRequest(UpdateUserRequest): status: str | None = Field( default=None, pattern="^(NO_COMPANY|PENDING|ACTIVE|INACTIVE|REJECTED)$" ) class UpdateCompanyAssetRequest(BaseModel): label: str = Field(min_length=1, max_length=100) # 사용자 계정에 물릴 수도(개인 서명) 아닐 수도(회사 공용 직인) 있다. user_id: int | None = Field(default=None, gt=0)