AttendanceServiceImpl.java 13.8 KB
package com.ruoyi.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.domain.*;
import com.ruoyi.driver.mapper.DriverMapper;
import com.ruoyi.num.domain.RuleNum;
import com.ruoyi.num.service.IRuleNumService;
import com.ruoyi.pojo.dto.DriverDto;
import com.ruoyi.pojo.dto.RuleSchedulingDto;
import com.ruoyi.pojo.dto.SchedulingDto;
import com.ruoyi.pojo.dto.SchedulingSettingDto;
import com.ruoyi.pojo.vo.*;
import com.ruoyi.scheduling.domain.RuleScheduling;
import com.ruoyi.scheduling.service.IRuleSchedulingService;
import com.ruoyi.scheduling.service.impl.RuleSchedulingServiceImpl;
import com.ruoyi.service.*;
import com.ruoyi.utils.ConstDateUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.ruoyi.common.RuleSchedulingProperties.*;
import static com.ruoyi.common.WeekEnum.FREE;

/**
 * @author 20412
 */
@Service
public class AttendanceServiceImpl implements AttendanceService {

    @Autowired
    private DriverMapper driverMapper;

    @Autowired
    private IRuleSchedulingService ruleSchedulingService;

    @Autowired
    private RuleNumSettingService ruleNumSettingService;

    @Autowired
    private RuleSettingDriverService settingDriverService;

    @Autowired
    private RuleSettingSchedulingService settingSchedulingService;

    @Autowired
    private RuleAttendanceMainService attendanceMainService;

    @Autowired
    private IRuleNumService ruleNumService;


    @Override
    public List<PeopleResponseVo> getDriverInfo(Long id) {
        List<PeopleResponseVo> vos;
        if (id != null) {
            vos = driverMapper.queryAttendanceInfoById(id);
        } else {
            // 获取所有为设置考勤的人员
            vos = driverMapper.queryAttendanceInfoAll();
        }
        return vos;
    }

    @Override
    public List<SchedulingResponseVo> getSchedulingList(SchedulingRequestVo vo) {
        // 查询排班设置表
        PageUtils.startPage();
        List<SchedulingResponseVo> vos = ruleNumSettingService.getSchedulingList(vo);
        if (CollectionUtil.isEmpty(vos)) {
            return vos;
        }
        List<Integer> settingIdList = vos.stream().map(SchedulingResponseVo::getId).collect(Collectors.toList());
        // 查询对应的规则
        List<DriverDto> driverList = settingDriverService.queryDriverListBySettingId(settingIdList);
        List<RuleSchedulingDto> schedulingList = settingSchedulingService.querySchedulingListBySettingId(settingIdList);
        handleSchedulingResponse(vos, driverList, schedulingList);
        return vos;
    }

    @Override
    public List<RuleNumTemplateVo> getTemplate(Long id) {
        RuleNum ruleNum = ruleNumService.selectRuleNumById(id);
        if (Objects.isNull(ruleNum)) {
            return null;
        }
        // 当为固定规则时
        if (RULE_TYPE_FIXED.equals(ruleNum.getRuleType())) {
            return handleFixedTemplate(ruleNum);
        }
        // 处理按星期
        else {
            return handleWeekTemplate(ruleNum);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSchedulingSetting(SchedulingSettingDto dto) {
        RuleNumSetting setting = getRuleNumSetting(dto);
        ruleNumSettingService.save(setting);
        List<RuleSettingScheduling> schedulingList = getSettingSchedulingList(dto, setting.getId());
        settingSchedulingService.saveBatch(schedulingList);
        if (CollectionUtil.isNotEmpty(dto.getPeopleList())) {
            List<RuleSettingDriver> peopleList = getSettingDriverList(dto, setting.getId());
            settingDriverService.remove(new QueryWrapper<RuleSettingDriver>().lambda().in(RuleSettingDriver::getJobCode, peopleList.stream().map(RuleSettingDriver::getJobCode).collect(Collectors.toList())));
            settingDriverService.saveBatch(peopleList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSchedulingSetting(SchedulingDto dto) {
        RuleNumSetting setting = new RuleNumSetting();
        getRumSettingByDto(dto, setting);
        ruleNumSettingService.updateById(setting);
        // 更新规则
        settingSchedulingService.remove(new QueryWrapper<RuleSettingScheduling>().lambda().eq(RuleSettingScheduling::getSettingId, dto.getId()));
        settingSchedulingService.saveBatch(dto.getRuleSchedulingList());
        // 更新人员
        settingDriverService.remove(new QueryWrapper<RuleSettingDriver>()
                .lambda()
                .eq(RuleSettingDriver::getSettingId, dto.getId()));
        settingDriverService.saveBatch(dto.getPeopleList());
    }

    @Override
    public void deleteSchedulingSetting(Integer settingId) {
        ruleNumSettingService.removeById(settingId);
        // 更新规则
        settingSchedulingService.remove(new QueryWrapper<RuleSettingScheduling>().lambda().eq(RuleSettingScheduling::getSettingId, settingId));
        // 更新人员
        settingDriverService.remove(new QueryWrapper<RuleSettingDriver>()
                .lambda()
                .eq(RuleSettingDriver::getSettingId, settingId));
    }

    @Override
    public List<RuleAttendanceMain> queryAttendanceMain(RuleAttendanceMainRequestVo vo) {
        PageUtils.startPage();
        List<RuleAttendanceMain> list = attendanceMainService.list(new QueryWrapper<RuleAttendanceMain>()
                .lambda()
                .eq(RuleAttendanceMain::getSchedulingDate, vo.getDate()));
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAttendance(UpdateAttendanceVo vo) {
        RuleAttendanceMain main = new RuleAttendanceMain();
        RuleScheduling ruleScheduling = ruleSchedulingService.selectRuleSchedulingById(vo.getRuleId().longValue());
        BeanUtils.copyProperties(ruleScheduling, main);
        main.setFirstWorkSignInTime(ConstDateUtil.dateAddition(LocalDate.now().toString(), ConstDateUtil.formatDate("HH:mm:ss", main.getFirstWorkSignInTime())));
        if (HAVE_SEGMENTATION.equals(ruleScheduling.getSecondFlag())) {
            main.setFirstQuittingSignInTime(ConstDateUtil.dateAddition(LocalDate.now().toString(), ConstDateUtil.formatDate("HH:mm:ss", main.getFirstQuittingSignInTime())));
            main.setSecondWorkSignInTime(ConstDateUtil.dateAddition(LocalDate.now().toString(), ConstDateUtil.formatDate("HH:mm:ss", main.getSecondWorkSignInTime())));
            // 处理隔天
            if (TOMORROW_YES.equals(ruleScheduling.getFirstSignInDayTomorrow())) {
                main.setSecondQuittingSignInTime(ConstDateUtil.dateAddition(LocalDate.now().plusDays(1).toString(), ConstDateUtil.formatDate("HH:mm:ss", main.getSecondQuittingSignInTime())));
            } else {
                main.setSecondQuittingSignInTime(ConstDateUtil.dateAddition(LocalDate.now().toString(), ConstDateUtil.formatDate("HH:mm:ss", main.getSecondQuittingSignInTime())));
            }
        } else {
            // 处理隔天
            if (TOMORROW_YES.equals(ruleScheduling.getFirstSignInDayTomorrow())) {
                main.setFirstQuittingSignInTime(ConstDateUtil.dateAddition(LocalDate.now().plusDays(1).toString(), ConstDateUtil.formatDate("HH:mm:ss", main.getFirstQuittingSignInTime())));
            } else {
                main.setFirstQuittingSignInTime(ConstDateUtil.dateAddition(LocalDate.now().toString(), ConstDateUtil.formatDate("HH:mm:ss", main.getFirstQuittingSignInTime())));
            }
        }
        main.setWorkFlag(ruleScheduling.getId() == 0 ? FREE_FLAG : WORK_FLAG);
        attendanceMainService.updateByJobCodeTotalQuantity(vo, main);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAttendance(DeleteAttendanceVo vo) {
        attendanceMainService.deleteByJobCodeTotalRecord(vo);
    }

    @Override
    public List<RuleAttendanceMainHelp> getPeopleList(PeopleRequestVo vo) {
        return attendanceMainService.queryPeopleList(vo);
    }

    private static void getRumSettingByDto(SchedulingDto dto, RuleNumSetting setting) {
        setting.setId(dto.getId());
        setting.setUpdateTime(DateUtils.getNowDate());
        setting.setUpdateBy(SecurityUtils.getUsername());
        setting.setRuleNumId(dto.getRuleNumId());
        setting.setRuleDictName(dto.getRuleDictName());
    }

    private List<RuleSettingDriver> getSettingDriverList(SchedulingSettingDto dto, Integer id) {
        return dto
                .getPeopleList()
                .stream()
                .map(item -> {
                    RuleSettingDriver driver = new RuleSettingDriver();
                    driver.setSettingId(id);
                    driver.setJobCode(item.getJobCode());
                    if (item.getStartDate() == null) {
                        throw new RuntimeException("非法开始时间");
                    }
                    driver.setStartDate(item.getStartDate());
                    return driver;
                })
                .collect(Collectors.toList());
    }

    private List<RuleSettingScheduling> getSettingSchedulingList(SchedulingSettingDto dto, Integer id) {
        // TODO 规则校验
        return dto.getRuleSchedulingList().stream().peek(item -> {
            item.setSettingId(id);
        }).collect(Collectors.toList());
    }

    private static RuleNumSetting getRuleNumSetting(SchedulingSettingDto dto) {
        RuleNumSetting setting = new RuleNumSetting();
        setting.setCreateTime(DateUtils.getNowDate());
        setting.setUpdateTime(DateUtils.getNowDate());
        String username = SecurityUtils.getUsername();
        setting.setCreateBy(username);
        setting.setUpdateBy(username);
        setting.setRuleDictName(dto.getRuleDictName());
        setting.setRuleNumId(dto.getRuleNumId());
        return setting;
    }

    private List<RuleNumTemplateVo> handleWeekTemplate(RuleNum ruleNum) {
        String[] strings = ruleNum.getRuleWeek().split(",");
        Map<Integer, Integer> weeks = Stream.of(strings).collect(Collectors.toMap(s -> Integer.parseInt(s), s -> Integer.parseInt(s)));
        List<RuleNumTemplateVo> vos = new ArrayList<>(7);
        for (int i = 1; i <= 7; i++) {
            Integer integer = weeks.get(i);
            if (Objects.isNull(integer)) {
                vos.add(getRuleNumTemplateVo(i, false));
            } else {
                vos.add(getRuleNumTemplateVo(integer, true));
            }
        }
        return vos;
    }

    private List<RuleNumTemplateVo> handleFixedTemplate(RuleNum ruleNum) {
        int countDay = ruleNum.getWorkDay() + ruleNum.getFreeDay();
        List<RuleNumTemplateVo> vos = new ArrayList<>(countDay);
        for (int i = 1; i <= countDay; i++) {
            vos.add(getRuleNumTemplateVo(i, i <= ruleNum.getWorkDay()));
        }
        return vos;
    }

    private RuleNumTemplateVo getRuleNumTemplateVo(Integer serialNumber, Boolean workFlag) {
        RuleNumTemplateVo vo = new RuleNumTemplateVo();
        vo.setSerialNumber(serialNumber);
        vo.setType(workFlag ? WORK_FLAG : FREE_FLAG);
        return vo;
    }

    private void handleSchedulingResponse(List<SchedulingResponseVo> vos, List<DriverDto> driverList, List<RuleSchedulingDto> schedulingList) {
        Map<Integer, List<DriverDto>> driverMap = transFromMapByDriver(driverList);
        Map<Integer, List<RuleScheduling>> schedulingMap = transFromMapByScheduling(schedulingList);
        for (SchedulingResponseVo vo : vos) {
            vo.setPeopleList(handlePeopleList(vo.getId(), driverMap.get(vo.getId())));
            vo.setRuleList(handleRuleList(vo.getId(), schedulingMap.get(vo.getId())));
        }
    }

    private Map<Integer, List<RuleScheduling>> transFromMapByScheduling(List<RuleSchedulingDto> schedulingList) {
        Map<Integer, List<RuleScheduling>> map = new HashMap<>(16);
        for (RuleSchedulingDto scheduling : schedulingList) {
            List<RuleScheduling> list = map.get(scheduling.getSettingId());
            if (CollectionUtil.isEmpty(list)) {
                map.put(scheduling.getSettingId(), new ArrayList<>(Arrays.asList(scheduling)));
            } else {
                list.add(scheduling);
            }
        }
        return map;
    }

    private Map<Integer, List<DriverDto>> transFromMapByDriver(List<DriverDto> driverList) {
        Map<Integer, List<DriverDto>> map = new HashMap<>(16);
        for (DriverDto driver : driverList) {
            List<DriverDto> list = map.get(driver.getSettingId());
            if (CollectionUtil.isEmpty(list)) {
                map.put(driver.getSettingId(), new ArrayList<>(Arrays.asList(driver)));
            } else {
                list.add(driver);
            }
        }
        return map;
    }

    private List<String> handleRuleList(Integer id, List<RuleScheduling> schedulingList) {
        List<RuleSchedulingVo> list = RuleSchedulingServiceImpl.handleRuleScheduling(schedulingList);
        if (CollectionUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        return list.stream().map(item -> {
            if (item.getRuleName().equals(FREE.getDescription())) {
                return item.getRuleName();
            }
            return item.getRuleName() + "(" + item.getRangeTime() + ")";
        }).collect(Collectors.toList());
    }

    private List<String> handlePeopleList(Integer id, List<DriverDto> driverList) {
        if (CollectionUtil.isEmpty(driverList)) {
            return new ArrayList<>();
        }
        return driverList.stream().map(item -> item.getPersonnelName() + "(" + item.getJobCode() + ")").collect(Collectors.toList());
    }
}