# coding=utf-8 """ 构建 Main.seq - 合同建单流程(多节点可视化 + 真实浏览器) """ import json import base64 def b64_apa(val): """将值编码为 APA val 格式""" return json.dumps({"val": base64.b64encode(str(val).encode()).decode()}, indent=4) def b64_raw(val): """纯 base64 编码""" return base64.b64encode(str(val).encode()).decode() # ============================================================ # 各步骤代码 # ============================================================ # S01: 初始化环境 s01_body = """\ import sys, os, json, time from pathlib import Path _CODES_DIR = Path(r'd:\\RPA\\AutoRpa\\codes') if str(_CODES_DIR) not in sys.path: sys.path.insert(0, str(_CODES_DIR)) from rpa_yisaiqi.contract_flow_steps import ContractFlowContext, ContractGoodsLine print("=" * 60) print("合同建单 CONTRACT_CREATE - 初始化") print("=" * 60) self._ctx = ContractFlowContext( contract_url="http://contract-test.gzmpc.com:8080/", username="test002", password="1", supplier_name="测试供应商", order_date="2026-08-12", source_type="YYC", template_type="NON_FORMAT", template_name="非格式--采购协议", customer_code="CUST-001", customer_name="测试供应商", contract_category="采购协议", settlement_type="付款", contract_background="自动化测试合同起草", contract_nature="主合同", amount_currency="人民币", amount="50000.00", contract_end_date="2026-12-31", is_major_contract="否", is_prepayment="否", belong_year="2026", payment_method="账期支付", payment_days="30", contract_status="正式合同", contains_blood_products="否", submit_mode="dry_run", goods_lines=[ ContractGoodsLine( operation_code="ADD", goods_code="YP-001", goods_name="测试药品A", approval_no="国药准字H00000001", spec="50mg*30片", unit="盒", quantity=10.0, ), ], merged_pdf_path=None, ) print(f"[OK] 上下文就绪: source={self._ctx.source_type}") print(f"[OK] 模板: {self._ctx.template_name}") print(f"[OK] 货品行数: {len(self._ctx.goods_lines)}") """ # S02: 打开浏览器 s02_body = """\ from ubpa.iobject.browser import Browser from rpa_yisaiqi.contract_flow_steps import open_contract_system print("[S02] 打开 Edge 浏览器...") print(f" URL: {self._ctx.contract_url}") browser = Browser(Browser.AppName.edge) browser.open(url=self._ctx.contract_url, timeout=30) self._browser = browser print("[OK] 浏览器已打开") """ # S03: 登录 + 进入起草 s03_body = """\ from rpa_yisaiqi.contract_flow_steps import login_contract_system, enter_contract_create from rpa_yisaiqi.apa_browser_adapter import ApaBrowserAdapter adapter = ApaBrowserAdapter() adapter._browser = self._browser adapter._is_open = True print("[S03] 登录合同系统...") login_contract_system(adapter, self._ctx) print("[OK] 登录完成") print("[S04] 进入合同起草...") enter_contract_create(adapter) print("[OK] 已进入合同起草页面") self._adapter = adapter """ # S04: 选择模板 + 签约方信息 s04_body = """\ from rpa_yisaiqi.contract_flow_steps import select_contract_template, fill_contract_signatory_info adapter = self._adapter print("[S05] 选择合同模板...") select_contract_template(adapter, self._ctx) print(f"[OK] 模板: {self._ctx.template_name}") print("[S06] 填写签约方信息...") fill_contract_signatory_info(adapter, self._ctx) print(f"[OK] 签约方: {self._ctx.customer_name}") """ # S05: 基础表单 + 金额日期 s05_body = """\ from rpa_yisaiqi.contract_flow_steps import fill_contract_basic_info, fill_contract_amount_and_dates adapter = self._adapter print("[S07] 填写基础表单...") fill_contract_basic_info(adapter, self._ctx) print(f"[OK] 类别={self._ctx.contract_category}, 结算={self._ctx.settlement_type}") print("[S08] 填写金额与日期...") fill_contract_amount_and_dates(adapter, self._ctx) print(f"[OK] 金额={self._ctx.amount}, 结束日期={self._ctx.contract_end_date}") """ # S06: 货品明细 + 付款信息 + 提交 s06_body = """\ from rpa_yisaiqi.contract_flow_steps import ( fill_contract_goods_lines, fill_contract_payment_info, upload_contract_document_if_needed, submit_contract_for_approval, read_contract_number ) adapter = self._adapter print("[S09] 填写货品明细...") fill_contract_goods_lines(adapter, self._ctx) print(f"[OK] 货品: {len(self._ctx.goods_lines)} 行") print("[S10] 填写付款信息...") fill_contract_payment_info(adapter, self._ctx) print(f"[OK] 付款方式={self._ctx.payment_method}") if self._ctx.source_type == "YYC": print("[S11] 合并PDF [YYC专属]... (单PDF, 跳过合并)") print("[S12] 上传PDF附件 [YYC专属]... (dry_run 跳过)") print() print("[S13] 提交审批...") if not submit_contract_for_approval(adapter, self._ctx): print("[DRY-RUN] 演练模式,跳过实际提交") print("=" * 60) print("合同建单流程演练完成") print("=" * 60) else: print("[S14] 读取合同编号...") contract_no = read_contract_number(adapter) print(f"[OK] 合同编号: {contract_no}") print("=" * 60) print(f"[COMPLETED] 合同创建成功: {contract_no}") print("=" * 60) """ # ============================================================ # 节点定义 # ============================================================ steps = [ ("S01", "S01 初始化 & 上下文构建", s01_body, "设置环境变量并构建YYC测试上下文"), ("S02", "S02 打开Edge浏览器", s02_body, "打开Edge浏览器并导航到合同系统"), ("S03", "S03-S04 登录 & 进入起草", s03_body, "登录系统并进入合同起草页面"), ("S04", "S05-S06 模板选择 & 签约方", s04_body, "选择模板并填写签约方信息"), ("S05", "S07-S08 基础表单 & 金额日期", s05_body, "填写合同类别、金额、日期"), ("S06", "S09-S15 货品/付款/提交", s06_body, "填写货品明细、付款信息并提交"), ] def make_code_import_props(pimport, pbody): """创建 EP_CONTROL_IMPORT 的 JSON 字符串""" inner = json.dumps({ "PImport": pimport, "PBCode": pbody }, indent=4, ensure_ascii=False) return inner # ============================================================ # 构建 Main.seq # ============================================================ nodes = [] lines = [] # 开始节点 begin_tag = "20260812100000" nodes.append({ "NodePanelData": { "ExpandedGroups": [], "InputProperty": {"mouse_x": 0, "mouse_y": 0}, "PubProperty": "", "RetPins": [] }, "NodeProperty": "", "NodeUI": { "NodeElementID": "", "NodeModel": "2", "NodePropErr": False, "NodePx": "300", "NodePy": "200", "NodeSubType": "EnumWidget_Begin", "NodeTag": begin_tag, "NodeTitle": "开始" } }) prev_tag = begin_tag start_x = 500 start_y = 200 space_y = 120 for i, (sid, title, body, note) in enumerate(steps): tag = f"20260812{200000 + i:06d}" py = start_y + i * space_y # Encode as raw base64 for PBCode/PImport pimport_b64 = b64_raw("sys, os, json, pathlib, time") pbody_b64 = b64_raw(body) props = { "EP_CONTROL": { "EP_CONTROL_IMPORT": json.dumps({"PImport": pimport_b64, "PBCode": pbody_b64}, indent=4) }, "EP_Gen": { "EP_Gen_AFTERDELAY": b64_apa("0"), "EP_Gen_BEFOREDELAY": b64_apa("0"), "EP_Gen_NOTE": b64_apa(note) } } nodes.append({ "NodePanelData": { "ExpandedGroups": [], "InputProperty": {"mouse_x": 0, "mouse_y": 0}, "PubProperty": "", "RetPins": [] }, "NodeProperty": props, "NodeUI": { "NodeElementID": "", "NodeModel": "2", "NodePropErr": False, "NodePx": str(start_x - 15), "NodePy": str(py), "NodeSubType": "EnumWidget_Code_Custom", "NodeTag": tag, "NodeTitle": title } }) lines.append({ "LineColor": "255, 255, 255", "LineNote": "", "LineType": 0, "LineSplit": {"Px": "", "Py": ""}, "LineEnd": { "Pidx": f"{tag}/EPin_Flow_In", "Px": str(start_x - 25), "Py": str(py + 30) }, "LineStart": { "Pidx": f"{prev_tag}/EPin_Flow_Out", "Px": str(start_x - 100) if i > 0 else "415", "Py": str(start_y + 30) if i == 0 else str(start_y + (i-1) * space_y + 30) }, "LineTag": f"20260812{300000 + i:06d}" }) prev_tag = tag center_y = start_y + len(steps) * space_y // 2 main_seq = { "LineList": lines, "NodeList": nodes, "SeqTag": "Main", "ViewCenterPx": "600", "ViewCenterPy": str(center_y), "ViewScaling": "1" } with open(r"d:\RPA\AutoRpa\Main.seq", "w", encoding="utf-8") as f: json.dump(main_seq, f, ensure_ascii=False, indent=4) print(f"Main.seq 已生成: {len(nodes)} 节点, {len(lines)} 连线") for n in nodes: print(f" [{n['NodeUI']['NodeSubType'].replace('EnumWidget_','').replace('_Code_Custom','CODE').replace('_Begin','START')}] {n['NodeUI']['NodeTitle']}")