# ScheduleDepartmentEmployeeServiceImpl.java

    package cloud.wconnect.workperformance.service.schedule.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.schedule.ScheduleDepartment;
    import cloud.wconnect.workperformance.entity.schedule.ScheduleDepartmentEmployee;
    import cloud.wconnect.workperformance.entity.schedule.ScheduleInfo;
    import cloud.wconnect.workperformance.mapper.schedule.ScheduleDepartmentEmployeeMapper;
    import cloud.wconnect.workperformance.pojo.bo.schedule.ScheduleDepartmentEmployeeBO;
    import cloud.wconnect.workperformance.pojo.dto.schedule.ScheduleDepartmentEmployeeDTO;
    import cloud.wconnect.workperformance.pojo.dto.schedule.UpdateEmployeeDTO;
    import cloud.wconnect.workperformance.pojo.query.schedule.ScheduleEmployeeQuery;
    import cloud.wconnect.workperformance.service.schedule.IScheduleDepartmentEmployeeService;
    import cloud.wconnect.workperformance.service.schedule.IScheduleDepartmentService;
    import cloud.wconnect.workperformance.service.schedule.IScheduleInfoService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.util.*;
    import java.util.stream.Collectors;

    /**
     * <p>
     * 排班部门下员工 服务实现类
     * </p>
     *
     * @author yyt
     * @since 2023-06-28
     */
    @Service
    @DS("work_performance")
    public class ScheduleDepartmentEmployeeServiceImpl extends ServiceImpl<ScheduleDepartmentEmployeeMapper, ScheduleDepartmentEmployee> implements IScheduleDepartmentEmployeeService {

        @Autowired
        private IScheduleInfoService scheduleInfoService;
        @Autowired
        private IScheduleDepartmentService scheduleDepartmentService;
        @Autowired
        private BeanMapper beanMapper;

        /**
         * 校验存在
         *
         * @param id 员工 id
         * @return 员工
         * @author yyt
         * @date 2023/6/30
         */
        @Override
        public ScheduleDepartmentEmployee checkExist(int id) {
            ScheduleDepartmentEmployee employee = getById(id);
            if (Objects.isNull(employee)) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "the scheduleDepartmentEmployee is not found;id:" + id);
            }
            return employee;
        }

        /**
         * 变更用户部门
         *
         * @param employeeId   员工 id
         * @param departmentId 部门 id
         * @author yyt
         * @date 2023/6/30
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void changeEmployeeDepartment(Integer employeeId, Integer departmentId) {
            ScheduleDepartmentEmployee updateEmployee = new ScheduleDepartmentEmployee();
            updateEmployee.setDepartmentId(departmentId);
            updateEmployee.setId(employeeId);
            updateById(updateEmployee);

            scheduleInfoService.update(new UpdateWrapper<ScheduleInfo>().lambda().set(ScheduleInfo::getDepartmentId, departmentId)
                    .eq(ScheduleInfo::getEmployeeId, employeeId));
        }

        /**
         * 校验存在
         *
         * @param propertyId 资产 id
         * @param name       姓名
         * @param id         排除自身
         * @author yyt
         * @date 2023/7/3
         */
        @Override
        public void checkExist(Integer propertyId, String name, Integer id) {
            ScheduleDepartmentEmployee employee = getOne(new QueryWrapper<ScheduleDepartmentEmployee>().lambda()
                    .eq(ScheduleDepartmentEmployee::getPropertyId, propertyId)
                    .eq(ScheduleDepartmentEmployee::getName, name)
                    .ne(Objects.nonNull(id), ScheduleDepartmentEmployee::getId, id));
            if (Objects.nonNull(employee)) {
                String msg = "the scheduleDepartmentEmployee is existing;propertyId:" + propertyId + ",name:" + name;
                if (Objects.nonNull(id)) {
                    msg += ",id:" + id;
                }
                throw new BadRequestException(CommonErrorI18nConstant.DATA_EXISTED, BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        msg);
            }
        }

        /**
         * 处理员工报告数据
         *
         * @param properties               资产
         * @param employeeInfoByPropertyId 员工报告数据
         * @param uid                      操作人
         * @author yyt
         * @date 2023/7/7
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void handleEmployeeReportData(List<PropertyDTO> properties, Map<Integer, List<ScheduleDepartmentEmployeeBO>> employeeInfoByPropertyId,
                                             Integer uid) {
            for (PropertyDTO property : properties) {
                Integer propertyId = property.getId();
                List<ScheduleDepartmentEmployeeBO> employeeInfos = employeeInfoByPropertyId.get(propertyId);
                if (CollectionUtils.isNotEmpty(employeeInfos)) {
                    handleInsertDepartmentAndEmployee(propertyId, employeeInfos, uid);
                }
            }
        }

        /**
         * 处理插入部门、员工数据
         *
         * @param propertyId          资产 id
         * @param departmentEmployees 部门、员工信息
         * @param operatorId          操作人 id
         * @author yyt
         * @date 2023/7/8
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void handleInsertDepartmentAndEmployee(Integer propertyId, List<ScheduleDepartmentEmployeeBO> departmentEmployees, int operatorId) {
            // 插入部门
            Map<String, String> departmentNameByDepartmentCode = departmentEmployees.stream()
                    .collect(Collectors.toMap(ScheduleDepartmentEmployeeBO::getDepartmentCode,
                            ScheduleDepartmentEmployeeBO::getDepartmentName, (v1, v2) -> v2));
            Map<String, Integer> departmentIdByCode = scheduleDepartmentService.handleInsertDepartment(propertyId,
                    departmentNameByDepartmentCode);

            // 插入员工
            long nowTime = DateTimeUtils.nowTimestamp();
            baseMapper.insertOrUpdateBatch(departmentEmployees.stream().map(item -> {
                ScheduleDepartmentEmployee scheduleDepartmentEmployee = new ScheduleDepartmentEmployee();
                scheduleDepartmentEmployee.setPropertyId(propertyId);
                scheduleDepartmentEmployee.setDepartmentId(departmentIdByCode.get(item.getDepartmentCode()));
                scheduleDepartmentEmployee.setPositionId(item.getPositionId());
                scheduleDepartmentEmployee.setName(item.getName());
                scheduleDepartmentEmployee.setUpdatedBy(operatorId);
                scheduleDepartmentEmployee.setUpdatedTime(nowTime);
                return scheduleDepartmentEmployee;
            }).sorted(Comparator.comparing(ScheduleDepartmentEmployee::getName)).collect(Collectors.toList()));
        }

        /**
         * 匹配用户
         *
         * @param propertyId 资产
         * @param userNames  用户名称
         * @return 员工信息
         * @author yyt
         * @date 2023/7/10
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public Map<String, ScheduleDepartmentEmployee> matchUser(Integer propertyId, List<String> userNames) {
            Map<String, ScheduleDepartmentEmployee> employeeByLowerCaseName = list(new QueryWrapper<ScheduleDepartmentEmployee>()
                    .lambda().eq(ScheduleDepartmentEmployee::getPropertyId, propertyId)
                    .in(ScheduleDepartmentEmployee::getName, userNames)).stream()
                    .collect(Collectors.toMap(item -> StringUtils.lowerCase(item.getName()), v -> v));

            long nowTime = DateTimeUtils.nowTimestamp();

            List<ScheduleDepartmentEmployee> insertEmployees = userNames.stream()
                    .filter(item -> employeeByLowerCaseName.get(item.toLowerCase()) == null)
                    .map(item -> new ScheduleDepartmentEmployee(null, propertyId, ScheduleDepartment.MISCELLANEOUS_ID, StringUtils.EMPTY,
                            item, null, 0, nowTime)).collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(insertEmployees)) {
                saveBatch(insertEmployees);
                insertEmployees.forEach(item -> employeeByLowerCaseName.put(item.getName().toLowerCase(), item));
            }
            return employeeByLowerCaseName;
        }

        /**
         * 查询员工信息
         *
         * @param propertyId   资产 id
         * @param departmentId 部门 id
         * @param query        查询套件
         * @return 员工信息
         * @author yyt
         * @date 2024/11/22
         **/
        @Override
        public List<ScheduleDepartmentEmployee> list(Integer propertyId, Integer departmentId, ScheduleEmployeeQuery query) {
            return list(new QueryWrapper<ScheduleDepartmentEmployee>().lambda()
                    .eq(ScheduleDepartmentEmployee::getPropertyId, propertyId)
                    .eq(ScheduleDepartmentEmployee::getDepartmentId, departmentId)
                    .eq(StringUtils.isNotEmpty(query.getName()), ScheduleDepartmentEmployee::getName, query.getName())
                    .ne(Objects.nonNull(query.getEmployeeId()), ScheduleDepartmentEmployee::getId, query.getEmployeeId()));
        }

        /**
         * 获取员工信息
         *
         * @param propertyId    资产 id
         * @param id            部门 id
         * @param employeeQuery 查询套件
         * @return 员工信息
         * @author yyt
         * @date 2024/11/22
         **/
        @Override
        public List<ScheduleDepartmentEmployeeDTO> listEmployee(Integer propertyId, int id, ScheduleEmployeeQuery employeeQuery) {
            List<ScheduleDepartmentEmployee> employees = list(propertyId, id, employeeQuery);
            if (CollectionUtils.isEmpty(employees)) {
                return Collections.emptyList();
            }

            List<ScheduleDepartmentEmployeeDTO> employeeDTOList = employees.stream().peek(item -> {
                        if (Objects.isNull(item.getSort())) {
                            // 设置 -1，防止 npe
                            item.setSort(-1);
                        }
                    }).map(item -> beanMapper.map(item, ScheduleDepartmentEmployeeDTO.class))
                    .sorted(Comparator.comparing(ScheduleDepartmentEmployeeDTO::getSort)
                            .thenComparing(ScheduleDepartmentEmployeeDTO::getName, String.CASE_INSENSITIVE_ORDER))
                    .collect(Collectors.toList());
            // 去掉 -1
            employeeDTOList.forEach(item->{
                if(item.getSort() == -1){
                    item.setSort(null);
                }
            });

            return employeeDTOList;
        }

        /**
         * 保存员工信息
         *
         * @param propertyId          资产 id
         * @param departmentId        部门 id
         * @param updateEmployeeDTO   员工信息
         * @param userId              操作人
         * @author yyt
         * @date 2024/11/22
         **/
        @Override
        public void save(Integer propertyId, int departmentId, UpdateEmployeeDTO updateEmployeeDTO, int userId) {
            save(new ScheduleDepartmentEmployee()
                    .setPropertyId(propertyId)
                    .setDepartmentId(departmentId)
                    .setName(updateEmployeeDTO.getName())
                    .setSort(updateEmployeeDTO.getSort())
                    .setUpdatedBy(userId)
                    .setUpdatedTime(DateTimeUtils.nowTimestamp()));
        }

        /**
         * 更新员工信息
         *
         * @param employeeId        员工 id
         * @param updateEmployeeDTO 员工信息
         * @param userId            操作人
         * @author yyt
         * @date 2024/11/22
         **/
        @Override
        public void update(int employeeId, UpdateEmployeeDTO updateEmployeeDTO, int userId) {
            update(new UpdateWrapper<ScheduleDepartmentEmployee>().lambda()
                    .set(ScheduleDepartmentEmployee::getName, updateEmployeeDTO.getName())
                    .set(ScheduleDepartmentEmployee::getSort, updateEmployeeDTO.getSort())
                    .set(ScheduleDepartmentEmployee::getUpdatedBy, userId)
                    .set(ScheduleDepartmentEmployee::getUpdatedTime, DateTimeUtils.nowTimestamp())
                    .eq(ScheduleDepartmentEmployee::getId, employeeId));
        }

    }