109 lines
4.0 KiB
Python
109 lines
4.0 KiB
Python
# 返利班次入口:领表 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())
|