217 lines
6.1 KiB
Python
217 lines
6.1 KiB
Python
from typing import List, Optional
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
from pydantic.alias_generators import to_camel
|
|
|
|
from app.schemas.bx.common import DatetimeToStr, OptDateToStr, OptDatetimeToStr
|
|
|
|
|
|
def _coerce_id(value):
|
|
if value is None:
|
|
return None
|
|
return str(value).strip()
|
|
|
|
|
|
class ReimburseDetailCreate(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
expense_item_id: str
|
|
amount: float
|
|
remark: Optional[str] = None
|
|
|
|
@field_validator("expense_item_id", mode="before")
|
|
@classmethod
|
|
def validate_expense_item_id(cls, value):
|
|
s = _coerce_id(value)
|
|
if not s:
|
|
raise ValueError("费用项目不能为空")
|
|
return s
|
|
|
|
|
|
class ReimburseDetailOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True, populate_by_name=True, alias_generator=to_camel)
|
|
|
|
id: str
|
|
expense_id: str
|
|
expense_name: str
|
|
amount: float
|
|
remark: Optional[str] = None
|
|
|
|
|
|
class ReimburseInvoiceBriefOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True, populate_by_name=True, alias_generator=to_camel)
|
|
|
|
id: str
|
|
amount: float
|
|
owner_user_name: Optional[str] = None
|
|
|
|
|
|
class ReimburseApplyCreate(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
title: Optional[str] = None
|
|
reimburse_date: Optional[str] = None
|
|
details: List[ReimburseDetailCreate] = Field(..., min_length=1)
|
|
remark: Optional[str] = None
|
|
invoice_ids: Optional[List[str]] = None
|
|
|
|
@field_validator("details")
|
|
@classmethod
|
|
def details_must_not_be_empty(cls, value):
|
|
if not value or len(value) < 1:
|
|
raise ValueError("至少需要一条报销明细")
|
|
return value
|
|
|
|
|
|
class ReimburseApplyUpdate(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
details: Optional[List[ReimburseDetailCreate]] = None
|
|
title: Optional[str] = None
|
|
reimburse_date: Optional[str] = None
|
|
remark: Optional[str] = None
|
|
invoice_ids: Optional[List[str]] = None
|
|
|
|
|
|
class ReimburseSubmitBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
invoice_ids: Optional[List[str]] = None
|
|
|
|
|
|
class ReimburseApplyOut(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
|
|
title: str
|
|
reimburse_date: OptDateToStr = None
|
|
expense_id: Optional[str] = None
|
|
expense_name: str
|
|
amount: float
|
|
current_node: Optional[str] = None
|
|
apply_time: DatetimeToStr = Field(validation_alias="create_time")
|
|
create_by: Optional[str] = Field(default=None, validation_alias="create_by")
|
|
status: Optional[str] = None
|
|
remark: Optional[str] = None
|
|
invoice_count: int = 0
|
|
attach_count: int = 0
|
|
pay_status: Optional[str] = None
|
|
pay_time: OptDatetimeToStr = None
|
|
pay_user_name: Optional[str] = None
|
|
actual_amount: Optional[float] = None
|
|
offset_advance_id: Optional[str] = None
|
|
offset_amount: Optional[float] = None
|
|
details: Optional[List[ReimburseDetailOut]] = None
|
|
invoice_ids: Optional[List[str]] = None
|
|
invoices: Optional[List[ReimburseInvoiceBriefOut]] = None
|
|
|
|
|
|
class ReimburseApprovalCreate(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
approval_status: Optional[str] = None
|
|
approval_opinion: Optional[str] = None
|
|
|
|
|
|
class ReimburseApprovalOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True, populate_by_name=True, alias_generator=to_camel)
|
|
|
|
id: str
|
|
reimburse_id: str
|
|
node_name: str
|
|
node_order: int
|
|
approval_status: str
|
|
approval_opinion: Optional[str] = None
|
|
approver_name: str
|
|
approval_time: OptDatetimeToStr = None
|
|
|
|
|
|
class ReimburseMyStatsOut(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
total_count: int
|
|
pending_count: int
|
|
approved_count: int
|
|
rejected_count: int
|
|
approved_amount: float
|
|
month_apply_amount: float
|
|
month_apply_count: int
|
|
|
|
|
|
class ReimburseApproverPendingStatsOut(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
pending_total: int
|
|
month_pending_amount: float
|
|
|
|
|
|
class PayRequest(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
pay_remark: Optional[str] = None
|
|
actual_amount: Optional[float] = None
|
|
|
|
|
|
class OffsetRequest(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
advance_id: str
|
|
offset_amount: float
|
|
remark: Optional[str] = None
|
|
|
|
@field_validator("advance_id", mode="before")
|
|
@classmethod
|
|
def validate_advance_id(cls, value):
|
|
s = _coerce_id(value)
|
|
if not s:
|
|
raise ValueError("备用金单不能为空")
|
|
return s
|
|
|
|
|
|
class OffsetItem(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
advance_id: str
|
|
offset_amount: float
|
|
|
|
@field_validator("advance_id", mode="before")
|
|
@classmethod
|
|
def validate_advance_id(cls, value):
|
|
s = _coerce_id(value)
|
|
if not s:
|
|
raise ValueError("备用金单不能为空")
|
|
return s
|
|
|
|
|
|
class BatchOffsetRequest(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
items: List[OffsetItem]
|
|
pay_amount: float = 0
|
|
remark: Optional[str] = None
|
|
|
|
|
|
class ReimburseOffsetRecordOut(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
advance_id: str
|
|
advance_apply_code: str
|
|
advance_applicant_name: Optional[str] = None
|
|
advance_reason: Optional[str] = None
|
|
offset_amount: float
|
|
remark: Optional[str] = None
|
|
operator: Optional[str] = None
|
|
create_time: OptDatetimeToStr = None
|
|
|
|
|
|
class PaymentFinanceStatsOut(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
|
|
|
|
pending_count: int
|
|
paid_count: int
|
|
offset_count: int
|
|
month_processed_amount: float
|