AutoRpa/rpa_cart/cart_match.py

55 lines
1.7 KiB
Python

# 按供应商名对上搜到的仓。无 sku_id 时靠条形码结果 + 商家全称。
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any
SELF_OPERATED_PREFIX = "[自营]"
# 再搜到的一条报价:商家全称、库存、价格。加车前靠它对上表 2 的供应商。
@dataclass
class CartOffer:
sku_id: str
vendor_raw: str
vendor_norm: str
stock: float | None
price: float | None = None
extra: dict[str, Any] = field(default_factory=dict)
# 去掉「[自营]」前缀和多余空白,用来对商家全称。
def normalize_supplier(raw: str) -> str:
text = (raw or "").replace("\u3000", " ").strip()
if text.startswith(SELF_OPERATED_PREFIX):
text = text[len(SELF_OPERATED_PREFIX) :]
return " ".join(text.split())
# 条形码结果里对上商家全称。同仓留低价,价格相同留库存多的。对不上返回 None。
def match_offer(offers: list[CartOffer], supplier_name: str) -> CartOffer | None:
target = normalize_supplier(supplier_name)
if not target:
return None
matched = [
offer
for offer in offers
if normalize_supplier(offer.vendor_raw) == target
or normalize_supplier(offer.vendor_norm) == target
]
if not matched:
return None
return min(matched, key=_offer_rank)
# 同仓排序:有价格的优先,低价优先,同价库存多的优先。
def _offer_rank(offer: CartOffer) -> tuple[int, float, float]:
price = offer.price
stock = offer.stock
return (
0 if price is not None else 1,
float(price) if price is not None else 0.0,
-float(stock) if stock is not None else 0.0,
)