{"record":{"id":"bde5faf386049733","repo":"jeecgboot/JeecgBoot","slug":"phone-realname-tenanterrorinfo","errorCode":null,"errorMessage":"手机号用户:{phone} 昵称：{realname}，{tenantErrorInfo}","messagePattern":"手机号用户:(.+?) 昵称：(.+?)，(.+?)","errorType":"exception","errorClass":"JeecgBootException","httpStatus":null,"severity":"warning","filePath":"jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantServiceImpl.java","lineNumber":147,"sourceCode":"        //循环租户id\n        for (String id:idArray) {\n            //获取被邀请人是否已存在\n            SysUserTenant userTenant = userTenantMapper.getUserTenantByTenantId(userId, Integer.valueOf(id));\n            if(null == userTenant){\n                SysUserTenant relation = new SysUserTenant();\n                relation.setUserId(userId);\n                relation.setTenantId(Integer.valueOf(id));\n                relation.setStatus(CommonConstant.USER_TENANT_NORMAL);\n                userTenantMapper.insert(relation);\n                //给当前用户添加租户下的所有套餐\n                this.addPackUser(userId,id);\n                //邀请用户加入租户，发送消息\n                this.sendInvitationTenantMessage(userByPhone,id);\n            }else{\n                // 代码逻辑说明: 【QQYUN-5885】邀请用户加入提示不准确------------\n                String tenantErrorInfo = getTenantErrorInfo(userTenant.getStatus());\n                String errMsg = \"手机号用户:\" + userByPhone.getPhone() + \" 昵称：\" + userByPhone.getRealname() + \"，\" + tenantErrorInfo;\n                throw new JeecgBootException(errMsg);\n            }\n        }\n    }\n\n    /**\n     * 低代码下发送邀请加入租户消息\n     * \n     * @param user\n     * @param id\n     */\n    private void sendInvitationTenantMessage(SysUser user, String id) {\n        LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();\n        // 发消息\n        SysTenant sysTenant = this.baseMapper.querySysTenant((Integer.valueOf(id)));\n        MessageDTO messageDTO = new MessageDTO();\n        messageDTO.setToAll(false);\n        messageDTO.setToUser(user.getUsername());\n        messageDTO.setFromUser(\"system\");","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantServiceImpl.java#L129-L165","documentation":"Thrown by invitationUserJoin when, for a given tenant id, the user is already linked (userTenantMapper.getUserTenantByTenantId returns non-null). The message is built dynamically: it embeds the phone, realname, and a tenantErrorInfo string describing the existing relation's status (e.g. already a member / under review / refused). JeecgBootException carries the full concatenated message.","triggerScenarios":"Inviting a user who already has a SysUserTenant relation with one of the tenants in the ids list. getTenantErrorInfo(status) maps the existing status code to a human reason; the loop throws on the first conflicting tenant.","commonSituations":"Re-inviting a user who is already a member; inviting into a tenant where the user is pending review; a previous invitation left a relation row that was never cleaned up; bulk invite that includes tenants the user already belongs to.","solutions":["Read the tenantErrorInfo in the message to see the existing status; if 'already a member', no action is needed.","If the user is under review, have an admin approve/reject the pending relation before re-inviting.","Filter the requested tenant ids to exclude tenants where the user already has an active relation before calling invitationUserJoin.","If the relation is stale/erroneous, remove the SysUserTenant row then retry."],"exampleFix":"// before\ntenantService.invitationUserJoin(allTenantIds, phone, \"\");\n\n// after\nList<Integer> eligible = allTenantIds.stream()\n    .filter(id -> userTenantMapper.getUserTenantByTenantId(userId, id) == null)\n    .collect(Collectors.toList());\nif (eligible.isEmpty()) {\n    return Result.ok(\"该用户已加入全部所选组织\");\n}\ntenantService.invitationUserJoin(String.join(\",\", eligible), phone, \"\");","handlingStrategy":"validation","validationCode":"for (String id : ids.split(\",\")) {\n    if (userTenantMapper.getUserTenantByTenantId(userId, Integer.valueOf(id)) != null) {\n        // exclude or notify; do not pass this tenant id\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    tenantService.invitationUserJoin(ids, phone, username);\n} catch (JeecgBootException e) {\n    if (e.getMessage().startsWith(\"手机号用户:\")) {\n        return Result.error(\"用户已在某组织中：\" + e.getMessage());\n    }\n    throw e;\n}","preventionTips":["Pre-filter requested tenant ids against existing relations before inviting.","Surface the tenantErrorInfo so the operator understands the existing status.","Clean up stale relation rows before bulk invites."],"tags":["tenant","invitation","state-conflict","jeecg-boot"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}