feat(backend): harden pricing mutation contract and sync backend docs
- add typed response schemas for pricing write endpoints - add stale draft version guard for pricing mutations - unify pricing API contract around expected_scheme_version_id - update API route map - add smoke regression checklist for backend routes and artifact flows
This commit is contained in:
@@ -1,22 +1,4 @@
|
||||
from decimal import Decimal, InvalidOperation
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
|
||||
def _validate_decimal_amount(value: Decimal) -> Decimal:
|
||||
try:
|
||||
normalized = Decimal(value)
|
||||
except (InvalidOperation, TypeError, ValueError) as exc:
|
||||
raise ValueError("Некорректная сумма") from exc
|
||||
|
||||
if not normalized.is_finite():
|
||||
raise ValueError("Некорректная сумма")
|
||||
|
||||
return normalized
|
||||
|
||||
|
||||
class DeleteResponse(BaseModel):
|
||||
status: str
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class PricingCategoryCreateRequest(BaseModel):
|
||||
@@ -29,6 +11,22 @@ class PricingCategoryUpdateRequest(BaseModel):
|
||||
code: str | None = Field(default=None, max_length=128)
|
||||
|
||||
|
||||
class PriceRuleCreateRequest(BaseModel):
|
||||
pricing_category_id: str = Field(..., max_length=32)
|
||||
target_type: str = Field(..., pattern="^(seat|group|sector)$")
|
||||
target_ref: str = Field(..., min_length=1, max_length=128)
|
||||
amount: str = Field(..., min_length=1, max_length=32)
|
||||
currency: str = Field(default="RUB", min_length=3, max_length=8)
|
||||
|
||||
|
||||
class PriceRuleUpdateRequest(BaseModel):
|
||||
pricing_category_id: str = Field(..., max_length=32)
|
||||
target_type: str = Field(..., pattern="^(seat|group|sector)$")
|
||||
target_ref: str = Field(..., min_length=1, max_length=128)
|
||||
amount: str = Field(..., min_length=1, max_length=32)
|
||||
currency: str = Field(default="RUB", min_length=3, max_length=8)
|
||||
|
||||
|
||||
class PricingCategoryItem(BaseModel):
|
||||
pricing_category_id: str
|
||||
scheme_id: str
|
||||
@@ -37,6 +35,22 @@ class PricingCategoryItem(BaseModel):
|
||||
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: str
|
||||
currency: str
|
||||
created_at: str
|
||||
|
||||
|
||||
class PricingBundleResponse(BaseModel):
|
||||
categories: list[PricingCategoryItem]
|
||||
rules: list[PriceRuleItem]
|
||||
|
||||
|
||||
class PricingCategoryCreateResponse(BaseModel):
|
||||
pricing_category_id: str
|
||||
scheme_id: str
|
||||
@@ -51,50 +65,13 @@ class PricingCategoryUpdateResponse(BaseModel):
|
||||
code: str | None
|
||||
|
||||
|
||||
class PriceRuleCreateRequest(BaseModel):
|
||||
pricing_category_id: str | None = Field(default=None, max_length=32)
|
||||
target_type: str = Field(..., pattern="^(seat|group|sector)$")
|
||||
target_ref: str = Field(..., min_length=1, max_length=128)
|
||||
amount: Decimal
|
||||
currency: str = Field(default="RUB", min_length=3, max_length=8)
|
||||
|
||||
@field_validator("amount")
|
||||
@classmethod
|
||||
def validate_amount(cls, value: Decimal) -> Decimal:
|
||||
return _validate_decimal_amount(value)
|
||||
|
||||
|
||||
class PriceRuleUpdateRequest(BaseModel):
|
||||
pricing_category_id: str | None = Field(default=None, max_length=32)
|
||||
target_type: str = Field(..., pattern="^(seat|group|sector)$")
|
||||
target_ref: str = Field(..., min_length=1, max_length=128)
|
||||
amount: Decimal
|
||||
currency: str = Field(default="RUB", min_length=3, max_length=8)
|
||||
|
||||
@field_validator("amount")
|
||||
@classmethod
|
||||
def validate_amount(cls, value: Decimal) -> Decimal:
|
||||
return _validate_decimal_amount(value)
|
||||
|
||||
|
||||
class PriceRuleItem(BaseModel):
|
||||
price_rule_id: str
|
||||
scheme_id: str
|
||||
pricing_category_id: str | None
|
||||
target_type: str
|
||||
target_ref: str
|
||||
amount: Decimal | str
|
||||
currency: str
|
||||
created_at: str
|
||||
|
||||
|
||||
class PriceRuleCreateResponse(BaseModel):
|
||||
price_rule_id: str
|
||||
scheme_id: str
|
||||
pricing_category_id: str | None
|
||||
pricing_category_id: str
|
||||
target_type: str
|
||||
target_ref: str
|
||||
amount: Decimal
|
||||
amount: str
|
||||
currency: str
|
||||
|
||||
|
||||
@@ -104,10 +81,16 @@ class PriceRuleUpdateResponse(BaseModel):
|
||||
pricing_category_id: str | None
|
||||
target_type: str
|
||||
target_ref: str
|
||||
amount: Decimal
|
||||
amount: str
|
||||
currency: str
|
||||
|
||||
|
||||
class DeleteResponse(BaseModel):
|
||||
deleted: bool
|
||||
pricing_category_id: str | None = None
|
||||
price_rule_id: str | None = None
|
||||
|
||||
|
||||
class EffectiveSeatPriceResponse(BaseModel):
|
||||
scheme_id: str
|
||||
scheme_version_id: str
|
||||
@@ -117,15 +100,5 @@ class EffectiveSeatPriceResponse(BaseModel):
|
||||
matched_rule_level: str
|
||||
matched_target_ref: str
|
||||
pricing_category_id: str | None
|
||||
amount: Decimal | str
|
||||
amount: str
|
||||
currency: str
|
||||
|
||||
|
||||
class SchemePricingResponse(BaseModel):
|
||||
categories: list[PricingCategoryItem]
|
||||
rules: list[PriceRuleItem]
|
||||
|
||||
|
||||
class PricingBundleResponse(BaseModel):
|
||||
categories: list[PricingCategoryItem]
|
||||
rules: list[PriceRuleItem]
|
||||
|
||||
Reference in New Issue
Block a user