qmj před 2 měsíci
rodič
revize
4f54d5fa48

+ 2 - 1
.claude/settings.local.json

@@ -25,7 +25,8 @@
       "Bash(grep -E \"\\\\.\\(json|js|ts|jsx|tsx|sql|py|java|go\\)$\")",
       "Bash(powershell -ExecutionPolicy Bypass -File \".specify/scripts/powershell/check-prerequisites.ps1\" -Json)",
       "Bash(powershell -ExecutionPolicy Bypass -File \".specify/scripts/powershell/check-prerequisites.ps1\" -Json -RequireTasks -IncludeTasks)",
-      "Bash(mvn compile *)"
+      "Bash(mvn compile *)",
+      "mcp__zread__get_repo_structure"
     ]
   }
 }

+ 140 - 0
docs/taiwan-einvoice-plan.md

@@ -0,0 +1,140 @@
+# 台湾外卖平台 — 电子发票实施方案
+
+## 一、哪些商家需要开票,哪些不需要?
+
+| 场景 | 是否需要开票 | 说明 |
+|------|------------|------|
+| 月营业额 ≥ 20万 NT$ 的商家 | 需要开统一发票 | 一般餐饮店、连锁品牌 |
+| 月营业额 < 20万 NT$ 的小规模商家 | **免用发票** | 向国税局申请后,只开收据即可 |
+| 夜市摊位、小吃摊 | **大概率免用** | 大部分属于小规模商家 |
+| 消费者要求开票 | 免用商家也只需开收据 | 收据不经过财政部系统 |
+
+**结论:系统需要在店铺级别设置"免用发票"开关。** 免用商家订单完成后只生成收据,不触发开票流程。
+
+---
+
+## 二、需要开票时,怎么做?— 三种方式
+
+### 方式 A:加值中心 API(推荐)
+
+```
+你的系统 → 调用加值中心API → 加值中心处理 → 上传财政部 → 返回发票数据
+```
+
+| 项目 | 说明 |
+|------|------|
+| 接入方式 | REST API,POST 请求即可 |
+| 开发周期 | 1~2 周 |
+| 每张成本 | 0.5~2 元新台币 |
+| 维护成本 | 低,加值中心负责财政部对接 |
+| 代表服务商 | UBC、ezreceipt、GateWeb、中华电信 |
+
+### 方式 B:自建 Turnkey(不推荐)
+
+```
+你的系统 → 按MIG规范拼XML → 放入Turnkey目录 → Turnkey上传财政部 → 解析返回结果
+```
+
+| 项目 | 说明 |
+|------|------|
+| 接入方式 | 部署财政部免费软件 + 工商憑證 + MIG XML 格式 |
+| 开发周期 | 2~3 个月 |
+| 每张成本 | 免费(软件本身) |
+| 维护成本 | 高,需要专人负责 |
+
+### 方式 C:免用发票(部分商家)
+
+- 不需要对接任何发票系统
+- 订单完成后只生成普通收据
+
+---
+
+## 三、为什么不推荐自建 Turnkey?
+
+### 3.1 技术风险
+
+| 风险项 | 说明 |
+|--------|------|
+| 规范频繁变更 | 财政部定期更新电子发票规范(2025年已升级到Turnkey 3.2),每次变更需要重新适配 |
+| 憑證管理复杂 | 工商憑證需要申请、续签、管理,过期或丢失会导致开票中断 |
+| 上线检测门槛 | 需要通过财政部上线检测、取得通行码,流程不可控 |
+| 故障影响大 | 发票开不了 = 商家无法报税 = 平台被投诉 = 可能被财政部处罚 |
+
+### 3.2 隐性成本
+
+| 成本项 | 说明 |
+|--------|------|
+| 人力 | 需要专人维护 Turnkey 服务器、跟踪规范变更、处理憑證 |
+| 运维 | 7×24 监控,发票上传失败要能自动重试 |
+| 合规 | 定期与财政部做上线检测、审计 |
+| 机会成本 | 团队精力放在发票基础设施上,而不是业务功能开发 |
+
+### 3.3 台湾主流外卖平台也不用 Turnkey
+
+| 平台 | 使用的加值中心 |
+|------|--------------|
+| Uber Eats | 关网资讯 GateWeb |
+| Foodpanda | UBC 或中华电信 |
+| 虾皮购物(电商) | e首发票 |
+
+**台湾最大的外卖平台 Foodpanda 和 Uber Eats 都选择加值中心而非自建 Turnkey。** 它们的技术团队规模远大于我们,仍然选择外包发票基础设施,原因是:
+
+1. **发票不是核心业务** — 外卖平台的核心竞争力是配送和商家运营,不是财税基础设施
+2. **规模经济** — 加值中心服务成百上千家平台,分摊了合规和运维成本
+3. **风险转移** — 发票系统出问题由加值中心承担责任,平台不需要自己扛
+4. **快速上线** — API 串接 1~2 周搞定,自建 Turnkey 至少 2~3 个月
+
+---
+
+## 四、推荐方案
+
+### 加值中心 API + 免用发票开关
+
+```
+订单完成
+  ↓
+判断店铺是否"免用发票"?
+  ├── 是 → 生成普通收据,结束
+  └── 否 → 调用加值中心 API 开立电子发票
+              ↓
+         返回发票号 + QR Code + PDF
+              ↓
+         保存副本到平台数据库
+              ↓
+         通知消费者(App/Email)
+```
+
+### 推荐加值中心
+
+| 优先级 | 服务商 | 理由 |
+|--------|--------|------|
+| 首选 | UBC(统一电子发票加值中心) | 餐饮覆盖率高,Foodpanda 在用,0.8~1.5元/张 |
+| 备选 | ezreceipt 易发票 | 可免费测试,按量计费灵活 |
+| 大平台级 | GateWeb 关网资讯 | Uber Eats 在用,服务更完善但成本较高 |
+
+### 系统改造点
+
+1. **店铺表(pos_store)** 增加 `invoice_exempt` 字段(是否免用发票)
+2. **订单完成流程** 增加发票/收据判断分支
+3. **新增发票服务模块** 封装加值中心 API 调用
+4. **消费者端** 展示发票 QR Code + 发票详情
+
+---
+
+## 五、费用预估
+
+假设日均 1000 笔需开票订单(扣除免用商家后):
+
+| 项目 | 月费用(NT$) |
+|------|-------------|
+| 加值中心 API 费用(1元/张) | ~30,000 |
+| 开发接入成本(一次性) | 内部消化 |
+| 月度维护 | 接近零 |
+
+对比自建 Turnkey:
+| 项目 | 月费用(NT$) |
+|------|-------------|
+| 软件费用 | 0 |
+| 专人维护人力(1人) | ~60,000~80,000 |
+| 服务器 + 憑證管理 | ~5,000 |
+| **风险成本**(出问题一次) | 不可估量 |

+ 10 - 8
ruoyi-admin/src/main/java/com/ruoyi/app/tableqrcode/TableQrcodeController.java

@@ -12,7 +12,6 @@ import com.ruoyi.system.service.ITableQrcodeService;
 import com.ruoyi.system.utils.Auth;
 import com.ruoyi.system.utils.JwtUtil;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
@@ -35,8 +34,6 @@ public class TableQrcodeController extends BaseController
     @Autowired
     private IPosStoreService posStoreService;
 
-    @Value("${table-qrcode.base-url:}")
-    private String baseUrl;
 
     /**
      * 创建餐桌码
@@ -433,16 +430,21 @@ public class TableQrcodeController extends BaseController
 
     /**
      * 构建二维码URL
+     * 摊位码(type=0): id=摊位storeId
+     * 公用码(type=1): id=夜市nightMarketId
      */
     private String buildQrcodeUrl(TableQrcode tableQrcode)
     {
-        String url = baseUrl;
-        if (url == null || url.isEmpty())
+        String id;
+        if (tableQrcode.getType() == 0)
+        {
+            id = String.valueOf(tableQrcode.getStoreId());
+        }
+        else
         {
-            url = "https://your-domain.com";
+            id = String.valueOf(tableQrcode.getNightMarketId());
         }
-        url = url.endsWith("/") ? url.substring(0, url.length() - 1) : url;
-        return url + "/table-qrcode/scan?tableId=" + tableQrcode.getId();
+        return "chachaeatapp://scan?id=" + id + "&type=" + tableQrcode.getType() + "&tableId=" + tableQrcode.getId();
     }
 
     /**