Files
svg-backend/backend/app/schemas/pricing.py
2026-03-19 13:39:32 +03:00

180 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from decimal import Decimal, InvalidOperation
from typing import List
from pydantic import BaseModel, field_validator
class PricingCategoryCreateRequest(BaseModel):
name: str
code: str | None = None
class PricingCategoryUpdateRequest(BaseModel):
name: str
code: str | None = None
class PricingCategoryCreateResponse(BaseModel):
pricing_category_id: str
scheme_id: str
name: str
code: str | None
class PricingCategoryUpdateResponse(BaseModel):
pricing_category_id: str
scheme_id: str
name: str
code: str | None
class DeleteResponse(BaseModel):
status: str
class PriceRuleCreateRequest(BaseModel):
pricing_category_id: str | None = None
target_type: str
target_ref: str
amount: Decimal
currency: str = "RUB"
@field_validator("target_type")
@classmethod
def validate_target_type(cls, value: str) -> str:
allowed = {"sector", "group", "seat"}
if value not in allowed:
raise ValueError("Поле target_type должно быть одним из: sector, group, seat")
return value
@field_validator("currency")
@classmethod
def validate_currency(cls, value: str) -> str:
if value != "RUB":
raise ValueError("В v1 поддерживается только валюта RUB")
return value
@field_validator("amount", mode="before")
@classmethod
def parse_amount(cls, value):
if value is None:
raise ValueError("Поле amount обязательно")
text = str(value).strip()
if text == "":
raise ValueError("Поле amount обязательно")
try:
return Decimal(text)
except (InvalidOperation, ValueError):
raise ValueError("Некорректная сумма. Используйте формат 2500.00")
@field_validator("amount")
@classmethod
def validate_amount(cls, value: Decimal) -> Decimal:
if value < Decimal("0.00"):
raise ValueError("Сумма не может быть отрицательной")
if value.quantize(Decimal("0.01")) != value:
raise ValueError("Сумма должна быть с точностью до 2 знаков после запятой")
return value
class PriceRuleUpdateRequest(BaseModel):
pricing_category_id: str | None = None
target_type: str
target_ref: str
amount: Decimal
currency: str = "RUB"
@field_validator("target_type")
@classmethod
def validate_target_type(cls, value: str) -> str:
allowed = {"sector", "group", "seat"}
if value not in allowed:
raise ValueError("Поле target_type должно быть одним из: sector, group, seat")
return value
@field_validator("currency")
@classmethod
def validate_currency(cls, value: str) -> str:
if value != "RUB":
raise ValueError("В v1 поддерживается только валюта RUB")
return value
@field_validator("amount", mode="before")
@classmethod
def parse_amount(cls, value):
if value is None:
raise ValueError("Поле amount обязательно")
text = str(value).strip()
if text == "":
raise ValueError("Поле amount обязательно")
try:
return Decimal(text)
except (InvalidOperation, ValueError):
raise ValueError("Некорректная сумма. Используйте формат 2500.00")
@field_validator("amount")
@classmethod
def validate_amount(cls, value: Decimal) -> Decimal:
if value < Decimal("0.00"):
raise ValueError("Сумма не может быть отрицательной")
if value.quantize(Decimal("0.01")) != value:
raise ValueError("Сумма должна быть с точностью до 2 знаков после запятой")
return value
class PriceRuleCreateResponse(BaseModel):
price_rule_id: str
scheme_id: str
pricing_category_id: str | None
target_type: str
target_ref: str
amount: Decimal
currency: str
class PriceRuleUpdateResponse(BaseModel):
price_rule_id: str
scheme_id: str
pricing_category_id: str | None
target_type: str
target_ref: str
amount: Decimal
currency: str
class PricingCategoryItem(BaseModel):
pricing_category_id: str
scheme_id: str
name: str
code: str | None
created_at: str
class PriceRuleItem(BaseModel):
price_rule_id: str
scheme_id: str
pricing_category_id: str | None
target_type: str
target_ref: str
amount: Decimal
currency: str
created_at: str
class SchemePricingResponse(BaseModel):
categories: List[PricingCategoryItem]
rules: List[PriceRuleItem]
class EffectiveSeatPriceResponse(BaseModel):
scheme_id: str
scheme_version_id: str
seat_id: str
sector_id: str | None
group_id: str | None
matched_rule_level: str
matched_target_ref: str
pricing_category_id: str | None
amount: Decimal
currency: str