# 返利班次入口:领表 4 起草行 / 表 3 只录协议行,runner 查号 → 总单 → 细单 → 送审,写表 4。 from __future__ import annotations import argparse from pathlib import Path from apa_browser_adapter import ApaBrowserAdapter from rpa_oracle import load_job_env from job import recorder, run_batch from persist import KIND_HOLD, KIND_NOT_FOUND, AgreementOutcome, RebateGroup from rebate_finder import RebateFinder, context_from_env from rebate_flow_steps import ( import_draft_for_contract, run_header_flow, run_import_flow, run_submit_flow, ) from repo import OracleRebateRepo DEFAULT_CLAIM_LIMIT = 10 def parse_args(argv: list[str] | None = None) -> argparse.Namespace: """解析返利班次参数。不传 --limit 时按行领 10 条,不再全部领走。""" parser = argparse.ArgumentParser(description="返利班次:查号 + 总单 + 细单 + 送审") parser.add_argument( "--limit", type=int, default=DEFAULT_CLAIM_LIMIT, help="本班最多领取 N 条,默认 10", ) return parser.parse_args(argv) def production_runner(browser, ctx, finder: RebateFinder, group: RebateGroup) -> AgreementOutcome: """一组合同:先查号。确认没有单据才留给下一班。 送审前按合同号查已有协议。已有总单号则补写,不再新建。 读号失败保持处理中,不把起草行改回待领。 """ contract_no = group.contract_no print(f"find contract_no={contract_no}", flush=True) try: found = bool(finder(contract_no)) except Exception as exc: text = str(exc).strip() return AgreementOutcome(KIND_HOLD, None, None, "读号失败", text or None) print(f"found={'yes' if found else 'no'} contract_no={contract_no}", flush=True) if not found: return AgreementOutcome(KIND_NOT_FOUND, None, None, None) def existing(number: str) -> str: """读当前页上的协议总单号。合同号本身不算已有协议。""" from rebate_common import _scan_rebate_order_no found_id = (_scan_rebate_order_no(browser, contract_no=number) or "").strip() if found_id == (number or "").strip(): return "" return found_id # 填总单并返回协议总单号。没拿到号后面就不送审。 def header(number: str) -> str: print(f"header contract_no={number}", flush=True) return run_header_flow(browser, ctx, number) # 按表 3 货品新增细单。有失败行时这一组不算录入成功。 def importer(number: str): print(f"import contract_no={number}", flush=True) return run_import_flow(browser, ctx, number, import_draft_for_contract(number)) # 送审。成功才由落表逻辑插 actionCode=2。 def submitter(number: str): print(f"submit contract_no={number}", flush=True) return run_submit_flow(browser, ctx, number) return recorder(contract_no, header, importer, submitter, existing=existing) def main(argv: list[str] | None = None, repo=None, runner=None) -> int: """领表 4 起草行和表 3 只录协议行,跑完查号到送审。有失败则进程退出码 1。 不传 --limit 时最多领 10 行。传入 repo 和 runner 时不打开浏览器。 """ args = parse_args(argv) load_job_env(Path(__file__).resolve().parent) if repo is None: repo = OracleRebateRepo.from_env() if runner is None: ctx = context_from_env() browser = ApaBrowserAdapter(url=ctx.rebate_url, flow="REBATE_FIND") finder = RebateFinder(browser, ctx) runner = lambda group: production_runner(browser, ctx, finder, group) summary = run_batch( repo, runner=runner, limit=args.limit, ) print( f"claimed={summary.claimed} groups={summary.groups} " f"ok={summary.ok} not_found={summary.not_found} failed={summary.failed}", flush=True, ) return 0 if summary.failed == 0 else 1 if __name__ == "__main__": raise SystemExit(main())