from typing import Optional from pydantic import BaseModel, ConfigDict, Field, field_validator from pydantic.alias_generators import to_camel from app.schemas.bx.common import DatetimeToStr, OptDatetimeToStr def _coerce_optional_id(value): if value is None: return None s = str(value).strip() return s or None class AdvanceApplyCreate(BaseModel): model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel) reason: str purpose: Optional[str] = None amount: float remark: Optional[str] = None expense_item_id: Optional[str] = None @field_validator("expense_item_id", mode="before") @classmethod def validate_expense_item_id(cls, value): return _coerce_optional_id(value) class AdvanceApplyUpdate(BaseModel): model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel) reason: Optional[str] = None purpose: Optional[str] = None amount: Optional[float] = None remark: Optional[str] = None expense_item_id: Optional[str] = None @field_validator("expense_item_id", mode="before") @classmethod def validate_expense_item_id(cls, value): return _coerce_optional_id(value) class AdvanceApplyOut(BaseModel): model_config = ConfigDict(from_attributes=True, populate_by_name=True, alias_generator=to_camel) id: str apply_code: str applicant_id: str applicant_name: str reason: str purpose: Optional[str] = None expense_item_id: Optional[str] = None amount: float status: str current_node: Optional[str] = None apply_time: DatetimeToStr = Field(validation_alias="create_time") create_by: Optional[str] = Field(default=None, validation_alias="create_by") remark: Optional[str] = None actual_amount: Optional[float] = None offset_amount: Optional[float] = None issue_status: Optional[str] = None issue_time: OptDatetimeToStr = None issue_user_name: Optional[str] = None issue_remark: Optional[str] = None class AdvanceApprovalCreate(BaseModel): model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel) approval_status: Optional[str] = None approval_opinion: Optional[str] = None class AdvanceApprovalOut(BaseModel): model_config = ConfigDict(from_attributes=True, populate_by_name=True, alias_generator=to_camel) id: str advance_id: str node_name: str node_order: int approval_status: str approval_opinion: Optional[str] = None approver_name: str approval_time: OptDatetimeToStr = None class AdvanceMyStatsOut(BaseModel): model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel) total_count: int pending_count: int approved_pass_count: int rejected_count: int pending_issue_count: int issued_count: int issued_amount: float month_apply_amount: float month_apply_count: int offset_total: float class AdvanceApproverPendingStatsOut(BaseModel): model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel) pending_total: int month_pending_amount: float class AdvanceIssueOut(BaseModel): model_config = ConfigDict(from_attributes=True, populate_by_name=True, alias_generator=to_camel) id: str apply_code: str applicant_id: str applicant_name: str reason: str amount: float apply_time: DatetimeToStr = Field(validation_alias="create_time") approve_time: DatetimeToStr = Field(validation_alias="update_time") issue_status: Optional[str] = None issue_time: OptDatetimeToStr = None issue_user_name: Optional[str] = None issue_remark: Optional[str] = None actual_amount: Optional[float] = None offset_amount: Optional[float] = None class AdvanceIssueRequest(BaseModel): model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel) issue_remark: Optional[str] = None actual_amount: Optional[float] = None class AdvanceOffsetRecordOut(BaseModel): model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel) reimburse_id: str reimburse_apply_code: str reimburse_title: Optional[str] = None reimburse_applicant_name: Optional[str] = None offset_amount: float remark: Optional[str] = None operator: Optional[str] = None create_time: OptDatetimeToStr = None class AdvanceFinanceIssueStatsOut(BaseModel): model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel) pending_count: int issued_count: int pending_amount: float issued_month_amount: float