- project_members 표 신설(016 마이그레이션, 기존 프로젝트는 생성자 자동 채움) - 프로젝트 수정 모달에 참여자 선택 추가, 참여자로 지정된 일반사용자는 해당 프로젝트 수정 가능 (백엔드 _can_edit_project 동반 수정) - B02 프로젝트 생성 시 생성자를 참여자로 자동 등록, 참여자도 같은 회사 구성원인지 검증 - 가입 요청 목록을 대기 상태만 표시 (처리 완료 건이 사용자 관리 목록과 중복 노출되던 문제) - 팀원 등록 시 남아 있던 가입 신청 자동 정리 - 서명·로고 선택 문구를 뜻이 드러나게 수정 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
96 lines
4.1 KiB
Python
96 lines
4.1 KiB
Python
"""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 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)
|