"""普通报销填报流程 负责普通发票报销的完整填报步骤: 基本信息 → 总明细 → 支付方式 → 附件上传 """ from typing import Any from ... import get_logger from .base import BaseBot, format_date log = get_logger("bot.normal") # ------------------------------------------------------------------ # 普通报销流程 # ------------------------------------------------------------------ def run( bot: BaseBot, normal_info: dict[str, Any], ) -> None: """执行普通发票报销填报流程 Args: bot: 已启动并登录的 BaseBot 实例。 normal_info: 普通发票信息字典。 """ log.info("开始普通发票报销填报...") log.info("填写基本信息...") description = normal_info.get("basic_info", {}).get("reimbursement_description", "元器件采购报销") fill_basic_info(bot, description) total_invoices = normal_info.get("reimbursement_details", {}).get("total_invoices", 0) total_amount = normal_info.get("reimbursement_details", {}).get("total_amount", 0) log.info(f"录入普通发票总明细 (共 {total_invoices} 张, 合计 ¥{total_amount:.2f})...") add_normal_item(bot, total_invoices, total_amount) payment_info = normal_info.get("payment_methods", []) log.info(f"录入普通发票支付信息 (共 {len(payment_info)} 笔)...") fill_normal_payment(bot, payment_info) log.info("上传普通发票附件...") attachment_info = normal_info.get("attachments", []) upload_normal_attachments(bot, attachment_info) log.info("普通发票报销填报完成") # ------------------------------------------------------------------ # 基本信息 # ------------------------------------------------------------------ def fill_basic_info(bot: BaseBot, description: str = "元器件采购报销") -> None: """填写基本信息""" try: bot.page.fill("#EXPENEXPLAIN", description) bot.page.click("#PROJECTCODE", timeout=10000) bot.page.wait_for_timeout(1000) bot.page.wait_for_selector("#promodal .fixed-table-body tbody tr", timeout=10000) first_row = bot.page.query_selector("#promodal .fixed-table-body tbody tr") if first_row: first_row.click() bot.page.wait_for_timeout(1000) bot.page.click("#saveAndNext", timeout=5000) bot.page.wait_for_timeout(2000) bot._screenshot("step3_done") except Exception as e: log.error(f"填写基本信息失败: {e}") bot._screenshot("basic_info_error") raise # ------------------------------------------------------------------ # 总明细 # ------------------------------------------------------------------ def add_normal_item(bot: BaseBot, total_invoices: int, total_amount: float) -> None: """录入普通发票总明细""" try: bot.page.click("#insertDetail", timeout=5000) bot._wait_for('text="经济事项名称"', timeout=5000) bot.page.click("#economicscode2") bot.page.wait_for_timeout(1000) try: bot.page.wait_for_selector("#econmodal .fixed-table-body tbody tr", timeout=10000) rows = bot.page.query_selector_all("#econmodal .fixed-table-body tbody tr") if len(rows) >= 3: rows[2].click() bot.page.wait_for_timeout(1000) except Exception: pass bot.page.fill('input[name="expenPwCommondetail.HOWBILLS"]', str(total_invoices)) bot.page.fill("#je_zwzcdz", f"{total_amount:.2f}") bot.page.click("#detailAdd", timeout=3000) bot.page.wait_for_timeout(1000) bot._screenshot("normal_item_done") except Exception as e: log.error(f"录入总明细失败: {e}") bot._screenshot("normal_item_error") raise # ------------------------------------------------------------------ # 支付方式 # ------------------------------------------------------------------ def fill_normal_payment(bot: BaseBot, payment_info: list[dict[str, Any]]) -> None: """录入普通发票支付信息""" try: bot.page.click('text="下一步(支付方式)"', timeout=5000) bot._wait_for('text="下一步(附件清单)"', timeout=5000) for info in payment_info: bot.page.click("#insertPay", timeout=5000) bot.page.wait_for_timeout(1000) bot.page.fill("#personid2", bot.config["default_person_id"]) bot.page.fill("#accountname2", bot.config["default_name"]) bot.page.fill("#receiptdate2", format_date(str(info.get("card_date", "")))) bot.page.fill("#localaccount2", bot.config["default_card_no"]) bot.page.fill("#receiptmoney2", str(info.get("card_amount", 0))) bot.page.fill("#money2", str(info.get("card_amount", 0))) bot.page.fill("#merchant2", str(info.get("merchant", ""))) bot.page.fill("#smark2", str(info.get("remark", ""))) bot.page.click("#payAdd", timeout=3000) bot.page.wait_for_timeout(1000) except Exception as e: log.error(f"支付方式录入失败: {e}") bot._screenshot("normal_payment_error") raise bot._screenshot("normal_payment_done") # ------------------------------------------------------------------ # 附件上传 # ------------------------------------------------------------------ def upload_normal_attachments(bot: BaseBot, attachment_info: list[dict[str, Any]]) -> None: """上传普通发票附件""" log.info(f"上传普通发票附件 (共 {len(attachment_info)} 个)...") try: bot.page.click("#next3", timeout=5000) bot._wait_for("#submit2", timeout=5000) for info in attachment_info: attachment_file = bot.work_dir / info["filename"] bot._wait_for("#insertAcc", timeout=20000) bot.page.click("#insertAcc", timeout=5000) bot._wait_for("#fjlx", timeout=5000) if info.get("attachment_type") == "invoice": bot.page.select_option("#fjlx", "1") else: bot.page.select_option("#fjlx", "2") bot.page.fill("#fpsmxx", info.get("attachment_desc", "")) if attachment_file and attachment_file.exists(): bot.page.set_input_files("#file", str(attachment_file)) bot.page.wait_for_timeout(1000) bot.page.click("#cjtj", timeout=5000) log.info("上传普通发票附件完成") except Exception as e: log.error(f"附件上传失败: {e}") bot._screenshot("normal_attachment_error") raise bot._screenshot("normal_attachment_done")