@Override
  public List<DataApprovalLevel> getUserDataApprovalLevels() {
    UserCredentials userCredentials = currentUserService.getCurrentUser().getUserCredentials();

    boolean mayApprove = userCredentials.isAuthorized(DataApproval.AUTH_APPROVE);
    boolean mayApproveAtLowerLevels =
        userCredentials.isAuthorized(DataApproval.AUTH_APPROVE_LOWER_LEVELS);
    boolean mayAcceptAtLowerLevels =
        userCredentials.isAuthorized(DataApproval.AUTH_ACCEPT_LOWER_LEVELS);

    if (!mayApprove && !mayApproveAtLowerLevels && !mayAcceptAtLowerLevels) {
      return new ArrayList<>();
    }

    int lowestNumberOrgUnitLevel = getCurrentUsersLowestNumberOrgUnitLevel();

    boolean canSeeAllDimensions =
        CollectionUtils.isEmpty(userService.getCoDimensionConstraints(userCredentials))
            && CollectionUtils.isEmpty(userService.getCogDimensionConstraints(userCredentials));

    List<DataApprovalLevel> approvalLevels = getAllDataApprovalLevels();
    List<DataApprovalLevel> userDataApprovalLevels = new ArrayList<>();

    boolean addLevel = false;

    for (DataApprovalLevel approvalLevel : approvalLevels) {
      if (!addLevel && approvalLevel.getOrgUnitLevel() >= lowestNumberOrgUnitLevel) {
        CategoryOptionGroupSet cogs = approvalLevel.getCategoryOptionGroupSet();

        addLevel =
            securityService.canRead(approvalLevel) && cogs == null
                ? canSeeAllDimensions
                : (securityService.canRead(cogs)
                    && !CollectionUtils.isEmpty(categoryService.getCategoryOptionGroups(cogs)));
      }

      if (addLevel) {
        userDataApprovalLevels.add(approvalLevel);
      }
    }

    return userDataApprovalLevels;
  }
  /**
   * Get the approval level for a user for a given organisation unit. It is assumed that the user
   * has access to the organisation unit (must be checked elsewhere, it is not checked here.) If the
   * organisation unit is above all approval levels, returns null (no approval levels apply.)
   *
   * <p>If users are restricted to viewing approved data only, users may see data from lower levels
   * *only* if it is approved *below* this approval level (higher number approval level). Or, if
   * this method returns the lowest (highest number) approval level, users may see unapproved data.
   *
   * <p>If users have approve/unapprove authority (checked elsewhere, not here), the returned level
   * is the level at which users may approve/unapprove. If users have authority to approve at lower
   * levels, they may approve at levels below the returned level.
   *
   * <p>If users have accept/unaccept authority (checked elsewhere, not here), users may
   * accept/unaccept at the level just *below* this level.
   *
   * @param orgUnit organisation unit to test.
   * @param user the user.
   * @param approvalLevels app data approval levels.
   * @return approval level for user.
   */
  private DataApprovalLevel getUserApprovalLevel(
      OrganisationUnit orgUnit, User user, List<DataApprovalLevel> approvalLevels) {
    int userOrgUnitLevel = orgUnit.getLevel();

    DataApprovalLevel userLevel = null;

    for (DataApprovalLevel level : approvalLevels) {
      if (level.getOrgUnitLevel() >= userOrgUnitLevel
          && securityService.canRead(level)
          && canReadCOGS(user, level.getCategoryOptionGroupSet())) {
        userLevel = level;
        break;
      }
    }

    return userLevel;
  }