# 钉钉组织同步端点与管理员角色配置接口 Label: wayfinder:task Type: task Status: resolved Blocked by: 04 ## Question 在 crm-auth 实现两个接口,为联调铺设真实用户/组织数据: 1. **钉钉组织同步端点**(如 `POST /api/system/sync/dingtalk`,超管权限): - 引入 `com.github.tingyugetc520:dt-java:0.1.2` 依赖(用法结论见票据 04 的研究成果) - 复用 application.yml 现有钉钉配置与企业级 access token 能力(`DingTalkAuthClient.getCorpAccessToken`) - 拉取部门树 → `sys_dept`;拉取部门下用户 → `auth_user`(姓名/手机号/钉钉 userid 作 account/部门挂载) - **部门负责人是钉钉字段**(dept_manager_userid),随部门存入,不映射为系统角色 - 幂等 upsert:重跑不重复,钉钉侧改名可更新 2. **管理员角色配置接口**:给指定用户分配/回收管理员类角色(部门负责人/销售角色仍由角色管理体系承载,此接口只解决「同步进来的用户如何拿到角色」) 验收:同步全量组织后,用户列表/部门树接口能查到真实数据,角色配置接口可给 2~3 个用户配上角色。 ## Answer 两个接口均落在 crm-auth,测试全绿(`DtOrgSyncServiceImplTest` 3/3、`AuthUserServiceImplTest` 11/11,排除 crm-lead 既有失败后全量 EXIT=0)。 1. **钉钉组织同步** `POST /api/system/sync/dingtalk`(`@PreAuthorize("hasRole('ADMIN')")`,`SystemController`): - `DtOrgSyncServiceImpl`:部门链路用 dt-java SDK(`DtDepartmentService.list(null, true)`),用户链路因 dt-java 0.1.2 发布版 `DtUser` 缺 `isLeaderInDeparts` 改为 Hutool HTTP 直调 `/topapi/user/listbypage`(与 `DingTalkAuthClient` 同款手法,分页 100 + 100ms 限流);企业 token 共享 Redis key `crm:auth:dingtalk:corp-token`。 - 幂等键:`sys_dept.dt_dept_id`(新增字段 + 唯一索引 `uk_dt_dept_id`)匹配部门;`crm_auth_user.account`=钉钉 userid 匹配用户;unionId 写 `crm_auth_identity` 保证扫码登录映射。 - BFS 排序保证父部门先落库;主/兼职部门拆分(首个出现部门为主部门,其余 `sys_user_dept` 全量替换);`isLeaderInDepts` 聚合反写 `sys_dept.leader_user_id`(负责人只是部门字段,不映射角色);离职用户置 `employment_status=resigned` 不动 enabled;AtomicBoolean 防并发重入。 - 返回 `DtSyncResultDTO` 统计(部门/用户增改数、负责人反写数);失败统一错误码 61017 `CODE_DINGTALK_SYNC_FAIL`。 2. **管理员角色配置** `POST /api/system/users/admin-role`(`@PreAuthorize("hasRole('ADMIN')")`): - `IAuthUserService.configureAdminRoles(userId, roleCodes, grant)`:增量授予/回收,只动目标角色行(授予幂等、回收无则忽略),不影响其他角色;`roleCodes` 缺省 `ROLE_ADMIN`(`AuthConstants.ROLE_CODE_ADMIN`)。 - 校验顺序:userId null → codes 空 → 用户存在 → 角色编码存在;DTO 为 `ConfigureAdminRoleDTO`(ADR-0017 风格)。 已知边界:crm-lead `LeadServiceImplTest` 3 个「省份不能为空」失败为既有 committed 问题(必填误校验),归票据 07 盘点范围;`syncOrg()` 整体包在单个 `@Transactional` 内(含 HTTP 拉取),大规模组织下事务较长,若联调遇连接池/超时问题再拆小事务。 **真实同步验证挂起(用户确认「先留着」)**:端点链路已实测跑通(本地 :8081 verify profile,调试 token 见 `tmp/dt-token.txt`),但钉钉侧返回 errcode=60011——应用 `dingikqv3al2koirnku7` 未开通 `qyapi_get_department_list`(部门读)与 `qyapi_get_member`(成员读)权限。权限就绪后直接重试 `POST /api/system/sync/dingtalk` 即可,无需改代码。