diff --git a/rpa_cart/parse_xls.py b/rpa_cart/parse_xls.py index 84cce71..887a220 100644 --- a/rpa_cart/parse_xls.py +++ b/rpa_cart/parse_xls.py @@ -67,6 +67,9 @@ def _text(value: object) -> str: def _barcode(value: object) -> str: 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(): return text[:-2] return text diff --git a/rpa_cart/settle.py b/rpa_cart/settle.py index 412eaaa..69beb44 100644 --- a/rpa_cart/settle.py +++ b/rpa_cart/settle.py @@ -74,6 +74,9 @@ def match_pay_lines( if not line.pay_order_dtl_id: result.unmatched.append((line, "NO_DTL_ID")) 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) if key in seen: 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): qty = int(Decimal(str(product.get("quantity") or 0))) pay_price = money4(product.get("payPrice4") or 0) - name = str(product.get("productName") or "") if qty != line.qty: continue if pay_price != money4(line.pay_price): continue - if name and line.goods_name and name != line.goods_name: + if not _goods_name_matches(product, line.goods_name): continue return idx 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 diff --git a/rpa_cart/tests/test_parse_xls.py b/rpa_cart/tests/test_parse_xls.py index faf37fb..5ebd8b5 100644 --- a/rpa_cart/tests/test_parse_xls.py +++ b/rpa_cart/tests/test_parse_xls.py @@ -66,3 +66,40 @@ def test_parse_order_xls_reads_settlement_columns(tmp_path: Path): assert line.pay_price == Decimal("65.49") assert line.unit_price == Decimal("65.49") 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" diff --git a/rpa_cart/tests/test_settle.py b/rpa_cart/tests/test_settle.py index d704858..58b86cb 100644 --- a/rpa_cart/tests/test_settle.py +++ b/rpa_cart/tests/test_settle.py @@ -97,6 +97,15 @@ def test_unmatched_without_dtl_is_not_inserted(): 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(): lines = [ _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"] +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(): row = build_pay_row(_line()) assert row["oms_id"] == 0