Tyche Pro — Invoice & Fortune Engine — Tyche Pro — 发票与财运引擎
v1.0.0Tyche Pro — 发票与财务引擎。生成专业的PDF格式发票,跟踪多币种支付,应用税费和滞纳金计算,发送...
运行时依赖
安装命令
点击复制技能文档
Tyche Pro — 发票和收入仪表盘 Tyche 的所有功能,外加多币种支持、收入目标跟踪、项目代码分组、逾期应收账款报告和所有分析的 CSV 导出。 Pro 功能 vs 免费 Tyche 功能 Tyche(免费) Tyche Pro 发票 Unlimited Unlimited 滞纳金计算 √ √ + 每张发票覆盖 提醒等级 3 个等级 3 个等级 + 逐步日志 多币种 × √ 每张发票币种 项目分组 × √ 按 project_code 分组 收入目标 × √ 进度条 逾期应收账款 × √ 30/60/90 天分组 分析导出 × √ 全部 CSV 仪表盘 → 获取 Tyche Pro:openclaw skills 安装 tyche-pro + 密钥在 ko-fi.com/occupythemilkyway 安全 所有数据存储在您的机器上。无传输,无云。 步骤 1 — 安装 pip3 install rich --break-system-packages --quiet 步骤 2 — 全面发票和收入仪表盘(Pro) 导入 os, csv, re, json 从 datetime 导入 datetime, timedelta 从 collections 导入 defaultdict 从 rich.console 导入 Console 从 rich.table 导入 Table 从 rich.panel 导入 Panel 从 rich.progress 导入 Progress, BarColumn, TextColumn 从 rich 导入 box console = Console() LICENSE_KEY = os.environ.get("LICENSE_KEY", "").strip() 如果没有 LICENSE_KEY: console.print(Panel( "[red bold] Tyche Pro 需要许可密钥。[/red bold]\n\n" "获取您的密钥在:[bold cyan]ko-fi.com/occupythemilkyway[/bold cyan]\n\n" "或者使用免费版本:[dim]openclaw skills 安装 tyche[/dim]", 标题="许可密钥要求", 边框样式="red" )) 引发 SystemExit(1) INVOICES_FILE = os.environ.get("INVOICES_FILE", "").strip() YOUR_NAME = os.environ.get("YOUR_NAME", "您的公司") YOUR_EMAIL = os.environ.get("YOUR_EMAIL", "") YOUR_ADDRESS = os.environ.get("YOUR_ADDRESS", "") PAYMENT_TERMS = os.environ.get("PAYMENT_TERMS", "Net 30") CURRENCY = os.environ.get("CURRENCY", "USD").upper() PAYMENT_METHOD = os.environ.get("PAYMENT_METHOD", "") 尝试: TAX_RATE = float(os.environ.get("TAX_RATE", "0")) LATE_FEE_RATE = float(os.environ.get("LATE_FEE_RATE", "1.5")) REVENUE_GOAL = float(os.environ.get("REVENUE_GOAL", "0")) 除 ValueError 外: TAX_RATE = LATE_FEE_RATE = REVENUE_GOAL = 0.0 SYM = {"USD": "$", "EUR": "€", "GBP": "£", "CAD": "CA$", "AUD": "AU$"}.get(CURRENCY, "$") now = datetime.now() 定义 fmt(amount, sym=None): 返回 f"{sym or SYM}{amount:,.2f}" 定义 parse_amount(raw): c = re.sub(r"[^0-9.]", "", str(raw)) 或 "0" 尝试: 返回 float(c) 如果 c.count(".") <= 1 否则 0.0 除外: 返回 0.0 定义 parse_date(raw): 对于 f 在 ("%Y-%m-%d","%m/%d/%Y","%d/%m/%Y","%d-%m-%Y"): 尝试: 返回 datetime.strptime(raw.strip(), f) 除外: 传递 返回 None 发票 = [] 如果 INVOICES_FILE 和 os.path.exists(INVOICES_FILE): 使用 open(INVOICES_FILE, encoding="utf-8", errors="replace") 作为 f: reader = csv.DictReader(f) 对于 i, row 在 enumerate(reader, 1): rk = {k.lower().strip(): v.strip() 为 k,v 在 row.items()} inv_cur = rk.get("currency", CURRENCY).upper() inv_sym = {"USD":"$","EUR":"€","GBP":"£","CAD":"CA$","AUD":"AU$"}.get(inv_cur, "$") 发票.append({ "inv_number": rk.get("inv_number", f"INV-{i:04d}"), "client_name": rk.get("client_name","客户"), "client_email": rk.get("client_email",""), "描述": rk.get("描述","服务提供"), "金额": parse_amount(rk.get("金额","0")), "到期日期": rk.get("到期日期",""), "状态": rk.get("状态","未付款").lower(), "币种": inv_cur, "符号": inv_sym, "项目代码": rk.get("项目代码","").upper() 或 "GENERAL", }) 否则: console.print("[yellow] No INVOICES_FILE — 使用演示数据。[/yellow]\n") 发票 = [ {"inv_number":"INV-0001","client_name":"Acme Corp","client_email":"billing@acme.com","描述":"网站重新设计","金额":2500,"到期日期":(now-timedelta(days=15)).strftime("%Y-%m-%d"),"状态":"逾期","币种":"USD","符号":"$","项目代码":"WEB"}, {"inv_number":"INV-0002","client_name":"Globex Inc","client_email":"ap@globex.com","描述":"咨询保留金","金额":1800,"到期日期":(now+timedelta(days=10)).strftime("%Y-%m-%d"),"状态":"未付款","币种":"USD","符号":"$","项目代码":"CONSULT"}, {"inv_number":"INV-0003","client_name":"Initech Ltd","client_email":"pay@initech.com","描述":"标志设计","金额":750,"到期日期":(now-timedelta(days=5)).strftime("%Y-%m-%d"),"状态":"已付款","币种":"GBP","符号":"£","项目代码":"DESIGN"}, {"inv_number":"INV-0004","client_name":"Umbrella Co","client_email":"finance@umbrella.co","描述":"SEO 审计","金额":1200,"到期日期":(now-timedelta(days=35)).strftime("%Y-%m-%d"),"状态":"逾期","币种":"GBP","符号":"£","项目代码":"SEO"}, ]