Commit ee9fc420 by huangjinxin

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

2 parents 9d156871 028b12b4
...@@ -2,6 +2,7 @@ package com.dituhui.pea.dispatch.quartz; ...@@ -2,6 +2,7 @@ package com.dituhui.pea.dispatch.quartz;
import com.dituhui.pea.dispatch.service.SchedulerService; import com.dituhui.pea.dispatch.service.SchedulerService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; import org.quartz.JobExecutionException;
import org.quartz.JobKey; import org.quartz.JobKey;
......
...@@ -201,6 +201,10 @@ public class BatchServiceImpl implements BatchService { ...@@ -201,6 +201,10 @@ public class BatchServiceImpl implements BatchService {
String batchNo = ""; String batchNo = "";
String batchDay = ""; String batchDay = "";
if("team_suzhou_001".equals(teamId)){
System.out.println(teamId);
}
Optional<DispatchBatch> optional = batchRepository.findByTeamIdAndBatchDate(teamId, day); Optional<DispatchBatch> optional = batchRepository.findByTeamIdAndBatchDate(teamId, day);
if (!optional.isPresent()) { if (!optional.isPresent()) {
// 创建batch // 创建batch
...@@ -227,22 +231,26 @@ public class BatchServiceImpl implements BatchService { ...@@ -227,22 +231,26 @@ public class BatchServiceImpl implements BatchService {
log.info("写入新批次技术员、工单数据, teamId:{}, day:{}, batchNo:{}", teamId, batchDay, batchNo); log.info("写入新批次技术员、工单数据, teamId:{}, day:{}, batchNo:{}", teamId, batchDay, batchNo);
String sqlEngineer = "INSERT INTO dispatch_engineer (team_id, batch_no, engineer_code, engineer_name, x, y, max_num, max_minute, max_distance, vehicle_type)\n" String sqlEngineer = "INSERT INTO dispatch_engineer (team_id, batch_no, engineer_code, engineer_name, x, y, max_num, max_minute, max_distance, vehicle_type)\n"
+ "SELECT o.team_id,?,o.engineer_code, a.name , b.x, b.y , max_num, max_minute, max_distance, b.vehicle FROM `org_team_engineer` o,engineer_info a,engineer_business b \r\n" + "SELECT o.team_id,?,o.engineer_code, a.name , b.x, b.y , max_num, max_minute, max_distance, b.vehicle FROM `org_team_engineer` o,engineer_info a,engineer_business b \n"
+ " WHERE o.team_id=? AND `status`=1\r\n" + " WHERE o.team_id=? AND o.`status`=1\n"
+ " AND o.engineer_code=a.engineer_code AND a.engineer_code = b.engineer_code \r\n" + " AND o.engineer_code=a.engineer_code AND a.engineer_code = b.engineer_code \n"
+ " AND b.x IS NOT NULL AND b.x !=''" + " order by a.engineer_code asc"; + " AND b.x IS NOT NULL AND b.x !=''" + " order by a.engineer_code asc";
int engCount = jdbcTemplate.update(sqlEngineer, batchNo, teamId); int engCount = jdbcTemplate.update(sqlEngineer, batchNo, teamId);
if("team_suzhou_001".equals(teamId)){
System.out.println(teamId);
}
// 未派过的工单(已派过PRE状态还可以再次派) // 未派过的工单(已派过PRE状态还可以再次派)
String sqlOrder = "INSERT INTO dispatch_order (group_id, batch_no, team_id, order_id , dt, x, y, \n" String sqlOrder = "INSERT INTO dispatch_order (group_id, batch_no, team_id, order_id , dt, x, y, \n"
+ " expect_time_begin, expect_time_end, tags, priority , skills , take_time, status )\n" + " expect_time_begin, expect_time_end, tags, priority , skills , take_time, status )\n"
+ " SELECT a.org_group_id, ?, a.org_team_id , a.order_id, ?, a.x, a.y , \r\n" + " SELECT a.org_group_id, ?, a.org_team_id , a.order_id, ?, a.x, a.y , \n"
+ " a.expect_time_begin, a.expect_time_end, a.tags, a.priority , \r\n" + " a.expect_time_begin, a.expect_time_end, a.tags, a.priority , \n"
+ " CONCAT(a.brand, '-', a.type, '-', a.skill) skills , a.take_time , a.appointment_status\r\n" + " CONCAT(a.brand, '-', a.type, '-', a.skill) skills , a.take_time , a.appointment_status\n"
+ " FROM order_info a \r\n" + " WHERE a.org_team_id=? AND a.dt = ? AND bean_status='OPEN'\r\n" + " FROM order_info a \n" + " WHERE a.org_team_id=? AND a.dt = ? AND bean_status='OPEN'\n"
+ " AND appointment_method LIKE 'AUTO%' AND a.appointment_status IN ('INIT', 'PRE')\r\n" + " AND appointment_method LIKE 'AUTO%' AND a.appointment_status IN ('INIT', 'PRE')\n"
+ " AND order_status ='NORMAL' AND service_status='INIT'\r\n" + " AND order_status ='NORMAL' AND service_status='INIT'\n"
+ " ORDER BY a.expect_time_begin ASC \r\n"; + " ORDER BY a.expect_time_begin ASC \n";
int orderCount = jdbcTemplate.update(sqlOrder, batchNo, batchDay, teamId, batchDay); int orderCount = jdbcTemplate.update(sqlOrder, batchNo, batchDay, teamId, batchDay);
// confirm的要做预占用,所以也加入进来 // confirm的要做预占用,所以也加入进来
......
...@@ -49,23 +49,21 @@ public class SchedulerServiceImpl implements SchedulerService { ...@@ -49,23 +49,21 @@ public class SchedulerServiceImpl implements SchedulerService {
OrgTeamDao orgTeamDao; OrgTeamDao orgTeamDao;
private DefaultSolverFactory<DispatchSolution> solverFactory; private DefaultSolverFactory<DispatchSolution> solverFactory;
private Solver<DispatchSolution> solver; //private Solver<DispatchSolution> solver;
public SchedulerServiceImpl() { public SchedulerServiceImpl() {
solverFactory = DispatchSolutionUtils.getSolverFactory(30, 60 * 5); solverFactory = DispatchSolutionUtils.getSolverFactory(30, 60 * 5);
solver = solverFactory.buildSolver(); //solver = solverFactory.buildSolver();
} }
@Override @Override
@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
public void dispatchRun2(String teamId) { public void dispatchRun2(String teamId) {
OrgTeamEntity orgTeamEntity = orgTeamDao.findByTeamId(teamId); OrgTeamEntity orgTeamEntity = orgTeamDao.findByTeamId(teamId);
String groupId = orgTeamEntity.getGroupId(); String groupId = orgTeamEntity.getGroupId();
log.info("dispatchRun group:{}, team:{} done", groupId, teamId); log.info("dispatchRun group:{}, team:{} done", groupId, teamId);
try {
for (int i = 1; i <= nextDaysLimit; i++) { for (int i = 1; i <= nextDaysLimit; i++) {
String currDay = LocalDate.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE); String currDay = LocalDate.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE);
try {
log.info("dispatchRun begin----- teamId:{}, day:{}", teamId, currDay); log.info("dispatchRun begin----- teamId:{}, day:{}", teamId, currDay);
String batchNo = batchService.buildBatchData2(teamId, currDay); String batchNo = batchService.buildBatchData2(teamId, currDay);
...@@ -79,6 +77,7 @@ public class SchedulerServiceImpl implements SchedulerService { ...@@ -79,6 +77,7 @@ public class SchedulerServiceImpl implements SchedulerService {
continue; continue;
} }
log.info("dispatchRun prepare done, teamId:{}, day:{}, batch:{}, problemId:{}", teamId, currDay, batchNo, problemId); log.info("dispatchRun prepare done, teamId:{}, day:{}, batch:{}, problemId:{}", teamId, currDay, batchNo, problemId);
Solver<DispatchSolution> solver = solverFactory.buildSolver();
DispatchSolution solution = solver.solve(problem); DispatchSolution solution = solver.solve(problem);
DispatchSolutionUtils.removeHardConstraintCustomer(solution, solverFactory); DispatchSolutionUtils.removeHardConstraintCustomer(solution, solverFactory);
log.info("dispatchRun solve done, teamId:{}, day:{}, batch:{}, problemId:{}, score:{}", teamId, currDay, batchNo, problemId, solution.getScore().toShortString()); log.info("dispatchRun solve done, teamId:{}, day:{}, batch:{}, problemId:{}, score:{}", teamId, currDay, batchNo, problemId, solution.getScore().toShortString());
...@@ -90,10 +89,10 @@ public class SchedulerServiceImpl implements SchedulerService { ...@@ -90,10 +89,10 @@ public class SchedulerServiceImpl implements SchedulerService {
exporter.write(solution, new File(String.format("dispatchSolution_%s_%s.json", teamId, currDay))); exporter.write(solution, new File(String.format("dispatchSolution_%s_%s.json", teamId, currDay)));
//log.info("dispatchRun group:{}, team:{} done", groupId, teamId); //log.info("dispatchRun group:{}, team:{} done", groupId, teamId);
}
} catch (Exception e) { } catch (Exception e) {
log.error(">>> (teamId:{})自动排班失败:{}", teamId, e.getMessage(), e); log.error(">>> (teamId:{}, day:{})自动排班失败:{}", teamId, currDay, e.getMessage(), e);
throw e; throw e;
} }
} }
}
} }
\ No newline at end of file
...@@ -416,7 +416,6 @@ public class SolveServiceImpl implements SolveService { ...@@ -416,7 +416,6 @@ public class SolveServiceImpl implements SolveService {
saveSolutionToDispatch2(teamId, batchNo, solution); saveSolutionToDispatch2(teamId, batchNo, solution);
} }
......
...@@ -28,6 +28,7 @@ import java.util.List; ...@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalLong;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
...@@ -244,11 +245,11 @@ public class CapacityUtils { ...@@ -244,11 +245,11 @@ public class CapacityUtils {
.flatMap(Collection::stream).collect(Collectors.toList()); .flatMap(Collection::stream).collect(Collectors.toList());
timeSlots = calculateUnion(timeSlots); timeSlots = calculateUnion(timeSlots);
long engineerMaxDuration = Optional.ofNullable(timeSlots).orElse(Collections.emptyList()) OptionalLong optionalEngineerMaxDuration = Optional.ofNullable(timeSlots).orElse(Collections.emptyList())
.stream() .stream()
.mapToLong(OccupyInfoDetail::getDuration) .mapToLong(t1 -> Duration.between(t1.getBeginTime(), t1.getEndTime()).abs().toMinutes())
.sum(); .max();
engineerMaxDurationList.add(engineerMaxDuration); engineerMaxDurationList.add(optionalEngineerMaxDuration.orElse(0L));
}); });
long maxDuration = Collections.max(engineerMaxDurationList); long maxDuration = Collections.max(engineerMaxDurationList);
......
...@@ -71,7 +71,7 @@ public interface EngineerInfoDao extends JpaRepository<EngineerInfoEntity, Integ ...@@ -71,7 +71,7 @@ public interface EngineerInfoDao extends JpaRepository<EngineerInfoEntity, Integ
" LEFT JOIN engineer_info ei ON esg.engineer_code = ei.engineer_code\n" + " LEFT JOIN engineer_info ei ON esg.engineer_code = ei.engineer_code\n" +
" LEFT JOIN org_team_engineer ote ON ote.engineer_code = ei.engineer_code \n" + " LEFT JOIN org_team_engineer ote ON ote.engineer_code = ei.engineer_code \n" +
" WHERE si.brand = :brand AND si.type= :productType AND si.skill = :skill \n" + " WHERE si.brand = :brand AND si.type= :productType AND si.skill = :skill \n" +
" AND ote.team_id = :teamId ", nativeQuery = true) " AND ote.team_id = :teamId AND ote.status = 1", nativeQuery = true)
Set<EngineerInfoEntity> listByBrandAndTypeAndSkillAndTeamId(@Param("brand") String brand, @Param("productType") String productType, Set<EngineerInfoEntity> listByBrandAndTypeAndSkillAndTeamId(@Param("brand") String brand, @Param("productType") String productType,
@Param("skill") String skill, @Param("teamId") String teamId); @Param("skill") String skill, @Param("teamId") String teamId);
...@@ -98,4 +98,15 @@ public interface EngineerInfoDao extends JpaRepository<EngineerInfoEntity, Integ ...@@ -98,4 +98,15 @@ public interface EngineerInfoDao extends JpaRepository<EngineerInfoEntity, Integ
" order by mlc.priority ", nativeQuery = true) " order by mlc.priority ", nativeQuery = true)
List<EngineerInfoEntity> listBrandAndSkillAndEngineerCodes(@Param("brand") String brand, @Param("productType") String productType, List<EngineerInfoEntity> listBrandAndSkillAndEngineerCodes(@Param("brand") String brand, @Param("productType") String productType,
@Param("skill") String skill, @Param("engineerCodes") List<String> engineerCodes); @Param("skill") String skill, @Param("engineerCodes") List<String> engineerCodes);
/**
* 查询工作队下的指定工程师信息
*
* @param engineerCode 工程师编号
* @param teamId 工作队ID
* @return 工作队下没有工程师则返回空
*/
@Query(value = "SELECT ei.* from org_team_engineer ote left join engineer_info ei ON ote.engineer_code = ei.engineer_code " +
"WHERE ote.team_id = :teamId AND ote.engineer_code = :engineerCode AND ote.`status` = 1", nativeQuery = true)
EngineerInfoEntity selectEngineerByEngineerCodeAndTeamId(@Param("engineerCode") String engineerCode, @Param("teamId") String teamId);
} }
...@@ -51,6 +51,7 @@ public interface OrgTeamDao extends JpaRepository<OrgTeamEntity, Integer>, JpaSp ...@@ -51,6 +51,7 @@ public interface OrgTeamDao extends JpaRepository<OrgTeamEntity, Integer>, JpaSp
* @param engineerCode 工程师代码 * @param engineerCode 工程师代码
* @return 工程师所在工作队信息 * @return 工程师所在工作队信息
*/ */
@Query(value = "SELECT ot.* FROM org_team ot LEFT JOIN org_team_engineer ote ON ote.team_id = ot.team_id WHERE ote.engineer_code = :engineerCode", nativeQuery = true) @Query(value = "SELECT ot.* FROM org_team_engineer ote LEFT JOIN org_team ot ON ote.team_id = ot.team_id WHERE ote.engineer_code = :engineerCode " +
" AND ote.`status` = 1 AND ot.status = 1 ", nativeQuery = true)
Set<OrgTeamEntity> selectTeamByEngineerCode(String engineerCode); Set<OrgTeamEntity> selectTeamByEngineerCode(String engineerCode);
} }
...@@ -6,6 +6,11 @@ import lombok.Data; ...@@ -6,6 +6,11 @@ import lombok.Data;
public class ScheduleEngineerOverviewDynamics { public class ScheduleEngineerOverviewDynamics {
/** /**
* 分站名称
*/
private String groupName;
/**
* 姓名 * 姓名
*/ */
private String name; private String name;
......
...@@ -43,11 +43,21 @@ public interface EngineerCalendarService { ...@@ -43,11 +43,21 @@ public interface EngineerCalendarService {
EngineerCalendarResultDTO queryEngineerCalendar(String engineerCode, LocalDate startDate, LocalDate endDate); EngineerCalendarResultDTO queryEngineerCalendar(String engineerCode, LocalDate startDate, LocalDate endDate);
/** /**
* 获取工程师在指定日期的非工作时间安排 包含工作队休息时间和日程表事件记录时间, 其中日程表内事件未与工作队时间判定交集, 实际计算非工作时间时需求并集 * 获取工程师在指定日期的“非工作”时间安排 包含工作队休息时间和日程表事件记录时间, 其中日程表内事件未与工作队时间判定交集, 实际计算非工作时间时需求并集
* *
* @param engineerCode 工程师编号 * @param engineerCode 工程师编号
* @param targetDate 目标日期 * @param targetDate 目标日期
* @return 没有交集的事件日程时间段即已占用的时间段 * @return 没有交集的事件日程时间段即已占用的时间段
*/ */
List<OccupyInfoDetail> getEngineerWorkDayCalendar(String engineerCode, LocalDate targetDate); List<OccupyInfoDetail> getEngineerWorkDayCalendar(String engineerCode, LocalDate targetDate);
/**
* 判定工程师指定日期是否在工作队的工作日期
*
* @param teamId 工作队
* @param engineerCode 工程师编号
* @param targetDate 目标日期
* @return 工作队内日期工作时间信息
*/
boolean engineerTeamDateWorkTime(String teamId, String engineerCode, LocalDate targetDate);
} }
package com.dituhui.pea.order.service.impl; package com.dituhui.pea.order.service.impl;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result; import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.common.DateUtils; import com.dituhui.pea.order.common.DateUtils;
import com.dituhui.pea.order.dao.*; import com.dituhui.pea.order.dao.EngineerInfoDao;
import com.dituhui.pea.order.dto.*; import com.dituhui.pea.order.dao.OrgGroupDao;
import com.dituhui.pea.order.dao.OrgTeamDao;
import com.dituhui.pea.order.dao.OrgTeamEngineerDao;
import com.dituhui.pea.order.dao.OrgWarehouseInfoDao;
import com.dituhui.pea.order.dto.BusinessTeamAddDTO;
import com.dituhui.pea.order.dto.BusinessTeamConfigInitDTO;
import com.dituhui.pea.order.dto.BusinessTeamConfigSubmitDTO;
import com.dituhui.pea.order.dto.BusinessTeamDeleteDTO;
import com.dituhui.pea.order.dto.BusinessTeamDetailDTO;
import com.dituhui.pea.order.dto.BusinessTeamUpdateDTO;
import com.dituhui.pea.order.dto.BusinessTeamWarehousesDTO;
import com.dituhui.pea.order.dto.BusinessTeamsDTO;
import com.dituhui.pea.order.entity.OrgGroupEntity; import com.dituhui.pea.order.entity.OrgGroupEntity;
import com.dituhui.pea.order.entity.OrgTeamEngineerEntity; import com.dituhui.pea.order.entity.OrgTeamEngineerEntity;
import com.dituhui.pea.order.entity.OrgTeamEntity; import com.dituhui.pea.order.entity.OrgTeamEntity;
...@@ -12,6 +24,7 @@ import com.dituhui.pea.order.entity.OrgWarehouseInfoEntity; ...@@ -12,6 +24,7 @@ import com.dituhui.pea.order.entity.OrgWarehouseInfoEntity;
import com.dituhui.pea.order.service.BusinessTeamService; import com.dituhui.pea.order.service.BusinessTeamService;
import com.dituhui.pea.order.service.CommonService; import com.dituhui.pea.order.service.CommonService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
...@@ -20,10 +33,18 @@ import org.springframework.data.domain.Pageable; ...@@ -20,10 +33,18 @@ import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.text.MessageFormat;
import java.time.Duration; import java.time.Duration;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.LocalTime; import java.time.LocalTime;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.dituhui.pea.order.config.OrderConfig.TEAMTYPE_PEA; import static com.dituhui.pea.order.config.OrderConfig.TEAMTYPE_PEA;
...@@ -190,20 +211,47 @@ public class BusinessTeamServiceImpl implements BusinessTeamService { ...@@ -190,20 +211,47 @@ public class BusinessTeamServiceImpl implements BusinessTeamService {
// 技术员列表 // 技术员列表
if (req.getEngineerCodes() != null && !req.getEngineerCodes().isEmpty()) { if (req.getEngineerCodes() != null && !req.getEngineerCodes().isEmpty()) {
updateTeamEngineers(req.getTeamId(), req.getEngineerCodes()); updateTeamEngineers(entity, req.getEngineerCodes());
} }
return Result.success(null); return Result.success(null);
} }
public void updateTeamEngineers(String teamId, List<String> engineerCodes) { public void updateTeamEngineers(OrgTeamEntity targetTeam, List<String> engineerCodes) {
// 获取现有的工作队和技术员之间的所有关系 // 获取现有的工作队和技术员之间的所有关系
List<OrgTeamEngineerEntity> existingRelations = orgTeamEngineerDao.findAllByTeamId(teamId); final String targetTeamId = String.valueOf(targetTeam.getId());
List<String> targetTeamWorkDayOfWeek = List.of(targetTeam.getWorkdays().split(","));
List<OrgTeamEngineerEntity> existingRelations = orgTeamEngineerDao.findAllByTeamId(targetTeamId);
// 查询工程师在其它工作队的工作时间以及当前工作队的工作时间
final String message = "工号为{0}的工程师在{1}工作队的周{2}已有工作日安排";
List<String> warnMessage = new ArrayList<>();
for (String engineerCode : engineerCodes) {
Set<OrgTeamEntity> teamEntitySet = orgTeamDao.selectTeamByEngineerCode(engineerCode);
if (CollectionUtils.isEmpty(teamEntitySet)) {
continue;
}
//移除当前工作队并校验工作队工作时间
teamEntitySet.stream()
.filter(t -> !Objects.equals(targetTeamId, t.getTeamId()))
.forEach(team -> {
//返回任何一个有工作日冲突的工作队
List<String> fixedWorkDayOfWeek = List.of(team.getWorkdays().split(","));
List<String> workDays = targetTeamWorkDayOfWeek.stream().filter(dayOfWeek -> fixedWorkDayOfWeek.stream().anyMatch(fixDay -> Objects.equals(fixDay, dayOfWeek)))
.collect(Collectors.toList());
if (!CollectionUtils.isEmpty(workDays)) {
warnMessage.add(MessageFormat.format(message, engineerCode, team.getTeamName(), StringUtils.join(workDays, ",")));
}
});
}
if (!CollectionUtils.isEmpty(warnMessage)) {
throw new BusinessException(StringUtils.join(warnMessage, ";"));
}
// 构建新的关系映射 // 构建新的关系映射
Map<String, OrgTeamEngineerEntity> newRelationsMap = new HashMap<>(); Map<String, OrgTeamEngineerEntity> newRelationsMap = new HashMap<>();
for (String engineerCode : engineerCodes) { for (String engineerCode : engineerCodes) {
OrgTeamEngineerEntity relation = new OrgTeamEngineerEntity(); OrgTeamEngineerEntity relation = new OrgTeamEngineerEntity();
relation.setTeamId(teamId); relation.setTeamId(targetTeamId);
relation.setEngineerCode(engineerCode); relation.setEngineerCode(engineerCode);
relation.setCreateTime(LocalDateTime.now()); relation.setCreateTime(LocalDateTime.now());
relation.setUpdateTime(LocalDateTime.now()); relation.setUpdateTime(LocalDateTime.now());
......
...@@ -31,6 +31,7 @@ import com.dituhui.pea.order.entity.SkillInfoEntity; ...@@ -31,6 +31,7 @@ import com.dituhui.pea.order.entity.SkillInfoEntity;
import com.dituhui.pea.order.entity.TimeSliceEntity; import com.dituhui.pea.order.entity.TimeSliceEntity;
import com.dituhui.pea.order.feign.ISaaSRemoteService; import com.dituhui.pea.order.feign.ISaaSRemoteService;
import com.dituhui.pea.order.service.CapacityQueryService; import com.dituhui.pea.order.service.CapacityQueryService;
import com.dituhui.pea.order.service.EngineerCalendarService;
import com.dituhui.pea.pojo.fendan.FendanDTO; import com.dituhui.pea.pojo.fendan.FendanDTO;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
...@@ -92,6 +93,8 @@ public class CapacityQueryServiceImpl implements CapacityQueryService { ...@@ -92,6 +93,8 @@ public class CapacityQueryServiceImpl implements CapacityQueryService {
private TimeSliceDao timeSliceDao; private TimeSliceDao timeSliceDao;
@Autowired @Autowired
private EngineerSliceUsedCapacityDao engineerSliceUsedCapacityDao; private EngineerSliceUsedCapacityDao engineerSliceUsedCapacityDao;
@Autowired
private EngineerCalendarService engineerCalendarService;
@Override @Override
public Result<CapacityQueryDTO.Result> matchCapacityData(CapacityQueryDTO.Request request, public Result<CapacityQueryDTO.Result> matchCapacityData(CapacityQueryDTO.Request request,
...@@ -118,16 +121,18 @@ public class CapacityQueryServiceImpl implements CapacityQueryService { ...@@ -118,16 +121,18 @@ public class CapacityQueryServiceImpl implements CapacityQueryService {
} }
//分站、网点ID //分站、网点ID
List<String> groupIdList = mapBlockInBlockIdsList.stream().map(MapBlockInfoEntity::getGroupId).distinct() List<String> teamIdList = mapBlockInBlockIdsList.stream().map(MapBlockInfoEntity::getTeamId).distinct()
.collect(Collectors.toList());
List<String> groupList = mapBlockInBlockIdsList.stream().map(MapBlockInfoEntity::getGroupId).distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
final String groupId = groupIdList.get(0); final String teamId = teamIdList.get(0);
//3. 查询分站下拥有对应技能的工程师(排重) 技能码转换为对应的技能汉字 //3. 查询分站下拥有对应技能的工程师(排重) 技能码转换为对应的技能汉字
List<SkillInfoEntity> querySkillGroup = new ArrayList<>(); List<SkillInfoEntity> querySkillGroup = new ArrayList<>();
Set<EngineerInfoEntity> allFulfillEngineer = Sets.newConcurrentHashSet(); Set<EngineerInfoEntity> allFulfillEngineer = Sets.newConcurrentHashSet();
for (CapacityQueryDTO.Service service : services) { for (CapacityQueryDTO.Service service : services) {
Set<EngineerInfoEntity> engineerInfoEntities = engineerInfoDao.listByBrandAndTypeAndSkillAndGroupId(service.getBrand(), Set<EngineerInfoEntity> engineerInfoEntities = engineerInfoDao.listByBrandAndTypeAndSkillAndTeamId(service.getBrand(),
service.getProductType(), service.getServiceType(), groupId); service.getProductType(), service.getServiceType(), teamId);
//查询对应的技能信息 //查询对应的技能信息
SkillInfoEntity skillInfo = skillInfoDao.getByBrandAndTypeAndSkill(service.getBrand(), SkillInfoEntity skillInfo = skillInfoDao.getByBrandAndTypeAndSkill(service.getBrand(),
...@@ -154,7 +159,7 @@ public class CapacityQueryServiceImpl implements CapacityQueryService { ...@@ -154,7 +159,7 @@ public class CapacityQueryServiceImpl implements CapacityQueryService {
LocalDate currentDate = beginDate; LocalDate currentDate = beginDate;
//定义返回值 //定义返回值
CapacityQueryDTO.Result result = new CapacityQueryDTO.Result(); CapacityQueryDTO.Result result = new CapacityQueryDTO.Result();
result.setGroupId(groupId); result.setGroupId(groupList.get(0));
result.setTakeTime(totalTakeTime); result.setTakeTime(totalTakeTime);
final int corePoolSize = Runtime.getRuntime().availableProcessors(); final int corePoolSize = Runtime.getRuntime().availableProcessors();
...@@ -166,7 +171,7 @@ public class CapacityQueryServiceImpl implements CapacityQueryService { ...@@ -166,7 +171,7 @@ public class CapacityQueryServiceImpl implements CapacityQueryService {
while (!currentDate.isAfter(endDate)) { while (!currentDate.isAfter(endDate)) {
log.info("【matchCapacityData】----------->开始计算{}的容量", currentDate); log.info("【matchCapacityData】----------->开始计算{}的容量", currentDate);
Task task = new Task(allFulfillEngineer, currentDate, halfDayTypeTimeSlice, Task task = new Task(allFulfillEngineer, currentDate, halfDayTypeTimeSlice,
totalTakeTime, allDayTypeTimeSlice, timeSliceEntities, semaphore); totalTakeTime, allDayTypeTimeSlice, timeSliceEntities, semaphore, teamId);
Future<CapacityQueryDTO.Data> dataFuture = poolExecutor.submit(task); Future<CapacityQueryDTO.Data> dataFuture = poolExecutor.submit(task);
futureDatas.add(dataFuture); futureDatas.add(dataFuture);
currentDate = currentDate.plusDays(1); currentDate = currentDate.plusDays(1);
...@@ -210,10 +215,13 @@ public class CapacityQueryServiceImpl implements CapacityQueryService { ...@@ -210,10 +215,13 @@ public class CapacityQueryServiceImpl implements CapacityQueryService {
List<CapacityEngineerSliceUsedEntity> allEngineerTimeSlice = new CopyOnWriteArrayList<>(); List<CapacityEngineerSliceUsedEntity> allEngineerTimeSlice = new CopyOnWriteArrayList<>();
for (EngineerInfoEntity engineerInfo : engineerInfoEntities) { for (EngineerInfoEntity engineerInfo : engineerInfoEntities) {
boolean isWorkDay = engineerCalendarService.engineerTeamDateWorkTime(teamId, engineerInfo.getEngineerCode(), targetDate);
if (isWorkDay) {
List<CapacityEngineerSliceUsedEntity> engineerTimeSlice = engineerSliceUsedCapacityDao List<CapacityEngineerSliceUsedEntity> engineerTimeSlice = engineerSliceUsedCapacityDao
.findByWorkdayAndEngineerCode(DateTimeUtil.formatDate(targetDate), engineerInfo.getEngineerCode()); .findByWorkdayAndEngineerCode(DateTimeUtil.formatDate(targetDate), engineerInfo.getEngineerCode());
allEngineerTimeSlice.addAll(engineerTimeSlice); allEngineerTimeSlice.addAll(engineerTimeSlice);
} }
}
log.info("[matchCapacityData]【符合技能要求的工程师总数为:{} 个】", engineerInfoEntities.size()); log.info("[matchCapacityData]【符合技能要求的工程师总数为:{} 个】", engineerInfoEntities.size());
return CapacityUtils.caculateTargetTimeSlice(skillInfo.getTakeTime(), "时间段", allEngineerTimeSlice, startTime, endTime, targetDate); return CapacityUtils.caculateTargetTimeSlice(skillInfo.getTakeTime(), "时间段", allEngineerTimeSlice, startTime, endTime, targetDate);
...@@ -354,6 +362,10 @@ public class CapacityQueryServiceImpl implements CapacityQueryService { ...@@ -354,6 +362,10 @@ public class CapacityQueryServiceImpl implements CapacityQueryService {
private CopyOnWriteArrayList<TimeSliceEntity> allDayTypeTimeSlice; private CopyOnWriteArrayList<TimeSliceEntity> allDayTypeTimeSlice;
private CopyOnWriteArrayList<TimeSliceEntity> timeSliceEntities; private CopyOnWriteArrayList<TimeSliceEntity> timeSliceEntities;
private Semaphore semaphore; private Semaphore semaphore;
/**
* 工作队ID
*/
private String teamId;
@Override @Override
public CapacityQueryDTO.Data call() throws Exception { public CapacityQueryDTO.Data call() throws Exception {
...@@ -361,7 +373,7 @@ public class CapacityQueryServiceImpl implements CapacityQueryService { ...@@ -361,7 +373,7 @@ public class CapacityQueryServiceImpl implements CapacityQueryService {
try { try {
semaphore.acquire(); semaphore.acquire();
data = getData(allFulfillEngineer, currentDate, halfDayTypeTimeSlice, data = getData(allFulfillEngineer, currentDate, halfDayTypeTimeSlice,
totalTakeTime, allDayTypeTimeSlice, timeSliceEntities); totalTakeTime, allDayTypeTimeSlice, timeSliceEntities, teamId);
} catch (InterruptedException e) { } catch (InterruptedException e) {
log.error("【计算日期为:{} 的容量失败】Task: 失败原因{}", currentDate, e.getMessage()); log.error("【计算日期为:{} 的容量失败】Task: 失败原因{}", currentDate, e.getMessage());
} finally { } finally {
...@@ -373,13 +385,17 @@ public class CapacityQueryServiceImpl implements CapacityQueryService { ...@@ -373,13 +385,17 @@ public class CapacityQueryServiceImpl implements CapacityQueryService {
public CapacityQueryDTO.Data getData(Set<EngineerInfoEntity> allFulfillEngineer, LocalDate currentDate, public CapacityQueryDTO.Data getData(Set<EngineerInfoEntity> allFulfillEngineer, LocalDate currentDate,
List<TimeSliceEntity> halfDayTypeTimeSlice, int totalTakeTime, List<TimeSliceEntity> halfDayTypeTimeSlice, int totalTakeTime,
List<TimeSliceEntity> allDayTypeTimeSlice, List<TimeSliceEntity> allDayTypeTimeSlice,
List<TimeSliceEntity> timeSliceEntities) { List<TimeSliceEntity> timeSliceEntities, String targetTeamId) {
List<CapacityEngineerSliceUsedEntity> allEngineerTimeSlice = new CopyOnWriteArrayList<>(); List<CapacityEngineerSliceUsedEntity> allEngineerTimeSlice = new CopyOnWriteArrayList<>();
for (EngineerInfoEntity engineerInfo : allFulfillEngineer) { for (EngineerInfoEntity engineerInfo : allFulfillEngineer) {
//一个工程师多个工作队情况,获取当前工作队的工作日期, 如果是则将当天的时间片容量纳入计算范围, 否则不纳入
boolean isWorkDay = engineerCalendarService.engineerTeamDateWorkTime(targetTeamId, engineerInfo.getEngineerCode(), currentDate);
if (isWorkDay) {
List<CapacityEngineerSliceUsedEntity> engineerTimeSlice = engineerSliceUsedCapacityDao List<CapacityEngineerSliceUsedEntity> engineerTimeSlice = engineerSliceUsedCapacityDao
.findByWorkdayAndEngineerCode(DateTimeUtil.formatDate(currentDate), engineerInfo.getEngineerCode()); .findByWorkdayAndEngineerCode(DateTimeUtil.formatDate(currentDate), engineerInfo.getEngineerCode());
allEngineerTimeSlice.addAll(engineerTimeSlice); allEngineerTimeSlice.addAll(engineerTimeSlice);
} }
}
List<CapacityQueryDTO.Segment> objects = new ArrayList<>(); List<CapacityQueryDTO.Segment> objects = new ArrayList<>();
//计算所有工程师全天天类型容量 //计算所有工程师全天天类型容量
if (CollectionUtils.isNotEmpty(allDayTypeTimeSlice)) { if (CollectionUtils.isNotEmpty(allDayTypeTimeSlice)) {
......
...@@ -92,6 +92,8 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -92,6 +92,8 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
@Autowired @Autowired
private IUser user; private IUser user;
private final static List<String> ALL_WORK_DAY_OF_WEEK = List.of("1", "2", "3", "4", "5", "6", "7");
@Override @Override
public Result<?> getEngineersCalendar(EngineerCalendarDTO.Request req) { public Result<?> getEngineersCalendar(EngineerCalendarDTO.Request req) {
// 技术员日历,查询 capacity_engineer_calendar表,如果当日有各种事项,进行显示;否则显示正常上班; // 技术员日历,查询 capacity_engineer_calendar表,如果当日有各种事项,进行显示;否则显示正常上班;
...@@ -579,11 +581,10 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -579,11 +581,10 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
.flatMap(Collection::stream) .flatMap(Collection::stream)
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
List<String> allWorkDayOfWeek = List.of("1", "2", "3", "4", "5", "6", "7");
// 求多个工作队的公共空闲时间 // 求多个工作队的公共空闲时间
final int dayOfWeek = targetDate.getDayOfWeek().getValue(); final int dayOfWeek = targetDate.getDayOfWeek().getValue();
List<String> commonLeisureDayOfWeek = allWorkDayOfWeek.stream().filter(day -> teamCommonWorkdaysOfWeek.stream().noneMatch(tDay -> Objects.equals(day, tDay))) List<String> commonLeisureDayOfWeek = ALL_WORK_DAY_OF_WEEK.stream().filter(day -> teamCommonWorkdaysOfWeek.stream().noneMatch(tDay -> Objects.equals(day, tDay)))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (commonLeisureDayOfWeek.contains(String.valueOf(dayOfWeek))) { if (commonLeisureDayOfWeek.contains(String.valueOf(dayOfWeek))) {
LocalDateTime startTime = LocalDateTime.of(targetDate, LocalTime.of(8, 0)); LocalDateTime startTime = LocalDateTime.of(targetDate, LocalTime.of(8, 0));
...@@ -596,6 +597,20 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService { ...@@ -596,6 +597,20 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
return calendarInfoList; return calendarInfoList;
} }
@Override
public boolean engineerTeamDateWorkTime(String teamId, String engineerCode, LocalDate targetDate) {
//根据工作队信息查工程师, 如果该工作队不存在该工程师直接返回空数组
EngineerInfoEntity engineerInfoEntity = engineerInfoDao.selectEngineerByEngineerCodeAndTeamId(engineerCode, teamId);
if (Objects.isNull(engineerInfoEntity)) {
return false;
}
//排除工作队休息时间(整天)
OrgTeamEntity e = orgTeamDao.getByTeamId(teamId);
List<String> workDay = List.of(e.getWorkdays().split(","));
final int dayOfWeek = targetDate.getDayOfWeek().getValue();
return workDay.contains(String.valueOf(dayOfWeek));
}
private EngineerCalendarDTO.Calendar getEmptyCalendar(String teamId, String date) { private EngineerCalendarDTO.Calendar getEmptyCalendar(String teamId, String date) {
// 初始化一天的日历 // 初始化一天的日历
OrgTeamEntity e = orgTeamDao.getByTeamId(teamId); OrgTeamEntity e = orgTeamDao.getByTeamId(teamId);
......
...@@ -128,6 +128,10 @@ public class ScheduleServiceImpl implements ScheduleService { ...@@ -128,6 +128,10 @@ public class ScheduleServiceImpl implements ScheduleService {
List<ScheduleOverviewResp.Item> children = new ArrayList<>(); List<ScheduleOverviewResp.Item> children = new ArrayList<>();
Integer teamDistance = 0; Integer teamDistance = 0;
Integer minOrderSum=null;
Integer maxOrderSum=null;
Integer minDistance=null;
Integer maxDistance=null;
for (Map.Entry<String, List<EngineerInfoEntity>> entry : engineers.entrySet()) { for (Map.Entry<String, List<EngineerInfoEntity>> entry : engineers.entrySet()) {
ScheduleOverviewResp.Item child = new ScheduleOverviewResp.Item(); ScheduleOverviewResp.Item child = new ScheduleOverviewResp.Item();
...@@ -148,12 +152,45 @@ public class ScheduleServiceImpl implements ScheduleService { ...@@ -148,12 +152,45 @@ public class ScheduleServiceImpl implements ScheduleService {
child.setDistanceDesc(distanceSum + ""); child.setDistanceDesc(distanceSum + "");
children.add(child); children.add(child);
if(null==minOrderSum||null==maxOrderSum){
minOrderSum=child.getOrder().getTotal();
maxOrderSum=child.getOrder().getTotal();
}else {
if(child.getOrder().getTotal()<minOrderSum){
minOrderSum=child.getOrder().getTotal();
}
if(child.getOrder().getTotal()>maxOrderSum){
maxOrderSum=child.getOrder().getTotal();
}
}
if(null==minDistance||null==maxDistance){
minDistance=distanceSum;
maxDistance=distanceSum;
}else {
if(distanceSum<minDistance){
minDistance=distanceSum;
}
if(distanceSum>maxDistance){
maxDistance=distanceSum;
}
}
} }
team.setChildren(children); team.setChildren(children);
team.setOrderDesc(String.format("人均:%d", teamEngineers.size() > 0 ? (orders.size() / teamEngineers.size()) : 0)); team.setOrderDesc(String.format("人数:%d,人均:%d,%s-%s",
team.setDistanceDesc(teamDistance + ""); teamEngineers.size(),
teamEngineers.size() > 0 ? (orders.size() / teamEngineers.size()) : 0,
minOrderSum,
maxOrderSum));
team.setDistanceDesc(String.format("人均:%s,%s-%s",
teamEngineers.size() > 0 ? new BigDecimal(teamDistance)
.divide(new BigDecimal(teamEngineers.size()), 2, RoundingMode.HALF_UP)
.stripTrailingZeros() : 0,
minDistance,
maxDistance));
teams.add(team); teams.add(team);
} }
...@@ -202,11 +239,18 @@ public class ScheduleServiceImpl implements ScheduleService { ...@@ -202,11 +239,18 @@ public class ScheduleServiceImpl implements ScheduleService {
sumElapsed += Objects.isNull(o.getArriveElapsed()) ? 0 : o.getArriveElapsed(); sumElapsed += Objects.isNull(o.getArriveElapsed()) ? 0 : o.getArriveElapsed();
} }
String groupName = "";
OrgGroupEntity group = orgGroupDao.getByGroupId(engineer.getGroupId());
if (group != null) {
groupName = group.getGroupName();
}
Map<String, List<OrderInfoEntity>> statusGroup = orderAppointments.stream().collect(Collectors.groupingBy(OrderInfoEntity::getServiceStatus)); Map<String, List<OrderInfoEntity>> statusGroup = orderAppointments.stream().collect(Collectors.groupingBy(OrderInfoEntity::getServiceStatus));
List<OrderInfoEntity> empty = new ArrayList<>(); List<OrderInfoEntity> empty = new ArrayList<>();
Integer countPending = statusGroup.getOrDefault("INIT", empty).size() + statusGroup.getOrDefault("CONTACTED", empty).size() + statusGroup.getOrDefault("PENDING", empty).size(); Integer countPending = statusGroup.getOrDefault("INIT", empty).size() + statusGroup.getOrDefault("CONTACTED", empty).size() + statusGroup.getOrDefault("PENDING", empty).size();
ScheduleEngineerOverviewDynamics dynamics = new ScheduleEngineerOverviewDynamics(); ScheduleEngineerOverviewDynamics dynamics = new ScheduleEngineerOverviewDynamics();
dynamics.setGroupName(groupName);
dynamics.setName(engineer.getName()); dynamics.setName(engineer.getName());
dynamics.setEngineerCode(engineer.getEngineerCode()); dynamics.setEngineerCode(engineer.getEngineerCode());
dynamics.setPhone(engineer.getPhone()); dynamics.setPhone(engineer.getPhone());
...@@ -273,12 +317,6 @@ public class ScheduleServiceImpl implements ScheduleService { ...@@ -273,12 +317,6 @@ public class ScheduleServiceImpl implements ScheduleService {
orders.add(item); orders.add(item);
} }
String groupName = "";
OrgGroupEntity group = orgGroupDao.getByGroupId(engineer.getGroupId());
if (group != null) {
groupName = group.getGroupName();
}
ScheduleEngineerOverviewResp res = new ScheduleEngineerOverviewResp(); ScheduleEngineerOverviewResp res = new ScheduleEngineerOverviewResp();
// res.setTitle(String.format("%s_%s_%s_%s_%s", groupName, // res.setTitle(String.format("%s_%s_%s_%s_%s", groupName,
// engineer.getName(), // engineer.getName(),
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!