# 意大利 EPR 数据处理器

持久化运行的 Laravel 命令行应用，自动处理意大利 EPR（Extended Producer Responsibility）业务记录：从 SQL Server 源数据库轮询待处理记录 → 数据转换 → 翻译 → 生成 Word 文档 → 上传腾讯云 COS → 保存结果到目标数据库。

同时提供 **HTTP API 接入模式**：对接系统通过 `POST /api/epr/italy` 提交数据（不依赖 source 库），处理结果（成功/失败）通过异步结果回调接口通知。详见 [API 对接文档](docs/api.md)。

## 技术栈

- PHP 8.3 + Laravel 11
- SQL Server（source / target 双库）
- DeepL API（国家名英→意翻译，带缓存）
- 腾讯云 COS SDK（对象存储）
- WordTemplateProcessor（Word 模板填充）
- Windows 环境 + PowerShell + NSSM 服务

## 快速开始

```bash
# 1. 安装依赖
composer install

# 2. 配置环境变量（复制并填写）
cp .env.example .env
php artisan key:generate

# 3. 确保 Word 模板存在
# 将 Certificate_of_Use_Template.docx 放到 storage/ 目录

# 4. 启动处理器
php artisan epr:process-italy
```

## 配置说明

| 环境变量 | 说明 |
|----------|------|
| `SOURCE_DB_*` | 源 SQL Server 连接（读取待处理记录） |
| `TARGET_DB_*` | 目标 SQL Server 连接（写入处理结果） |
| `DEEPL_API_KEY` | DeepL API 密钥 |
| `TENCENT_COS_*` | 腾讯云 COS 凭证与 Bucket |
| `EPR_POLL_INTERVAL` | 轮询间隔秒数（默认 8） |
| `EPR_WORD_TEMPLATE_PATH` | Word 模板文件名 |
| `EPR_API_TOKEN` | API 受理接口 Bearer 鉴权 token |
| `EPR_RESULT_CALLBACK_URL` | 异步结果回调地址；受理时写入行内**供 RPA 读取**（受理路径自身不发回调） |
| `EPR_RESULT_CALLBACK_MAX_RETRIES` / `_RETRY_DELAY` | 回调发送失败重试（默认 3 次 / 间隔 5 秒） |
| `EPR_API_COS_BUCKET` | API 行 COS 桶（留空=与 `TENCENT_COS_BUCKET` 同桶） |
| `EPR_API_OSS_PREFIX` | API 行 COS 相对路径前缀（须与 RPA 常量一致） |
| `EPR_API_POLL_INTERVAL` | API 兜底处理器轮询间隔（默认 8） |
| `EPR_API_DESC_MAX_RETRIES` | API 说明书阶段最大重试（默认 3，仅兜底路径） |

完整配置项见 `.env.example`。

## API 接入模式

```
POST /api/epr/italy（Bearer 鉴权；受理请求内同步生成「EPR 注册文件」）
  → INSERT italia_epr_file（data_source='api'，desc_status=1 处理中）
  → 受理内同步生成 EPR 注册文件（desc_status 1→2 成功 / 3 失败 + 信封 code=500（HTTP 恒 200）,失败不发回调,另有企业微信）
  → RPA 授权书阶段（auth_status 0→1→2/3），授权书上传 {前缀}{年}/epr_italia/{流水号}/
  → RPA 生成完成后调 EPR_RESULT_CALLBACK_URL：data.files 下发两份文件
    （EPR注册文件 + 授权书，url 为 OSS 相对路径）；失败时 data=null、原因放 msg
```

说明：EPR 注册文件在受理请求内同步生成，`epr:process-api` 仅保留为兜底（回收历史遗留/陈旧行）；授权书由 RPA 程序读取数据生成后回写并发送成功回调。API 流程与 source 流程共用同一处理管线，差异只在数据来源（HTTP 受理 vs 源库轮询）与结果通道（异步回调 vs 源库状态）。

- 接口契约、字段清单、回调信封：[docs/api.md](docs/api.md)
- 样例：`docs/api/italy_epr_request.json`、`docs/api/italy_epr_callback_success.json`、`docs/api/italy_epr_callback_failure.json`
- 上线前先在 target 库执行 `database/italia_epr_file_api_columns.sql`
- API 模式全程不依赖 source 库（不读附件表、不更新 EPRRegInfo）

## 处理流程

```
轮询 source DB（PushTaxBureauStatus=5, Country='IT'）
  → 读取 TOP 1 记录
  → 数据转换（电话格式化、姓名拆分、日期拆分）
  → DeepL 翻译国家名（带文件缓存）
  → 生成 Word 文档（替换 {{占位符}}）
  → 上传腾讯云 COS（路径: epr/italy/desc/{年}/{月}/）
  → 写入 target DB（italia_epr_file 表）
  → 失败时更新 source 状态 = -1（成功状态由 RPA 授权书阶段完成后回写 = 6/7）
  → 8 秒后继续轮询
```

## 日志

- 专用通道：`epr`
- 文件：`storage/logs/epr-processor.log`
- 每日轮转，保留 30 天

## Windows 服务部署

```bash
# 前台运行
php artisan epr:process-italy

# NSSM 服务方式（源流程：安装 ItalyEPRFileProcess）
install-service.bat
```

API 接入模式额外两个服务（无安装脚本，需手动 NSSM 注册或按 runbook）：

```bash
# API 兜底任务处理器 + API 受理 HTTP 监听（php artisan serve --port=8010）
nssm install ItalyEprApiProcessor "path\to\php.exe"   # AppParameters: "artisan epr:process-api"
nssm install ItalyEprApiServer    "path\to\php.exe"   # AppParameters: "artisan serve --host=0.0.0.0 --port=8010"

# 前台运行（调试）
php artisan epr:process-api
php artisan serve --host=0.0.0.0 --port=8010
```

## 文档

- [架构设计](docs/architecture.md) — 分层架构、数据流、组件职责、数据库字段映射
- [运维手册](docs/runbook.md) — 故障排查、配置参考
- [API 对接文档](docs/api.md) — 接口契约、字段清单、回调信封、状态机

## License

MIT
