018 add parcel type

This commit is contained in:
Раис Юсупалиев
2026-03-16 01:14:46 +03:00
parent 54160a0e38
commit c4175121a0
10 changed files with 346 additions and 11 deletions
+46 -1
View File
@@ -12,6 +12,7 @@ DIMENSIONS_ROUND_SCALE = 1
MIN_WEIGHT_KG = Decimal("0.01")
MIN_DIMENSION_CM = Decimal("0.1")
INTEGER_PRICE_QUANTIZER = Decimal("1")
DOC_SERVICE_MARKERS = ("документ", "document")
_MISSING = object()
@@ -108,14 +109,36 @@ def filter_and_sort_prices(
prices: Iterable[object],
*,
price_multiplier: Decimal = DEFAULT_PROVIDER_PRICE_MULTIPLIER,
parcel_type: object | None = None,
) -> list[ProviderPrice]:
"""Apply domain filtering and return prices ordered by value."""
return sort_prices_by_price(
filter_valid_prices(prices, price_multiplier=price_multiplier)
filter_prices_by_parcel_type(
filter_valid_prices(prices, price_multiplier=price_multiplier),
parcel_type=parcel_type,
)
)
def filter_prices_by_parcel_type(
prices: Iterable[ProviderPrice],
*,
parcel_type: object | None = None,
) -> list[ProviderPrice]:
"""Filter aggregated prices according to the requested parcel type."""
normalized_parcel_type = _normalize_parcel_type(parcel_type)
if normalized_parcel_type is None:
return list(prices)
return [
price
for price in prices
if _matches_parcel_type(price.service_name, normalized_parcel_type)
]
def _normalize_price(
candidate: object,
*,
@@ -225,6 +248,28 @@ def _normalize_price_multiplier(value: Decimal) -> Decimal:
return multiplier
def _normalize_parcel_type(value: object) -> str | None:
normalized = _normalize_text(value).casefold()
if normalized in {"doc", "parcel"}:
return normalized
return None
def _matches_parcel_type(service_name: str, parcel_type: str) -> bool:
is_document_tariff = _contains_document_marker(service_name)
if parcel_type == "doc":
return is_document_tariff
return not is_document_tariff
def _contains_document_marker(service_name: str) -> bool:
normalized_service_name = service_name.casefold()
return any(
marker in normalized_service_name
for marker in DOC_SERVICE_MARKERS
)
def _apply_price_multiplier_and_round(
price: Decimal,
*,
+6
View File
@@ -10,6 +10,11 @@ class DeliveryEntity(StrEnum):
LEGAL = "legal"
class ParcelType(StrEnum):
DOC = "doc"
PARCEL = "parcel"
class DeliveryRequest(BaseModel):
entity: DeliveryEntity
from_city: str = Field(min_length=1)
@@ -19,3 +24,4 @@ class DeliveryRequest(BaseModel):
length_cm: float = Field(gt=0)
width_cm: float = Field(gt=0)
height_cm: float = Field(gt=0)
parcel_type: ParcelType | None = None
+2
View File
@@ -48,6 +48,7 @@ class FilterAndSortPricesFn(Protocol):
prices: Iterable[object],
*,
price_multiplier: Decimal = DEFAULT_PROVIDER_PRICE_MULTIPLIER,
parcel_type: object | None = None,
) -> list[object]: ...
@@ -118,6 +119,7 @@ class AggregatorService:
filtered_and_sorted = self._filter_and_sort_prices(
successful_results,
price_multiplier=self._provider_price_multiplier,
parcel_type=request.parcel_type,
)
return [self._coerce_delivery_price(price) for price in filtered_and_sorted]