Commit 4adf9aaa by huangjinxin

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

2 parents a55dfd99 23e192c9
......@@ -24,6 +24,10 @@ public class CalendarDetailDTO {
private String phone;
private String planId;
private String remark;
/**
* 是否全天
*/
private Boolean wholeDay;
private String type;
private String typeName;
......
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.NotNull;
import java.util.Date;
public class CalendarUpdateDTO {
@lombok.Data
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;
@NotBlank
/**
* 结束时间:HH:mm:ss, wholeDay为true时可不传
*/
private String endTime;
/**
* 日程所属工程师编号
*/
@NotBlank
private String engineerCode;
/**
* 日程计划ID
*/
@NotBlank
private String planId;
/**
* 备注
*/
private String remark;
}
......
......@@ -18,6 +18,12 @@ public class CapacityEngineerCalendarEntity {
@Column(nullable = false)
private String workday;
/**
* 事件日程是否是全天类型
*/
@Column(name = "whole_day", nullable = false)
private Boolean wholeDay;
@Column(name = "engineer_code", nullable = false, columnDefinition = "varchar(50) default '0'")
private String engineerCode;
......
......@@ -52,20 +52,23 @@ public interface EngineerCalendarService {
List<OccupyInfoDetail> getEngineerWorkDayCalendar(String engineerCode, LocalDate targetDate);
/**
* 判定工程师指定日期是否在工作队的工作日期
* 判定工程师指定日期是否在指定工作队的工作日期
*
* @param teamId 工作队
* @param engineerCode 工程师编号
* @param targetDate 目标日期
* @return 是否是工作队内日期工作时间
* @return 是否是指定工作队内日期工作时间
* @apiNote 仅考虑工作队工作日期, 不考虑事件日程
*/
boolean engineerTeamDateWorkTime(String teamId, String engineerCode, LocalDate targetDate);
/**
* 判定工程师只顶你日期是否休息日
* 判定工程师指定日期是否休息日
*
* @param engineerCode 工程师编号
* @param targetDate 目标日期
* @return 是否是工作日
* @apiNote 仅考虑工作队工作日期, 不考虑事件日程
*/
boolean engineerWorkDay(String engineerCode, LocalDate targetDate);
......@@ -89,4 +92,14 @@ public interface EngineerCalendarService {
* @return 时间窗格式
*/
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 {
rs.setStartTime(DateUtils.formatDateTime(entity.getStartTime()));
rs.setEndTime(DateUtils.formatDateTime(entity.getEndTime()));
rs.setRemark(entity.getMemo());
rs.setWholeDay(entity.getWholeDay());
// todo 操作员
rs.setOperator(entity.getOperatorName());
return Result.success(rs);
......@@ -169,15 +170,39 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
if (entity == null) {
return Result.failed("日历配置信息不存在");
}
// todo 业务检查,暂时只需要检查日期时间必须为将来; 后面还需要检查配置项是否与其他配置项在时间上有交叉
LocalDateTime time1 = DateUtils.localDateTimeFromStr(reqDTO.getStartTime());
LocalDateTime time2 = DateUtils.localDateTimeFromStr(reqDTO.getEndTime());
final Date itineraryDate = reqDTO.getItineraryDate();
final LocalDate itineraryLocalDate = itineraryDate.toInstant().atZone(ZoneId.systemDefault())
.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)) {
return Result.failed("开始/结束时间输入错误");
}
if (time1.isBefore(LocalDateTime.now()) || time2.isBefore(LocalDateTime.now())) {
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.setEndTime(time2);
entity.setMemo(reqDTO.getRemark());
......@@ -229,7 +254,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
endTime = String.format("%s %s:00", endTime, config.getWorkOff());
}
if ("none".equals(repeatType)) {
addOneEngineerPlan(userId, engineerCode, type, beginTime, endTime, remark);
addOneEngineerPlan(userId, engineerCode, type, beginTime, endTime, remark, isAllday);
} else {
LocalDate beginDate = DateUtils.localDateFromStr(beginTime);
LocalDate endDate = DateUtils.localDateFromStr(repeatEndDate);
......@@ -242,7 +267,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
long days = beginDate.until(current, ChronoUnit.DAYS);
beginTime = DateUtils.formatDateTime(DateUtils.localDateTimeFromStr(finalBeginTime).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);
}
}
......@@ -276,7 +301,8 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
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);
String userName = user.getUserInfo(userId).getResult().getAccount();
......@@ -305,6 +331,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
e.setStartTime(startTime);
e.setEndTime(endTime1);
e.setWorkday(DateUtils.formatDate(beginDate));
e.setWholeDay(allDay);
e.setMemo(remark);
//
e.setOperatorId(userId);
......@@ -355,6 +382,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
e.setOperatorId(userId);
e.setOperatorName(userName);
all.add(e);
e.setWholeDay(allDay);
// 按日迭代
current = current.plusDays(1);
}
......@@ -628,7 +656,7 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
.distinct()
.collect(Collectors.toList());
final int dayOfWeek = targetDate.getDayOfWeek().getValue();
return ALL_WORK_DAY_OF_WEEK.contains(String.valueOf(dayOfWeek));
return teamCommonWorkdaysOfWeek.contains(String.valueOf(dayOfWeek));
}
@Override
......@@ -688,6 +716,31 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
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) {
// 初始化一天的日历
EngineerCalendarDTO.Calendar calendar = new EngineerCalendarDTO.Calendar();
......
......@@ -364,6 +364,9 @@ public class OrderAssignImpl implements OrderAssign {
double orderLongitude = Double.parseDouble(order.getX());
double orderLatitude = Double.parseDouble(order.getY());
//TODO 排除当天已经请假或者休息的人员
//均计算距离
List<TempEngineer> result = engineerCodes1.stream()
.map(engineerCode -> {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!