# DepartmentCategoryController.java

    package cloud.wconnect.workperformance.controller.sva;

    import cloud.wconnect.commonlib.annotation.ApiId;
    import cloud.wconnect.commonlib.component.SessionContext;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.pojo.dto.group.Addition;
    import cloud.wconnect.commonlib.pojo.dto.group.Edition;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.workperformance.cons.sva.SvaErrorI18nConstant;
    import cloud.wconnect.workperformance.cons.sva.SvaI18nConstant;
    import cloud.wconnect.workperformance.entity.sva.setting.DepCodeToCategory;
    import cloud.wconnect.workperformance.entity.sva.setting.DepartmentCategory;
    import cloud.wconnect.workperformance.pojo.dto.sva.category.CategoryDTO;
    import cloud.wconnect.workperformance.pojo.dto.sva.category.DepartmentCategoryDTO;
    import cloud.wconnect.workperformance.pojo.dto.sva.category.DepartmentCodeUsableDTO;
    import cloud.wconnect.workperformance.pojo.query.sva.setting.DepartmentCodeUsableQuery;
    import cloud.wconnect.workperformance.pojo.query.sva.setting.DepartmentQuery;
    import cloud.wconnect.workperformance.service.sva.actualschedulehour.ISvaActualScheduleRecordService;
    import cloud.wconnect.workperformance.service.sva.employees.IAttendanceEmployeeService;
    import cloud.wconnect.workperformance.service.sva.setting.IDepCodeToCategoryService;
    import cloud.wconnect.workperformance.service.sva.setting.IDepartmentCategoryService;
    import com.google.common.collect.ImmutableMap;
    import jakarta.annotation.Resource;
    import jakarta.validation.Valid;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;

    import java.text.MessageFormat;
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;

    /**
     * <p>
     * 控制器类：部门分类
     * </p>
     *
     * @author zc
     * @since 2023-02-22
     */
    @RestController
    @RequestMapping("/sva/setting/department/category")
    public class DepartmentCategoryController {
        @Resource
        private IDepartmentCategoryService departmentCategoryService;
        @Resource
        private IAttendanceEmployeeService attendanceEmployeeService;
        @Resource
        private IDepCodeToCategoryService depCodeToCategoryService;
        @Resource
        private ISvaActualScheduleRecordService actualScheduleRecordService;
        @Resource
        private SessionContext sessionContext;
        @Resource
        private I18nMessageUtils i18nMessageUtils;

        /**
         * 根据 property id 获取 Category 数据
         *
         * @param property 资产标识
         * @return Category 数据
         * @author zc
         * @date 2023/2/22
         */
        @ApiId(63)
        @GetMapping("/list")
        public List<DepartmentCategoryDTO> list(@RequestParam String property, @Valid DepartmentQuery query) {
            int propertyId = sessionContext.getPropertyId(property);
            return departmentCategoryService.list(propertyId, query);
        }

        /**
         * 新增 department category
         *
         * @param property    资产标识
         * @param categoryDTO department category
         * @return department category id
         * @author zc
         * @date 2023/3/13
         */
        @ApiId(93)
        @PostMapping
        public Map<String, Integer> insert(@RequestParam String property, @RequestBody @Validated(Addition.class) CategoryDTO categoryDTO) {
            int propertyId = sessionContext.getPropertyId(property);

            // 若新增的是正在使用及历史版本，则增加限制，不能操作
            if (Objects.nonNull(categoryDTO.getVersion())) {
                departmentCategoryService.checkUpdateVersion(propertyId, Integer.parseInt(categoryDTO.getVersion()));
            }

            // 检查指定 property id、指定 版本下, code 是否重复
            int version = Objects.isNull(categoryDTO.getVersion()) ? BaseConstant.ZERO : Integer.parseInt(categoryDTO.getVersion());
            if (depCodeToCategoryService.checkRepeat(propertyId, version, categoryDTO.getDepartmentCode(), null)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_EXISTED,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "the department code is already exist");
            }

            categoryDTO.setPropertyId(propertyId);
            return ImmutableMap.of("id", departmentCategoryService.insert(categoryDTO, sessionContext.getLoginUserId()));
        }

        /**
         * 编辑 department category
         *
         * @param property    资产标识
         * @param categoryDTO department category
         * @return empty map
         * @author zc
         * @date 2023/3/13
         */
        @ApiId(94)
        @PutMapping
        public Map<Object, Object> update(@RequestParam String property, @RequestBody @Validated(Edition.class) CategoryDTO categoryDTO) {
            DepartmentCategory departmentCategory = departmentCategoryService.getById(categoryDTO.getCategoryId());
            if (Objects.isNull(departmentCategory)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The department category to be update is not found; departmentCategoryId: " + categoryDTO.getCategoryId());
            }
            int propertyId = sessionContext.getPropertyId(property);
            if (!departmentCategory.getPropertyId().equals(propertyId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("Cannot update the department category. paramPropertyId: {0}; propertyId: {1}",
                                propertyId, departmentCategory.getPropertyId()));
            }

            // 若修改的部门分类属于当前正在使用或历史版本的数据，则不支持操作
            if (departmentCategory.getVersion() != BaseConstant.ZERO) {
                departmentCategoryService.checkUpdateVersion(propertyId, departmentCategory.getVersion());
            }

            DepCodeToCategory depCodeToCategory = depCodeToCategoryService.getById(categoryDTO.getDepartmentId());
            if (Objects.isNull(depCodeToCategory)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        MessageFormat.format("The depCodeToCategory is not found; id: {0}",
                                categoryDTO.getDepartmentId()));
            }
            if (!Objects.equals(depCodeToCategory.getVersion(), departmentCategory.getVersion())) {
                throw new BadRequestException(SvaErrorI18nConstant.DEPARTMENT_VERSION_NOT_CONSISTENT,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        MessageFormat.format("The version of the department and department category is inconsistent;" +
                                        " departmentVersion: {0}; departmentCategoryVersion: {1}",
                                depCodeToCategory.getVersion(), departmentCategory.getVersion()));
            }

            // 编辑部门分类时，若 department code 被当前版本下的 考勤 / 员工 占用，则 department code 不支持编辑；
            Integer categoryId = depCodeToCategory.getDepCategoryId();
            String departmentCode = categoryDTO.getDepartmentCode();
            if (!departmentCode.equals(depCodeToCategory.getDepartmentCode())) {
                if (actualScheduleRecordService.checkOccupied(propertyId, categoryId)
                        || attendanceEmployeeService.checkOccupied(propertyId, categoryId)) {
                    throw new BadRequestException(CommonErrorI18nConstant.DATA_IS_IN_USE,
                            i18nMessageUtils.getErrorParamMapNeedTranslate(SvaI18nConstant.DEPARTMENT_CODE),
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                            "The department code is occupied by attendance data/employees and cannot be edited.");
                }
            }
            // 检查指定 property id、指定 版本下, code 是否重复
            if (depCodeToCategoryService.checkRepeat(propertyId, departmentCategory.getVersion(), departmentCode, depCodeToCategory.getId())) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_EXISTED,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "the department code is already exist");
            }

            categoryDTO.setPropertyId(propertyId);
            departmentCategoryService.update(depCodeToCategory, categoryDTO, sessionContext.getLoginUserId());
            return Collections.emptyMap();
        }

        /**
         * 删除 department category
         *
         * @param property 资产标识
         * @param id       department category id
         * @return empty map
         * @author zc
         * @date 2023/3/13
         */
        @ApiId(95)
        @DeleteMapping("/{id:\\d+}")
        public Map<Object, Object> remove(@RequestParam String property, @PathVariable int id) {
            DepartmentCategory departmentCategory = departmentCategoryService.getById(id);
            if (Objects.isNull(departmentCategory)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The department category to be remove is not found; departmentCategoryId: " + id);
            }
            int propertyId = sessionContext.getPropertyId(property);
            // 校验数据归属
            departmentCategoryService.checkBelong(propertyId, departmentCategory);

            // 若删除的部门分类属于当前正在使用或历史版本的数据，则不支持操作
            if (departmentCategory.getVersion() != BaseConstant.ZERO) {
                departmentCategoryService.checkUpdateVersion(propertyId, departmentCategory.getVersion());
            }

            // 如果在 考勤 / 员工 中被使用，则不可删除
            if (actualScheduleRecordService.checkOccupied(propertyId, departmentCategory.getId())
                    || attendanceEmployeeService.checkOccupied(propertyId, departmentCategory.getId())) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_IS_IN_USE,
                        i18nMessageUtils.getErrorParamMapNeedTranslate(SvaI18nConstant.DEPARTMENT),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "This category is being used and cannot be deleted; categoryId:" + id);
            }

            departmentCategoryService.removeDepartmentCategory(id);

            return Collections.emptyMap();
        }

        /**
         * 1351 - 校验 department code 是否可用
         *
         * @param property       资产标识
         * @param id             department category id
         * @param departmentCode department code
         * @param query          查询条件
         * @return 是否可用
         * @author yyt
         * @date 2025/3/24
         **/
        @ApiId(1351)
        @GetMapping("/{id:\\d+}/departmentCode/{departmentCode}/usable")
        public DepartmentCodeUsableDTO getUsable(@RequestParam String property, @PathVariable int id, @PathVariable String departmentCode,
                                                 @Valid DepartmentCodeUsableQuery query) {
            int propertyId = sessionContext.getPropertyId(property);

            if (id == BaseConstant.ZERO) {
                String versionStr = query.getVersion();
                // 新增部门分类时，若 department code 没有被其他部门分类占用，则可用
                int version = Objects.isNull(versionStr) ? BaseConstant.ZERO : Integer.parseInt(versionStr);
                Boolean repeat = depCodeToCategoryService.checkRepeat(propertyId, version, departmentCode, null);
                return new DepartmentCodeUsableDTO(repeat, null);
            } else {
                DepartmentCategory departmentCategory = departmentCategoryService.checkExist(id);
                departmentCategoryService.checkBelong(propertyId, departmentCategory);
                return departmentCategoryService.getUsable(departmentCategory, departmentCode);
            }
        }
    }