248 lines
7.2 KiB
Python
248 lines
7.2 KiB
Python
from cart_job import KIND_BUSINESS, KIND_OK, KIND_SYSTEM, AddOutcome, run_cart_batch
|
||
from cart_match import CartOffer
|
||
from cart_repo import STAMP_DONE, STAMP_SELECTION, MemoryCartRepo
|
||
|
||
|
||
HANGZHOU = "杭州小药药自营旗舰店"
|
||
GUANGDONG = "广东壹号药业有限公司"
|
||
YBM = 48
|
||
YAOEX = 66
|
||
|
||
|
||
def _row(**overrides) -> dict:
|
||
data = {
|
||
"fid": 1,
|
||
"oms_id": 2026100201,
|
||
"platform_type": YAOEX,
|
||
"supplier_name": GUANGDONG,
|
||
"bar_code": "06901234567890",
|
||
"purchase_qty": 7,
|
||
"status": 1,
|
||
"fail_reason": None,
|
||
"push_status": 0,
|
||
"update_user_name": STAMP_SELECTION,
|
||
"operate_type": 1,
|
||
}
|
||
data.update(overrides)
|
||
return data
|
||
|
||
|
||
def _offer(vendor: str, **overrides) -> CartOffer:
|
||
data = dict(
|
||
sku_id="S-" + vendor[:2],
|
||
vendor_raw=vendor,
|
||
vendor_norm=vendor,
|
||
stock=20.0,
|
||
price=90.0,
|
||
)
|
||
data.update(overrides)
|
||
return CartOffer(**data)
|
||
|
||
|
||
def test_job_adds_split_rows_without_insert():
|
||
repo = MemoryCartRepo(
|
||
[
|
||
_row(fid=1, platform_type=YBM, supplier_name=HANGZHOU, purchase_qty=3),
|
||
_row(fid=2, platform_type=YAOEX, supplier_name=GUANGDONG, purchase_qty=7),
|
||
]
|
||
)
|
||
added: list[tuple[int, str, int]] = []
|
||
|
||
def search_ybm(bar_code: str):
|
||
assert bar_code == "06901234567890"
|
||
return [_offer(HANGZHOU, sku_id="HZ", stock=5.0)]
|
||
|
||
def search_yaoex(bar_code: str):
|
||
assert bar_code == "06901234567890"
|
||
return [_offer(GUANGDONG, sku_id="GD", stock=20.0)]
|
||
|
||
def add_ybm(offer: CartOffer, qty: int):
|
||
added.append((YBM, offer.sku_id, qty))
|
||
return AddOutcome(kind=KIND_OK)
|
||
|
||
def add_yaoex(offer: CartOffer, qty: int):
|
||
added.append((YAOEX, offer.sku_id, qty))
|
||
return AddOutcome(kind=KIND_OK)
|
||
|
||
summary = run_cart_batch(
|
||
repo,
|
||
searchers={YBM: search_ybm, YAOEX: search_yaoex},
|
||
adders={YBM: add_ybm, YAOEX: add_yaoex},
|
||
login_errors={},
|
||
)
|
||
assert summary.claimed == 2
|
||
assert summary.added == 2
|
||
assert summary.failed == 0
|
||
assert added == [(YBM, "HZ", 3), (YAOEX, "GD", 7)]
|
||
assert list(repo.rows) == [1, 2]
|
||
assert repo.rows[1]["status"] == 1
|
||
assert repo.rows[2]["status"] == 1
|
||
assert repo.rows[1]["update_user_name"] == STAMP_DONE
|
||
assert repo.rows[2]["update_user_name"] == STAMP_DONE
|
||
assert repo.rows[1]["push_status"] == 0
|
||
|
||
|
||
def test_job_marks_out_of_stock():
|
||
repo = MemoryCartRepo([_row(purchase_qty=10)])
|
||
|
||
def search_yaoex(bar_code: str):
|
||
return [_offer(GUANGDONG, stock=4.0)]
|
||
|
||
summary = run_cart_batch(
|
||
repo,
|
||
searchers={YAOEX: search_yaoex},
|
||
adders={YAOEX: lambda offer, qty: AddOutcome(kind=KIND_OK)},
|
||
login_errors={},
|
||
)
|
||
assert summary.added == 0
|
||
assert summary.failed == 1
|
||
assert repo.rows[1]["status"] == 2
|
||
assert repo.rows[1]["fail_reason"] == "库存不足"
|
||
assert repo.rows[1]["update_user_name"] == STAMP_DONE
|
||
|
||
|
||
def test_job_marks_login_fail_as_system_error():
|
||
repo = MemoryCartRepo(
|
||
[
|
||
_row(fid=1, platform_type=YAOEX),
|
||
_row(fid=2, platform_type=YBM, supplier_name=HANGZHOU, purchase_qty=3),
|
||
]
|
||
)
|
||
ybm_added = []
|
||
|
||
def search_ybm(bar_code: str):
|
||
return [_offer(HANGZHOU)]
|
||
|
||
def add_ybm(offer: CartOffer, qty: int):
|
||
ybm_added.append(qty)
|
||
return AddOutcome(kind=KIND_OK)
|
||
|
||
summary = run_cart_batch(
|
||
repo,
|
||
searchers={YBM: search_ybm},
|
||
adders={YBM: add_ybm},
|
||
login_errors={YAOEX: "账号密码错误"},
|
||
)
|
||
assert summary.added == 1
|
||
assert summary.failed == 1
|
||
assert repo.rows[1]["status"] == 2
|
||
assert repo.rows[1]["fail_reason"].startswith("系统故障:")
|
||
assert "账号密码错误" in repo.rows[1]["fail_reason"]
|
||
assert repo.rows[2]["status"] == 1
|
||
assert repo.rows[2]["update_user_name"] == STAMP_DONE
|
||
assert ybm_added == [3]
|
||
|
||
|
||
def test_job_skips_already_stamped_rows():
|
||
repo = MemoryCartRepo([_row(update_user_name=STAMP_DONE)])
|
||
called = []
|
||
|
||
def search_yaoex(bar_code: str):
|
||
called.append(bar_code)
|
||
return [_offer(GUANGDONG)]
|
||
|
||
summary = run_cart_batch(
|
||
repo,
|
||
searchers={YAOEX: search_yaoex},
|
||
adders={YAOEX: lambda offer, qty: AddOutcome(kind=KIND_OK)},
|
||
login_errors={},
|
||
)
|
||
assert summary.claimed == 0
|
||
assert called == []
|
||
assert repo.rows[1]["update_user_name"] == STAMP_DONE
|
||
|
||
|
||
def test_job_marks_missing_warehouse():
|
||
repo = MemoryCartRepo([_row()])
|
||
|
||
def search_yaoex(bar_code: str):
|
||
return [_offer(HANGZHOU)]
|
||
|
||
summary = run_cart_batch(
|
||
repo,
|
||
searchers={YAOEX: search_yaoex},
|
||
adders={YAOEX: lambda offer, qty: AddOutcome(kind=KIND_OK)},
|
||
login_errors={},
|
||
)
|
||
assert summary.failed == 1
|
||
assert repo.rows[1]["status"] == 2
|
||
assert repo.rows[1]["fail_reason"] == "未找到对应仓"
|
||
|
||
|
||
def test_job_marks_pack_reject():
|
||
repo = MemoryCartRepo([_row(purchase_qty=7)])
|
||
|
||
def search_yaoex(bar_code: str):
|
||
return [_offer(GUANGDONG, extra={"raw": {"middlePackNum": 10}})]
|
||
|
||
summary = run_cart_batch(
|
||
repo,
|
||
searchers={YAOEX: search_yaoex},
|
||
adders={YAOEX: lambda offer, qty: AddOutcome(kind=KIND_OK)},
|
||
login_errors={},
|
||
)
|
||
assert summary.failed == 1
|
||
assert repo.rows[1]["status"] == 2
|
||
assert repo.rows[1]["fail_reason"].startswith("中包装加不进")
|
||
|
||
|
||
def test_job_records_mall_add_failure():
|
||
repo = MemoryCartRepo([_row()])
|
||
|
||
def search_yaoex(bar_code: str):
|
||
return [_offer(GUANGDONG)]
|
||
|
||
def add_yaoex(offer: CartOffer, qty: int):
|
||
return AddOutcome(kind=KIND_BUSINESS, reason="中包装加不进:数量须为10的倍数")
|
||
|
||
summary = run_cart_batch(
|
||
repo,
|
||
searchers={YAOEX: search_yaoex},
|
||
adders={YAOEX: add_yaoex},
|
||
login_errors={},
|
||
)
|
||
assert summary.failed == 1
|
||
assert repo.rows[1]["fail_reason"] == "中包装加不进:数量须为10的倍数"
|
||
|
||
|
||
def test_job_platform_filter_leaves_other_mall_pending():
|
||
repo = MemoryCartRepo(
|
||
[
|
||
_row(fid=1, platform_type=YAOEX),
|
||
_row(fid=2, platform_type=YBM, supplier_name=HANGZHOU, purchase_qty=3),
|
||
]
|
||
)
|
||
|
||
def search_yaoex(bar_code: str):
|
||
return [_offer(GUANGDONG)]
|
||
|
||
summary = run_cart_batch(
|
||
repo,
|
||
searchers={YAOEX: search_yaoex},
|
||
adders={YAOEX: lambda offer, qty: AddOutcome(kind=KIND_OK)},
|
||
login_errors={},
|
||
platform_types=[YAOEX],
|
||
)
|
||
assert summary.claimed == 1
|
||
assert summary.added == 1
|
||
assert repo.rows[1]["update_user_name"] == STAMP_DONE
|
||
assert repo.rows[2]["update_user_name"] == STAMP_SELECTION
|
||
assert repo.rows[2]["status"] == 1
|
||
|
||
|
||
def test_job_search_error_is_system_fail():
|
||
repo = MemoryCartRepo([_row()])
|
||
|
||
def search_yaoex(bar_code: str):
|
||
raise RuntimeError("网关 502")
|
||
|
||
summary = run_cart_batch(
|
||
repo,
|
||
searchers={YAOEX: search_yaoex},
|
||
adders={YAOEX: lambda offer, qty: AddOutcome(kind=KIND_OK)},
|
||
login_errors={},
|
||
)
|
||
assert summary.failed == 1
|
||
assert repo.rows[1]["fail_reason"].startswith("系统故障:")
|
||
assert "网关 502" in repo.rows[1]["fail_reason"]
|