jeecgboot/JeecgBoot · error · JeecgBootBizTipException

当前子级存在子公司,无法变更为部门!

Error message

当前子级存在子公司,无法变更为部门!

What it means

verifyOrgCategory rule: a node cannot become a DEPART (部门) if any of its children are COMPANY or SUB_COMPANY, because a department may not be the parent of a company-level node. Children are counted by parent_id where orgCategory is in {COMPANY, SUB_COMPANY}.

Source

Thrown at jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysDepartServiceImpl.java:362

        //如果是子公司的情况下,则上级不能为部门或者岗位
        if (oConvertUtils.isNotEmpty(sysDepart.getOrgCategory()) && DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue().equals(sysDepart.getOrgCategory())
                && oConvertUtils.isNotEmpty(sysDepart.getParentId())) {
            LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysDepart::getId, sysDepart.getParentId());
            queryWrapper.in(SysDepart::getOrgCategory, DepartCategoryEnum.DEPART_CATEGORY_POST.getValue(), DepartCategoryEnum.DEPART_CATEGORY_DEPART.getValue());
            long count = this.count(queryWrapper);
            if (count > 0) {
                throw new JeecgBootBizTipException("当前父级为部门或岗位,无法变更为子公司!");
            }
        }
        //如果是部门的情况下,下级不能为子公司或者公司
        if (oConvertUtils.isNotEmpty(sysDepart.getOrgCategory()) && DepartCategoryEnum.DEPART_CATEGORY_DEPART.getValue().equals(sysDepart.getOrgCategory())) {
            LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysDepart::getParentId, sysDepart.getId());
            queryWrapper.in(SysDepart::getOrgCategory, DepartCategoryEnum.DEPART_CATEGORY_COMPANY.getValue(), DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue());
            long count = this.count(queryWrapper);
            if (count > 0) {
                throw new JeecgBootBizTipException("当前子级存在子公司,无法变更为部门!");
            }
        }
    }
    
    @Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteBatchWithChildren(List<String> ids) {
		//存放子级的id
		List<String> idList = new ArrayList<String>();
		//存放父级的id
		List<String> parentIdList = new ArrayList<>();
		for(String id: ids) {
			idList.add(id);
			//此步骤是为了删除子级
			this.checkChildrenExists(id, idList);
			// 代码逻辑说明: 【QQYUN-5757】批量删除部门时未正确置为叶子节点 ------------
			SysDepart depart = this.getDepartById(id);
			if (oConvertUtils.isNotEmpty(depart.getParentId())) {

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Re-parent the COMPANY/SUB_COMPANY children to another company-level node first.
  2. Alternatively, keep the node as COMPANY or SUB_COMPANY.
  3. Count company-level children before applying the demotion and warn the user.

Example fix

// before
sysDepart.setOrgCategory(DepartCategoryEnum.DEPART_CATEGORY_DEPART.getValue());
sysDepartService.updateById(sysDepart); // has SUB_COMPANY child -> throws
// after
long coKids = sysDepartService.count(new LambdaQueryWrapper<SysDepart>()
        .eq(SysDepart::getParentId, sysDepart.getId())
        .in(SysDepart::getOrgCategory,
            DepartCategoryEnum.DEPART_CATEGORY_COMPANY.getValue(),
            DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue()));
if (coKids > 0) {
    return Result.error("存在公司级子级, 无法变更为部门");
}
sysDepart.setOrgCategory(DepartCategoryEnum.DEPART_CATEGORY_DEPART.getValue());
sysDepartService.updateById(sysDepart);
Defensive patterns

Strategy: validation

Validate before calling

// Count company-level children before demoting to DEPART.
long coKids = sysDepartService.count(new LambdaQueryWrapper<SysDepart>()
    .eq(SysDepart::getParentId, sysDepart.getId())
    .in(SysDepart::getOrgCategory,
        DepartCategoryEnum.DEPART_CATEGORY_COMPANY.getValue(),
        DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue()));
if (DepartCategoryEnum.DEPART_CATEGORY_DEPART.getValue().equals(sysDepart.getOrgCategory()) && coKids > 0) {
    return Result.error("存在公司级子级, 无法变更为部门");
}

Type guard

public boolean canBecomeDepart(SysDepart node) {
    if (!DepartCategoryEnum.DEPART_CATEGORY_DEPART.getValue().equals(node.getOrgCategory())) return true;
    long n = this.count(new LambdaQueryWrapper<SysDepart>()
        .eq(SysDepart::getParentId, node.getId())
        .in(SysDepart::getOrgCategory,
            DepartCategoryEnum.DEPART_CATEGORY_COMPANY.getValue(),
            DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue()));
    return n == 0;
}

Try / catch

try {
    sysDepartService.updateById(sysDepart);
} catch (JeecgBootBizTipException e) {
    if (e.getMessage() != null && e.getMessage().contains("无法变更为部门")) {
        return Result.error("请先转移公司级子级");
    }
    throw e;
}

Prevention

When it happens

Trigger: Setting orgCategory=DEPART on a node that has child rows whose orgCategory is COMPANY or SUB_COMPANY.

Common situations: Demoting a company-level node that still owns subsidiaries; restructuring that flattens the tree without re-parenting company children first.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/40e921d5d7b50674. Report an issue: GitHub.