Commit 4adf9aaa by huangjinxin

Merge remote-tracking branch 'origin/develop' into develop

2 parents a55dfd99 23e192c9
...@@ -24,6 +24,10 @@ public class CalendarDetailDTO { ...@@ -24,6 +24,10 @@ public class CalendarDetailDTO {
private String phone; private String phone;
private String planId; private String planId;
private String remark; private String remark;
/**
* 是否全天
*/
private Boolean wholeDay;
private String type; private String type;
private String typeName; private String typeName;
......
package com.dituhui.pea.order.dto; package com.dituhui.pea.order.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;
public class CalendarUpdateDTO { public class CalendarUpdateDTO {
@lombok.Data @lombok.Data
public static class Request { public static class Request {
@NotBlank /**
* 日程是否是全天
*/
@NotNull(message = "请指定日程是否是全天")
private Boolean wholeDay;
/**
* 日程所属日期, 格式: yyyy-MM-dd
*/
@NotNull(message = "请指定日程所属日期, 格式:yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date itineraryDate;
/**
* 开始时间:HH:mm:ss, wholeDay为true时可不传
*/
private String startTime; private String startTime;
@NotBlank /**
* 结束时间:HH:mm:ss, wholeDay为true时可不传
*/
private String endTime; private String endTime;
/**
* 日程所属工程师编号
*/
@NotBlank @NotBlank
private String engineerCode; private String engineerCode;
/**
* 日程计划ID
*/
@NotBlank @NotBlank
private String planId; private String planId;
/**
* 备注
*/
private String remark; private String remark;
} }
......
...@@ -18,6 +18,12 @@ public class CapacityEngineerCalendarEntity { ...@@ -18,6 +18,12 @@ public class CapacityEngineerCalendarEntity {
@Column(nullable = false) @Column(nullable = false)
private String workday; private String workday;
/**
* 事件日程是否是全天类型
*/
@Column(name = "whole_day", nullable = false)
private Boolean wholeDay;
@Column(name = "engineer_code", nullable = false, columnDefinition = "varchar(50) default '0'") @Column(name = "engineer_code", nullable = false, columnDefinition = "varchar(50) default '0'")
private String engineerCode; private String engineerCode;
......
...@@ -52,20 +52,23 @@ public interface EngineerCalendarService { ...@@ -52,20 +52,23 @@ public interface EngineerCalendarService {
List<OccupyInfoDetail> getEngineerWorkDayCalendar(String engineerCode, LocalDate targetDate); List<OccupyInfoDetail> getEngineerWorkDayCalendar(String engineerCode, LocalDate targetDate);
/** /**
* 判定工程师指定日期是否在工作队的工作日期 * 判定工程师指定日期是否在指定工作队的工作日期
* *
* @param teamId 工作队 * @param teamId 工作队
* @param engineerCode 工程师编号 * @param engineerCode 工程师编号
* @param targetDate 目标日期 * @param targetDate 目标日期
* @return 是否是工作队内日期工作时间 * @return 是否是指定工作队内日期工作时间
* @apiNote 仅考虑工作队工作日期, 不考虑事件日程
*/ */
boolean engineerTeamDateWorkTime(String teamId, String engineerCode, LocalDate targetDate); boolean engineerTeamDateWorkTime(String teamId, String engineerCode, LocalDate targetDate);
/** /**
* 判定工程师只顶你日期是否休息日 * 判定工程师指定日期是否休息日
*
* @param engineerCode 工程师编号 * @param engineerCode 工程师编号
* @param targetDate 目标日期 * @param targetDate 目标日期
* @return 是否是工作日 * @return 是否是工作日
* @apiNote 仅考虑工作队工作日期, 不考虑事件日程
*/ */
boolean engineerWorkDay(String engineerCode, LocalDate targetDate); boolean engineerWorkDay(String engineerCode, LocalDate targetDate);
...@@ -89,4 +92,14 @@ public interface EngineerCalendarService { ...@@ -89,4 +92,14 @@ public interface EngineerCalendarService {
* @return 时间窗格式 * @return 时间窗格式
*/ */
List<OccupyInfoDetail> timeWindowsSlice(String engineerCode, String teamId, LocalDate targetDate); List<OccupyInfoDetail> timeWindowsSlice(String engineerCode, String teamId, LocalDate targetDate);
/**
* 判定工程师是否全天请假(非派工时间)或者全天休息
*
* @param engineerCode 工程师编号
* @param targetDate 目标日期
* @return 全天休息(含请假)返回true, 否则false
*/
boolean engineerTargetLeave(String engineerCode, LocalDate targetDate);
} }
...@@ -156,6 +156,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -156,6 +156,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
rs.setStartTime(DateUtils.formatDateTime(entity.getStartTime())); rs.setStartTime(DateUtils.formatDateTime(entity.getStartTime()));
rs.setEndTime(DateUtils.formatDateTime(entity.getEndTime())); rs.setEndTime(DateUtils.formatDateTime(entity.getEndTime()));
rs.setRemark(entity.getMemo()); rs.setRemark(entity.getMemo());
rs.setWholeDay(entity.getWholeDay());
// todo 操作员 // todo 操作员
rs.setOperator(entity.getOperatorName()); rs.setOperator(entity.getOperatorName());
return Result.success(rs); return Result.success(rs);
...@@ -169,15 +170,39 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -169,15 +170,39 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
if (entity == null) { if (entity == null) {
return Result.failed("日历配置信息不存在"); return Result.failed("日历配置信息不存在");
} }
// todo 业务检查,暂时只需要检查日期时间必须为将来; 后面还需要检查配置项是否与其他配置项在时间上有交叉 final Date itineraryDate = reqDTO.getItineraryDate();
LocalDateTime time1 = DateUtils.localDateTimeFromStr(reqDTO.getStartTime()); final LocalDate itineraryLocalDate = itineraryDate.toInstant().atZone(ZoneId.systemDefault())
LocalDateTime time2 = DateUtils.localDateTimeFromStr(reqDTO.getEndTime()); .toLocalDate();
// 日程所属工程师
final String engineerCode = entity.getEngineerCode();
// 业务检查,暂时只需要检查日期时间必须为将来; 后面还需要检查配置项是否与其他配置项在时间上有交叉
LocalDateTime time1, time2;
if (Objects.equals(Boolean.TRUE, reqDTO.getWholeDay())) {
//获取工程师上下班时间
EngineerBusinessEntity config = engineerBusinessDao.getByEngineerCode(engineerCode);
LocalTime startTime = LocalTime.parse(String.format("%s:00", config.getWorkOn()), DateUtil.TIME_FORMATTER);
LocalTime endTime = LocalTime.parse(String.format("%s:00", config.getWorkOff()), DateUtil.TIME_FORMATTER);
time1 = LocalDateTime.of(itineraryLocalDate, startTime);
time2 = LocalDateTime.of(itineraryLocalDate, endTime);
} else {
time1 = LocalDateTime.of(itineraryLocalDate, LocalTime.parse(reqDTO.getStartTime(), DateUtil.TIME_FORMATTER));
time2 = LocalDateTime.of(itineraryLocalDate, LocalTime.parse(reqDTO.getEndTime(), DateUtil.TIME_FORMATTER));
}
if (time1.isAfter(time2)) { if (time1.isAfter(time2)) {
return Result.failed("开始/结束时间输入错误"); return Result.failed("开始/结束时间输入错误");
} }
if (time1.isBefore(LocalDateTime.now()) || time2.isBefore(LocalDateTime.now())) { if (time1.isBefore(LocalDateTime.now()) || time2.isBefore(LocalDateTime.now())) {
return Result.failed("只能更新未来时间"); return Result.failed("只能更新未来时间");
} }
Optional<CheckTime> checkTimeOptional = checkTimesHasOverlap(time1.toLocalDate(), engineerCode, time1, time2);
if (checkTimeOptional.isPresent()) {
CheckTime checkTime = checkTimeOptional.get();
throw new BusinessException("工号为" + engineerCode + "的工程师在"
+ checkTime.getStartTime() + "到"
+ checkTime.getEndTime() + "区间已有日程安排");
}
entity.setWholeDay(reqDTO.getWholeDay());
entity.setStartTime(time1); entity.setStartTime(time1);
entity.setEndTime(time2); entity.setEndTime(time2);
entity.setMemo(reqDTO.getRemark()); entity.setMemo(reqDTO.getRemark());
...@@ -229,7 +254,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -229,7 +254,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
endTime = String.format("%s %s:00", endTime, config.getWorkOff()); endTime = String.format("%s %s:00", endTime, config.getWorkOff());
} }
if ("none".equals(repeatType)) { if ("none".equals(repeatType)) {
addOneEngineerPlan(userId, engineerCode, type, beginTime, endTime, remark); addOneEngineerPlan(userId, engineerCode, type, beginTime, endTime, remark, isAllday);
} else { } else {
LocalDate beginDate = DateUtils.localDateFromStr(beginTime); LocalDate beginDate = DateUtils.localDateFromStr(beginTime);
LocalDate endDate = DateUtils.localDateFromStr(repeatEndDate); LocalDate endDate = DateUtils.localDateFromStr(repeatEndDate);
...@@ -242,7 +267,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -242,7 +267,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
long days = beginDate.until(current, ChronoUnit.DAYS); long days = beginDate.until(current, ChronoUnit.DAYS);
beginTime = DateUtils.formatDateTime(DateUtils.localDateTimeFromStr(finalBeginTime).plusDays(days)); beginTime = DateUtils.formatDateTime(DateUtils.localDateTimeFromStr(finalBeginTime).plusDays(days));
endTime = DateUtils.formatDateTime(DateUtils.localDateTimeFromStr(finalEndTime).plusDays(days)); endTime = DateUtils.formatDateTime(DateUtils.localDateTimeFromStr(finalEndTime).plusDays(days));
addOneEngineerPlan(userId, engineerCode, type, beginTime, endTime, remark); addOneEngineerPlan(userId, engineerCode, type, beginTime, endTime, remark, isAllday);
current = getNextDate(current, repeatType); current = getNextDate(current, repeatType);
} }
} }
...@@ -276,7 +301,8 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -276,7 +301,8 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
return current; return current;
} }
private void addOneEngineerPlan(String userId, String engineerCode, String type, String beginTime, String endTime, String remark) { private void addOneEngineerPlan(String userId, String engineerCode, String type, String beginTime, String endTime, String remark,
Boolean allDay) {
// 一个工程师、一条配置处理;可能一条会跨多天,需要分别补充处理 // 一个工程师、一条配置处理;可能一条会跨多天,需要分别补充处理
log.info("addOneEngineerPlan ==> [engineerCode:{}][beginTime:{}]", engineerCode, beginTime); log.info("addOneEngineerPlan ==> [engineerCode:{}][beginTime:{}]", engineerCode, beginTime);
String userName = user.getUserInfo(userId).getResult().getAccount(); String userName = user.getUserInfo(userId).getResult().getAccount();
...@@ -305,6 +331,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -305,6 +331,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
e.setStartTime(startTime); e.setStartTime(startTime);
e.setEndTime(endTime1); e.setEndTime(endTime1);
e.setWorkday(DateUtils.formatDate(beginDate)); e.setWorkday(DateUtils.formatDate(beginDate));
e.setWholeDay(allDay);
e.setMemo(remark); e.setMemo(remark);
// //
e.setOperatorId(userId); e.setOperatorId(userId);
...@@ -355,6 +382,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -355,6 +382,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
e.setOperatorId(userId); e.setOperatorId(userId);
e.setOperatorName(userName); e.setOperatorName(userName);
all.add(e); all.add(e);
e.setWholeDay(allDay);
// 按日迭代 // 按日迭代
current = current.plusDays(1); current = current.plusDays(1);
} }
...@@ -628,7 +656,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -628,7 +656,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
final int dayOfWeek = targetDate.getDayOfWeek().getValue(); final int dayOfWeek = targetDate.getDayOfWeek().getValue();
return ALL_WORK_DAY_OF_WEEK.contains(String.valueOf(dayOfWeek)); return teamCommonWorkdaysOfWeek.contains(String.valueOf(dayOfWeek));
} }
@Override @Override
...@@ -688,6 +716,31 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -688,6 +716,31 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
return CapacityUtils.intervalTime(workStartTime, workEndTime, usedTimeInfo); return CapacityUtils.intervalTime(workStartTime, workEndTime, usedTimeInfo);
} }
@Override
public boolean engineerTargetLeave(String engineerCode, LocalDate targetDate) {
Set<OrgTeamEntity> teams = orgTeamDao.selectTeamByEngineerCode(engineerCode);
List<String> teamCommonWorkdaysOfWeek = Optional.ofNullable(teams).orElse(Collections.emptySet()).stream()
.map(team -> Arrays.asList(team.getWorkdays().split(",")))
.flatMap(Collection::stream)
.distinct()
.collect(Collectors.toList());
// 求多个工作队的公共空闲时间
final int dayOfWeek = targetDate.getDayOfWeek().getValue();
List<String> commonLeisureDayOfWeek = ALL_WORK_DAY_OF_WEEK.stream()
.filter(day -> teamCommonWorkdaysOfWeek.stream().noneMatch(tDay -> Objects.equals(day, tDay)))
.collect(Collectors.toList());
if (!commonLeisureDayOfWeek.contains(String.valueOf(dayOfWeek))) {
//日程表事件记录时间
List<CapacityEngineerCalendarEntity> configs = capacityEngineerCalendarDao.findCalendarByWorkdayAndEngineerCode(DateTimeUtil.formatDate(targetDate), engineerCode);
return Optional.ofNullable(configs).orElse(Collections.emptyList())
.stream()
.anyMatch(t -> Objects.equals(Boolean.TRUE, t.getWholeDay()));
}
return true;
}
private EngineerCalendarDTO.Calendar getEmptyCalendar(String teamId, String date) { private EngineerCalendarDTO.Calendar getEmptyCalendar(String teamId, String date) {
// 初始化一天的日历 // 初始化一天的日历
EngineerCalendarDTO.Calendar calendar = new EngineerCalendarDTO.Calendar(); EngineerCalendarDTO.Calendar calendar = new EngineerCalendarDTO.Calendar();
......
...@@ -364,6 +364,9 @@ public class OrderAssignImpl implements OrderAssign { ...@@ -364,6 +364,9 @@ public class OrderAssignImpl implements OrderAssign {
double orderLongitude = Double.parseDouble(order.getX()); double orderLongitude = Double.parseDouble(order.getX());
double orderLatitude = Double.parseDouble(order.getY()); double orderLatitude = Double.parseDouble(order.getY());
//TODO 排除当天已经请假或者休息的人员
//均计算距离 //均计算距离
List<TempEngineer> result = engineerCodes1.stream() List<TempEngineer> result = engineerCodes1.stream()
.map(engineerCode -> { .map(engineerCode -> {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!