发票机
面向自由职业者和小型企业的自托管发票应用程序。创建发票和报价、管理客户和生成PDF。
特性
- 使用自动编号创建和跟踪发票和报价
- 包含地址和付款条件的客户数据库
- 可定制品牌和徽标的PDF生成
- 税收支持 按发票、按客户或全局默认值
- 经常性发票 用于预订和订阅
- SMTP电子邮件 直接向客户发送发票
- 全文搜索 跨发票和客户
- 具有速率限制的内置身份验证
- 使用可选的S3存储进行自动每日备份
- 带系统偏好检测的暗模式
- 逾期发票突出显示和自动状态更新
- 分析 用于收入跟踪和客户洞察
- Claude Desktop的MCP集成(与REST机器人API分开的密钥)
- 传统的Bot API密钥
/api/*托管自动化SKILL.md - SQLite存储,可在任何地方运行
快速开始
码头工人
git clone https://github.com/davidtorcivia/invoice-machine.git
cd invoice-machine
docker-compose up -d打开http://localhost:8080并创建您的管理员帐户。
生产部署
对于生产环境,设置环境变量以配置端口和数据目录:
# Set your production values
export PORT=8085
export DATA_DIR=/nvme-mirror/apps/invoice-machine/data
export APP_BASE_URL=https://invoices.yourdomain.com
# Start the container
docker-compose up -d或者创建一个 .env 项目目录中的文件:
PORT=8085
DATA_DIR=/nvme-mirror/apps/invoice-machine/data
APP_BASE_URL=https://invoices.yourdomain.com容器始终在内部监听端口8080。这 PORT 变量将其映射到所需的外部端口。
首映
- 在设置屏幕上创建管理员帐户
- 转到“设置”以配置您的企业名称、地址和徽标
- 添加付款说明(银行详细信息、Venmo等)
- 开始创建发票
配置
将这些设置为 .env 文件或作为环境变量。看 .env.example 一个完整的模板。
核心设置
| 变量 | 描述 | 默认值 |
|---|---|---|
PORT | 外部端口映射 | 8080 |
DATA_DIR | 数据存储目录 | ./data |
APP_BASE_URL | 应用程序的基本URL | http://localhost:8080 |
ENVIRONMENT | 环境模式(开发/分期/生产) | development |
TRASH_RETENTION_DAYS | 自动清除垃圾的前几天 | 90 |
安全设置
| 变量 | 描述 | 默认值 |
|---|---|---|
INVOICE_MACHINE_ENCRYPTION_KEY | 敏感数据的加密密钥(SMTP密码) | 生产中需要 |
SECURE_COOKIES | 启用安全Cookie(需要HTTPS) | false |
CORS_ORIGINS | 允许的CORS源(逗号分隔) | http://localhost:3000,http://localhost:8080 |
生成加密密钥
加密密钥保护敏感数据,如SMTP凭据。在生产中,这把钥匙是 必需的--没有它,应用程序将拒绝启动。
使用以下任何方法生成安全的32字节(64个十六进制字符)密钥:
python
python -c "import secrets; print(secrets.token_hex(32))"OpenSSL:
openssl rand -hex 32PowerShell:
-join ((1..32) | ForEach-Object { "{0:x2}" -f (Get-Random -Maximum 256) })安全地存储密钥 永远不要将其提交给版本控制。如果丢失密钥,任何加密凭据(SMTP密码)都将无法读取,必须重新输入。
发票默认值
| 变量 | 描述 | 默认值 |
|---|---|---|
DEFAULT_PAYMENT_TERMS_DAYS | 默认付款条件 | 30 |
DEFAULT_CURRENCY_CODE | 默认货币 | USD |
DEFAULT_ACCENT_COLOR | PDF强调色(十六进制) | #16a34a |
生产配置
对于HTTPS(Cloudflare Tunnel、nginx等)背后的生产部署,这些设置是 必需的:
# Required for production
INVOICE_MACHINE_ENCRYPTION_KEY=your_64_character_hex_key_here
APP_BASE_URL=https://invoices.yourdomain.com
ENVIRONMENT=production
SECURE_COOKIES=true
CORS_ORIGINS=https://invoices.yourdomain.com
# Recommended: persistent data storage
DATA_DIR=/var/lib/invoice-machine/data| 变量 | 必填 | 描述 |
|---|---|---|
INVOICE_MACHINE_ENCRYPTION_KEY | 是 | 敏感数据的加密密钥(请参见 生成加密密钥) |
APP_BASE_URL | 是 | 必须与PDF链接、MCP和托管的公共URL匹配 SKILL.md |
ENVIRONMENT | 是 | 设置为 production 用于正确的日志记录和默认值 |
SECURE_COOKIES | 是 | 必须是 true 使用HTTPS时 |
CORS_ORIGINS | 是 | 必须与您的域匹配以防止CORS错误 |
DATA_DIR | 推荐 | 容器外的持久存储位置 |
用法
发票
- 转到发票>新发票
- 选择客户或手动输入详细信息
- 添加带有描述、数量或小时数以及价格的行项目
- 设置发行日期和到期日期
- 单击创建发票
语录
与发票相同,但请勾选“这是报价”。引号用Q前缀单独编号。
PDF生成
在任何发票上单击下载PDF。发票更改时,PDF会自动重新生成。文件名格式: [Client Name] - [Invoice Number].pdf
发票号码
格式: YYYYMMDD-N 其中N每天重置。
- 2025年6月23日的第一张发票:
20250623-1 - 第二张发票当天:
20250623-2 - 引用:
Q-YYYYMMDD-N
更改发票日期会重新生成其编号。
税务处理
Invoice Machine支持级联系统的可选税:
- 发票级别:覆盖单个发票上的税务设置
- 客户端级别:为特定客户设置默认税款
- 全球违约:在“设置”>“税务设置”中配置
级联优先级为:发票>客户>全局。默认情况下禁用税务。
要启用税务:
- 转到“设置”,使用默认税率启用税款
- 在客户端编辑器中可选择设置每个客户端的费率
- 根据需要覆盖特定发票
经常性发票
为客户、订阅或常规服务设置定期发票:
- 转到客户>选择客户>定期计划
- 使用以下内容创建日程表:
- 姓名(例如,“月度保留人”) - 频率(每日、每周、每月、每季度、每年) - 计划日(每月1-31,每周0-6) - 行项目和金额
- 发票在UTC凌晨2点自动生成
您还可以手动触发计划或暂停/恢复计划。
电子邮件投递
通过SMTP直接向客户端发送发票:
- 前往“设置”>“电子邮件配置”
- 配置SMTP服务器:
- 主机和端口(587用于TLS,465用于SSL) - 用户名和密码 - 来自姓名和电子邮件
- 点击“测试连接”进行验证
- 在任何发票上,单击“发送电子邮件”以发送PDF
适用于任何SMTP提供商(Gmail、SendGrid、Mailgun等)。
搜索
使用搜索栏查找发票和客户:
- 按发票号码、客户名称或备注搜索
- 使用全文搜索按相关性对结果进行排名
- 支持部分匹配
MCP集成
发票机通过MCP与克劳德桌面协同工作。您可以通过自然语言创建发票、管理客户和生成PDF。
设置
- 前往“设置”>“MCP集成”
- 单击生成API密钥
- 将配置复制到您的Claude Desktop配置:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json 窗户: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"invoice-machine": {
"command": "npx",
"args": [
"mcp-remote",
"https://your-server.com/mcp/sse",
"--header",
"Authorization: Bearer YOUR_MCP_API_KEY"
]
}
}
}替换 your-server.com 使用您的实际域名和 YOUR_MCP_API_KEY 使用设置中的键。
MCP端点与web应用程序在同一端口上运行。适用于Cloudflare隧道或任何反向代理。
关键范围
MCP API密钥仅适用于MCP(/mcp/*)来自Claude Desktop的连接。 对于传统的REST API调用(/api/*),使用下面描述的单独Bot API密钥。
Bot API集成
使用专门的Bot API密钥来实现自动化工具、脚本和代理的标准HTTP请求。
设置
- 前往“设置”>“Bot API密钥”
- 单击生成Bot API密钥
- 立即保存密钥(只显示一次)
- 在REST API请求中将其作为承载令牌发送
认证
使用此标头 /api/* 请求:
Authorization: Bearer YOUR_BOT_API_KEY技能档案
Invoice Machine公开了一个托管技能文件,用于在以下位置设置代理:
https://your-server.com/SKILL.md示例请求
curl -H "Authorization: Bearer YOUR_BOT_API_KEY" \
"https://your-server.com/api/invoices/paginated?page=1&per_page=10"本地Docker设置
如果使用Docker在本地运行,则可以使用stdio传输:
{
"mcpServers": {
"invoice-machine": {
"command": "docker",
"args": ["exec", "-i", "invoice-machine", "python", "-m", "invoice_machine.mcp.server"]
}
}
}示例命令
发票:
- “为Acme Corp开具网站开发发票,40小时,150美元/小时”
- “为标志设计报价500美元,品牌指南报价1200美元”
- “列出上个月所有未付发票”
- “将发票20250115-1标记为已付款”
- “为所有发票草稿生成PDF”
再发生:
- “为Acme Corp设立每月2000美元的聘用费”
- “暂停客户端X的定期计划”
- “立即触发Big Corp的季度发票”
分析:
- “我2024年的收入摘要是什么?”
- “按总收入计算,我的前五大客户是谁?”
- “显示Acme Corp的生命周期价值”
电子邮件:
- “将发票20250115-1发送至john@acme.com"
- “将最新发票通过电子邮件发送给客户”
搜索:
- 搜索包含“网站”的发票
- “查找所有名为Smith的客户”
MCP工具
企业简介: get_business_profile, update_business_profile, add_payment_method, remove_payment_method
客户: list_clients, get_client, create_client, update_client, delete_client, restore_client
发票: list_invoices, get_invoice, create_invoice, update_invoice, delete_invoice, restore_invoice
行项目: add_invoice_item, update_invoice_item, remove_invoice_item
再发生: list_recurring_schedules, get_recurring_schedule, create_recurring_schedule, update_recurring_schedule, delete_recurring_schedule, pause_recurring_schedule, resume_recurring_schedule, trigger_recurring_schedule
搜索: search -在发票和客户之间进行全文搜索
分析: get_revenue_summary, get_top_clients, get_client_lifetime_value
电子邮件: send_invoice_email, test_smtp_connection
其他: generate_pdf, list_trash
项目结构
invoice-machine/
├── invoice_machine/ # Python backend
│ ├── api/ # FastAPI routes
│ ├── mcp/ # MCP server
│ ├── pdf/ # PDF generation
│ ├── alembic/ # Database migrations
│ ├── database.py # SQLAlchemy models
│ ├── services.py # Business logic
│ ├── email.py # SMTP email service
│ ├── config.py # Configuration management
│ └── main.py # FastAPI app
├── frontend/ # SvelteKit frontend
├── tests/ # Test suite
│ ├── test_services.py # Service tests
│ ├── test_api.py # API tests
│ ├── test_new_features.py # Feature tests
│ └── test_security.py # Security tests
├── data/ # Runtime data (gitignored)
│ ├── invoice_machine.db # SQLite database
│ ├── backups/ # Database backups
│ ├── pdfs/ # Generated PDFs
│ └── logos/ # Uploaded logos
├── alembic.ini # Alembic configuration
├── .env.example # Environment template
└── docker-compose.yml发展
后端
pip install -e ".[dev]"
python -c "import mcp; print('mcp installed')"
uvicorn invoice_machine.main:app --reload --port 8080前端
cd frontend
npm install
npm run dev
npm run build # Production build测试
pytest tests/ -v备份
自动备份
Invoice Machine可以在UTC每天午夜自动备份您的数据库。
- 转到“设置”>“备份和还原”
- 启用“自动每日备份”
- 设置保留期(默认值:30天)
S3存储
可选择将备份上传到S3兼容存储(AWS S3、Backblaze B2、MinIO):
- 启用“将备份上传到S3兼容存储”
- 输入您的端点URL、凭据、存储桶和区域
- 点击“测试S3连接”进行验证
手动备份
所有数据都存在于 data/ 目录。复制它以备份所有内容。您还可以从“设置”页面创建手动备份并直接下载。
恢复
单击任何要还原的备份上的还原按钮。自动创建还原前备份。还原后需要重新启动应用程序。
安全
发票机包括几个安全功能:
认证
- PBKDF2-HMAC-SHA256密码散列,迭代次数为600000次
- 密码复杂性要求(至少8个字符,包括小写、大写和数字)
- 登录端点的速率限制(3次尝试/分钟)
- 30天过期的数据库支持会话
- 使用双重提交cookie模式的CSRF保护
- 用于HTTPS部署的可配置安全Cookie
凭证加密
- 使用Fernet(AES-128-CBC)对SMTP密码和其他敏感数据进行静态加密
- 生产中需要加密密钥(没有它,应用程序拒绝启动)
- 密钥推导使用PBKDF2-HMAC-SHA256和独特的盐
输入验证
- 文件操作的路径遍历预防
- 电子邮件头注入保护
- 图像上传验证(魔术字节+扩展名)
- 通过SQLAlchemy ORM防止SQL注入
- FTS5查询清理
集装箱安全
- Docker容器以非root用户身份运行(UID 1000)
- 仅依赖生产的最小攻击面
生产建议
- 设置加密密钥:生成并设置
INVOICE_MACHINE_ENCRYPTION_KEY(参见 生成加密密钥) - 使用HTTPS:设置
SECURE_COOKIES=true当位于HTTPS之后时 - 限制CORS:设置
CORS_ORIGINS仅限您的实际域名 - 定期备份:使用S3启用自动备份以进行异地存储
- 访问控制:使用Cloudflare Access或类似工具进行额外保护
- 保持更新:定期拉取最新的Docker镜像
部署
对于远程访问,请使用反向代理。Cloudflare隧道示例:
cloudflared tunnel create invoice-machine- 在Cloudflare仪表板中配置访问策略
- 集
APP_BASE_URL在.env - 集
SECURE_COOKIES=true对于HTTPS
Docker编写生产示例
version: '3.8'
services:
invoice-machine:
image: invoice-machine:latest
container_name: invoice-machine
ports:
- "8080:8080"
environment:
# Required for production
- INVOICE_MACHINE_ENCRYPTION_KEY=${INVOICE_MACHINE_ENCRYPTION_KEY}
- APP_BASE_URL=https://invoices.yourdomain.com
- ENVIRONMENT=production
- SECURE_COOKIES=true
- CORS_ORIGINS=https://invoices.yourdomain.com
# Database (uses container path)
- DATABASE_URL=sqlite+aiosqlite:////app/data/invoice_machine.db
- DATA_DIR=/app/data
# Optional: customize defaults
- DEFAULT_PAYMENT_TERMS_DAYS=30
- DEFAULT_CURRENCY_CODE=USD
- TRASH_RETENTION_DAYS=90
volumes:
- /var/lib/invoice-machine/data:/app/data
restart: unless-stopped
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')"]
interval: 30s
timeout: 3s
retries: 3重要提示:
- 这
DATABASE_URL使用4个斜线(////app/data/)因为SQLite URL需要3个斜杠加上绝对路径 - 卷装载(
/var/lib/invoice-machine/data:/app/data)保存所有数据,包括数据库、PDF、徽标和备份 - 集
container_name到invoice-machine如果使用MCPdocker exec
许可证
MIT许可证。看 许可证 了解详情。
