reimburse.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. from typing import List, Optional
  2. from pydantic import BaseModel, ConfigDict, Field, field_validator
  3. from pydantic.alias_generators import to_camel
  4. from app.schemas.common import DatetimeToStr, OptDatetimeToStr
  5. class ReimburseDetailCreate(BaseModel):
  6. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  7. expense_item_id: int
  8. amount: float
  9. remark: Optional[str] = None
  10. class ReimburseDetailOut(BaseModel):
  11. model_config = ConfigDict(from_attributes=True, populate_by_name=True, alias_generator=to_camel)
  12. id: int
  13. expense_id: int
  14. expense_name: str
  15. amount: float
  16. remark: Optional[str] = None
  17. class ReimburseApplyCreate(BaseModel):
  18. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  19. title: Optional[str] = None
  20. apply_date: Optional[str] = None
  21. details: List[ReimburseDetailCreate] = Field(..., min_length=1)
  22. remark: Optional[str] = None
  23. @field_validator("details")
  24. @classmethod
  25. def details_must_not_be_empty(cls, v):
  26. if not v or len(v) < 1:
  27. raise ValueError("至少需要一条报销明细")
  28. return v
  29. class ReimburseApplyUpdate(BaseModel):
  30. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  31. details: Optional[List[ReimburseDetailCreate]] = None
  32. remark: Optional[str] = None
  33. class ReimburseApplyOut(BaseModel):
  34. model_config = ConfigDict(from_attributes=True, populate_by_name=True, alias_generator=to_camel)
  35. id: int
  36. apply_code: str
  37. applicant_id: int
  38. applicant_name: str
  39. title: str
  40. expense_id: Optional[int] = None
  41. expense_name: str
  42. amount: float
  43. current_node: Optional[str] = None
  44. apply_time: DatetimeToStr = Field(validation_alias="create_time")
  45. status: Optional[str] = None
  46. remark: Optional[str] = None
  47. invoice_count: int = 0
  48. attach_count: int = 0
  49. pay_status: Optional[str] = None
  50. pay_time: OptDatetimeToStr = None
  51. pay_user_name: Optional[str] = None
  52. actual_amount: Optional[float] = None
  53. offset_advance_id: Optional[int] = None
  54. offset_amount: Optional[float] = None
  55. details: Optional[List[ReimburseDetailOut]] = None
  56. class ReimburseApprovalCreate(BaseModel):
  57. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  58. approval_status: Optional[str] = None
  59. approval_opinion: Optional[str] = None
  60. class ReimburseApprovalOut(BaseModel):
  61. model_config = ConfigDict(from_attributes=True, populate_by_name=True, alias_generator=to_camel)
  62. id: int
  63. reimburse_id: int
  64. node_name: str
  65. node_order: int
  66. approval_status: str
  67. approval_opinion: Optional[str] = None
  68. approver_name: str
  69. approval_time: OptDatetimeToStr = None
  70. class PaymentRequest(BaseModel):
  71. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  72. code: str
  73. type: str
  74. action: str
  75. offset_advance_id: Optional[int] = None
  76. offset_amount: Optional[float] = None
  77. class OffsetRequest(BaseModel):
  78. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  79. reimburse_id: int
  80. advance_id: int
  81. offset_amount: float
  82. remark: Optional[str] = None
  83. class PayRequest(BaseModel):
  84. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  85. pay_remark: Optional[str] = None
  86. actual_amount: Optional[float] = None
  87. class OffsetItem(BaseModel):
  88. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  89. advance_id: int
  90. offset_amount: float
  91. class BatchOffsetRequest(BaseModel):
  92. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  93. items: List[OffsetItem]
  94. pay_amount: float = 0
  95. remark: Optional[str] = None
  96. class ReimburseOffsetRecordOut(BaseModel):
  97. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  98. advance_id: int
  99. advance_apply_code: str
  100. advance_applicant_name: Optional[str] = None
  101. advance_reason: Optional[str] = None
  102. offset_amount: float
  103. remark: Optional[str] = None
  104. operator: Optional[str] = None
  105. create_time: OptDatetimeToStr = None
  106. class ReimburseMyStatsOut(BaseModel):
  107. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  108. total_count: int
  109. pending_count: int
  110. approved_count: int
  111. rejected_count: int
  112. approved_amount: float
  113. month_apply_amount: float
  114. month_apply_count: int
  115. class ReimburseApproverPendingStatsOut(BaseModel):
  116. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  117. pending_total: int
  118. month_pending_amount: float
  119. class PaymentFinanceStatsOut(BaseModel):
  120. model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
  121. pending_count: int
  122. paid_count: int
  123. offset_count: int
  124. month_processed_amount: float