# UAT 对象映射调查结论（2026-09-10，全程只读）

所有结论基于 `sf sobject describe` / FieldDefinition 查询，目标 org `sospdomain@sf-auto.com.uat`（组织 ID `00DC5000000kicLMAQ`，已过允许列表核验）。

## 1. 拜访日志 → `Visit_Plan__c`（拜访计划，UAT 真实在用，10004 条）

| Demo 数据 | UAT 字段 | 说明 |
| --- | --- | --- |
| 幂等/清理标记 | `Source_Id__c`（文本255，**外部 ID + 唯一区分大小写**） | 写 `SOSP-DEMO-<client-uuid>`，幂等 upsert 与清理都以此为凭 |
| 机会关联 | `Opty__c`（查找·业务机会） | 值必须来自真实 Opportunity Id，不允许模型编造 |
| 日志正文/六项字段摘要 | `Visit_Content__c`（长文本3000） | |
| 拜访目的 | `Visit_Goal__c`（长文本1000） | |
| 日志类型 | `logType__c`：客户交流 / 其他反馈 / 计划 | 默认「客户交流」 |
| 活动类型映射 | `visitCategory__c`：出差交流 / 视频会议 / 电话交流 | |
| 活动时间 | `ActivityDateTime__c`（日期/时间） | 模糊日期只写已确认值 |
| 客户 | `Account__c`（查找·客户） | |
| 拜访方式 | `Visit_Way__c`：主导 / 陪同 / 办公 | 可后置补充 |
| 状态 | `Visit_Status__c`：计划中 / 已完成 / 已取消 | 日志场景写「已完成」 |
| 计划类型 | `isjournal__c`（布尔，**必填**） | 日志场景 = true |
| OwnerId | 必填 | 用连接用户自身，不代写他人 |

备选：`logNew__c`（拜访计划日志，`logEffect__c` 完成内容、`logProgress__c` 进度，父对象必填 ViPlan__c）——当前 0 条记录，非业务主用对象，不采用。

## 2. 阶段推进 → `Opportunity.StageName`

组织真实取值（20 个）：线索、需求确认、初步方案、项目推进、方案验证、投标、中标、合同谈判、赢单、已关闭、丢单、项目暂停、引导客户、制定并提交解决方案、谈判与签订合同、可研、储备、资金批复、初设、招标文件编制。

Demo 演示脚本里的「初步方案 → 方案验证」在真实取值中存在，链路成立。

**边界**：只允许对可证明由本 Demo 创建的测试机会推进阶段（Name 带 `SOSP-DEMO-` 前缀 + 本地留痕创建记录 Id），**绝不动真实业务机会的阶段**。

## 3. 测试数据策略

- 清理与幂等凭据：`Source_Id__c = SOSP-DEMO-*`；Opportunity 无外部 ID 字段，用 Name 前缀 `SOSP-DEMO-` + 本地创建留痕表（记录 SF Id → 供清理与对账）。
- 阶段概率映射：写入后回读 StageName + ForecastCategoryName 核对，替换 `lib/engine/stage.js` 的演示概率配置并把标注从「演示配置」改为「组织核对后配置」。
- 待联调验证项（只读探测不到，写入时验证）：连接用户对 `Visit_Plan__c` 的 CRUD/FLS；`Opty__c` 查找过滤（业务机会限制的 record type）。

## 4. 集成接触面（等另一 AI 收尾后执行）

1. 新文件 `lib/adapters/sf-uat.js`（本目录已暂存骨架）——纯新增，零冲突。
2. 改 `lib/config.js`：`uatOrgIds`、`uatWriteEnabled`、`sfCliBin`、`uatTargetOrg`、SFDX_HOME 注入。
3. 改 `lib/adapters/store.js`：uat 分支从「直接拒绝」改为「核验通过 → 走 sf-uat 适配器」，保留失败拒绝语义。
4. systemd unit：`SOSP_MODE=uat`、`SOSP_UAT_ORG_IDS=00DC5000000kicLMAQ`、`SOSP_UAT_WRITE=true`（最后开）+ 给 `sosp-assistant` 用户的独立 SFDX_HOME（凭证导入，0600）。
5. opportunities 表加 `sf_opportunity_id` 列（本地迁移）。

## 5. 风险与红线（重申）

- 生产 org `00DC80000071iuEMAQ` 任何写路径都不存在；uat 失败一律拒绝并保留草稿，绝不回退。
- 超时对账：upsert 以 `Source_Id__c` 幂等，重试前先按外部 ID 回读，避免重复记录。
- 用户文本不进 shell；一律 execFile + 固定参数 + SOQL 转义（复用 sf-readonly.js 的转义函数模式）。
