146 lines
4.2 KiB
Python
146 lines
4.2 KiB
Python
"""Schemas for delivery payment initialization."""
|
|
|
|
from datetime import datetime
|
|
from decimal import Decimal, InvalidOperation
|
|
from typing import Literal
|
|
|
|
from pydantic import (
|
|
BaseModel,
|
|
ConfigDict,
|
|
EmailStr,
|
|
Field,
|
|
field_validator,
|
|
model_validator,
|
|
)
|
|
from pydantic.alias_generators import to_camel
|
|
|
|
|
|
def _validate_positive_decimal_string(value: str) -> str:
|
|
try:
|
|
parsed = Decimal(value)
|
|
except (InvalidOperation, TypeError, ValueError) as exc:
|
|
raise ValueError("must be a positive decimal number") from exc
|
|
if not parsed.is_finite() or parsed <= 0:
|
|
raise ValueError("must be a positive decimal number")
|
|
return value
|
|
|
|
|
|
class _CamelModel(BaseModel):
|
|
model_config = ConfigDict(
|
|
alias_generator=to_camel,
|
|
populate_by_name=False,
|
|
extra="forbid",
|
|
)
|
|
|
|
|
|
class Address(_CamelModel):
|
|
city_id: int = Field(gt=0, strict=True)
|
|
city: str = Field(min_length=1)
|
|
street: str = Field(min_length=1)
|
|
house: str = Field(min_length=1)
|
|
apartment: str | None = None
|
|
zip: str = Field(min_length=1)
|
|
comment: str | None = None
|
|
|
|
|
|
class Contact(_CamelModel):
|
|
full_name: str = Field(min_length=1)
|
|
email: str | None = None
|
|
phone: str = Field(min_length=1)
|
|
phone_ext: str | None = None
|
|
has_extra_phone: str | None = None
|
|
is_company: bool
|
|
company_name: str | None = None
|
|
inn: str | None = None
|
|
kpp: str | None = None
|
|
|
|
@model_validator(mode="after")
|
|
def _validate_company_requisites(self) -> "Contact":
|
|
if self.is_company:
|
|
missing = [
|
|
name
|
|
for name, value in (
|
|
("companyName", self.company_name),
|
|
("inn", self.inn),
|
|
("kpp", self.kpp),
|
|
)
|
|
if value is None or value == ""
|
|
]
|
|
if missing:
|
|
raise ValueError(
|
|
f"{', '.join(missing)} are required when isCompany is true"
|
|
)
|
|
return self
|
|
|
|
|
|
class Content(_CamelModel):
|
|
description: str | None = None
|
|
|
|
|
|
class SystemDataTariff(_CamelModel):
|
|
provider: str = Field(min_length=1)
|
|
service_name: str = Field(min_length=1)
|
|
price: int = Field(gt=0, strict=True, description="Payment amount in kopecks.")
|
|
delivery_days_min: int = Field(ge=0, strict=True)
|
|
delivery_days_max: int = Field(ge=0, strict=True)
|
|
tariff_code: int = Field(gt=0, strict=True)
|
|
|
|
|
|
class Dimensions(_CamelModel):
|
|
length: str = Field(min_length=1)
|
|
width: str = Field(min_length=1)
|
|
height: str = Field(min_length=1)
|
|
|
|
_validate_dimensions = field_validator("length", "width", "height")(
|
|
_validate_positive_decimal_string
|
|
)
|
|
|
|
|
|
class SystemData(_CamelModel):
|
|
tariff: SystemDataTariff
|
|
parcel_type: Literal["doc", "parcel"]
|
|
doc_packaging: Literal["envelope", "bag"] | None = None
|
|
weight: str = Field(min_length=1)
|
|
dimensions: Dimensions | None = None
|
|
|
|
_validate_weight = field_validator("weight")(_validate_positive_decimal_string)
|
|
|
|
@model_validator(mode="after")
|
|
def _validate_dimensions_for_parcel_type(self) -> "SystemData":
|
|
if self.parcel_type == "parcel" and self.dimensions is None:
|
|
raise ValueError("dimensions are required when parcelType is 'parcel'")
|
|
if self.parcel_type == "doc" and self.doc_packaging is None:
|
|
raise ValueError("docPackaging is required when parcelType is 'doc'")
|
|
return self
|
|
|
|
|
|
class InitPaymentRequest(_CamelModel):
|
|
sender_address: Address
|
|
sender_contact: Contact
|
|
receiver_address: Address
|
|
receiver_contact: Contact
|
|
content: Content
|
|
pickup_date: datetime
|
|
delivery_date: datetime | None = None
|
|
account_email: EmailStr
|
|
system_data: SystemData
|
|
agree_privacy: bool
|
|
agree_terms: bool
|
|
|
|
|
|
class InitPaymentResponse(BaseModel):
|
|
payment_url: str = Field(min_length=1)
|
|
|
|
|
|
class TBankPaymentNotification(BaseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
TerminalKey: str = Field(min_length=1)
|
|
OrderId: str = Field(min_length=1)
|
|
Success: bool
|
|
Status: str = Field(min_length=1)
|
|
PaymentId: int = Field(gt=0, strict=True)
|
|
ErrorCode: str = Field(min_length=1)
|
|
Amount: int
|
|
Token: str = Field(min_length=1)
|