yangys
2024-11-15 d66fe6d46cdbaeb88e68ad96da6deb0b35cd131b
smart-man-boot/src/main/java/com/qianwen/smartman/modules/smis/service/impl/CalendarServiceImpl.java
@@ -10,6 +10,7 @@
import java.time.temporal.TemporalUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
@@ -30,7 +31,7 @@
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.commons.lang3.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
@@ -94,6 +95,7 @@
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
@Service
public class CalendarServiceImpl extends ServiceImpl<CalendarMapper, ProductionCalendar> implements ICalendarService {
@@ -114,6 +116,9 @@
    @Transactional(rollbackFor = {Exception.class})
    public ProductionCalendar saveCalendar(CalendarSaveVO calendarSaveVO) {
        checkCalendar(calendarSaveVO, AuthUtil.getTenantId());
        checkDateDTOList(calendarSaveVO.getDateDTOList());
        ProductionCalendar productionCalendar = ProductionCalendarConvert.INSTANCE.conver(calendarSaveVO);
        save(productionCalendar);
        saveCalendarDayTime(calendarSaveVO.getDateDTOList(), productionCalendar);
@@ -130,13 +135,48 @@
        return productionCalendar;
    }
    @Transactional
    @Override
    public ProductionCalendar updateCalendar(CalendarUpdateVO calendarUpdateVO) {
       checkDateDTOList(calendarUpdateVO.getDateDTOList());
        this.calendarDayService.deleteByCalendarId(calendarUpdateVO.getId());
        this.calendarDaytimeService.deleteByCalendarId(calendarUpdateVO.getId());
        ProductionCalendar calendar = getById(calendarUpdateVO.getId());
        updateCalendarDayTime(calendarUpdateVO.getDateDTOList(), calendar);
        return calendar;
    }
    /**
     * 检查入参日期列表的重复数据,有重复则抛出错误信息
     * @param dateDTOList
     */
    void checkDateDTOList(List<CalendarDateDTO> dateDTOList) {
       List<LocalDate> dupList = dupulicateDate(dateDTOList);
       if(!dupList.isEmpty()) {
          String msg = StringUtils.join(dupList.stream().map(dt -> dt.format(DateTimeFormatter.ISO_DATE)).collect(Collectors.toList()), ",");
          throw new ServiceException("日期数据重复:"+msg);
       }
    }
    /***
     * 获取dateDTOList里面重复的数据(根据日期),日期一天只有一条
     * @param dateDTOList
     * @return
     */
    List<LocalDate> dupulicateDate(List<CalendarDateDTO> dateDTOList) {
       if(ObjectUtil.isEmpty(dateDTOList)) {
          return Collections.emptyList();
       }
       List<LocalDate> dupList = new ArrayList<>();
       Map<LocalDate, List<CalendarDateDTO>> map = dateDTOList.stream().collect(Collectors.groupingBy(CalendarDateDTO::getCalendarDate));
       map.forEach((date,dtoList) -> {
          if(dtoList.size()>1) {
             dupList.add(date);
          }
       });
       return dupList;
    }
    private void saveCalendarDayTime(List<CalendarDateDTO> dateDTOList, ProductionCalendar productionCalendar) {
@@ -258,52 +298,53 @@
    }
    private void updateCalendarDayTime(List<CalendarDateDTO> dateDTOList, ProductionCalendar calenadar) {
       final LocalDate localDateNow = LocalDate.now();
        Long calendarId = calenadar.getId();
        Integer year = calenadar.getYear();
        Integer currentYear = Integer.valueOf(LocalDate.now().getYear());
        Set<LocalDate> dateList = dateDTOList.stream().filter(c -> {
            return !Func.isNull(c.getModelId()) && Func.isNull(c.getOffDayId());
        }).map((v0) -> {
            return v0.getCalendarDate();
        }).collect(Collectors.toSet());
        Set<LocalDate> offDay = dateDTOList.stream().filter(c2 -> {
            return !Func.isNull(c2.getOffDayId());
        }).map((v0) -> {
            return v0.getCalendarDate();
        }).collect(Collectors.toSet());
        Integer currentYear = localDateNow.getYear();
        //提取出班制id不是null且不是休息日的 日期
        Set<LocalDate> dateList = dateDTOList.stream().filter(c -> (!Func.isNull(c.getModelId()) && Func.isNull(c.getOffDayId()))).map(CalendarDateDTO::getCalendarDate).collect(Collectors.toSet());
        //提取所有为休息日的日期
        /**/
        Set<LocalDate> offDay = dateDTOList.stream().filter(c -> !Func.isNull(c.getOffDayId())).map(CalendarDateDTO::getCalendarDate).collect(Collectors.toSet());
        //初始化最终要保存的day和daytime列表,等待后面代码填充
        List<ProductionCalendarDaytime> productionCalendarDaytimeList = new ArrayList<>();
        List<ProductionCalendarDay> productionCalendarDayList = new ArrayList<>();
        List<Long> modelIds = dateDTOList.stream().map((v0) -> {
            return v0.getModelId();
        }).distinct().collect(Collectors.toList());
        //提取所有班制id并去重
        List<Long> modelIds = dateDTOList.stream().map(CalendarDateDTO::getModelId).distinct().collect(Collectors.toList());
        Map<Long, ShiftVO> shiftDetailMap = this.shiftModelService.getShiftDetail(modelIds);
        Snowflake snowflake = IdUtil.createSnowflake(1L, 1L);
        
        //查询今天的daytime数据列表
        List<ProductionCalendarDaytime> todayDateTimeList = this.calendarDaytimeService.list(new QueryWrapper<ProductionCalendarDaytime>().lambda()
                .eq(ProductionCalendarDaytime::getCalendarDate, LocalDate.now())
                .eq(ProductionCalendarDaytime::getCalendarDate, localDateNow)
                .eq(ProductionCalendarDaytime::getCalendarId, calendarId)
                .orderByAsc(ProductionCalendarDaytime::getStartTime));
        
        
        List<ProductionCalendarDaytime> curProductionCalendarDayTimeList = new ArrayList<>();
        LocalDate lastDayOfYear = LocalDateTimeUtils.getLastDayOfYear(LocalDate.now());
        long difference = year.intValue() == LocalDate.now().getYear() ? LocalDateTimeUtils.getDifference(LocalDate.now(), lastDayOfYear).intValue() : LocalDateTimeUtils.getDayOfYear(year).intValue() - 1;
        long j = 0;
        while (true) {
            long i = j;
            if (i <= difference) {
                LocalDate needHandleDate = year.equals(currentYear) ? LocalDate.now().plus(difference - i, ChronoUnit.DAYS) : LocalDate.of(year.intValue(), 1, 1).plus(difference - i, ChronoUnit.DAYS);// (TemporalUnit) ChronoUnit.DAYS
                LocalDate nextNeedHandleDate = needHandleDate.plus(1L, (TemporalUnit) ChronoUnit.DAYS);
                buildCurrentDayTime(dateDTOList, calendarId, year, dateList, offDay, productionCalendarDaytimeList, productionCalendarDayList, shiftDetailMap, snowflake, curProductionCalendarDayTimeList, needHandleDate);
                handleConflietDayTime(calenadar, year, productionCalendarDaytimeList, todayDateTimeList, curProductionCalendarDayTimeList, difference, i, needHandleDate, nextNeedHandleDate);
                j = i + 1;
            } else {
                this.calendarDayService.saveBatchDay(productionCalendarDayList);
                this.calendarDaytimeService.saveBatchDaytime(productionCalendarDaytimeList);
                return;
            }
        LocalDate lastDayOfYear = LocalDateTimeUtils.getLastDayOfYear(localDateNow);//今年最后一天
        //日历的年份与当前年份相同,则返回: 今年最后一天-今天 的天数差.否则返回:一整年的天数-1
        //difference 也就是实际需要排班的总天数
        long difference = year.intValue() == localDateNow.getYear() ? LocalDateTimeUtils.getDifference(localDateNow, lastDayOfYear) : LocalDateTimeUtils.getDayOfYear(year) - 1;
        //计算并生成day和daytime数据
        for (long i = 0; i < difference; i++) {//修改i<=difference 改为i<difference,下面代码difference - i在最后一次循环difference - i=0,也就是当天了,当天是不能排班的,而且会造成day数据重复
           //考虑LocalDate.now()实例化,plus改为plusDays
           //LocalDate needHandleDate = year.equals(currentYear) ? localDateNow.plus(difference - i, ChronoUnit.DAYS) : LocalDate.of(year, 1, 1).plus(difference - i, ChronoUnit.DAYS);
           LocalDate needHandleDate = year.equals(currentYear) ? localDateNow.plusDays(difference - i) : LocalDate.of(year, 1, 1).plusDays(difference - i);
           //LocalDate nextNeedHandleDate = needHandleDate.plus(1, ChronoUnit.DAYS);
           LocalDate nextNeedHandleDate = needHandleDate.plusDays(1);
           buildCurrentDayTime(dateDTOList, calendarId, year, dateList, offDay, productionCalendarDaytimeList, productionCalendarDayList, shiftDetailMap, snowflake, curProductionCalendarDayTimeList, needHandleDate);
           handleConflietDayTime(calenadar, year, productionCalendarDaytimeList, todayDateTimeList, curProductionCalendarDayTimeList, difference, i, needHandleDate, nextNeedHandleDate);
        }
        //保存day和daytime数据
        this.calendarDayService.saveBatchDay(productionCalendarDayList);
        this.calendarDaytimeService.saveBatchDaytime(productionCalendarDaytimeList);
    }
    private void handleConflietDayTime(ProductionCalendar calenadar, Integer year, List<ProductionCalendarDaytime> productionCalendarDaytimeList, List<ProductionCalendarDaytime> todayDateTimeList, List<ProductionCalendarDaytime> curProductionCalendarDayTimeList, long difference, long i, LocalDate needHandleDate, LocalDate nextNeedHandleDate) {