018 add parcel type
This commit is contained in:
+46
-1
@@ -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,
|
||||
*,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user