99 lines
2.8 KiB
Python
99 lines
2.8 KiB
Python
"""加购班次:领表 2 选品成功行 → 再搜条形码对仓 → 加车。成功盖章,失败改 status=2。"""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Callable
|
|
|
|
from cart_add import ( # noqa: F401
|
|
KIND_BUSINESS,
|
|
KIND_OK,
|
|
KIND_SYSTEM,
|
|
AddOutcome,
|
|
)
|
|
from cart_match import CartOffer, match_offer, middle_pack, qty_fits_pack
|
|
from cart_repo import CartRow, clip_reason
|
|
|
|
Searcher = Callable[[str], list[CartOffer]]
|
|
Adder = Callable[[CartOffer, int], AddOutcome]
|
|
|
|
|
|
@dataclass
|
|
class CartSummary:
|
|
claimed: int = 0
|
|
added: int = 0
|
|
failed: int = 0
|
|
|
|
|
|
def run_cart_batch(
|
|
repo,
|
|
*,
|
|
searchers: dict[int, Searcher],
|
|
adders: dict[int, Adder],
|
|
login_errors: dict[int, str],
|
|
limit: int | None = None,
|
|
platform_types: list[int] | None = None,
|
|
) -> CartSummary:
|
|
rows = repo.claim_pending(limit=limit, platform_types=platform_types)
|
|
summary = CartSummary(claimed=len(rows))
|
|
for row in rows:
|
|
reason = _add_one(row, searchers, adders, login_errors)
|
|
if reason is None:
|
|
repo.mark_success(row.fid)
|
|
summary.added += 1
|
|
else:
|
|
repo.mark_fail(row.fid, reason)
|
|
summary.failed += 1
|
|
return summary
|
|
|
|
|
|
def _add_one(
|
|
row: CartRow,
|
|
searchers: dict[int, Searcher],
|
|
adders: dict[int, Adder],
|
|
login_errors: dict[int, str],
|
|
) -> str | None:
|
|
platform = row.platform_type
|
|
if platform in login_errors:
|
|
return _system(login_errors[platform])
|
|
searcher = searchers.get(platform)
|
|
if searcher is None:
|
|
return _system("未登录该平台")
|
|
adder = adders.get(platform)
|
|
if adder is None:
|
|
return _system("未配置加车")
|
|
bar_code = (row.bar_code or "").strip()
|
|
if not bar_code:
|
|
return "缺少条形码"
|
|
qty = int(row.purchase_qty)
|
|
if qty <= 0:
|
|
return "采购数量无效"
|
|
try:
|
|
offers = searcher(bar_code)
|
|
except Exception as exc:
|
|
return _system(f"查询失败:{exc}")
|
|
offer = match_offer(offers, row.supplier_name)
|
|
if offer is None:
|
|
return "未找到对应仓"
|
|
if offer.stock is not None and offer.stock < qty:
|
|
return "库存不足"
|
|
pack = middle_pack(offer)
|
|
if not qty_fits_pack(qty, pack):
|
|
return f"中包装加不进:数量须为{pack}的倍数"
|
|
try:
|
|
outcome = adder(offer, qty)
|
|
except Exception as exc:
|
|
return _system(f"加购失败:{exc}")
|
|
if outcome.kind == KIND_OK:
|
|
return None
|
|
reason = (outcome.reason or "加购失败").strip()
|
|
if outcome.kind == KIND_SYSTEM:
|
|
return _system(reason)
|
|
return clip_reason(reason)
|
|
|
|
|
|
def _system(detail: str) -> str:
|
|
text = (detail or "未知错误").strip()
|
|
if text.startswith("系统故障"):
|
|
return clip_reason(text)
|
|
return clip_reason(f"系统故障:{text}")
|