diff --git a/.gitignore b/.gitignore
index c2f12895..eb80c82e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,3 +52,4 @@ nbdist/
effective-pom.xml
/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/resources/参考代码/
+/datai-scenes/datai-scene-salesforce/docs/sql/
diff --git a/README.md b/README.md
index d56dc933..0484699e 100644
--- a/README.md
+++ b/README.md
@@ -1,222 +1,277 @@
-
-
-
-
- +
-
-
-
-
-datai v3.8.9-G
-基于SpringBoot3+Vue3前后端分离的Java快速开发框架
-
-
-
+# Datai - Salesforce 集成系统
-# 当前版本是3.8.9-G
+## 项目概述
-本人的其他两个推荐搭配的项目
+Datai 是一个基于若依Geek框架构建的企业级管理系统,采用模块化架构设计,提供可扩展的插件和场景模块。系统集成了 Salesforce 平台,支持多种 API 交互方式,实现数据同步、认证管理和元数据处理等核心功能。
-1. [DataI-App-Geek: 这是集成系统生态的小程序版本 (gitee.com)](https://gitee.com/geek-xd/geek-uniapp-vue3-uview-plus-uchart)
-2. [DataI-Vue3-Geek: 这是集成系统生态的Vue3版本 (gitee.com)](https://gitee.com/geek-xd/ruo-yi-vue3-geek)
+**当前实现状态**:项目目前专注于从 Salesforce 源系统同步数据到本地数据库,包括元数据管理、批量数据同步、实时数据同步等功能。
-与本项目同为一个作者开发,兼容性最好,学习成本最低。
+## 技术栈
-# 引言
+| 技术 | 版本 | 说明 |
+|------|------|------|
+| Java | 21 / 22 | 根项目使用 Java 21,Salesforce 模块使用 Java 22 |
+| Spring Boot | 3.5.7 | 核心框架 |
+| MyBatis | 3.5.16 | 持久层框架 |
+| MySQL | 8.3.0 | 关系型数据库 |
+| PostgreSQL | 42.7.7 | 关系型数据库 |
+| Knife4j | 4.5.0 | API 文档工具 |
+| Druid | 1.2.27 | 数据库连接池 |
+| Maven | - | 构建工具 |
+| Salesforce Partner API | 0.0.1 | Salesforce SOAP API 客户端 |
+| Salesforce Pub/Sub Client | 0.2.21 | Salesforce CDC 实时同步客户端 |
+| Apache Avro | 1.11.3 | 数据序列化格式 |
+| Fastjson | 2.0.58 | JSON 解析器 |
+| JWT | 0.12.6 | Token 生成与解析 |
+| PageHelper | 2.1.1 | 分页插件 |
-DataI-Vue与DataI-App是基于SpringBoot2+Vue2打造的企业级开发框架,得到了广大开发者的喜爱和积极反馈。随着技术的迭代进步,SpringBoot3与Vue3逐渐进入开发者的视野。为了满足开发者对于新技术的追求,DataI官方文档提供了SpringBoot2至SpringBoot3的升级方法。与此同时,社区也涌现出了DataI-Vue3、DataI-App-Vue3的版本,展现了开发者社区对于技术升级的热情与努力。
+## 项目结构
-然而,在升级的过程中,官方的方法为了兼顾Java1.8的特性与一些老旧的方法,未完全拥抱SpringBoot3与Java17的全部特性。而社区的DataI-Vue3、DataI-App-Vue3版本由于出自不同的团队之手,兼容性及整合性上存在些许不足。更为关键的是,尽管这些版本支持TypeScript,但缺乏与之相匹配的tsconfig.json配置文件,这使得在主流编辑器如VSCode中,TypeScript的语法提示环境并未达到最佳状态。
-
-鉴于此,datai生态应运而生。它旨在为广大开发者提供一个既保留原版本核心特性,又整合社区版优点的全新解决方案。在datai中,我们深入调研了企业开发中常用的DataI扩展,并直接在框架中集成,确保开发者能够快速上手,高效开发。同时,我们采用了最新的SpringBoot3+Vue3技术栈,彻底移除了为了兼容Java1.8而保留的老旧方法。更为重要的是,我们为TypeScript开发环境加入了常用的tsconfig.json配置,使得开发者在VSCode等编辑器中能够获得更为舒适、便捷的语法提示体验。
-
-datai不仅仅是一个简单的升级版本,更是对于DataI生态的一次全面优化与整合。我们相信,通过datai,开发者将能够更为高效、愉悦地开发出优秀的企业级应用。
-
-## 平台简介
-
-若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
-
-* 前端采用Vue3、Element Plus。
-* 后端采用Spring Boot3、Spring Security、Redis & Jwt。
-* 权限认证使用Jwt,支持多终端认证系统。
-* 支持加载动态权限菜单,多方式轻松权限控制。
-* 高效率开发,使用代码生成器可以一键生成前后端代码。
-* 多数据源与分库分表默认集成
-* 所有非基本模块可随意插拔,让开发更加简单高效
-* 提供了多个工具模块助力开发,如:在线接口模块、mybatis-jpa模块
-* 提供了多个常见业务模块简化开发,如:第三方认证模块、支付模块
-* 提供了多个常见的服务模块集成开发,如:websocket模块、minio模块
-* 特别鸣谢:[element](https://github.com/ElemeFE/element),[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin),[eladmin-web](https://github.com/elunez/eladmin-web)。
-* 阿里云折扣场:[点我进入](http://aly.datai.vip),腾讯云秒杀场:[点我进入](http://txy.datai.vip)
-* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)
-
-## 本项目与原项目的区别
-
-### 核心
-
-**模块化架构设计,支持各个模块的快速安拆,对第三方认证、第三方支付模块设计了基础的规范和基础模块。**
-
-### 细节
-
-1. 改用SpringBoot3+java17的更新的技术栈并改掉所有的弃用的方法,全面拥抱java17的全新特性。
-2. 升级了代码生成器(配合本项目的vue3版本才可用),使关联表生成更加简单!
-3. 改用最新版本的SpringSecurity安全框架,以及采用最新的lambda 表达式的配置方式,更加通俗易懂!
-4. 自动Api文档以springfox替代springdoc来适配knife4j框架的4.x版本,更好的适配springboot3!
-5. 默认引入mybatis-plus增强mybatis,并自创工具模块mybatis-jpa简化CRUD!
-6. 默认引入lombok简化代码(注:基础模块并未使用mybatis-plus和lombok,对这两个扩展有争议的小伙伴可以直接删除,不会影响到框架本身滴,以及knife4j直接删除也不会影响到springdoc,主要还是为了方便咱们开发者呢!)
-7. 提供了大量可随意插拔的模块,助力快速开发!同时datai插件集成中的常用插件也以模块的形式直接集成在了项目中,也是可以随意插拔的嗷~
-
-## 模块介绍(简单开发必看)
-
-* 最简单的开发就是删除所有的可移除模块,按需添加模块。
-* 测试中的模块请自己使用的时候一定要测试一下。
-* 对于小白,开发中的模块请直接删除。
-
-```plaintext
-com.datai
-├── datai-admin // 后台服务
-├── common // 工具类
-│ └── annotation // 自定义注解
-│ └── config // 全局配置
-│ └── constant // 通用常量
-│ └── core // 核心控制
-│ └── enums // 通用枚举
-│ └── exception // 通用异常
-│ └── filter // 过滤器处理
-│ └── utils // 通用类处理
-├── framework // 框架核心
-│ └── aspectj // 注解实现
-│ └── config // 系统配置
-│ └── datasource // 数据权限
-│ └── interceptor // 拦截器
-│ └── manager // 异步处理
-│ └── security // 权限控制
-│ └── web // 前端控制
-├── datai-models // 业务模块
-│ └── online // 在线开发模块(可移除)
-│ └── quartz // 定时任务(可移除)
-│ └── generator // 代码生成(可移除)
-│ └── form // 自定义在线表单(可移除)
-│ └── flowable // 流程管理(可移除)(依赖于form模块)
-│ └── message // 消息模块(可移除)(可以与phone、email模块协同)
-│ └── starter // 业务场景启动器
-├── datai-plugins // 插件
-│ └── ehcache // ehcache缓存插件(与redis模块同类,两者二选一)
-│ └── mybatis-jpa // mybatis-jpa插件(可移除)(简化CRUD,以数据模型为基础开发)
-│ └── mybatis-plus // mybatis-plus插件(可移除)(简化CRUD)
-│ └── mybatis-interceptor // mybatis-interceptor插件(可移除)(简化数据鉴权和分页,扩展性强)
-│ └── atomikos // atomikos分布式事务插件(可移除)
-│ └── netty // netty插件(可移除)
-│ └── rabbitmq // rabbitmq队列服务模块
-│ └── redis // redis缓存服务模块(与ehcache插件同类,两者二选一)
-│ └── websocket // websocket插件(可移除)
-│ └── starter // 插件整合模块
-├── datai-scenes // 业务场景
-│ ├── datai-scenes-pay // 支付场景(基本业务完成)
-│ │ └── common // 支付框架基础模块(基础框架搭建完成)
-│ │ └── sqb // 收钱吧支付模块(功能可用,业务需要开发)
-│ │ └── wx // 微信支付模块(基础业务完成)
-│ │ └── alipay // 支付宝支付模块(基础业务完成)
-│ │ └── starter // 支付场景启动器
-│ ├── datai-scenes-auth // 第三方认证场景(基础框架搭建完成)
-│ │ └── common // 第三方认证基础模块(开发中)
-│ │ └── justauth // 网站第三方认证模块(测试中,参照若依扩展改进,因没有这么多场景的code,请大家测试出问题后help解决一下发出来)
-│ │ └── wx // 微信小程序认证模块(测试中)
-│ │ └── phone // 手机认证模块(基础业务完成)
-│ │ └── email // 邮箱认证模块(基础业务完成)
-│ │ └── starter // 第三方认证启动器
-│ ├── datai-scenes-file // 文件服务系统(支持公开访问、临时凭证、分片上传等常见功能)
-│ │ └── common // 基础模块和本地磁盘方式
-│ │ └── minio // minio分布式文件服务
-│ │ └── oss-alibaba // alibaba的oss云储存服务
-│ │ └── starter // 第三方认证启动器
-├── datai-system // 系统代码
+```
+datai/
+├── datai-admin/ # 管理后台启动模块
+├── datai-framework/ # 框架核心模块
+├── datai-system/ # 系统管理模块
+├── datai-common/ # 通用工具模块
+├── datai-scenes/ # 场景模块
+│ ├── datai-scene-salesforce/ # Salesforce 集成场景
+│ │ ├── datai-salesforce-auth/ # 认证相关模块
+│ │ ├── datai-salesforce-common/ # 通用工具和常量
+│ │ ├── datai-salesforce-integration/ # 核心集成模块
+│ │ ├── datai-salesforce-setting/ # 配置管理模块
+│ │ └── datai-salesforce-starter/ # 启动器模块
+│ ├── datai-scene-auth/ # 认证场景
+│ │ ├── datai-auth-common/ # 认证通用模块
+│ │ ├── datai-auth-starter/ # 认证启动器
+│ │ ├── datai-oauth-justauth/ # JustAuth OAuth
+│ │ ├── datai-oauth-wx/ # 微信 OAuth
+│ │ ├── datai-tfa-email/ # 邮箱双因子认证
+│ │ └── datai-tfa-phone/ # 手机双因子认证
+│ ├── datai-scene-pay/ # 支付场景
+│ │ ├── datai-pay-common/ # 支付通用模块
+│ │ ├── datai-pay-starter/ # 支付启动器
+│ │ ├── datai-pay-alipay/ # 支付宝支付
+│ │ ├── datai-pay-wx/ # 微信支付
+│ │ └── datai-pay-sqb/ # 收钱吧支付
+│ └── datai-scene-file/ # 文件场景
+│ ├── datai-file-common/ # 文件通用模块
+│ ├── datai-file-starter/ # 文件启动器
+│ ├── datai-file-local/ # 本地文件存储
+│ ├── datai-file-minio/ # MinIO 文件存储
+│ └── datai-file-aliyun-oss/ # 阿里云 OSS 文件存储
+├── datai-plugins/ # 插件模块
+│ ├── datai-plugins-starter/ # 插件启动器
+│ ├── datai-mybatis-plus/ # MyBatis Plus 插件
+│ ├── datai-cache-redis/ # Redis 缓存插件
+│ ├── datai-cache-ehcache/ # Ehcache 缓存插件
+│ ├── datai-rabbitmq/ # RabbitMQ 消息队列插件
+│ ├── datai-websocket/ # WebSocket 插件
+│ ├── datai-netty/ # Netty 网络插件
+│ └── datai-atomikos/ # Atomikos 分布式事务插件
+└── datai-models/ # 模型模块
+ ├── datai-models-starter/ # 模型启动器
+ ├── datai-quartz/ # Quartz 定时任务
+ ├── datai-form/ # 表单管理
+ ├── datai-message/ # 消息管理
+ ├── datai-generator/ # 代码生成器
+ ├── datai-online/ # 在线用户
+ └── datai-flowable/ # 工作流
```
-## 内置功能
+## 核心功能
-1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
-2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
-3. 岗位管理:配置系统用户所属担任职务。
-4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
-5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
-6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
-7. 参数管理:对系统动态配置常用参数。
-8. 通知公告:系统通知公告信息发布维护。
-9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
-10. 登录日志:系统登录日志记录查询包含登录异常。
-11. 在线用户:当前系统中活跃用户状态监控。
-12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
-13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
-14. 系统接口:根据业务代码自动生成相关的api接口文档。
-15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
-16. 缓存监控:对系统的缓存信息查询,命令统计等。
-17. 在线构建器:拖动表单元素生成相应的HTML代码。
-18. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
-19. 支付场景
-20. 第三方登录场景
-21. 中间件场景
+### Salesforce 集成模块(当前实现)
-## 演示图
+提供与 Salesforce 源系统的数据集成解决方案,支持从 Salesforce 同步数据到本地数据库。
-### 新加功能和增强功能演示
+#### 认证管理
+- **多种登录方式**: OAuth2、SessionId、CLI、Legacy Credential
+- **会话管理**: 登录会话的创建、查询和销毁
+- **历史记录**: 登录历史记录的查询和统计
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
+#### 数据同步(源系统 → 本地)
+- **Bulk API v1/v2**: 批量数据同步,支持大规模数据导入导出
+- **Partner API**: SOAP API 数据交互,支持 CRUD 操作
+- **REST API**: RESTful API 数据交互
+- **CDC 实时同步**: Change Data Capture 实时数据同步
-### 原有功能演示
+#### 元数据管理
+- **对象管理**: Salesforce 对象的查询、同步和结构创建
+- **字段管理**: 对象字段的查询和管理
+- **Picklist 管理**: Picklist 值的查询和管理
+- **Lookup 过滤器**: Lookup 过滤器的查询和管理
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
+#### 批次管理
+- **批次创建**: 创建数据同步批次
+- **批次数据插入**: 将本地数据插入到 Salesforce,保存返回 ID
+- **批次数据更新**: 使用保存的 ID 更新 Salesforce 数据
+- **批次重试**: 失败批次的重试机制
+- **批次历史**: 批次操作历史记录
-# 联系我们:
+#### 实时同步
+- **Pub/Sub API**: Salesforce Event Bus 实时数据订阅
+- **事件处理**: CDC 事件的接收和处理
+- **数据同步**: 实时数据同步到本地数据库
+- **服务管理**: 实时同步服务的启动、停止和重启
-QQ交流群:744785891
+#### 监控日志
+- **API 调用日志**: Salesforce API 调用记录和统计
+- **同步日志**: 数据同步操作日志
+- **速率限制监控**: Salesforce API 速率限制监控
+- **实时同步日志**: CDC 实时同步日志
+
+### 开发计划
+
+#### 1. 数据推送到目标 Salesforce 系统
+- **目标系统认证**: 支持目标 Salesforce 系统的多种认证方式
+- **数据推送**: 支持将本地数据批量推送到目标 Salesforce 系统
+- **双向同步**: 实现源系统 → 本地 → 目标系统的数据流转
+- **数据映射**: 支持源系统和目标系统之间的字段映射
+- **推送监控**: 数据推送任务的监控和日志记录
+
+#### 2. 源 Salesforce 系统文件下载
+- **文件元数据**: 获取 Salesforce 附件和文档的元数据信息
+- **文件下载**: 支持批量下载 Salesforce 中的文件(Attachment、Document、ContentVersion)
+- **文件存储**: 支持本地存储、MinIO、阿里云 OSS 等多种存储方式
+- **文件同步**: 文件与数据的关联同步
+- **下载监控**: 文件下载任务的监控和进度追踪
+
+#### 3. User 权限同步集成系统
+- **权限元数据**: 同步 Salesforce User、Profile、PermissionSet、Role 等权限相关对象
+- **权限映射**: 将 Salesforce 权限映射到系统用户权限
+- **数据权限控制**: 基于用户权限控制数据访问范围
+- **权限同步**: 实时同步用户权限变更
+- **权限审计**: 权限变更的审计日志
+
+#### 4. 集成可视化报表插件
+- **报表设计器**: 可视化拖拽式报表设计器,支持自定义报表布局
+- **数据源配置**: 支持从本地数据库和 Salesforce 系统配置数据源
+- **图表组件**: 提供丰富的图表类型(柱状图、折线图、饼图、表格等)
+- **数据筛选**: 支持动态筛选条件和参数化查询
+- **报表导出**: 支持导出为 PDF、Excel、图片等多种格式
+- **报表分享**: 支持报表分享和权限控制
+- **实时刷新**: 支持报表数据的实时刷新和定时更新
+- **报表模板**: 提供常用报表模板,快速生成标准报表
+
+### 认证场景模块
+
+- **OAuth 集成**: JustAuth 和微信 OAuth 登录
+- **双因子认证**: 邮箱和手机双因子认证
+- **用户管理**: OAuth 用户信息管理
+
+
+### 文件场景模块
+
+- **本地存储**: 本地文件系统存储
+- **MinIO 存储**: MinIO 对象存储
+- **阿里云 OSS**: 阿里云对象存储服务
+- **文件管理**: 文件上传、下载和管理
+
+### 插件模块
+
+- **MyBatis Plus**: MyBatis 增强工具
+- **Redis 缓存**: Redis 分布式缓存
+- **Ehcache 缓存**: Ehcache 本地缓存
+- **RabbitMQ**: 消息队列中间件
+- **WebSocket**: WebSocket 实时通信
+- **Netty**: Netty 网络框架
+- **Atomikos**: 分布式事务管理
+
+### 模型模块
+
+- **Quartz**: 定时任务调度
+- **表单管理**: 动态表单生成和管理
+- **消息管理**: 系统消息管理
+- **代码生成器**: 代码自动生成工具
+- **在线用户**: 在线用户管理
+- **工作流**: Flowable 工作流引擎
+
+## 快速开始
+
+### 环境要求
+
+- JDK 21+
+- Maven 3.6+
+- MySQL 8.3.0+ 或 PostgreSQL 42.7.7+
+- Redis(可选,用于缓存)
+
+### 配置说明
+
+#### 关键配置项
+
+| 配置项 | 默认值 | 说明 |
+|--------|--------|------|
+| server.port | 8080 | 服务端口 |
+| datai.profile | D:/datai/uploadPath | 文件上传路径 |
+| datai.fileServer | local | 文件服务类型(local/minio/oss) |
+| datai.fileMaxSize | 50 | 文件上传最大大小(MB) |
+| spring.cache.type | redis | 缓存类型(redis/jcache) |
+| token.expireTime | 1440 | Token 有效期(分钟) |
+| pagehelper.helperDialect | mysql | 数据库方言 |
+
+#### 启用配置文件
+
+- `application-druid.yml`: 数据库连接池配置
+- `application-file.yml`: 文件服务配置
+- `application-auth.yml`: 认证配置
+- `application-pay.yml`: 支付配置
+- `application-plugins.yml`: 插件配置
+- `application-model.yml`: 模型配置
+- `application-apidoc.yml`: API 文档配置
+
+### 构建项目
+
+```bash
+mvn clean install
+```
+
+### 运行项目
+
+```bash
+cd datai-admin
+mvn spring-boot:run
+```
+
+启动成功后,访问:
+- 应用地址: http://localhost:8080
+- API 文档: http://localhost:8080/doc.html
+
+## 文档
+
+### 项目规则
+
+项目采用基于单一真源 (Single Source of Truth) 的 Workflow,所有项目相关文档和决策均集中在 `docs/` 目录中。
+
+### Salesforce 模块文档
+
+详细文档请参考 [Salesforce 集成模块文档中心](datai-scenes/datai-scene-salesforce/docs/index.md)
+
+- **唯一入口**: [datai-scene-salesforce/docs/index.md](datai-scenes/datai-scene-salesforce/docs/index.md)
+- **架构看板**: [datai-scene-salesforce/docs/Authentication.canvas](datai-scenes/datai-scene-salesforce/docs/Authentication.canvas)
+- **接口文档**: [datai-scene-salesforce/docs/api-docs/](datai-scenes/datai-scene-salesforce/docs/api-docs/)
+
+### 文档目录
+
+- **需求文档**: [datai-scenes/datai-scene-salesforce/docs/requirements/](datai-scenes/datai-scene-salesforce/docs/requirements/)
+- **设计文档**: [datai-scenes/datai-scene-salesforce/docs/design/](datai-scenes/datai-scene-salesforce/docs/design/)
+- **架构决策**: [datai-scenes/datai-scene-salesforce/docs/decisions/adr/](datai-scenes/datai-scene-salesforce/docs/decisions/adr/)
+- **提示词库**: [datai-scenes/datai-scene-salesforce/docs/prompts/](datai-scenes/datai-scene-salesforce/docs/prompts/)
+- **会话记录**: [datai-scenes/datai-scene-salesforce/docs/sessions/](datai-scenes/datai-scene-salesforce/docs/sessions/)
+- **变更日志**: [datai-scenes/datai-scene-salesforce/docs/changelog/](datai-scenes/datai-scene-salesforce/docs/changelog/)
+
+## 贡献指南
+
+请参考 [CONTRIBUTING.md](CONTRIBUTING.md) 了解如何参与项目贡献。
+
+## 变更日志
+
+请参考 [CHANGELOG.md](CHANGELOG.md) 查看项目变更记录。
+
+## 许可证
+
+本项目基于若依Geek框架开发,遵循相应的开源许可证。
+
+## 联系方式
+
+- 项目地址: https://gitee.com/geek-xd/datai-springboot3.git
+- 文档中心: [datai-scenes/datai-scene-salesforce/docs/index.md](datai-scenes/datai-scene-salesforce/docs/index.md)
diff --git a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/controller/DataiIntegrationBatchController.java b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/controller/DataiIntegrationBatchController.java
index 4075fc6c..a98a4b95 100644
--- a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/controller/DataiIntegrationBatchController.java
+++ b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/controller/DataiIntegrationBatchController.java
@@ -28,6 +28,7 @@ import com.datai.common.utils.poi.ExcelUtil;
import com.datai.common.core.page.TableDataInfo;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
+import lombok.extern.slf4j.Slf4j;
/**
* 数据批次Controller
@@ -38,6 +39,7 @@ import io.swagger.v3.oas.annotations.Operation;
@RestController
@RequestMapping("/integration/batch")
@Tag(name = "【数据批次】管理")
+@Slf4j
public class DataiIntegrationBatchController extends BaseController
{
@Autowired
@@ -180,4 +182,104 @@ public class DataiIntegrationBatchController extends BaseController
return error((String) result.get("message"));
}
}
+
+ /**
+ * 批次数据插入目标系统
+ *
+ * 该方法用于将本地数据库中的指定批次数据插入到目标Salesforce系统
+ * 插入操作会查询本地表中符合批次条件的数据,然后通过SOAP API插入到目标系统
+ * 插入成功后,会将返回的ID保存到new_id字段,并更新is_insert字段
+ *
+ * @param id 批次ID,用于标识需要插入的批次
+ * @param targetOrgType 目标ORG类型,用于标识目标Salesforce系统
+ * @return AjaxResult 插入结果,包含成功/失败状态、插入数据量、耗时等信息
+ * - 成功时返回:success=true, message="批次数据插入完成", 以及详细的插入信息
+ * - 失败时返回:success=false, message=错误信息
+ */
+ @Operation(summary = "批次数据插入目标系统")
+ @PreAuthorize("@ss.hasPermi('integration:batch:insertData')")
+ @Log(title = "数据批次", businessType = BusinessType.INSERT)
+ @PostMapping("/{id}/insertData")
+ public AjaxResult insertBatchDataToTarget(@PathVariable("id") Integer id,
+ @org.springframework.web.bind.annotation.RequestParam("targetOrgType") String targetOrgType)
+ {
+ if (id == null) {
+ log.error("批次ID为空,无法插入数据");
+ return error("批次ID不能为空");
+ }
+
+ if (targetOrgType == null || targetOrgType.trim().isEmpty()) {
+ log.error("目标ORG类型为空,无法插入数据");
+ return error("目标ORG类型不能为空");
+ }
+
+ try {
+ log.info("开始插入批次数据到目标系统,批次ID: {}, 目标ORG类型: {}", id, targetOrgType);
+
+ Map result = dataiIntegrationBatchService.insertBatchDataToTarget(id, targetOrgType);
+
+ if ((Boolean) result.get("success")) {
+ log.info("批次数据插入成功,批次ID: {}, 目标ORG类型: {}", id, targetOrgType);
+ return success(result);
+ } else {
+ log.error("批次数据插入失败,批次ID: {}, 目标ORG类型: {}, 错误信息: {}",
+ id, targetOrgType, result.get("message"));
+ return error((String) result.get("message"));
+ }
+
+ } catch (Exception e) {
+ log.error("插入批次数据时发生异常,批次ID: {}, 目标ORG类型: {}", id, targetOrgType, e);
+ return error("插入批次数据时发生异常: " + e.getMessage());
+ }
+ }
+
+ /**
+ * 批次数据更新目标系统
+ *
+ * 该方法用于将本地数据库中的指定批次数据更新到目标Salesforce系统
+ * 更新操作会查询本地表中符合批次条件的数据,然后通过SOAP API更新到目标系统
+ * 更新时使用new_id作为目标系统的ID,更新成功后,更新is_update字段
+ *
+ * @param id 批次ID,用于标识需要更新的批次
+ * @param targetOrgType 目标ORG类型,用于标识目标Salesforce系统
+ * @return AjaxResult 更新结果,包含成功/失败状态、更新数据量、耗时等信息
+ * - 成功时返回:success=true, message="批次数据更新完成", 以及详细的更新信息
+ * - 失败时返回:success=false, message=错误信息
+ */
+ @Operation(summary = "批次数据更新目标系统")
+ @PreAuthorize("@ss.hasPermi('integration:batch:updateData')")
+ @Log(title = "数据批次", businessType = BusinessType.UPDATE)
+ @PostMapping("/{id}/updateData")
+ public AjaxResult updateBatchDataToTarget(@PathVariable("id") Integer id,
+ @org.springframework.web.bind.annotation.RequestParam("targetOrgType") String targetOrgType)
+ {
+ if (id == null) {
+ log.error("批次ID为空,无法更新数据");
+ return error("批次ID不能为空");
+ }
+
+ if (targetOrgType == null || targetOrgType.trim().isEmpty()) {
+ log.error("目标ORG类型为空,无法更新数据");
+ return error("目标ORG类型不能为空");
+ }
+
+ try {
+ log.info("开始更新批次数据到目标系统,批次ID: {}, 目标ORG类型: {}", id, targetOrgType);
+
+ Map result = dataiIntegrationBatchService.updateBatchDataToTarget(id, targetOrgType);
+
+ if ((Boolean) result.get("success")) {
+ log.info("批次数据更新成功,批次ID: {}, 目标ORG类型: {}", id, targetOrgType);
+ return success(result);
+ } else {
+ log.error("批次数据更新失败,批次ID: {}, 目标ORG类型: {}, 错误信息: {}",
+ id, targetOrgType, result.get("message"));
+ return error((String) result.get("message"));
+ }
+
+ } catch (Exception e) {
+ log.error("更新批次数据时发生异常,批次ID: {}, 目标ORG类型: {}", id, targetOrgType, e);
+ return error("更新批次数据时发生异常: " + e.getMessage());
+ }
+ }
}
diff --git a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/controller/DataiIntegrationObjectController.java b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/controller/DataiIntegrationObjectController.java
index 9f56f0cc..50135c1f 100644
--- a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/controller/DataiIntegrationObjectController.java
+++ b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/controller/DataiIntegrationObjectController.java
@@ -318,4 +318,79 @@ public class DataiIntegrationObjectController extends BaseController
return error("同步多个对象数据时发生异常: " + e.getMessage());
}
}
+
+ @Operation(summary = "推送单对象数据到目标系统")
+ @PreAuthorize("@ss.hasPermi('integration:object:pushData')")
+ @Log(title = "对象同步控制", businessType = BusinessType.UPDATE)
+ @PostMapping("/{id}/pushData")
+ public AjaxResult pushObjectData(@PathVariable("id") Integer id,
+ @org.springframework.web.bind.annotation.RequestParam("targetOrgType") String targetOrgType)
+ {
+ if (id == null) {
+ log.error("对象ID为空,无法推送数据");
+ return error("对象ID不能为空");
+ }
+
+ if (targetOrgType == null || targetOrgType.trim().isEmpty()) {
+ log.error("目标ORG类型为空,无法推送数据");
+ return error("目标ORG类型不能为空");
+ }
+
+ try {
+ log.info("开始推送对象数据到目标系统,对象ID: {}, 目标ORG类型: {}", id, targetOrgType);
+
+ Map result = dataiIntegrationObjectService.pushSingleObjectDataToTarget(id, targetOrgType);
+
+ if ((Boolean) result.get("success")) {
+ log.info("对象数据推送成功,对象ID: {}, 目标ORG类型: {}", id, targetOrgType);
+ return success(result);
+ } else {
+ log.error("对象数据推送失败,对象ID: {}, 目标ORG类型: {}, 错误信息: {}",
+ id, targetOrgType, result.get("message"));
+ return error((String) result.get("message"));
+ }
+
+ } catch (Exception e) {
+ log.error("推送对象数据时发生异常,对象ID: {}, 目标ORG类型: {}", id, targetOrgType, e);
+ return error("推送对象数据时发生异常: " + e.getMessage());
+ }
+ }
+
+
+ @Operation(summary = "推送多个对象数据到目标系统")
+ @PreAuthorize("@ss.hasPermi('integration:object:pushData')")
+ @Log(title = "对象同步控制", businessType = BusinessType.UPDATE)
+ @PostMapping("/pushMultipleData")
+ public AjaxResult pushMultipleObjectData(@RequestBody Integer[] ids,
+ @org.springframework.web.bind.annotation.RequestParam("targetOrgType") String targetOrgType)
+ {
+ if (ids == null || ids.length == 0) {
+ log.error("对象ID数组为空,无法推送数据");
+ return error("对象ID不能为空");
+ }
+
+ if (targetOrgType == null || targetOrgType.trim().isEmpty()) {
+ log.error("目标ORG类型为空,无法推送数据");
+ return error("目标ORG类型不能为空");
+ }
+
+ try {
+ log.info("开始推送多个对象数据到目标系统,对象ID数量: {}, 目标ORG类型: {}", ids.length, targetOrgType);
+
+ Map result = dataiIntegrationObjectService.pushMultipleObjectDataToTarget(ids, targetOrgType);
+
+ if ((Boolean) result.get("success")) {
+ log.info("多对象数据推送完成,成功数量: {}, 失败数量: {}",
+ result.get("successCount"), result.get("failureCount"));
+ return success(result);
+ } else {
+ log.error("多对象数据推送失败,错误信息: {}", result.get("message"));
+ return error((String) result.get("message"));
+ }
+
+ } catch (Exception e) {
+ log.error("推送多个对象数据时发生异常", e);
+ return error("推送多个对象数据时发生异常: " + e.getMessage());
+ }
+ }
}
diff --git a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/domain/DataiIntegrationBatch.java b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/domain/DataiIntegrationBatch.java
index 755c21d6..d49e6e48 100644
--- a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/domain/DataiIntegrationBatch.java
+++ b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/domain/DataiIntegrationBatch.java
@@ -9,7 +9,7 @@ import com.datai.common.annotation.Excel;
import com.datai.common.core.domain.BaseEntity;
/**
- * 数据批次对象 datai_integration_batch
+ * 数据批次对象 datai_integr ation_batch
*
* 字段更新规则:
* 1. 创建批次时设置的字段(后续不允许修改):
@@ -30,6 +30,12 @@ import com.datai.common.core.domain.BaseEntity;
* - lastSyncTime: 最后同步时间(每次同步时更新)
* - updateTime: 更新时间(每次更新时自动设置)
*
+ * 3. 推送时更新的字段:
+ * - sfInsertNum: SF插入数据量(每次推送时更新)
+ * - sfUpdateNum: SF更新数据量(每次推送时更新)
+ * - firstPushTime: 首次推送时间(仅在首次推送时设置)
+ * - lastPushTime: 最后推送时间(每次推送时更新)
+ *
* @author datai
* @date 2026-01-01
*/
@@ -67,6 +73,16 @@ public class DataiIntegrationBatch extends BaseEntity
@Excel(name = "本地数据量")
private Integer dbNum;
+ /** SF插入数据量 */
+ @Schema(title = "SF插入数据量")
+ @Excel(name = "SF插入数据量")
+ private Integer sfInsertNum;
+
+ /** SF更新数据量 */
+ @Schema(title = "SF更新数据量")
+ @Excel(name = "SF更新数据量")
+ private Integer sfUpdateNum;
+
/** 同步类型 */
@Schema(title = "同步类型")
@Excel(name = "同步类型")
@@ -101,6 +117,16 @@ public class DataiIntegrationBatch extends BaseEntity
@Schema(title = "最后同步时间")
@Excel(name = "最后同步时间")
private LocalDateTime lastSyncTime;
+
+ /** 首次推送时间 */
+ @Schema(title = "首次推送时间")
+ @Excel(name = "首次推送时间")
+ private LocalDateTime firstPushTime;
+
+ /** 最后推送时间 */
+ @Schema(title = "最后推送时间")
+ @Excel(name = "最后推送时间")
+ private LocalDateTime lastPushTime;
public void setId(Integer id)
{
this.id = id;
@@ -167,6 +193,28 @@ public class DataiIntegrationBatch extends BaseEntity
}
+ public void setSfInsertNum(Integer sfInsertNum)
+ {
+ this.sfInsertNum = sfInsertNum;
+ }
+
+ public Integer getSfInsertNum()
+ {
+ return sfInsertNum;
+ }
+
+
+ public void setSfUpdateNum(Integer sfUpdateNum)
+ {
+ this.sfUpdateNum = sfUpdateNum;
+ }
+
+ public Integer getSfUpdateNum()
+ {
+ return sfUpdateNum;
+ }
+
+
public void setSyncType(String syncType)
{
this.syncType = syncType;
@@ -244,6 +292,28 @@ public class DataiIntegrationBatch extends BaseEntity
}
+ public void setFirstPushTime(LocalDateTime firstPushTime)
+ {
+ this.firstPushTime = firstPushTime;
+ }
+
+ public LocalDateTime getFirstPushTime()
+ {
+ return firstPushTime;
+ }
+
+
+ public void setLastPushTime(LocalDateTime lastPushTime)
+ {
+ this.lastPushTime = lastPushTime;
+ }
+
+ public LocalDateTime getLastPushTime()
+ {
+ return lastPushTime;
+ }
+
+
@Override
public String toString() {
@@ -254,6 +324,8 @@ public class DataiIntegrationBatch extends BaseEntity
.append("label", getLabel())
.append("sfNum", getSfNum())
.append("dbNum", getDbNum())
+ .append("sfInsertNum", getSfInsertNum())
+ .append("sfUpdateNum", getSfUpdateNum())
.append("syncType", getSyncType())
.append("batchField", getBatchField())
.append("syncStatus", getSyncStatus())
@@ -261,6 +333,8 @@ public class DataiIntegrationBatch extends BaseEntity
.append("syncEndDate", getSyncEndDate())
.append("firstSyncTime", getFirstSyncTime())
.append("lastSyncTime", getLastSyncTime())
+ .append("firstPushTime", getFirstPushTime())
+ .append("lastPushTime", getLastPushTime())
.append("remark", getRemark())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
diff --git a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/dto/DataiIntegrationBatchDto.java b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/dto/DataiIntegrationBatchDto.java
index 0b76af9a..7fd09c74 100644
--- a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/dto/DataiIntegrationBatchDto.java
+++ b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/dto/DataiIntegrationBatchDto.java
@@ -42,6 +42,12 @@ public class DataiIntegrationBatchDto implements Serializable
/** 本地数据量 */
private Integer dbNum;
+ /** SF插入数据量 */
+ private Integer sfInsertNum;
+
+ /** SF更新数据量 */
+ private Integer sfUpdateNum;
+
/** 同步类型 */
private String syncType;
@@ -63,6 +69,12 @@ public class DataiIntegrationBatchDto implements Serializable
/** 最后同步时间 */
private LocalDateTime lastSyncTime;
+ /** 首次推送时间 */
+ private LocalDateTime firstPushTime;
+
+ /** 最后推送时间 */
+ private LocalDateTime lastPushTime;
+
/** 备注 */
private String remark;
diff --git a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/vo/DataiIntegrationBatchVo.java b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/vo/DataiIntegrationBatchVo.java
index 4b3e330c..7ab7b174 100644
--- a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/vo/DataiIntegrationBatchVo.java
+++ b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/model/vo/DataiIntegrationBatchVo.java
@@ -37,6 +37,12 @@ public class DataiIntegrationBatchVo implements Serializable {
/** 本地数据量 */
private Integer dbNum;
+ /** SF插入数据量 */
+ private Integer sfInsertNum;
+
+ /** SF更新数据量 */
+ private Integer sfUpdateNum;
+
/** 同步类型 */
private String syncType;
@@ -58,6 +64,12 @@ public class DataiIntegrationBatchVo implements Serializable {
/** 最后同步时间 */
private LocalDateTime lastSyncTime;
+ /** 首次推送时间 */
+ private LocalDateTime firstPushTime;
+
+ /** 最后推送时间 */
+ private LocalDateTime lastPushTime;
+
/** 备注 */
private String remark;
diff --git a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/IDataiIntegrationBatchService.java b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/IDataiIntegrationBatchService.java
index 79482df1..5aec5eae 100644
--- a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/IDataiIntegrationBatchService.java
+++ b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/IDataiIntegrationBatchService.java
@@ -90,4 +90,22 @@ public interface IDataiIntegrationBatchService
* @return 所有批次统计信息
*/
public Map getAllBatchStatistics();
+
+ /**
+ * 批次数据插入目标系统
+ *
+ * @param id 批次ID
+ * @param targetOrgType 目标ORG类型
+ * @return 插入结果
+ */
+ public Map insertBatchDataToTarget(Integer id, String targetOrgType);
+
+ /**
+ * 批次数据更新目标系统
+ *
+ * @param id 批次ID
+ * @param targetOrgType 目标ORG类型
+ * @return 更新结果
+ */
+ public Map updateBatchDataToTarget(Integer id, String targetOrgType);
}
diff --git a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/IDataiIntegrationObjectService.java b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/IDataiIntegrationObjectService.java
index 35211f08..c052f0b5 100644
--- a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/IDataiIntegrationObjectService.java
+++ b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/IDataiIntegrationObjectService.java
@@ -136,5 +136,23 @@ public interface IDataiIntegrationObjectService
*/
public Map syncMultipleObjectData(Integer[] ids);
+ /**
+ * 推送单对象数据到目标系统
+ *
+ * @param id 对象ID
+ * @param targetOrgType 目标ORG类型
+ * @return 推送结果
+ */
+ public Map pushSingleObjectDataToTarget(Integer id, String targetOrgType);
+
+ /**
+ * 推送多个对象数据到目标系统
+ *
+ * @param ids 对象ID集合
+ * @param targetOrgType 目标ORG类型
+ * @return 推送结果
+ */
+ public Map pushMultipleObjectDataToTarget(Integer[] ids, String targetOrgType);
+
Set getRealtimeSyncObjects();
}
diff --git a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/impl/DataiIntegrationBatchServiceImpl.java b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/impl/DataiIntegrationBatchServiceImpl.java
index d3e0ee8b..9e78247f 100644
--- a/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/impl/DataiIntegrationBatchServiceImpl.java
+++ b/datai-scenes/datai-scene-salesforce/datai-salesforce-integration/src/main/java/com/datai/integration/service/impl/DataiIntegrationBatchServiceImpl.java
@@ -993,4 +993,400 @@ public class DataiIntegrationBatchServiceImpl implements IDataiIntegrationBatchS
return statistics;
}
+
+ @Override
+ public Map insertBatchDataToTarget(Integer id, String targetOrgType) {
+ Map result = new HashMap<>();
+ long startTime = System.currentTimeMillis();
+
+ try {
+ log.info("开始插入批次数据到目标系统,批次ID: {}, 目标ORG类型: {}", id, targetOrgType);
+
+ if (id == null) {
+ log.error("批次ID不能为空");
+ result.put("success", false);
+ result.put("message", "批次ID不能为空");
+ return result;
+ }
+
+ if (targetOrgType == null || targetOrgType.trim().isEmpty()) {
+ log.error("目标ORG类型不能为空");
+ result.put("success", false);
+ result.put("message", "目标ORG类型不能为空");
+ return result;
+ }
+
+ DataiIntegrationBatch batch = selectDataiIntegrationBatchById(id);
+ if (batch == null) {
+ log.error("批次不存在,批次ID: {}", id);
+ result.put("success", false);
+ result.put("message", "批次不存在");
+ return result;
+ }
+
+ String objectApi = batch.getApi();
+ if (objectApi == null || objectApi.trim().isEmpty()) {
+ log.error("批次对象API为空,批次ID: {}", id);
+ result.put("success", false);
+ result.put("message", "批次对象API不能为空");
+ return result;
+ }
+
+ String tableName = objectApi.trim();
+ if (customMapper.checkTable(tableName) == null) {
+ log.error("本地表不存在,表名: {}", tableName);
+ result.put("success", false);
+ result.put("message", "本地表不存在: " + tableName);
+ return result;
+ }
+
+ log.info("准备插入批次 {} 的对象 {} 数据到目标系统", id, objectApi);
+
+ IPartnerV1Connection targetConnection = null;
+ try {
+ targetConnection = soapConnectionFactory.getConnection(targetOrgType);
+ if (targetConnection == null) {
+ log.error("无法获取目标系统连接,ORG类型: {}", targetOrgType);
+ result.put("success", false);
+ result.put("message", "无法获取目标系统连接");
+ return result;
+ }
+
+ DescribeSObjectResult objDetail = targetConnection.describeSObject(objectApi);
+ if (objDetail == null) {
+ log.error("目标系统不存在该对象,对象API: {}", objectApi);
+ result.put("success", false);
+ result.put("message", "目标系统不存在该对象: " + objectApi);
+ return result;
+ }
+
+ String batchField = batch.getBatchField();
+ String whereClause = "";
+ if (batchField != null && !batchField.trim().isEmpty()) {
+ whereClause = "WHERE " + batchField.trim() + " = '" + batch.getBatchValue() + "'";
+ }
+
+ log.info("开始查询本地批次数据,表名: {}, 条件: {}", tableName, whereClause);
+ List