Files
query-payslip-default/examples/simulator_browser_rpa/scripts/service/task_service.py
skill-dev 3db196e49d feat: 工资查询助手首版 v1.0.105
基于 skill-template 脚手架开发,包含:
- payroll_config(费率配置,可编辑)+ payslip_snapshots(解析历史,只读)2 张业务表
- 全国默认 + 北上广 4 套费率(社保/公积金/个税起征点/7 级税率表)
- 5 个业务 Action:calculate-payslip-simple / calculate-payslip-full / explain-term / view-config / edit-config
- 个税累计预扣法计算,支持多月历史累加
- 20 个薪资名词库(社保/公积金/个税/全勤/加班费等)
- 完整市场文档(README/TUTORIAL/DEMO/CHANGELOG)
- 296 测试全部通过
2026-09-07 17:02:05 +08:00

101 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""轻量任务编排:校验输入 → 选 adapter → 提交批次。"""
from __future__ import annotations
import os
import tempfile
import uuid
from typing import Any, Dict, List, Optional
from service.adapter import BatchItem, select_adapter
from util.logging import get_logger
logger = get_logger(__name__)
def _validate_items(items: List[Dict[str, Any]]) -> tuple[List[BatchItem], Optional[str]]:
if not items:
return [], "items 不能为空"
parsed: List[BatchItem] = []
for idx, raw in enumerate(items, start=1):
name = str(raw.get("name") or "").strip()
account = str(raw.get("account") or "").strip()
note = str(raw.get("note") or "").strip()
try:
amount = float(raw.get("amount"))
except (TypeError, ValueError):
return [], f"第 {idx} 行 amount 无效"
if amount <= 0:
return [], f"第 {idx} 行 amount 必须大于 0"
if not name or not account:
return [], f"第 {idx} 行 name/account 不能为空"
parsed.append(
BatchItem(
row_index=int(raw.get("row_index") or idx),
name=name,
account=account,
amount=amount,
note=note,
)
)
return parsed, None
async def run_batch_submit(
target: str,
items: List[Dict[str, Any]],
*,
force: bool = False,
artifacts_dir: Optional[str] = None,
) -> Dict[str, Any]:
"""
最小编排示例。
真实 skill 中还应:写业务表、entitlement、RpaVideoSession 等。
账号 pick / lease 在 adapter 内完成,编排层不直接碰 account-manager。
"""
del force # 示例占位;真实 skill 可用于跳过确认
target_key = (target or "").strip()
if not target_key:
return {"success": False, "error": {"code": "INVALID_TARGET", "message": "target 不能为空"}}
batch_items, err = _validate_items(items)
if err:
return {"success": False, "error": {"code": "INVALID_ITEMS", "message": err}}
art_dir = artifacts_dir or os.path.join(
tempfile.gettempdir(),
"openclaw-simulator-rpa-artifacts",
uuid.uuid4().hex[:8],
)
os.makedirs(art_dir, exist_ok=True)
logger.info(
"batch_submit_start target=%s item_count=%s artifacts_dir=%s",
target_key,
len(batch_items),
art_dir,
)
adapter = select_adapter(artifacts_dir=art_dir)
result = await adapter.submit_batch(target_key, batch_items)
summary: Dict[str, Any] = {
"success": result.ok,
"target": target_key,
"adapter": result.artifacts.get("adapter") or adapter.name,
"submitted_count": result.submitted_count,
"submitted_amount": result.submitted_amount,
"batch_id": result.batch_id,
"artifacts": result.artifacts,
"artifacts_dir": art_dir,
}
if not result.ok:
summary["error"] = {"code": "BATCH_SUBMIT_FAILED", "message": result.error_msg or "提交失败"}
logger.info(
"batch_submit_done success=%s batch_id=%s adapter=%s",
result.ok,
result.batch_id,
adapter.name,
)
return summary