fix: 1号药城支付条码取首个、品名按短名匹配

This commit is contained in:
34BFF76918A9449ABAB323149DDCEA73 2026-10-03 20:53:30 +08:00
parent f58c7a73ab
commit bab6954584
4 changed files with 91 additions and 2 deletions

View File

@ -67,6 +67,9 @@ def _text(value: object) -> str:
def _barcode(value: object) -> str: def _barcode(value: object) -> str:
text = _text(value) text = _text(value)
if "," in text:
parts = [part.strip() for part in text.split(",") if part.strip()]
text = parts[0] if parts else ""
if text.endswith(".0") and text.replace(".", "", 1).isdigit(): if text.endswith(".0") and text.replace(".", "", 1).isdigit():
return text[:-2] return text[:-2]
return text return text

View File

@ -74,6 +74,9 @@ def match_pay_lines(
if not line.pay_order_dtl_id: if not line.pay_order_dtl_id:
result.unmatched.append((line, "NO_DTL_ID")) result.unmatched.append((line, "NO_DTL_ID"))
continue continue
if len(line.bar_code) > 40:
result.unmatched.append((line, "BAR_CODE_TOO_LONG"))
continue
key = (line.order_no, line.pay_order_dtl_id) key = (line.order_no, line.pay_order_dtl_id)
if key in seen: if key in seen:
result.skipped_dup.append(line) result.skipped_dup.append(line)
@ -109,12 +112,23 @@ def _find_product(pool: list[dict[str, Any]], line: MallLine) -> int | None:
for idx, product in enumerate(pool): for idx, product in enumerate(pool):
qty = int(Decimal(str(product.get("quantity") or 0))) qty = int(Decimal(str(product.get("quantity") or 0)))
pay_price = money4(product.get("payPrice4") or 0) pay_price = money4(product.get("payPrice4") or 0)
name = str(product.get("productName") or "")
if qty != line.qty: if qty != line.qty:
continue continue
if pay_price != money4(line.pay_price): if pay_price != money4(line.pay_price):
continue continue
if name and line.goods_name and name != line.goods_name: if not _goods_name_matches(product, line.goods_name):
continue continue
return idx return idx
return None return None
def _goods_name_matches(product: dict[str, Any], goods_name: str) -> bool:
if not goods_name:
return True
product_name = str(product.get("productName") or "")
short_name = str(product.get("shortName") or "")
if not product_name and not short_name:
return True
if goods_name in {product_name, short_name}:
return True
return goods_name in product_name

View File

@ -66,3 +66,40 @@ def test_parse_order_xls_reads_settlement_columns(tmp_path: Path):
assert line.pay_price == Decimal("65.49") assert line.pay_price == Decimal("65.49")
assert line.unit_price == Decimal("65.49") assert line.unit_price == Decimal("65.49")
assert line.pay_order_dtl_id == "" assert line.pay_order_dtl_id == ""
def test_parse_order_xls_takes_first_barcode_when_cell_has_many(tmp_path: Path):
path = tmp_path / "orders.xls"
book = xlwt.Workbook()
sheet = book.add_sheet("订单明细")
headers = [
"订单号",
"父订单号",
"商家",
"订单状态",
"品名",
"产品编码",
"产品条码",
"单价(元)",
"数量",
"商品金额(元)",
"折后单价",
"订单实付总金额",
]
for col, name in enumerate(headers):
sheet.write(0, col, name)
sheet.write(1, 0, "ZQD1")
sheet.write(1, 2, "广东壹号药业有限公司")
sheet.write(1, 3, "待收货")
sheet.write(1, 4, "参芪五味子片")
sheet.write(1, 5, "8353YCZ12965")
sheet.write(1, 6, "6930301630566,1601063192,6930301630627,6927245800070")
sheet.write(1, 7, 10)
sheet.write(1, 8, 1)
sheet.write(1, 9, 10)
sheet.write(1, 10, 10)
sheet.write(1, 11, 10)
book.save(str(path))
lines = parse_order_xls(path)
assert lines[0].bar_code == "6930301630566"

View File

@ -97,6 +97,15 @@ def test_unmatched_without_dtl_is_not_inserted():
assert result.unmatched[0][1] == "NO_DTL_ID" assert result.unmatched[0][1] == "NO_DTL_ID"
def test_unmatched_barcode_over_40_is_not_inserted():
result = match_pay_lines(
[_line(bar_code="1" * 41)],
existing_keys=set(),
)
assert result.rows == []
assert result.unmatched[0][1] == "BAR_CODE_TOO_LONG"
def test_attach_detail_ids_matches_qty_and_pay_price(): def test_attach_detail_ids_matches_qty_and_pay_price():
lines = [ lines = [
_line(pay_order_dtl_id="", qty=10, pay_price=Decimal("5.29"), goods_name="乳酶生片"), _line(pay_order_dtl_id="", qty=10, pay_price=Decimal("5.29"), goods_name="乳酶生片"),
@ -124,6 +133,32 @@ def test_attach_detail_ids_matches_qty_and_pay_price():
assert [line.pay_order_dtl_id for line in attached] == ["1001", "1002"] assert [line.pay_order_dtl_id for line in attached] == ["1001", "1002"]
def test_attach_detail_ids_matches_short_name_when_product_name_has_brand():
lines = [
_line(
pay_order_dtl_id="",
qty=120,
pay_price=Decimal("35.26"),
goods_name="艾司奥美拉唑镁肠溶胶囊",
)
]
details = {
"ZQD1": {
"productList": [
{
"orderDetailId": 366807077,
"productName": "艾速平 艾司奥美拉唑镁肠溶胶囊",
"shortName": "艾司奥美拉唑镁肠溶胶囊",
"quantity": 120,
"payPrice4": 35.26,
}
]
}
}
attached = attach_detail_ids(lines, details)
assert attached[0].pay_order_dtl_id == "366807077"
def test_build_pay_row_from_excel_fields(): def test_build_pay_row_from_excel_fields():
row = build_pay_row(_line()) row = build_pay_row(_line())
assert row["oms_id"] == 0 assert row["oms_id"] == 0