跳到主要内容

客户发票

交易 被组合在一起形成发票,发票会发送给客户以便付款。

发票有一个开始和结束日期,这表示发票覆盖的期间,以及到期日,这是发票到期付款的日期。

生成形式发票

发票可以由系统自动生成,例如,当服务被计费时,会为零售成本创建发票,或者它们可以手动创建,例如,如果客户请求发票副本,或者如果客户被计费一次性费用。

客户发票完全使用 Mailjet 模板化,并可以自定义以包含公司徽标、地址和付款详情,并可以通过电子邮件发送给客户,或下载为 PDF。

活动日志

自定义发票模板

OmniCRM 使用 HTML 模板和 Jinja2 模板生成发票。您可以完全自定义发票设计、品牌、颜色和布局。

发票模板位置

发票模板存储在 OmniCRM-API/invoice_templates/

默认模板:

  • norfone_invoice_template.html - 示例发票模板
  • cifi_invoice_template.html - 替代模板示例

配置:

活动发票模板在 OmniCRM-API/crm_config.yaml 中指定:

invoice:
template_filename: 'norfone_invoice_template.html'

可用模板变量

发票模板可以访问以下 Jinja2 变量:

发票信息:

  • {{ invoice_number }} - 唯一发票 ID(例如,INV-2025-001234
  • {{ date }} - 发票发行日期(ISO 格式:2025-01-10T12:00:00
  • {{ due_date }} - 付款到期日(例如,2025-02-10
  • {{ start_date }} - 计费期间开始日期
  • {{ end_date }} - 计费期间结束日期
  • {{ total_amount }} - 税前总发票金额(数值)
  • {{ total_tax }} - 从所有交易计算的总税额(数值)

客户信息:

  • {{ client.name }} - 客户的全名或公司名称
  • {{ client.address.address_line_1 }} - 地址行 1
  • {{ client.address.address_line_2 }} - 地址行 2
  • {{ client.address.city }} - 城市
  • {{ client.address.state }} - 州/省
  • {{ client.address.zip_code }} - 邮政编码
  • {{ client.address.country }} - 国家

交易行项目:

使用以下代码循环遍历交易:

{% for sub_transaction in transactions %}
<tr>
<td>{{ sub_transaction.transaction_id }}</td>
<td>{{ sub_transaction.created.split("T")[0] }}</td>
<td>{{ sub_transaction.title }}</td>
<td>{{ sub_transaction.description }}</td>
<td>${{ "%.2f"|format(sub_transaction.retail_cost) }}</td>
</tr>
{% endfor %}

交易字段:

  • sub_transaction.transaction_id - 交易 ID
  • sub_transaction.created - 交易日期/时间
  • sub_transaction.title - 交易标题
  • sub_transaction.description - 详细描述
  • sub_transaction.retail_cost - 行项目金额
  • sub_transaction.tax_percentage - 应用的税率(例如,10 表示 10%)
  • sub_transaction.tax_amount - 以美元计算的税额

在模板中显示税:

<td>
{% if sub_transaction.tax_amount and sub_transaction.tax_amount > 0 %}
${{ "%.2f"|format(sub_transaction.tax_amount) }} ({{ sub_transaction.tax_percentage }}%)
{% else %}
-
{% endif %}
</td>

创建自定义发票模板

步骤 1:复制现有模板

cd OmniCRM-API/invoice_templates/
cp norfone_invoice_template.html your_company_invoice_template.html

步骤 2:自定义 HTML/CSS

编辑 your_company_invoice_template.html 以匹配您的品牌:

关键自定义区域:

  1. 公司徽标和品牌

    <!-- 替换为您的徽标 URL -->
    <img src="https://yourcompany.com/logo.png" alt="您的公司" width="200">

    <!-- 更新公司名称 -->
    <h1>您的公司名称</h1>
  2. 配色方案

    <style>
    /* 主要品牌颜色 */
    .navbar {
    background: linear-gradient(to bottom right, #your-color-1, #your-color-2);
    }

    /* 表头 */
    .table thead th {
    background-color: #your-brand-color !important;
    color: white !important;
    }

    /* 按钮和链接 */
    .btn-primary {
    background-color: #your-brand-color;
    }
    </style>
  3. 公司信息页脚

    <footer>
    <p>您的公司名称</p>
    <p>123 商业街,城市,国家</p>
    <p>电话: +1-555-123-4567 | 邮箱: billing@yourcompany.com</p>
    <p>ABN/税号: 12345678900</p>
    </footer>
  4. 付款说明

    <div class="payment-info">
    <h3>付款方式</h3>
    <p><strong>在线:</strong> 在 https://yourcompany.com/pay 付款</p>
    <p><strong>银行转账:</strong></p>
    <ul>
    <li>账户名称:您的公司有限公司</li>
    <li>BSB:123-456</li>
    <li>账户号码:987654321</li>
    <li>参考:{{ invoice_number }}</li>
    </ul>
    </div>
  5. 条款和条件

    <div class="terms">
    <h4>付款条款</h4>
    <p>发票日期后 30 天内到期付款。</p>
    <p>逾期付款费用:逾期余额每月 2%。</p>
    <p>有关账单查询:billing@yourcompany.com</p>
    </div>

步骤 3:更新配置

编辑 OmniCRM-API/crm_config.yaml

invoice:
template_filename: 'your_company_invoice_template.html'

步骤 4:重启 API

cd OmniCRM-API
sudo systemctl restart omnicrm-api

步骤 5:测试发票生成

  1. 导航到有交易的客户
  2. 生成测试发票
  3. 下载 PDF 以验证格式
  4. 将发票通过电子邮件发送给自己以测试电子邮件发送

高级自定义

条件内容:

使用 Jinja2 条件显示/隐藏内容:

{% if total_amount > 1000 %}
<div class="high-value-notice">
<p><strong>注意:</strong> 大额余额 - 可根据请求提供付款计划。</p>
</div>
{% endif %}

{% if client.address.country == "Australia" %}
<p>包含 GST: ${{ "%.2f"|format(total_amount * 0.10) }}</p>
{% endif %}

多语言支持:

创建特定语言的模板:

invoice_template_en.html
invoice_template_es.html
invoice_template_fr.html

根据客户的语言偏好进行配置。

自定义计算:

<!-- 显示小计和税务明细 -->
<tr>
<td colspan="4" class="text-right"><strong>小计:</strong></td>
<td>${{ "%.2f"|format(total_amount) }}</td>
</tr>
<tr>
<td colspan="4" class="text-right"><strong>税:</strong></td>
<td>${{ "%.2f"|format(total_tax) }}</td>
</tr>
<tr>
<td colspan="4" class="text-right"><strong>总计:</strong></td>
<td>${{ "%.2f"|format(total_amount + total_tax) }}</td>
</tr>

注意: total_tax 变量是通过对发票中所有交易的 tax_amount 进行求和自动计算的。每个交易的税是根据其 tax_percentage 字段计算的,如果未指定,则默认为产品的 tax_percentage 或 0%。

付款的二维码:

生成用于移动支付的二维码:

<div class="qr-payment">
<img src="https://api.qrserver.com/v1/create-qr-code/?size=150x150&data={{ payment_url }}"
alt="扫描付款">
<p>用您的手机扫描以立即付款</p>
</div>

PDF 样式最佳实践

OmniCRM 使用 WeasyPrint 将 HTML 转换为 PDF。请遵循以下指南:

支持的 CSS:

  • 大多数 CSS 2.1 属性
  • 有限的 CSS3(flexbox,一些变换)
  • 通过 @font-face 使用网页字体

不支持:

  • JavaScript
  • CSS 网格(请使用表格)
  • 复杂动画
  • 一些现代 CSS 属性

页面大小和边距:

@page {
size: A4;
margin: 1cm;
}

body {
font-family: Arial, sans-serif;
font-size: 10pt;
}

打印特定样式:

@media print {
.no-print {
display: none;
}

.page-break {
page-break-after: always;
}
}

表格布局:

.table {
table-layout: fixed;
width: 100%;
}

.table th, .table td {
word-wrap: break-word;
padding: 4px;
}

字体嵌入:

对于自定义字体,使用网页安全字体或嵌入:

@font-face {
font-family: 'YourFont';
src: url('https://yourcompany.com/fonts/yourfont.woff2') format('woff2');
}

body {
font-family: 'YourFont', Arial, sans-serif;
}

测试发票模板

测试清单:

  1. 视觉检查:
    • 徽标正确显示
    • 颜色符合品牌指南
    • 文本可读(不太小)
    • 表格正确对齐
    • 所有部分均存在
  2. 数据准确性:
    • 客户详细信息正确
    • 交易金额正确相加
    • 日期格式正确
    • 所有变量正确替换
  3. PDF 质量:
    • 文件大小合理(<5MB)
    • 图像清晰锐利
    • 无文本截断或溢出
    • 页面在适当位置换行
  4. 多页发票:
    • 页眉在每页重复
    • 页码显示
    • 长交易列表正确分页
  5. 电子邮件发送:
    • PDF 附加到电子邮件
    • 文件大小低于 Mailjet 限制(15MB)
    • 在 Gmail、Outlook、Apple Mail 中呈现

测试命令(手动生成):

您可以通过 API 测试发票生成:

curl -X GET "http://localhost:5000/crm/invoice/{invoice_id}/pdf" \
-H "Authorization: Bearer YOUR_TOKEN" \
--output test_invoice.pdf

常见模板问题

变量未替换:

  • 原因: 变量名称拼写错误或缺少数据
  • 修复: 检查拼写是否完全正确(区分大小写),验证数据库中是否存在数据

PDF 样式破损:

  • 原因: 不支持的 CSS 属性
  • 修复: 使用 CSS 2.1 属性,测试 WeasyPrint 兼容的 CSS

图像未显示:

  • 原因: 相对 URL 或被阻止的外部资源
  • 修复: 使用绝对 HTTPS URL,确保图像公开可访问

表格溢出页面:

  • 原因: 固定列宽度过宽
  • 修复: 使用百分比宽度,table-layout: fixed

字体未呈现:

  • 原因: 字体未嵌入或不可用
  • 修复: 使用网页安全字体(Arial、Times New Roman 等)或正确嵌入自定义字体

PDF 生成失败:

  • 原因: HTML 语法错误或 WeasyPrint 崩溃
  • 修复: 验证 HTML,检查 WeasyPrint 日志,简化复杂布局

发票 PDF 缓存

为了提高性能并减少冗余的 PDF 生成,OmniCRM 包括一个发票 PDF 缓存系统。当首次生成发票 PDF 时,它会被缓存到数据库中以供后续请求使用。

PDF 缓存工作原理:

  1. 首次请求 - 当请求发票 PDF(下载或电子邮件)时,系统:
    • 从发票模板生成 PDF
    • 将 PDF 编码为 Base64
    • 计算 PDF 内容的 SHA256 哈希
    • 存储在 Invoice_PDF_Cache 表中,包含:
      • 发票 ID 引用
      • PDF 数据(Base64 编码)
      • 文件名
      • 内容哈希(用于完整性验证)
      • 创建时间戳
  2. 后续请求 - 当再次请求相同发票时:
    • 系统通过 invoice_id 检查缓存的 PDF
    • 如果缓存存在且有效,则立即返回缓存的 PDF
    • 更新 last_accessed 时间戳以跟踪缓存使用情况
  3. 缓存失效 - 当以下情况发生时,缓存的 PDF 会失效:
    • 发票被修改(添加/删除交���,详情更改)
    • 发票模板被更新
    • 手动触发缓存清除

好处:

  • 性能 - 对于重复请求,立即提供 PDF(无再生延迟)
  • 一致性 - 所有下载的发票都为相同 PDF(除非发票被修改)
  • 服务器负载 - 减少 PDF 生成的 CPU 使用
  • 用户体验 - 在初始生成期间出现加载指示器,后续请求立即响应

缓存管理:

发票 PDF 缓存由系统自动管理。可以根据以下条件定期清除旧的或未使用的缓存条目:

  • 年龄(例如,删除超过 90 天的缓存条目)
  • 访问模式(删除 30 天未访问的条目)
  • 存储限制(如有需要,实施缓存大小限制)

API 行为:

通过 API 或 UI 下载发票时:

  • 首次请求:在生成 PDF 时显示加载指示器,然后缓存
  • 后续请求:从缓存中立即下载
  • 缓存命中/未命中对用户是透明的

重要: 当您更新发票模板时,请清除缓存以确保新发票使用更新的设计:

-- 清除所有缓存的发票 PDF(在 MySQL 中运行)
DELETE FROM Invoice_PDF_Cache;

或更新 crm_config.yaml 以在模板更改时自动使缓存失效。

访问发票

可以在系统级别或按客户查看发票:

按客户查看:

  1. 导航到 客户 → [选择客户]
  2. 点击 账单 标签
  3. 在第三个卡片中查看发票列表

系统范围查看:

  1. 导航到 账单 → 发票(从主菜单)
  2. 查看所有客户的所有发票

发票统计小部件

在发票页面顶部,四个统计卡片显示财务摘要。

发票统计和列表{.align-center width="800px"}

小部件描述:

  • 总发票 - 所有发票零售成本的总和(所有时间)和发送的发票数量
  • 未付款发票 - 尚未支付的发票总和和未付款发票数量
  • 本月发票 - 本日历月创建的发票总和及数量
  • 上月发票 - 上日历月创建的发票总和及数量

值格式化:

  • 超过 1,000 的值:显示为 "k" 后缀(例如,$1.5k)
  • 超过 1,000,000 的值:显示为 "M" 后缀(例如,$2.3M)
  • 超过 1,000,000,000 的值:显示为 "B" 后缀(例如,$1.1B)

趋势指标:

  • "本月" 和 "上月" 的小部件显示百分比变化
  • 绿色向上箭头:与上一个周期相比增加
  • 红色向下箭头:与上一个周期相比减少
  • 灰色向右箭头:无变化

发票列表

发票表显示所有发票,包含以下列:

全球发票列表

列描述:

  • ID - 唯一发票 ID
  • 标题 - 发票标题/描述
  • 期间 - 计费期间(开始日期 - 结束日期)或 "N/A" 对于一次性发票
  • 到期日 - 付款到期日
  • 创建 - 发票创建日期
  • 金额 - 总发票金额(零售成本)
  • 状态 - 已付款、未付款或已退款
  • 操作 - 可用操作(根据状态有所不同)

操作图标:

  • ⬇ (下载) - 下载发票 PDF
  • 🗑️ (删除) - 作废发票(仅在未付款时)
  • 💰 (付款) - 在线支付发票(仅在未付款时)
  • ✉️ (电子邮件) - 将发票电子邮件发送给客户
  • 💸 (退款) - 退款 Stripe 付款(仅适用于已付款的 Stripe 发票)

生成发票

点击 "+ 生成形式发票" 创建新发票。

生成发票模态框与交易预览{.align-center width="800px"}

字段描述:

  • 搜索客户 - 选择客户(仅在系统范围视图中显示,在客户视图中预填)
  • 标题 - 发票标题/名称(可选,默认为 "发票 [期间]")
  • 开始日期 - 计费期间开始(默认为 14 天前)
  • 结束日期 - 计费期间结束(默认为今天)
  • 到期日期 - 付款截止日期(默认为今天)
  • 交易预览 - 显示日期范围内所有未开票交易,并能够包括/排除特定交易

交易选择:

  • ✓ (绿色加号) - 点击以从发票中排除交易
  • × (红色 X) - 点击以包括先前排除的交易
  • 全选 - 包括所有显示的交易
  • 清除所有 - 排除所有交易
  • 被排除的交易以灰色显示并带有删除线文本
  • 实时总计在选择/取消选择交易时更新

发生的事情:

  1. 系统查找客户在日期范围内的所有未开票交易
  2. 显示交易预览,能够包括/排除单个交易
  3. 根据所选交易显示小计、税和总计的实时计算
  4. 仅选定(包括)的交易被添加到发票中
  5. 生成发票 PDF 并缓存
  6. 将选定交易标记为已开票(invoice_id 字段填充)
  7. 被排除的交易保持未开票状态,并可用于将来的发票
  8. 发票在列表中显示为 "未付款" 状态

示例用例:

每月计费: 将开始日期设置为月初,结束日期设置为月末,预览显示该期间所有未开票交易。选择所有或手动排除特定交易。

服务特定发票: 使用相同的日期范围,然后手动排除不需要的交易(例如,排除非移动交易以创建仅移动的发票)。

一次性发票: 将开始和结束日期设置为同一天,预览仅显示该日期的交易。排除任何与此特定发票无关的费用。

查看发票详情

点击表中任何发票行以查看完整的发票详情,包括所有交易、总计和可用操作。

发票详情视图{.align-center width="800px"}

发票详情模态框:

  • 发票信息 - 显示发票 ID、标题、日期、付款状态和作废状态
  • 交易列表 - 显示发票中包含的所有交易,包含:
    • 交易日期
    • 标题和描述
    • 零售成本
    • 税额和百分比(格式为 $10.00 (10%)
    • 免税交易在税列中显示 "-"
  • 总计摘要 - 实时计算显示:
    • 交易数量
    • 小计(所有零售成本的总��)
    • 税(所有税额的总和)
    • 发票总计(小计 + 税)
  • 操作按钮 - 与表中相同的可用操作:
    • 下载 PDF - 下载发票 PDF(始终可用)
    • 发送电子邮件 - 将发票通过电子邮件发送给客户(未作废的发票)
    • 支付发票 - 处理付款(仅未付款、未作废的发票)
    • 退款 - 退款 Stripe 付款(仅适用于已付款的 Stripe 发票)
    • 删除 - 作废发票(仅适用于未付款、未作废的发票)

下载发票 PDF

点击表中的 下载图标 (⬇) 或发票详情模态框中的 "下载 PDF" 按钮以下载发票为 PDF。

下载过程:

  1. 点击发票旁边的下载图标
  2. 生成期间出现加载旋转器(仅首次)
  3. 浏览器提示保存文件:Invoice_01234.pdf
  4. PDF 打开或保存到下载文件夹

PDF 缓存行为:

  • 首次下载 - 从模板生成 PDF,缓存到数据库(可能需要 2-3 秒)
  • 后续下载 - 从缓存中立即下载
  • 缓存失效 - 如果发票被修改或模板更新,则缓存清除

下载问题排查:

  • 旋转器永远不停止 - 检查浏览器控制台,API 可能已关闭
  • PDF 空白或损坏 - 检查发票模板是否有语法错误
  • 下载���败 - 检查弹出窗口阻止程序设置,尝试不同的浏览器

支付发票

点击 支付图标 (💰) 在线支付发票。

支付发票模态框{.align-center width="800px"}

支付过程:

  1. 点击未付款发票上的支付图标
  2. 支付模态框打开,显示发票详情
  3. 选择支付方式:
    • Stripe 交易 - 收取保存的信用卡(所有用户可用)
    • 现金 - 手动现金支付(仅限员工)
    • 退款 - 将退款作为支付(仅限员工)
    • POS 交易 - 销售终端(仅限员工)
    • 银行转账 - 手动银行转账(仅限员工)
  4. 如果选择了 Stripe:
    • 从保存的支付方式中选择卡
    • 默认卡预选
    • 点击选择不同的卡
  5. 如果选择了其他方法:
    • 输入参考号码(可选)
  6. 点击 "支付发票" 进行处理
  7. 系统处理付款:
    • Stripe - 通过 Stripe API 收取卡费
    • 其他方法 - 为支付金额创建负交易
  8. 发票状态更改为 "已付款"
  9. 显示成功通知

自助服务与员工支付:

:doc:`自助服务门户 <self_care_portal>`(客户):

  • 仅提供 Stripe 支付
  • 必须有保存的支付方式
  • 如果没有支付方式,将显示警告
  • 提供添加支付方式的链接

员工门户(管理员):

  • 提供所有支付方式
  • 可以手动标记发票为已付款(现金、POS、银行转账)
  • 可以输入参考号码以便跟踪

支付方式警告:

如果客户没有保存的支付方式,将显示警告提示他们在支付发票之前添加支付方式。

缺少支付方式警告{.align-center width="800px"}

发送发票电子邮件

点击 电子邮件图标 (✉️) 将发票发送给客户。

发生的事情:

  1. 点击发票旁边的电子邮件图标
  2. 系统从缓存中检索发票 PDF(如果未缓存则生成)
  3. 通过 Mailjet 使用 api_crmCommunicationCustomerInvoice 模板发送电子邮件
  4. 电子邮件包括:
    • 附件中的发票 PDF
    • 客户姓名
    • 发票编号和到期日
    • 应付总额
    • 在线支付发票的链接
    • 查看/下载发票的链接
  5. 成功通知:"发票电子邮件成功发送"

电子邮件收件人:

电子邮件发送给所有类型为 "billing" 的客户联系人,或如果没有账单联系人,则发送给主要联系人。

电子邮件模板变量:

  • {{ var:customer_name }} - 客户的全名
  • {{ var:invoice_number }} - 发票 ID
  • {{ var:invoice_date }} - 发票发行日期
  • {{ var:due_date }} - 付款到期日
  • {{ var:total_amount }} - 应付总额
  • {{ var:invoice_url }} - 查看/下载 PDF 的链接
  • {{ var:pay_url }} - 在线支付发票的链接

电子邮件问题排查:

  • 电子邮件未发送 - 检查 crm_config.yaml 中的 Mailjet API 凭证
  • 客户未收到 - 验证客户联系电子邮件地址
  • PDF 未附加 - 检查 PDF 生成是否成功(先尝试下载)

作废发票

点击 删除图标 (🗑️) 作废发票。

要求:

  • 发票必须是 未付款
  • 已付款发票不能作废(必须退款)

如何作废:

  1. 在列表中找到未付款发票
  2. 点击删除图标 (🗑️)
  3. 在模态框中确认:

作废发票确认模态框{.align-center width="600px"}

发生的事情:

  • 发票标记为 void = true
  • 所有交易与发票解除链接(invoice_id 设置为 null)
  • 交易再次变为 "未开票"
  • 交易可以包含在新发票中
  • 发票在列表中显示为标题前带有 "Void:" 前缀
  • 发票操作被禁用(无法下载、付款或发送电子邮件)
  • 可以通过筛选 "Void" 发票进行查看

重要说明:

  • 作废与退款不同
  • 作废 = "该发票不应存在"(账单错误,重复)
  • 退款 = "撤销有效的已付款发票"(将钱退还给客户)

退款发票

点击 退款图标 (💸) 退款已付款发票。

要求:

  • 发票必须是 已付款
  • 发票必须通过 Stripe 付款
  • 发票必须有有效的 payment_reference(Stripe 付款意图 ID)
  • 仅限员工用户可用(不适用于自助服务)

如何退款:

  1. 找到已付款的 Stripe 发票
  2. 点击退款图标 (💸)
  3. 退款确认模态框打开:

退款发票确认模态框{.align-center width="800px"}

  1. 点击 "确认退款"
  2. 系统处理 Stripe 退款:
    • 调用 Stripe API 退款支付
    • 在 Stripe 中创建退款交易
    • 更新发票以包含 refund_reference
  3. 发票状态更改为 "已退款"
  4. 显示成功通知

退款后的事情:

  • 发票仍然存在于系统中(未作废)
  • 状态显示为 "已退款"
  • 交易仍然与发票关联
  • 客户收到退款至原支付方式(3-7 个工作日)
  • Stripe 仪表板显示退款交易

退款限制:

  • 不能退款通过现金、POS 或银行转账支付的发票(需要手动撤销)
  • 不能部分退款(仅限全额发票金额)
  • 不能退款两次

搜索和筛选发票

搜索

使用搜索栏查找发票。搜索范围包括:

  • 发票 ID
  • 发票标题
  • 客户姓名(仅限系统范围视图)

筛选

应用筛选以缩小发票列表:

可用筛选:

  • 作废状态 - 全部、作废、未作废
  • 付款状态 - 全部、已付款、尚未付款

筛选操作:

  • 应用筛选 - 将所选筛选应用于列表
  • 重置筛选 - 清除所有筛选并显示所有发票

排序

点击任何列标题进行排序:

  • ID - 按发票 ID 排序(最新/最旧)
  • 标题 - 按字母顺序排序
  • 到期日 - 按到期日排序
  • 创建 - 按创建日期排序
  • 金额 - 按零售成本排序(最高/最低)
  • 状态 - 按付款状态排序(已付款优先或未付款优先)

再次点击以反转排序方向(升序 ↔ 降序)。

分页

通过页面控件在大型发票列表中导航,显示当前页面、总页面和每页项目选择器(10、25、50 或 100 项)。

常见发票工作流程

工作流程 1:带交易预览的��月计费

  1. 月末到来(例如,1 月 31 日)
  2. 导航到 账单 → 发票
  3. 点击 "+ 生成形式发票"
  4. 选择客户(或如果计费多个客户则按客户操作)
  5. 设置日期:
    • 开始日期:2025-01-01
    • 结束日期:2025-01-31
    • 到期日期:2025-02-15(从现在起 15 天)
    • 标题:"2025 年 1 月服务"(可选)
  6. 交易预览 部分显示 1 月的所有未开票交易
  7. 审查预览:
    • 默认包含所有交易
    • 检查总计:小计、税和发票总计
    • 验证所有费用是否正确
  8. 点击 "生成发票"(按钮显示交易数量,例如,"生成发票 (15)")
  9. 发票创建,包含所有选定交易
  10. 点击发票行查看详情并验证
  11. 点击详情模态框中的 "发送电子邮件" 按钮或表中的电子邮件图标
  12. 客户收到带有 PDF 和支付链接的发票电子邮件

工作流程 2:选择性交易开票

  1. 客户有多项服务(移动 + 互联网)和杂项费用
  2. 希望为每项服务开具单独的发票
  3. 生成第一张发票(移动服务):
    • 点击 "+ 生成形式发票"
    • 标题:"移动服务 - 2025 年 1 月"
    • 开始/结束:1 月 1 日至 31 日
    • 到期日期:2 月 15 日
    • 在交易预览中,排除所有非移动交易:
      • 点击互联网交易旁的 X 按钮
      • 点击杂项费用旁的 X 按钮
      • 仅移动服务交易保持选中
    • 验证总计仅反映移动服务
    • 点击 "生成发票"(显示移动交易的数量)
  4. 生成第二张发票(互联网服务):
    • 再次点击 "+ 生成形式发票"
    • 标题:"互联网服务 - 2025 年 1 月"
    • 开始/结束:1 月 1 日至 31 日(相同期间)
    • 在交易预览中:
      • 移动交易已开票(不显示)
      • 使用 X 按钮排除杂项费用
      • 仅互联网服务交易保持
    • 点击 "生成发票"
  5. 生成第三张发票(附加费用):
    • 再次点击 "+ 生成形式发票"
    • 标题:"附加费用 - 2025 年 1 月"
    • 预览中仅显示未开票的杂项费用
    • 点击 "全选" 包括所有
    • 点击 "生成发票"
  6. 将所有三张发票发送给客户

工作流程 3:排除争议或待处理交易

  1. 计费期间结束
  2. 导航到客户 账单 标签
  3. 点击 "+ 生成形式发票"
  4. 设置��费期间日期
  5. 交易预览显示 20 个交易
  6. 客户对一项费用提出争议,另一项正在调查中
  7. 在交易预览中:
    • 找到争议交易(例如,"数据超额费用")
    • 点击 X 按钮将其排除
    • 找到待处理交易(例如,"安装费用")
    • 点击 X 按钮将其排除
    • 交易数量更新:"选择了 18 个交易"
    • 总计自动重新计算
  8. 审查更新后的总计(排除争议金额)
  9. 点击 "生成发票 (18)"
  10. 发票仅生成已批准的交易
  11. 争议/待处理交易保持未开票状态,待下一个计费周期

工作流程 4:快速发票审查和调整

  1. 员工生成每月发票
  2. 交易预览显示意外的高总计
  3. 审查预览中的每个交易:
    • 注意到同一服务的重复收费
    • 点击 X 排除重复费用
    • 注意到不应计费的测试交易
    • 点击 X 排除测试交易
  4. 总计实时更新
  5. 验证新总计与预期金额匹配
  6. 点击 "生成发票" 以更正交易
  7. 如果需要,返回并作废/删除排除的交易
  8. 将发票自信地发送给客户

工作流程 5:一次性安装发票

  1. 现场技术人员完成安装
  2. 员工手动添加安装交易
  3. 导航到客��� 账单 标签
  4. 点击 "+ 生成形式发票"
  5. 设置日期:
    • 开始日期:今天
    • 结束日期:今天
    • 到期日期:今天 + 7 天
    • 标题:"安装服务"
  6. 交易预览仅显示今天的交易
  7. 验证安装费用是否出现
  8. 使用 X 按钮排除任何重复费用(如果存在)
  9. 点击 "生成发票"
  10. 立即发送给客户
  11. 客户通过 Stripe 在线付款

工作流程 6:在客户联系之前查看发票

  1. 客户打电话询问账单问题
  2. 员工导航到客户的发票列表
  3. 点击发票行 打开发票详情模态框
  4. 审查发票信息:
    • 发票 ID、日期、状态
    • 包含的所有交易及描述
    • 每个交易的税务明细
    • 小计、税和总金额
  5. 用确切的细节回答客户的问题
  6. 如果客户请求 PDF,点击模态框中的 "下载 PDF" 按钮
  7. 如果客户请求重新发送电子邮件,点击 "发送电子邮件" 按钮
  8. 完成后关闭模态框

工作流程 7:更正账单错误

  1. 客户报告错误收费
  2. 员工点击发票行查看详情
  3. 在发票详情模态框中审查交易列表
  4. 确定错误交易
  5. 发票未付款,因此可以作废
  6. 点击模态框底部的 "删除" 按钮
  7. 确认作废
  8. 交易再次变为未开票
  9. 员工修改或删除交易列表中的错误交易
  10. 生成新发票,包含更正后的交易:
    • 如果需要,使用交易预览排除更正后的交易
    • 仅包括有效费用
  11. 将更正后的发票发送给客户

工作流程 8:处理多笔付款

  1. 客户带现金支付多张发票
  2. 导航到客户 账单 标签
  3. 查看未付款发票
  4. 点击第一张发票行查看详情
  5. 验证金额和交易
  6. 点击模态框底部的 "支付发票" 按钮
  7. 选择 "现金" 支付方式
  8. 输入参考:"现金支付 2025-01-15"
  9. 点击 "支付发票"
  10. 模态框关闭,发票标记为 "已付款"
  11. 对剩余发票重复此操作
  12. 所有发票现在标记为 "已付款"

工作流程 9:处理退款请求

  1. 客户请求退款以补偿多付
  2. 员工验证发票已通过 Stripe 付款
  3. 导航到发票列表
  4. 点击发票行查看详情
  5. 验证付款信息和金额
  6. 点击模态框底部的 "退款" 按钮(仅适用于 Stripe 发票)
  7. 确认退款
  8. 系统处理 Stripe 退款
  9. 发票状态更改为 "已退款"
  10. 客户在 3-7 个工作日内收到退款
  11. 员工跟进客户以确认收到

故障排除

无法生成发票 - 找不到交易

  • 原因: 指定日期范围内没有未开票交易
  • 修复: 检查交易列表,验证交易是否存在且未开票。调整日期范围或移除筛选。

发票 PDF 生成失败

  • 原因: 模板语法错误、WeasyPrint 崩溃或缺少客户数据
  • 修复: 检查发票模板 HTML 是否有错误,验证客户地址字段是否填充,查看 API 日志。

支付失败,出现 Stripe 错误

  • 原因: 卡被拒绝、资金不足、卡过期或 Stripe API 问题
  • 修复: 尝试不同的支付方式,验证卡是否有效,检查 Stripe 仪表板以获取拒绝原因。

无法作废发票

  • 原因: 发票已付款
  • 修复: 已付款发票无法作废。如果需要退款,请使用 Stripe 发票的退款功能或手动创建信用交易。

发票电子邮件未发送

  • 原因: Mailjet API 凭证无效、客户没有账单联系人或电子邮件模板缺失
  • 修复: 验证 crm_config.yaml 中的 Mailjet 配置,检查客户联系人,验证发票电子邮件模板是否存在。

退款按钮未出现

  • 原因: 发票通过现金/POS/银行转账支付(非 Stripe),或发票未付款
  • 修复: 退款按钮仅适用于 Stripe 付款。对于其他支付方式,请创建手动信用交易。

下载 PDF 显示旧模板设计

  • 原因: PDF 在模板更新之前缓存
  • 修复: 清除发票 PDF 缓存: DELETE FROM Invoice_PDF_Cache WHERE invoice_id = X;

客户无法支付发票(没有支付方式)

  • 原因: 自助服务门户中没有保存的支付方式
  • 修复: 客户必须在 支付方式 页面添加信用卡,然后才能支付发票。

为同一期间生成多张发票

  • 原因: 员工重复生成发票,或日期范围重叠
  • 修复: 作废重复发票。调整日期范围以防止重叠。使用交易预览确保唯一的交易集。

交易预览不显示交易

  • 原因: 日期范围内的所有交易已开票或没有交易
  • 修复: 验证日期范围是否正确。检查交易列表以确认交易是否存在。筛选发票以查看哪个发票包含交易。

无法从发票生成中排除交易

  • 原因: 交易已开票或浏览器问题
  • 修复: 验证交易在预览中显示并带有勾选标记。刷新页面并重试。如果问题仍然存在,请清除浏览器缓存。

发票总计与预期金额不匹配

  • 原因: 包含了意外交易、税未计算或排除的交易仍被计入
  • 修复: 仔细审查交易预览。检查每个交易的零售成本和税。验证排除的交易是否显示为灰色。检查生成发票按钮上的交易计数徽章。

生成发票按钮被禁用

  • 原因: 没有选择交易或日期范围无效
  • 修复: 确保至少包含一笔交易(未排除)。验证开始日期在结束日期之前。检查到期日期是否设置。

发票详情模态框未打开

  • 原因: JavaScript 错误或页面未完全加载
  • 修复: 刷新页面。检查浏览器控制台是否有错误。尝试不同的浏览器。验证互联网连接。

交易税未在发票详情中显示

  • 原因: 交易的税率为 0% 或 tax_amount 为 null
  • 修复: 验证交易是否设置了 tax_percentage。检查创建交易时是否计算了 tax_amount。如有需要,更新交易。

发票详情模态框中缺少操作按钮

  • 原因: 发票已作废或用户缺乏权限
  • 修复: 作废的发票仅显示下载 PDF 按钮。验证发票状态。检查用户角色和权限。

相关文档

  • integrations_mailjet - 电子邮件发票交付和模板
  • administration_configuration - 发票模板配置
  • payments_transaction - 创建出现在发票上的交易
  • payments_process - 处理发票付款
  • basics_payment - 付款方式和 Stripe 集成