dispatch_calendar.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. """手工派车日历输入,只接收可写业务字段。"""
  2. import re
  3. from datetime import date
  4. from typing import Optional
  5. from pydantic import BaseModel, ConfigDict, Field, field_validator
  6. class CreateBody(BaseModel):
  7. model_config = ConfigDict(populate_by_name=True, extra="forbid", str_strip_whitespace=True)
  8. dispatch_date: date = Field(..., alias="dispatchDate", description="派车日期,范围 1900-01-01 至 2100-12-31")
  9. vehicle_id: str = Field(..., alias="vehicleId", min_length=1, max_length=64)
  10. product_id: str = Field(..., alias="productId", min_length=1, max_length=64)
  11. origin: str = Field(..., min_length=1, max_length=255)
  12. destination: str = Field(..., min_length=1, max_length=255)
  13. quantity: Optional[str] = Field(default=None, max_length=16, description="数量文本,单位吨,最多两位小数;不参与汇总")
  14. calendar_kind: str = Field(default="acid", alias="calendarKind", min_length=1, max_length=16)
  15. remark: Optional[str] = Field(default=None, max_length=500)
  16. @field_validator("dispatch_date", mode="before")
  17. @classmethod
  18. def validate_date_format(cls, value):
  19. if not isinstance(value, str) or not re.fullmatch(r"[0-9]{4}-[0-9]{2}-[0-9]{2}", value):
  20. raise ValueError("派车日期须为 YYYY-MM-DD")
  21. return value
  22. @field_validator("dispatch_date")
  23. @classmethod
  24. def validate_date_range(cls, value: date) -> date:
  25. # Pydantic 2.5 的 date ge/le 会生成不合法的 OpenAPI 数字范围约束。
  26. if not date(1900, 1, 1) <= value <= date(2100, 12, 31):
  27. raise ValueError("派车日期须在 1900-01-01 至 2100-12-31 范围内")
  28. return value
  29. @field_validator("quantity", mode="before")
  30. @classmethod
  31. def validate_quantity(cls, value):
  32. if value is None:
  33. return None
  34. if not isinstance(value, str):
  35. raise ValueError("数量须为文本")
  36. text = value.strip()
  37. if not text:
  38. return None
  39. if not re.fullmatch(r"\d{1,12}(\.\d{1,2})?", text):
  40. raise ValueError("数量须为数字,最多两位小数")
  41. return text
  42. @field_validator("calendar_kind")
  43. @classmethod
  44. def validate_calendar_kind(cls, value: str) -> str:
  45. if value not in ("acid", "alkali", "other"):
  46. raise ValueError("日历类型须为 acid、alkali 或 other")
  47. return value
  48. class UpdateBody(CreateBody):
  49. """PUT 提交完整表单。"""