Commit 2896b157 by chamberone

Merge branch 'develop' of https://zhangguoping@gitlab.dituhui.com/bsh/project/pr…

…oject.git into develop
2 parents 5ae97a31 c679fb62
Showing with 1425 additions and 793 deletions
### 批次准备数据、aps引擎处理
* 接口
* ### 重新组织数据并开始计算
GET http://localhost:8011/dispatch/prepare/solveAsync/gsuzhou/2023-07-07
* 查看实时处理状态
GET http://localhost:8011/dispatch/prepare/solveStatus/gsuzhou/2023-07-07
* 停止实时处理状态
GET http://localhost:8011/dispatch/prepare/solveStop/gsuzhou/2023-07-07
...@@ -56,7 +56,7 @@ public class BatchController { ...@@ -56,7 +56,7 @@ public class BatchController {
@JsonDeserialize(using = LocalDateTimeDeserializer.class) @JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat( pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime endTime; LocalDateTime endTime;
String status; String status;
} }
...@@ -88,29 +88,10 @@ public class BatchController { ...@@ -88,29 +88,10 @@ public class BatchController {
} }
/* @GetMapping("/query/{groupId}/{day}")
* 检查指定日期的小组是否有在运行的批次任务,有则返回,没有则创建后返回批次码 public Result<?> queryBatch(@PathVariable String groupId, @PathVariable String day) {
*/
@GetMapping("/build/{groupId}/{day}")
public Result<?> buildBatch(@PathVariable String groupId, @PathVariable String day) {
log.info("buildBatch, groupId:{}, day:{}", groupId, day); log.info("buildBatch, groupId:{}, day:{}", groupId, day);
try { DispatchBatch batch = batchService.queryBatchInfoByDay(groupId, day);
String batchNo = batchService.buildBatchData(groupId, day);
DispatchBatch batch = batchService.queryBatch(groupId, batchNo);
DispatchBatchDTO batchDTO = new DispatchBatchDTO();
BeanUtil.copyProperties(batch, batchDTO, CopyOptions.create().setIgnoreNullValue(true));
return Result.success(batchDTO);
} catch (SQLException e) {
log.error("buildBatch error", e);
return Result.failed(e.getMessage());
}
}
@GetMapping("/query/{groupId}/{batchNo}")
public Result<?> queryBatch(@PathVariable String groupId, @PathVariable String batchNo) {
log.info("buildBatch, groupId:{}, batchNo:{}", groupId, batchNo);
DispatchBatch batch = batchService.queryBatch(groupId, batchNo);
DispatchBatchDTO batchDTO = new DispatchBatchDTO(); DispatchBatchDTO batchDTO = new DispatchBatchDTO();
BeanUtil.copyProperties(batch, batchDTO, CopyOptions.create().setIgnoreNullValue(true)); BeanUtil.copyProperties(batch, batchDTO, CopyOptions.create().setIgnoreNullValue(true));
......
...@@ -7,9 +7,11 @@ import com.dituhui.pea.dispatch.constraint.DispatchConstraintProvider; ...@@ -7,9 +7,11 @@ import com.dituhui.pea.dispatch.constraint.DispatchConstraintProvider;
import com.dituhui.pea.dispatch.pojo.Customer; import com.dituhui.pea.dispatch.pojo.Customer;
import com.dituhui.pea.dispatch.pojo.DispatchSolution; import com.dituhui.pea.dispatch.pojo.DispatchSolution;
import com.dituhui.pea.dispatch.pojo.Technician; import com.dituhui.pea.dispatch.pojo.Technician;
import com.dituhui.pea.dispatch.service.BatchService;
import com.dituhui.pea.dispatch.service.ExtractService; import com.dituhui.pea.dispatch.service.ExtractService;
import com.dituhui.pea.dispatch.service.SolveService; import com.dituhui.pea.dispatch.service.SolveService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.optaplanner.core.api.score.buildin.hardsoftlong.HardSoftLongScore; import org.optaplanner.core.api.score.buildin.hardsoftlong.HardSoftLongScore;
import org.optaplanner.core.api.solver.SolverManager; import org.optaplanner.core.api.solver.SolverManager;
import org.optaplanner.core.api.solver.SolverStatus; import org.optaplanner.core.api.solver.SolverStatus;
...@@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.PathVariable; ...@@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.sql.SQLException;
import java.time.Duration; import java.time.Duration;
import java.util.*; import java.util.*;
...@@ -39,6 +42,9 @@ public class PrepareController { ...@@ -39,6 +42,9 @@ public class PrepareController {
@Autowired @Autowired
SolveService solveService; SolveService solveService;
@Autowired
BatchService batchService;
private SolverManager<DispatchSolution, UUID> solverManager; private SolverManager<DispatchSolution, UUID> solverManager;
...@@ -54,7 +60,7 @@ public class PrepareController { ...@@ -54,7 +60,7 @@ public class PrepareController {
/* /*
* 运行批次任务,直接返回结果 * 运行批次任务,直接返回结果(不重新进行数据准备)
*/ */
@GetMapping("/solveTest/{groupId}/{batchNo}") @GetMapping("/solveTest/{groupId}/{batchNo}")
public Result<?> prepareAndSolve(@PathVariable String groupId, @PathVariable String batchNo) { public Result<?> prepareAndSolve(@PathVariable String groupId, @PathVariable String batchNo) {
...@@ -70,10 +76,12 @@ public class PrepareController { ...@@ -70,10 +76,12 @@ public class PrepareController {
return Result.success(resultMap); return Result.success(resultMap);
} }
// 异步任务运行 todo // 重新进行数据准备、异步任务运行
@GetMapping("/solveAsync/{groupId}/{batchNo}") @GetMapping("/solveAsync/{groupId}/{day}")
public Result<?> solveAsync(@PathVariable String groupId, @PathVariable String batchNo) { public Result<?> solveAsync(@PathVariable String groupId, @PathVariable String day) throws SQLException {
log.info("调用引擎处理-异步处理, groupId:{}, batchNo:{}", groupId, batchNo); log.info("调用引擎处理-异步处理, groupId:{}, day:{}", groupId, day);
String batchNo = batchService.buildBatchData(groupId, day);
log.info("调用引擎处理-异步处理, groupId:{}, day:{}, batchNo:{}", groupId, day, batchNo);
UUID problemId = solveService.generateProblemId(groupId, batchNo); UUID problemId = solveService.generateProblemId(groupId, batchNo);
// 提交问题开始求解 // 提交问题开始求解
DispatchSolution problem = solveService.prepareSolution(groupId, batchNo); DispatchSolution problem = solveService.prepareSolution(groupId, batchNo);
...@@ -86,22 +94,32 @@ public class PrepareController { ...@@ -86,22 +94,32 @@ public class PrepareController {
return Result.success("已触发异步执行"); return Result.success("已触发异步执行");
} }
@GetMapping("/solveStatus/{groupId}/{batchNo}") @GetMapping("/solveStatus/{groupId}/{day}")
public Result<?> solveStatus(@PathVariable String groupId, @PathVariable String batchNo) { public Result<?> solveStatus(@PathVariable String groupId, @PathVariable String day) {
log.info("查询引擎处理状态, groupId:{}, batchNo:{}", groupId, batchNo); log.info("查询引擎处理状态, groupId:{}, day:{}", groupId, day);
String batchNo = batchService.queryBatchNoByDay(groupId, day);
log.info("查询引擎处理状态, groupId:{}, day:{}, batchNo:{}", groupId, day, batchNo);
if (StringUtils.isEmpty(batchNo)) {
return Result.failed("未查询到到批次数据信息");
}
UUID problemId = solveService.generateProblemId(groupId, batchNo); UUID problemId = solveService.generateProblemId(groupId, batchNo);
SolverStatus status = solverManager.getSolverStatus(problemId); SolverStatus status = solverManager.getSolverStatus(problemId);
log.info("查询引擎处理状态, groupId:{}, batchNo:{}, status:{}", groupId, batchNo, status.toString()); log.info("查询引擎处理状态, groupId:{}, day:{}, batchNo:{}, status:{}", groupId, day, batchNo, status.toString());
return Result.success(status); return Result.success(status);
} }
@GetMapping("/solveStop/{groupId}/{batchNo}") @GetMapping("/solveStop/{groupId}/{day}")
public Result<?> solveStop(@PathVariable String groupId, @PathVariable String batchNo) { public Result<?> solveStop(@PathVariable String groupId, @PathVariable String day) {
log.info("停止引擎处理批次, groupId:{}, batchNo:{}", groupId, batchNo); log.info("停止引擎处理批次, groupId:{}, day:{}", groupId, day);
String batchNo = batchService.queryBatchNoByDay(groupId, day);
log.info("查询引擎处理状态, groupId:{}, day:{}, batchNo:{}", groupId, day, batchNo);
if (StringUtils.isEmpty(batchNo)) {
return Result.failed("未查询到到批次数据信息");
}
UUID problemId = solveService.generateProblemId(groupId, batchNo); UUID problemId = solveService.generateProblemId(groupId, batchNo);
solverManager.terminateEarly(problemId); solverManager.terminateEarly(problemId);
SolverStatus status = solverManager.getSolverStatus(problemId); SolverStatus status = solverManager.getSolverStatus(problemId);
log.info("停止引擎处理批次, groupId:{}, batchNo:{}, status:{}", groupId, batchNo, status.toString()); log.info("停止引擎处理批次, groupId:{}, day:{}, batchNo:{}, status:{}", groupId, day, batchNo, status.toString());
return Result.success(status); return Result.success(status);
} }
......
...@@ -4,12 +4,15 @@ package com.dituhui.pea.dispatch.entity; ...@@ -4,12 +4,15 @@ package com.dituhui.pea.dispatch.entity;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.Data; import lombok.Data;
import javax.persistence.*; import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@Data @Data
...@@ -46,6 +49,13 @@ public class OrderAppointment implements Serializable { ...@@ -46,6 +49,13 @@ public class OrderAppointment implements Serializable {
private Integer isWorkshop; private Integer isWorkshop;
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Column(name = "dt")
private LocalDate dt;
@JsonDeserialize(using = LocalDateTimeDeserializer.class) @JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
......
...@@ -4,12 +4,15 @@ package com.dituhui.pea.dispatch.entity; ...@@ -4,12 +4,15 @@ package com.dituhui.pea.dispatch.entity;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.Data; import lombok.Data;
import javax.persistence.*; import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@Data @Data
...@@ -57,6 +60,14 @@ public class OrderRequest implements Serializable { ...@@ -57,6 +60,14 @@ public class OrderRequest implements Serializable {
@Column(name = "fault_describe") @Column(name = "fault_describe")
private String faultDescribe; private String faultDescribe;
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Column(name = "dt")
private LocalDate dt;
@JsonDeserialize(using = LocalDateTimeDeserializer.class) @JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
......
...@@ -19,6 +19,8 @@ public interface BatchService { ...@@ -19,6 +19,8 @@ public interface BatchService {
@Transactional @Transactional
String buildBatchData(String groupId, String day) throws SQLException; String buildBatchData(String groupId, String day) throws SQLException;
DispatchBatch queryBatchInfoByDay(String groupId, String day);
String queryBatchNoByDay(String groupId, String day);
DispatchBatch queryBatch(String groupId, String day);
} }
...@@ -103,7 +103,7 @@ public class BatchServiceImpl implements BatchService { ...@@ -103,7 +103,7 @@ public class BatchServiceImpl implements BatchService {
" and a.dt = ? " + " and a.dt = ? " +
" and appointment_status ='NOT_ASSIGNED' and appointment_method like 'AUTO%' \n" + " and appointment_status ='NOT_ASSIGNED' and appointment_method like 'AUTO%' \n" +
" order by a.expect_time_begin asc "; " order by a.expect_time_begin asc ";
int orderCount = jdbcTemplate.update(sqlOrder, batchNo, groupId, batchDay ); int orderCount = jdbcTemplate.update(sqlOrder, batchNo, groupId, batchDay);
// 已派过PRE状态还可以再次派 // 已派过PRE状态还可以再次派
String sqlOrderPre = "INSERT INTO dispatch_order (group_id, batch_no, order_id , x, y, expect_time_begin, expect_time_end, tags, priority , skills , take_time )\n" + String sqlOrderPre = "INSERT INTO dispatch_order (group_id, batch_no, order_id , x, y, expect_time_begin, expect_time_end, tags, priority , skills , take_time )\n" +
...@@ -117,12 +117,14 @@ public class BatchServiceImpl implements BatchService { ...@@ -117,12 +117,14 @@ public class BatchServiceImpl implements BatchService {
" and a.appointment_status = 'ASSIGNED' and appointment_method like 'AUTO%' \n" + " and a.appointment_status = 'ASSIGNED' and appointment_method like 'AUTO%' \n" +
" and o.pre_status ='PRE' \n" + " and o.pre_status ='PRE' \n" +
" order by a.expect_time_begin asc "; " order by a.expect_time_begin asc ";
int orderCountPre = jdbcTemplate.update(sqlOrderPre, batchNo, groupId, batchDay ); int orderCountPre = jdbcTemplate.update(sqlOrderPre, batchNo, groupId, batchDay);
log.info("准备批次数据 order1 :{}", orderCount);
log.info("准备批次数据 order2 :{}", orderCountPre);
jdbcTemplate.update("update dispatch_batch set engineer_num=? , order_num=?, start_time=?, end_time=null, status='RUNNING' where group_id=? and batch_no=?", jdbcTemplate.update("update dispatch_batch set engineer_num=? , order_num=?, start_time=?, end_time=null, status='RUNNING' where group_id=? and batch_no=?",
engCount, orderCount+orderCountPre, LocalDateTime.now(), groupId, batchNo); engCount, orderCount + orderCountPre, LocalDateTime.now(), groupId, batchNo);
log.info("准备批次数据完成, groupId:{}, day:{}, batchNo:{}", groupId, batchDay, batchNo); log.info("准备批次数据完成, groupId:{}, day:{}, batchNo:{}", groupId, batchDay, batchNo);
...@@ -130,14 +132,21 @@ public class BatchServiceImpl implements BatchService { ...@@ -130,14 +132,21 @@ public class BatchServiceImpl implements BatchService {
} }
public DispatchBatch queryBatch(String groupId, String batchNo) { @Override
List<DispatchBatch> batchList = batchRepository.findLatestGroup(groupId, batchNo); public String queryBatchNoByDay(String groupId, String day) {
if (batchList.size() > 0) { Optional<DispatchBatch> optional = batchRepository.findByGroupIdAndBatchDate(groupId, day);
return batchList.get(0); if (optional.isPresent()) {
return optional.get().getBatchNo();
} else { } else {
return new DispatchBatch(); return "";
} }
} }
@Override
public DispatchBatch queryBatchInfoByDay(String groupId, String day) {
Optional<DispatchBatch> optional = batchRepository.findByGroupIdAndBatchDate(groupId, day);
return optional.orElseGet(DispatchBatch::new);
}
} }
...@@ -223,6 +223,7 @@ public class ExtractServiceImpl implements ExtractService { ...@@ -223,6 +223,7 @@ public class ExtractServiceImpl implements ExtractService {
appointment.setEngineerName(engName); appointment.setEngineerName(engName);
appointment.setEngineerPhone(phone); appointment.setEngineerPhone(phone);
appointment.setEngineerAge(age); appointment.setEngineerAge(age);
appointment.setDt(orderRequest.getDt());
appointment.setExpectStartTime(dispatchOrder.getTimeBegin()); appointment.setExpectStartTime(dispatchOrder.getTimeBegin());
appointment.setExpectEndTime(dispatchOrder.getTimeEnd()); appointment.setExpectEndTime(dispatchOrder.getTimeEnd());
appointment.setUpdateTime(LocalDateTime.now()); appointment.setUpdateTime(LocalDateTime.now());
...@@ -240,6 +241,7 @@ public class ExtractServiceImpl implements ExtractService { ...@@ -240,6 +241,7 @@ public class ExtractServiceImpl implements ExtractService {
appointment.setEngineerPhone(phone); appointment.setEngineerPhone(phone);
appointment.setEngineerAge(age); appointment.setEngineerAge(age);
appointment.setIsWorkshop(0); appointment.setIsWorkshop(0);
appointment.setDt(orderRequest.getDt());
appointment.setExpectStartTime(dispatchOrder.getTimeBegin()); appointment.setExpectStartTime(dispatchOrder.getTimeBegin());
appointment.setExpectEndTime(dispatchOrder.getTimeEnd()); appointment.setExpectEndTime(dispatchOrder.getTimeEnd());
appointment.setPreStatus("PRE"); appointment.setPreStatus("PRE");
......
package com.dituhui.pea.order.common;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.TextStyle;
import java.util.Locale;
public class DateUtil {
public static String toWeekChinese(String date) {
LocalDate d = LocalDate.parse(date);
return DateUtil.toWeekChinese(d.getDayOfWeek().getValue());
}
public static String toWeekChinese(int dayOfWeek) {
// TextStyle: SHORT 周一;LONG 星期一;NARROW 一
return DayOfWeek.of(dayOfWeek).getDisplayName(TextStyle.SHORT, Locale.CHINESE);
}
}
package com.dituhui.pea.order.common;
import com.dituhui.pea.order.dao.EngineerInfoDao;
import com.dituhui.pea.order.dao.OrgGroupDao;
import com.dituhui.pea.order.dao.OrgTeamEngineerDao;
import com.dituhui.pea.order.entity.EngineerInfoEntity;
import com.dituhui.pea.order.entity.OrgGroupEntity;
import com.dituhui.pea.order.entity.OrgTeamEngineerEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class EngineerUtil {
@Autowired
private OrgTeamEngineerDao orgTeamEngineerDao;
@Autowired
private EngineerInfoDao engineerInfoDao;
@Autowired
private OrgGroupDao orgGroupDao;
public List<EngineerInfoEntity> getEngineersByLevel(String levelType, String levelValue) {
List<EngineerInfoEntity> engineers = null;
List<String> groupIds = null;
switch (levelType) {
case "team":
List<String> engineerCodes = orgTeamEngineerDao.findAllByTeamId(levelValue).stream()
.map(OrgTeamEngineerEntity::getEngineerCode).collect(Collectors.toList());
engineers = engineerInfoDao.findByEngineerCodeIn(engineerCodes);
break;
case "group":
engineers = engineerInfoDao.findByGroupId(levelValue);
break;
case "branch":
groupIds = orgGroupDao.findAllByBranchId(levelValue).stream()
.map(OrgGroupEntity::getGroupId).collect(Collectors.toList());
engineers = engineerInfoDao.findByGroupIdIn(groupIds);
break;
default:
// "cluster".equals(levelType)
groupIds = orgGroupDao.findAllByClusterId(levelValue).stream()
.map(OrgGroupEntity::getGroupId).collect(Collectors.toList());
engineers = engineerInfoDao.findByGroupIdIn(groupIds);
break;
}
return engineers;
}
public Page<EngineerInfoEntity> filterEngineersByKeyAndPage(List<String> engineerCodes, String key, Integer page, Integer size) {
Pageable pageable = PageRequest.of(page - 1, size);
return engineerInfoDao.findAllByEngineerCodeIn(engineerCodes, buildSpecification(key), pageable);
}
public List<EngineerInfoEntity> filterEngineersByKey(List<String> engineerCodes, String key) {
return engineerInfoDao.findAllByEngineerCodeIn(engineerCodes, buildSpecification(key));
}
private Specification<EngineerInfoEntity> buildSpecification(String keyword) {
return new Specification<EngineerInfoEntity>() {
@Override
public Predicate toPredicate(Root<EngineerInfoEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>();
// 构建查询条件
Predicate engineerCodePredicate = criteriaBuilder.like(root.get("engineerCode"), "%" + keyword + "%");
Predicate mobilePredicate = criteriaBuilder.like(root.get("phone"), "%" + keyword + "%");
Predicate msgContentPredicate = criteriaBuilder.like(root.get("name"), "%" + keyword + "%");
predicates.add(criteriaBuilder.or(engineerCodePredicate, mobilePredicate, msgContentPredicate));
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
}
};
}
}
...@@ -9,7 +9,9 @@ import com.dituhui.pea.order.entity.OrderAppointment; ...@@ -9,7 +9,9 @@ import com.dituhui.pea.order.entity.OrderAppointment;
import com.dituhui.pea.order.entity.OrderRequest; import com.dituhui.pea.order.entity.OrderRequest;
import com.dituhui.pea.order.entity.SkillInfo; import com.dituhui.pea.order.entity.SkillInfo;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.LocalDate; import java.time.LocalDate;
...@@ -21,10 +23,9 @@ import java.util.List; ...@@ -21,10 +23,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Component
@Slf4j
public class OrderAssignCheck { public class OrderAssignCheck {
private String orderId;
private String engineerCode;
@Autowired @Autowired
OrderRequestMPDao orderRequestMPDao; OrderRequestMPDao orderRequestMPDao;
...@@ -37,11 +38,6 @@ public class OrderAssignCheck { ...@@ -37,11 +38,6 @@ public class OrderAssignCheck {
@Autowired @Autowired
EngineerBusinessMPDao engineerBusinessMPDao; EngineerBusinessMPDao engineerBusinessMPDao;
public OrderAssignCheck(String orderId, String engineerCode) {
this.orderId = orderId;
this.engineerCode = engineerCode;
}
@Data @Data
public class Result { public class Result {
private Boolean canAssign; private Boolean canAssign;
...@@ -61,8 +57,10 @@ public class OrderAssignCheck { ...@@ -61,8 +57,10 @@ public class OrderAssignCheck {
} }
} }
public Result orderAssignCheck() { public Result orderAssignCheck(String orderId, String engineerCode) {
OrderRequest order = orderRequestMPDao.getByOrderId(this.orderId); log.info("begin orderAssignCheck:orderId={}, engineerCode={}", orderId, engineerCode);
OrderRequest order = orderRequestMPDao.getByOrderId(orderId);
double curX = Double.parseDouble(order.getX()); double curX = Double.parseDouble(order.getX());
double curY = Double.parseDouble(order.getY()); double curY = Double.parseDouble(order.getY());
...@@ -73,17 +71,21 @@ public class OrderAssignCheck { ...@@ -73,17 +71,21 @@ public class OrderAssignCheck {
// 获取客户期望时间段 // 获取客户期望时间段
int start = this.timestamp2Point(order.getExpectTimeBegin()); int start = this.timestamp2Point(order.getExpectTimeBegin());
int end = this.timestamp2Point(order.getExpectTimeEnd()); int end = this.timestamp2Point(order.getExpectTimeEnd());
log.info("客户期望的时间段:{}-{}, 技能所需时长:{}, 坐标:{},{}", start, end, takeTime, curX, curY);
// 获取技术员的已分配订单的时间段, 根据时间段排序 // 获取技术员的已分配订单的时间段, 根据时间段排序
List<OrderSegment> orderSegments = getEngineerOrderSegments(engineerCode, order.getDt()); List<OrderSegment> orderSegments = getEngineerOrderSegments(engineerCode, order.getDt());
// 转化为SegmentInsertion需要的时间段 // 转化为SegmentInsertion需要的时间段
List<SegmentInsertion.Segment> segments = this.orderSegment2Segment(orderSegments); List<SegmentInsertion.Segment> segments = this.orderSegment2Segment(orderSegments);
log.info("技术员已分配时间段列表:{}", segments);
int index = SegmentInsertion.insertSegment(takeTime, start, end, segments); int index = SegmentInsertion.insertSegment(takeTime, start, end, segments);
if (index == -1) { if (index == -1) {
log.info("没有可连续插入的空间");
return new Result(false, "没有连续可插入空间(没计算时间)", 0, 0, null, null); return new Result(false, "没有连续可插入空间(没计算时间)", 0, 0, null, null);
} }
log.info("插入位置为第{}单", index);
// 计算距离 & 时间 // 计算距离 & 时间
if(index == 0) { if(index == 0) {
// 第一订单为出发地 // 第一订单为出发地
...@@ -97,12 +99,12 @@ public class OrderAssignCheck { ...@@ -97,12 +99,12 @@ public class OrderAssignCheck {
OrderSegment pre = orderSegments.get(index); OrderSegment pre = orderSegments.get(index);
// 为当前订单 // 为当前订单
OrderSegment post = new OrderSegment(start, end, Double.parseDouble(order.getX()), Double.parseDouble(order.getY())); OrderSegment post = new OrderSegment(start, end, Double.parseDouble(order.getX()), Double.parseDouble(order.getY()));
return this.getResult(curX, curY, pre, post, takeTime, order.getDt());
} else { } else {
OrderSegment pre = orderSegments.get(index); OrderSegment pre = orderSegments.get(index);
OrderSegment post = orderSegments.get(index+1); OrderSegment post = orderSegments.get(index+1);
return this.getResult(curX, curY, pre, post, takeTime, order.getDt()); return this.getResult(curX, curY, pre, post, takeTime, order.getDt());
} }
return null;
} }
private List<OrderSegment> getEngineerOrderSegments(String engineerCode, LocalDate dt) { private List<OrderSegment> getEngineerOrderSegments(String engineerCode, LocalDate dt) {
...@@ -117,6 +119,10 @@ public class OrderAssignCheck { ...@@ -117,6 +119,10 @@ public class OrderAssignCheck {
} }
orderIds.add(o.getOrderId()); orderIds.add(o.getOrderId());
} }
if(orderIds.isEmpty()){
return orderSegments;
}
Map<String, List<OrderAppointment>> m = appointments.stream().collect(Collectors.groupingBy(OrderAppointment::getOrderId)); Map<String, List<OrderAppointment>> m = appointments.stream().collect(Collectors.groupingBy(OrderAppointment::getOrderId));
List<OrderRequest> orderRequests = orderRequestMPDao.selectByOrderIds(orderIds); List<OrderRequest> orderRequests = orderRequestMPDao.selectByOrderIds(orderIds);
for(OrderRequest o: orderRequests) { for(OrderRequest o: orderRequests) {
......
...@@ -43,6 +43,10 @@ public class TimeUtils { ...@@ -43,6 +43,10 @@ public class TimeUtils {
return LocalDate.parse(s, DateTimeFormatter.ofPattern(pattern)); return LocalDate.parse(s, DateTimeFormatter.ofPattern(pattern));
} }
public static final String IsoLocalDate2String(LocalDate localDate) {
return localDate.format(DateTimeFormatter.ofPattern(DATE_GAP_FORMAT));
}
public static final LocalDate addDays(LocalDate date, long days) { public static final LocalDate addDays(LocalDate date, long days) {
return date.plusDays(days); return date.plusDays(days);
} }
......
...@@ -3,8 +3,11 @@ package com.dituhui.pea.order.controller; ...@@ -3,8 +3,11 @@ package com.dituhui.pea.order.controller;
import com.dituhui.pea.common.BusinessException; import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result; import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dto.EngineerBusinessUpdateReqDTO; import com.dituhui.pea.order.dto.EngineerBusinessUpdateReqDTO;
import com.dituhui.pea.order.dto.EngineerCalendarDTO;
import com.dituhui.pea.order.dto.EngineerSkillUpdateReqDTO; import com.dituhui.pea.order.dto.EngineerSkillUpdateReqDTO;
import com.dituhui.pea.order.dto.EngineersGanttReqDTO; import com.dituhui.pea.order.dto.EngineersGanttDTO;
import com.dituhui.pea.order.service.EngineerCalendarService;
import com.dituhui.pea.order.service.EngineerGanttService;
import com.dituhui.pea.order.service.EngineerService; import com.dituhui.pea.order.service.EngineerService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -16,130 +19,147 @@ import org.springframework.web.bind.annotation.*; ...@@ -16,130 +19,147 @@ import org.springframework.web.bind.annotation.*;
@RequestMapping("/pea-order") @RequestMapping("/pea-order")
public class EngineerController { public class EngineerController {
@Autowired @Autowired
private EngineerService engineerService; private EngineerService engineerService;
@GetMapping("/engineer/info/list") @Autowired
public Result<?> getEngineerInfoList(@RequestParam String levelType, private EngineerGanttService engineerGanttService;
@RequestParam String levelValue,
@RequestParam long page,
@RequestParam long size,
@RequestParam(required = false) String kind,
@RequestParam(required = false) String key) {
// 获取工程师基础信息列表
Result<?> res = null;
try {
res = engineerService.getEngineerInfoList(levelType, levelValue, page, size, kind, key);
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
@GetMapping("/engineer/info/detail") @Autowired
public Result<?> getEngineerInfoDetail(@RequestParam String engineerCode) { private EngineerCalendarService engineerCalendarService;
// 获取工程师基础信息列表
Result<?> res = null;
try {
res = engineerService.getEngineerInfoDetail(engineerCode);
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
@GetMapping("/engineer/skill/list") @GetMapping("/engineer/info/list")
public Result<?> getEngineerSkillList(@RequestParam String levelType, public Result<?> getEngineerInfoList(@RequestParam String levelType,
@RequestParam String levelValue, @RequestParam String levelValue,
@RequestParam long page, @RequestParam long page,
@RequestParam long size, @RequestParam long size,
@RequestParam(required = false) String kind, @RequestParam(required = false) String kind,
@RequestParam(required = false) String key) { @RequestParam(required = false) String key) {
// 获取工程师技能信息列表 // 获取工程师基础信息列表
Result<?> res = null; Result<?> res = null;
try { try {
res = engineerService.getEngineerSkillList(levelType, levelValue, page, size, kind, key); res = engineerService.getEngineerInfoList(levelType, levelValue, page, size, kind, key);
} catch (BusinessException e) { } catch (BusinessException e) {
return Result.failed(e.getMessage()); return Result.failed(e.getMessage());
} }
return res; return res;
} }
@GetMapping("/engineer/skill/detail") @GetMapping("/engineer/info/detail")
public Result<?> getEngineerSkillDetail(@RequestParam String engineerCode) { public Result<?> getEngineerInfoDetail(@RequestParam String engineerCode) {
// 获取工程师技能信息列表 // 获取工程师基础信息列表
Result<?> res = null; Result<?> res = null;
try { try {
res = engineerService.getEngineerSkillDetail(engineerCode); res = engineerService.getEngineerInfoDetail(engineerCode);
} catch (BusinessException e) { } catch (BusinessException e) {
return Result.failed(e.getMessage()); return Result.failed(e.getMessage());
} }
return res; return res;
} }
@PostMapping("/engineer/skill/update") @GetMapping("/engineer/skill/list")
public Result<?> engineerSkillUpdate(@RequestBody EngineerSkillUpdateReqDTO req) { public Result<?> getEngineerSkillList(@RequestParam String levelType,
// 获取工程师技能信息修改 @RequestParam String levelValue,
try { @RequestParam long page,
engineerService.engineerSkillUpdate(req.getEngineerCode(), req.getSkillGroupIds()); @RequestParam long size,
} catch (BusinessException e) { @RequestParam(required = false) String kind,
return Result.failed(e.getMessage()); @RequestParam(required = false) String key) {
} // 获取工程师技能信息列表
return Result.success(null); Result<?> res = null;
} try {
res = engineerService.getEngineerSkillList(levelType, levelValue, page, size, kind, key);
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
@GetMapping("/engineer/business/list") @GetMapping("/engineer/skill/detail")
public Result<?> getEngineerBusinessList(@RequestParam String levelType, public Result<?> getEngineerSkillDetail(@RequestParam String engineerCode) {
@RequestParam String levelValue, // 获取工程师技能信息列表
@RequestParam long page, Result<?> res = null;
@RequestParam long size, try {
@RequestParam(required = false) String kind, res = engineerService.getEngineerSkillDetail(engineerCode);
@RequestParam(required = false) String key) { } catch (BusinessException e) {
// 技术员业务属性配置列表 return Result.failed(e.getMessage());
Result<?> res = null; }
try { return res;
res = engineerService.getEngineerBusinessList(levelType, levelValue, page, size, kind, key); }
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
@GetMapping("/engineer/business/detail") @PostMapping("/engineer/skill/update")
public Result<?> getEngineerBusinessDetail(@RequestParam String engineerCode) { public Result<?> engineerSkillUpdate(@RequestBody EngineerSkillUpdateReqDTO req) {
// 技术员业务属性配置列表 // 获取工程师技能信息修改
Result<?> res = null; try {
try { engineerService.engineerSkillUpdate(req.getEngineerCode(), req.getSkillGroupIds());
res = engineerService.getEngineerBusinessDetail(engineerCode); } catch (BusinessException e) {
} catch (BusinessException e) { return Result.failed(e.getMessage());
return Result.failed(e.getMessage()); }
} return Result.success(null);
return res; }
}
@PostMapping("/engineer/business/update") @GetMapping("/engineer/business/list")
public Result<?> engineerBusinessUpdate(@RequestBody EngineerBusinessUpdateReqDTO req) { public Result<?> getEngineerBusinessList(@RequestParam String levelType,
// 技术员业务属性配置更新 @RequestParam String levelValue,
Result<?> res = null; @RequestParam long page,
try { @RequestParam long size,
res = engineerService.engineerBusinessUpdate( @RequestParam(required = false) String kind,
req.getEngineerCode(), req.getMaxNum(), req.getMaxMinute(), @RequestParam(required = false) String key) {
req.getDeparture(), req.getPriority()); // 技术员业务属性配置列表
} catch (BusinessException e) { Result<?> res = null;
return Result.failed(e.getMessage()); try {
} res = engineerService.getEngineerBusinessList(levelType, levelValue, page, size, kind, key);
return res; } catch (BusinessException e) {
} return Result.failed(e.getMessage());
}
return res;
}
@PostMapping(value = "/engineer/schedule/gantt") @GetMapping("/engineer/business/detail")
public Result<?> getEngineersGanttList(@Validated @RequestBody EngineersGanttReqDTO reqDTO) { public Result<?> getEngineerBusinessDetail(@RequestParam String engineerCode) {
log.info("getEngineersGanttList: {}", reqDTO); // 技术员业务属性配置列表
Result<?> res = null; Result<?> res = null;
try { try {
res = engineerService.getEngineersGanttList(reqDTO); res = engineerService.getEngineerBusinessDetail(engineerCode);
} catch (BusinessException e) { } catch (BusinessException e) {
return Result.failed(e.getMessage()); return Result.failed(e.getMessage());
} }
return res; return res;
} }
@PostMapping("/engineer/business/update")
public Result<?> engineerBusinessUpdate(@RequestBody EngineerBusinessUpdateReqDTO req) {
// 技术员业务属性配置更新
Result<?> res = null;
try {
res = engineerService.engineerBusinessUpdate(
req.getEngineerCode(), req.getMaxNum(), req.getMaxMinute(),
req.getDeparture(), req.getPriority());
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
@PostMapping("/engineer/schedule/gantt")
public Result<?> getEngineersGanttList(@Validated @RequestBody EngineersGanttDTO.Request reqDTO) {
log.info("getEngineersGanttList: {}", reqDTO);
Result<?> res = null;
try {
res = engineerGanttService.getEngineersGanttList(reqDTO);
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
@GetMapping("/engineer/calendar")
public Result<?> getEngineerCalendar(@Validated EngineerCalendarDTO.Request reqDTO) {
Result<?> res = null;
try {
res = engineerCalendarService.getEngineersCalendar(reqDTO);
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
} }
...@@ -3,6 +3,7 @@ package com.dituhui.pea.order.controller; ...@@ -3,6 +3,7 @@ package com.dituhui.pea.order.controller;
import com.dituhui.pea.common.BusinessException; import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result; import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dto.OrderAssignReq; import com.dituhui.pea.order.dto.OrderAssignReq;
import com.dituhui.pea.order.dto.OrderRevokeAssign;
import com.dituhui.pea.order.service.OrderAssign; import com.dituhui.pea.order.service.OrderAssign;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
...@@ -40,4 +41,16 @@ public class OrderAssignController { ...@@ -40,4 +41,16 @@ public class OrderAssignController {
} }
return res; return res;
} }
@PostMapping("/order/revoke/assign")
public Result<?> orderRevokeAssign(@RequestBody OrderRevokeAssign req){
// 放回工单池
Result<?> res = null;
try{
res = orderAssign.orderRevokeAssign(req.getOrderId());
} catch (BusinessException e){
return Result.failed(e.getMessage());
}
return res;
}
} }
package com.dituhui.pea.order.dao;
import com.dituhui.pea.order.entity.CapacityEngineerCalendarEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface CapacityEngineerCalendarDao extends JpaRepository<CapacityEngineerCalendarEntity, Long> {
@Query("select a from CapacityEngineerCalendarEntity a where a.engineerCode=:engineerCode and a.workday between :beginDate and :endDate")
List<CapacityEngineerCalendarEntity> findCalendarByEngineerCodeAndDateBetween(String engineerCode, String beginDate, String endDate);
}
...@@ -2,13 +2,17 @@ package com.dituhui.pea.order.dao; ...@@ -2,13 +2,17 @@ package com.dituhui.pea.order.dao;
import com.dituhui.pea.order.entity.EngineerInfoEntity; import com.dituhui.pea.order.entity.EngineerInfoEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.List; import java.util.List;
@Repository @Repository
public interface EngineerInfoDao extends JpaRepository<EngineerInfoEntity, Integer> { public interface EngineerInfoDao extends JpaRepository<EngineerInfoEntity, Integer>, JpaSpecificationExecutor<EngineerInfoEntity> {
EngineerInfoEntity getByEngineerCode(String engineerCode); EngineerInfoEntity getByEngineerCode(String engineerCode);
List<EngineerInfoEntity> findByGroupId(String groupId); List<EngineerInfoEntity> findByGroupId(String groupId);
...@@ -16,4 +20,18 @@ public interface EngineerInfoDao extends JpaRepository<EngineerInfoEntity, Integ ...@@ -16,4 +20,18 @@ public interface EngineerInfoDao extends JpaRepository<EngineerInfoEntity, Integ
List<EngineerInfoEntity> findByGroupIdIn(List<String> groupIds); List<EngineerInfoEntity> findByGroupIdIn(List<String> groupIds);
List<EngineerInfoEntity> findByEngineerCodeIn(List<String> engineerCodes); List<EngineerInfoEntity> findByEngineerCodeIn(List<String> engineerCodes);
default List<EngineerInfoEntity> findAllByEngineerCodeIn(List<String> engineerCodes, Specification<EngineerInfoEntity> engineerInfoEntitySpecification) {
Specification<EngineerInfoEntity> spec = Specification.where(engineerCodeIn(engineerCodes)).and(engineerInfoEntitySpecification);
return findAll(spec);
}
default Page<EngineerInfoEntity> findAllByEngineerCodeIn(List<String> engineerCodes, Specification<EngineerInfoEntity> engineerInfoEntitySpecification, Pageable pageable) {
Specification<EngineerInfoEntity> spec = Specification.where(engineerCodeIn(engineerCodes)).and(engineerInfoEntitySpecification);
return findAll(spec, pageable);
}
static Specification<EngineerInfoEntity> engineerCodeIn(List<String> engineerCodes) {
return (root, query, criteriaBuilder) -> root.get("engineerCode").in(engineerCodes);
}
} }
...@@ -17,6 +17,12 @@ public interface OrderAppointmentMPDao extends BaseMapper<OrderAppointment> { ...@@ -17,6 +17,12 @@ public interface OrderAppointmentMPDao extends BaseMapper<OrderAppointment> {
@Select("select * from order_appointment where order_id=#{orderId}") @Select("select * from order_appointment where order_id=#{orderId}")
List<OrderAppointment> selectByOrderId(String orderId); List<OrderAppointment> selectByOrderId(String orderId);
@Select("select * from order_appointment where order_id=#{orderId} and dt=#{dt}")
OrderAppointment getByOrderIdAndDt(String orderId, LocalDate dt);
@Select("select * from order_appointment where order_id=#{orderId} and dt=#{dt}")
List<OrderAppointment> selectByOrderIdAndDt(String orderId, LocalDate dt);
@Select("select * from order_appointment where engineer_code=#{engineerCode} and dt=#{dt}") @Select("select * from order_appointment where engineer_code=#{engineerCode} and dt=#{dt}")
List<OrderAppointment> selectByEngineerCodeAndDt(String engineerCode, LocalDate dt); List<OrderAppointment> selectByEngineerCodeAndDt(String engineerCode, LocalDate dt);
} }
package com.dituhui.pea.order.dao; package com.dituhui.pea.order.dao;
import com.dituhui.pea.order.entity.OrgTeamEntity; import com.dituhui.pea.order.entity.OrgTeamEntity;
import org.hibernate.annotations.Where;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
...@@ -12,14 +13,20 @@ import java.util.List; ...@@ -12,14 +13,20 @@ import java.util.List;
@Repository @Repository
public interface OrgTeamDao extends JpaRepository<OrgTeamEntity, Integer> { public interface OrgTeamDao extends JpaRepository<OrgTeamEntity, Integer> {
@Query("select t from OrgTeamEntity t where t.clusterId = :clusterId and t.status=1")
List<OrgTeamEntity> findAllByClusterId(String clusterId); List<OrgTeamEntity> findAllByClusterId(String clusterId);
@Query("select t from OrgTeamEntity t where t.branchId = :branchId and t.status=1")
List<OrgTeamEntity> findAllByBranchId(String branchId); List<OrgTeamEntity> findAllByBranchId(String branchId);
@Query("select t from OrgTeamEntity t where t.groupId = :groupId and t.status=1")
List<OrgTeamEntity> findAllByGroupId(String groupId); List<OrgTeamEntity> findAllByGroupId(String groupId);
@Query("select t from OrgTeamEntity t where t.groupId = :groupId and t.status=1")
Page<OrgTeamEntity> findAllByGroupId(String groupId, Pageable pageable); Page<OrgTeamEntity> findAllByGroupId(String groupId, Pageable pageable);
@Query("select t from OrgTeamEntity t where t.branchId = :branchId and t.status=1")
Page<OrgTeamEntity> findAllByBranchId(String branchId, Pageable pageable); Page<OrgTeamEntity> findAllByBranchId(String branchId, Pageable pageable);
OrgTeamEntity getByTeamId(String teamId); OrgTeamEntity getByTeamId(String teamId);
......
...@@ -12,14 +12,16 @@ import java.util.List; ...@@ -12,14 +12,16 @@ import java.util.List;
@Repository @Repository
@Where(clause = "status = 1")
public interface OrgTeamEngineerDao extends JpaRepository<OrgTeamEngineerEntity, Integer> { public interface OrgTeamEngineerDao extends JpaRepository<OrgTeamEngineerEntity, Integer> {
@Query("select t from OrgTeamEngineerEntity t where t.teamId = :teamId and t.status=1")
List<OrgTeamEngineerEntity> findAllByTeamId(String teamId); List<OrgTeamEngineerEntity> findAllByTeamId(String teamId);
@Query("select t from OrgTeamEngineerEntity t where t.teamId in :teamIds and t.status=1")
List<OrgTeamEngineerEntity> findAllByTeamIdIn(List<String> teamIds); List<OrgTeamEngineerEntity> findAllByTeamIdIn(List<String> teamIds);
List<OrgTeamEngineerEntity> findByTeamId(String teamId); @Query("select a.teamId from OrgTeamEngineerEntity a where a.engineerCode=:engineerCode")
List<String> getTeamIdsByEngineerCode(String engineerCode);
@Modifying @Modifying
@Query("UPDATE OrgTeamEngineerEntity tt SET tt.status = :status WHERE tt.teamId = :teamId") @Query("UPDATE OrgTeamEngineerEntity tt SET tt.status = :status WHERE tt.teamId = :teamId")
......
...@@ -19,6 +19,8 @@ public class BusinessTeamDetailDTO { ...@@ -19,6 +19,8 @@ public class BusinessTeamDetailDTO {
private ScheduleConfig scheduleConfig; private ScheduleConfig scheduleConfig;
private String teamId; private String teamId;
private String teamName; private String teamName;
private String groupId;
private String groupName;
private String warehouseId; private String warehouseId;
private List<String> workdays; private List<String> workdays;
} }
...@@ -45,7 +47,7 @@ public class BusinessTeamDetailDTO { ...@@ -45,7 +47,7 @@ public class BusinessTeamDetailDTO {
/** /**
* 网点指派策略 * 网点指派策略
*/ */
private String assiginStrategy; private String assignStrategy;
/** /**
* cutoff时间 * cutoff时间
*/ */
......
...@@ -2,6 +2,8 @@ package com.dituhui.pea.order.dto; ...@@ -2,6 +2,8 @@ package com.dituhui.pea.order.dto;
import java.util.List; import java.util.List;
import static com.dituhui.pea.order.config.OrderConfig.DEFAULT_PAGE_SIZE;
public class EngineerCalendarDTO { public class EngineerCalendarDTO {
@lombok.Data @lombok.Data
...@@ -13,11 +15,17 @@ public class EngineerCalendarDTO { ...@@ -13,11 +15,17 @@ public class EngineerCalendarDTO {
private String key; private String key;
private String levelType; private String levelType;
private String levelValue; private String levelValue;
private Integer size = DEFAULT_PAGE_SIZE;
private Integer page = 1;
} }
@lombok.Data @lombok.Data
public static class Result { public static class Result {
private long pageCurrent;
private long pages;
private long pageSize;
private long total;
private List<Engineer> engineers; private List<Engineer> engineers;
} }
......
package com.dituhui.pea.order.dto; package com.dituhui.pea.order.dto;
import com.dituhui.pea.order.config.OrderConfig;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
...@@ -11,12 +13,31 @@ import lombok.experimental.Accessors; ...@@ -11,12 +13,31 @@ import lombok.experimental.Accessors;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@lombok.Data
@Accessors(chain = true)
public class EngineersGanttRespDTO {
private String date; public class EngineersGanttDTO {
private List<?> engineers;
@lombok.Data
public static class Request {
// 2种模式:前端可以直接传入精确的engineerCodes,
// 或者是levelType/levelValue/brandIds/branchIds/groupIds/teamIds/key,后端查询匹配
private String levelType;
private String levelValue;
private Integer page = OrderConfig.DEFAULT_PAGE_INDEX;
private Integer size = OrderConfig.DEFAULT_PAGE_SIZE;
private String date;
private List<String> engineerCodes;
private List<String> branchIds;
private List<String> groupIds;
private List<String> teamIds;
private String key;
}
@lombok.Data
@Accessors(chain = true)
public static class Result {
private String date;
private List<?> engineers;
}
/** /**
* GanttChart * GanttChart
......
package com.dituhui.pea.order.dto;
import com.dituhui.pea.order.config.OrderConfig;
import java.util.List;
@lombok.Data
public class EngineersGanttReqDTO {
private String levelType;
private String levelValue;
private Integer page = OrderConfig.DEFAULT_PAGE_INDEX;
private Integer size = OrderConfig.DEFAULT_PAGE_SIZE;
private String date;
private List<String> engineerCodes;
}
package com.dituhui.pea.order.dto;
import lombok.Data;
@Data
public class OrderRevokeAssign {
private String orderId;
}
package com.dituhui.pea.order.dto; package com.dituhui.pea.order.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data; import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List; import java.util.List;
@Data @Data
...@@ -13,5 +15,17 @@ public class OrderServiceDetailResp { ...@@ -13,5 +15,17 @@ public class OrderServiceDetailResp {
private String risk; private String risk;
private String riskDesc; private String riskDesc;
private String location; private String location;
private OrderDetail reschedulingParams;
private List<KV> items; private List<KV> items;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class OrderDetail{
private String location;
private String address;
private String brand;
private String date;
private String type;
private String skill;
}
} }
...@@ -30,6 +30,6 @@ public class OrderServiceListReq { ...@@ -30,6 +30,6 @@ public class OrderServiceListReq {
private List<String> serviceCategory; private List<String> serviceCategory;
private String phone; private String phone;
private String orderId; private String orderId;
private String appointmentStatus; private List<String> appointmentStatus;
private String appointmentType; private List<String> appointmentType;
} }
\ No newline at end of file
package com.dituhui.pea.order.entity;
import lombok.Data;
import javax.persistence.*;
import java.sql.Timestamp;
import java.time.LocalDateTime;
@Entity
@Table(name = "capacity_engineer_calendar")
@Data
public class CapacityEngineerCalendarEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false)
private String workday;
@Column(name = "engineer_code", nullable = false, columnDefinition = "varchar(50) default '0'")
private String engineerCode;
@Column(name = "start_time", nullable = false)
private LocalDateTime startTime;
@Column(name = "end_time", nullable = false)
private LocalDateTime endTime;
@Column(nullable = false)
private String type;
@Column(nullable = false)
private String memo;
@Column(name = "create_time", nullable = false, updatable = false, columnDefinition = "timestamp default current_timestamp")
private Timestamp createTime;
@Column(name = "update_time", nullable = false, columnDefinition = "timestamp default current_timestamp on update current_timestamp")
private Timestamp updateTime;
// 其他字段和关联关系的定义
// ...
}
package com.dituhui.pea.order.service;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dto.EngineerCalendarDTO;
public interface EngineerCalendarService {
Result<?> getEngineersCalendar(EngineerCalendarDTO.Request engineerCalendarReq);
}
package com.dituhui.pea.order.service;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dto.EngineersGanttDTO;
public interface EngineerGanttService {
Result<?> getEngineersGanttList(EngineersGanttDTO.Request ganttReqDTO);
}
package com.dituhui.pea.order.service; package com.dituhui.pea.order.service;
import com.dituhui.pea.common.Result; import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dto.EngineersGanttReqDTO;
import java.util.List; import java.util.List;
...@@ -22,6 +21,4 @@ public interface EngineerService { ...@@ -22,6 +21,4 @@ public interface EngineerService {
// 技术员业务属性配置修改 // 技术员业务属性配置修改
Result<?> engineerBusinessUpdate(String engineerCode, Integer maxNum, Integer maxMutine, String departure, String priority); Result<?> engineerBusinessUpdate(String engineerCode, Integer maxNum, Integer maxMutine, String departure, String priority);
Result<?> getEngineersGanttList(EngineersGanttReqDTO ganttReqDTO);
} }
...@@ -9,4 +9,6 @@ public interface OrderAssign { ...@@ -9,4 +9,6 @@ public interface OrderAssign {
// 服务单指派-指派提交 // 服务单指派-指派提交
Result<?> orderAssign(String orderId, String engineerCode); Result<?> orderAssign(String orderId, String engineerCode);
Result<?> orderRevokeAssign(String orderId);
} }
package com.dituhui.pea.order.service; package com.dituhui.pea.order.service;
import com.dituhui.pea.common.Result; import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dto.EngineersGanttReqDTO;
import com.dituhui.pea.order.dto.OrderChangeListDTO; import com.dituhui.pea.order.dto.OrderChangeListDTO;
import java.time.LocalDate; import java.time.LocalDate;
......
package com.dituhui.pea.order.service.impl; package com.dituhui.pea.order.service.impl;
import cn.hutool.core.date.Week;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.dituhui.pea.common.Result; import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.common.DateUtil;
import com.dituhui.pea.order.dao.*; import com.dituhui.pea.order.dao.*;
import com.dituhui.pea.order.dto.*; import com.dituhui.pea.order.dto.*;
import com.dituhui.pea.order.entity.OrgGroupEntity; import com.dituhui.pea.order.entity.OrgGroupEntity;
...@@ -89,7 +89,7 @@ public class BusinessTeamServiceImpl implements BusinessTeamService { ...@@ -89,7 +89,7 @@ public class BusinessTeamServiceImpl implements BusinessTeamService {
List<String> days = Arrays.asList(workDays.split(",")); List<String> days = Arrays.asList(workDays.split(","));
Collections.sort(days); Collections.sort(days);
return days.stream().map(e -> { return days.stream().map(e -> {
return Week.of(Integer.valueOf(e)).toChinese("周"); return DateUtil.toWeekChinese(Integer.parseInt(e));
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} }
...@@ -185,7 +185,7 @@ public class BusinessTeamServiceImpl implements BusinessTeamService { ...@@ -185,7 +185,7 @@ public class BusinessTeamServiceImpl implements BusinessTeamService {
public void updateTeamEngineers(String teamId, List<String> engineerCodes) { public void updateTeamEngineers(String teamId, List<String> engineerCodes) {
// 获取现有的工作队和技术员之间的所有关系 // 获取现有的工作队和技术员之间的所有关系
List<OrgTeamEngineerEntity> existingRelations = orgTeamEngineerDao.findByTeamId(teamId); List<OrgTeamEngineerEntity> existingRelations = orgTeamEngineerDao.findAllByTeamId(teamId);
// 构建新的关系映射 // 构建新的关系映射
Map<String, OrgTeamEngineerEntity> newRelationsMap = new HashMap<>(); Map<String, OrgTeamEngineerEntity> newRelationsMap = new HashMap<>();
...@@ -204,9 +204,11 @@ public class BusinessTeamServiceImpl implements BusinessTeamService { ...@@ -204,9 +204,11 @@ public class BusinessTeamServiceImpl implements BusinessTeamService {
String engineerCode = relation.getEngineerCode(); String engineerCode = relation.getEngineerCode();
if (newRelationsMap.containsKey(engineerCode)) { if (newRelationsMap.containsKey(engineerCode)) {
OrgTeamEngineerEntity newRelation = newRelationsMap.get(engineerCode); OrgTeamEngineerEntity newRelation = newRelationsMap.get(engineerCode);
newRelation.setId(relation.getId());
newRelation.setUpdateTime(LocalDateTime.now()); newRelation.setUpdateTime(LocalDateTime.now());
newRelationsMap.put(engineerCode, newRelation); newRelationsMap.put(engineerCode, newRelation);
} else { } else {
// 新的关系不再,设置为0(删除)
relation.setStatus(0); relation.setStatus(0);
orgTeamEngineerDao.save(relation); orgTeamEngineerDao.save(relation);
} }
...@@ -227,8 +229,14 @@ public class BusinessTeamServiceImpl implements BusinessTeamService { ...@@ -227,8 +229,14 @@ public class BusinessTeamServiceImpl implements BusinessTeamService {
Result.failed(String.format("工作队[%s]不存在", req.getTeamId())); Result.failed(String.format("工作队[%s]不存在", req.getTeamId()));
} }
BusinessTeamDetailDTO.Result rs = new BusinessTeamDetailDTO.Result(); BusinessTeamDetailDTO.Result rs = new BusinessTeamDetailDTO.Result();
OrgGroupEntity g = orgGroupDao.getByGroupId(teamEntity.getGroupId());
if (g == null) {
return Result.failed("数据配置错误,工作队没有对应的站点");
}
rs.setTeamId(teamEntity.getTeamId()) rs.setTeamId(teamEntity.getTeamId())
.setTeamName(teamEntity.getTeamName()) .setTeamName(teamEntity.getTeamName())
.setGroupId(g.getGroupId())
.setGroupName(g.getGroupName())
.setWarehouseId(teamEntity.getWarehouseId()) .setWarehouseId(teamEntity.getWarehouseId())
.setWorkdays(Arrays.asList(teamEntity.getWorkdays().split(","))); .setWorkdays(Arrays.asList(teamEntity.getWorkdays().split(",")));
List<String> engineerCodes = orgTeamEngineerDao.findAllByTeamId(teamEntity.getTeamId()).stream() List<String> engineerCodes = orgTeamEngineerDao.findAllByTeamId(teamEntity.getTeamId()).stream()
...@@ -238,7 +246,7 @@ public class BusinessTeamServiceImpl implements BusinessTeamService { ...@@ -238,7 +246,7 @@ public class BusinessTeamServiceImpl implements BusinessTeamService {
}).collect(Collectors.toList()); }).collect(Collectors.toList());
rs.setEngineers(engineers); rs.setEngineers(engineers);
BusinessTeamDetailDTO.ScheduleConfig config = new BusinessTeamDetailDTO.ScheduleConfig(); BusinessTeamDetailDTO.ScheduleConfig config = new BusinessTeamDetailDTO.ScheduleConfig();
config.setAssiginStrategy(teamEntity.getStrategyAppointment()) config.setAssignStrategy(teamEntity.getStrategyAppointment())
.setCutoffTime(teamEntity.getCuteOff()) .setCutoffTime(teamEntity.getCuteOff())
.setTransportMode(teamEntity.getTransportMode()) .setTransportMode(teamEntity.getTransportMode())
.setScheduleStrategy(teamEntity.getStrategySchedule()) .setScheduleStrategy(teamEntity.getStrategySchedule())
......
package com.dituhui.pea.order.service.impl; package com.dituhui.pea.order.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.dituhui.pea.common.BusinessException; import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result; import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.common.TimeUtils; import com.dituhui.pea.order.common.TimeUtils;
...@@ -8,8 +10,6 @@ import com.dituhui.pea.order.dto.DispatchEngineerOrderListResp; ...@@ -8,8 +10,6 @@ import com.dituhui.pea.order.dto.DispatchEngineerOrderListResp;
import com.dituhui.pea.order.dto.DispatchOrderListResp; import com.dituhui.pea.order.dto.DispatchOrderListResp;
import com.dituhui.pea.order.entity.*; import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.service.DispatchService; import com.dituhui.pea.order.service.DispatchService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
...@@ -94,7 +94,7 @@ public class DispatchServiceImpl implements DispatchService { ...@@ -94,7 +94,7 @@ public class DispatchServiceImpl implements DispatchService {
@Transactional @Transactional
@Override @Override
public Result<?> getDispatchEngineerOrderList(String levelType, List<String> levelIds, String date) throws BusinessException{ public Result<?> getDispatchEngineerOrderList(String levelType, List<String> levelIds, String date) throws BusinessException {
// 派工台技术员预约单列表 // 派工台技术员预约单列表
// 获取技能耗时 // 获取技能耗时
...@@ -102,13 +102,13 @@ public class DispatchServiceImpl implements DispatchService { ...@@ -102,13 +102,13 @@ public class DispatchServiceImpl implements DispatchService {
// 获取groupIds // 获取groupIds
List<String> groupIds = this.queryOrgGroupIds(levelType, levelIds); List<String> groupIds = this.queryOrgGroupIds(levelType, levelIds);
if (groupIds.isEmpty()){ if (groupIds.isEmpty()) {
throw new BusinessException("大区/分部/小组组织结构配置可能错误或缺失,请联系管理员/研发"); throw new BusinessException("大区/分部/小组组织结构配置可能错误或缺失,请联系管理员/研发");
} }
// 获取engineer列表 // 获取engineer列表
List<EngineerInfo> engineers = this.queryEngineers(groupIds); List<EngineerInfo> engineers = this.queryEngineers(groupIds);
if(engineers.isEmpty()) { if (engineers.isEmpty()) {
// 该group下没有技术员,返回空 // 该group下没有技术员,返回空
DispatchEngineerOrderListResp res = new DispatchEngineerOrderListResp(); DispatchEngineerOrderListResp res = new DispatchEngineerOrderListResp();
List<DispatchEngineerOrderListResp.EngineerInfo> egs = new ArrayList<>(); List<DispatchEngineerOrderListResp.EngineerInfo> egs = new ArrayList<>();
...@@ -496,7 +496,7 @@ class OrderRequestScheduler { ...@@ -496,7 +496,7 @@ class OrderRequestScheduler {
return empty; return empty;
} }
LineSegmentScheduler scheduler = new LineSegmentScheduler(); LineSegmentScheduler scheduler = new LineSegmentScheduler();
return scheduler.scheduleLineSegments(used, newTasks); return scheduler.scheduleLineSegments(used, newTasks);
} }
......
package com.dituhui.pea.order.service.impl;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.common.DateUtil;
import com.dituhui.pea.order.common.EngineerUtil;
import com.dituhui.pea.order.dao.CapacityEngineerCalendarDao;
import com.dituhui.pea.order.dao.OrgTeamDao;
import com.dituhui.pea.order.dao.OrgTeamEngineerDao;
import com.dituhui.pea.order.dto.EngineerCalendarDTO;
import com.dituhui.pea.order.entity.CapacityEngineerCalendarEntity;
import com.dituhui.pea.order.entity.EngineerInfoEntity;
import com.dituhui.pea.order.entity.OrgTeamEntity;
import com.dituhui.pea.order.service.EngineerCalendarService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.dituhui.pea.order.config.OrderConfig.PATTERN_DATE;
import static com.dituhui.pea.order.config.OrderConfig.PATTERN_DATETIME;
@Slf4j
@Service
public class EngineerCalendarServiceImpl implements EngineerCalendarService {
@Autowired
private EngineerUtil engineerUtil;
@Autowired
private OrgTeamEngineerDao orgTeamEngineerDao;
@Autowired
private CapacityEngineerCalendarDao capacityEngineerCalendarDao;
@Autowired
private OrgTeamDao orgTeamDao;
@Override
public Result<?> getEngineersCalendar(EngineerCalendarDTO.Request req) {
// 技术员日历,查询 capacity_engineer_calendar表,如果当日有各种事项,进行显示;否则显示正常上班;
List<EngineerCalendarDTO.Engineer> engineers = new ArrayList<>();
List<String> allCodes = engineerUtil.getEngineersByLevel(req.getLevelType(), req.getLevelValue()).stream()
.map(EngineerInfoEntity::getEngineerCode).collect(Collectors.toList());
Page<EngineerInfoEntity> page = engineerUtil.filterEngineersByKeyAndPage(allCodes, req.getKey(), req.getPage(), req.getSize());
String edate = LocalDate.parse(req.getDate()).plusDays(14).toString();
for (EngineerInfoEntity e : page.getContent()) {
EngineerCalendarDTO.Engineer engineer = new EngineerCalendarDTO.Engineer();
engineer.setEngineerCode(e.getEngineerCode());
engineer.setName(e.getName());
engineer.setCalendar(getOneEngineerCalendars(e.getEngineerCode(), req.getDate(), edate));
engineers.add(engineer);
}
EngineerCalendarDTO.Result rs = new EngineerCalendarDTO.Result();
rs.setTotal(page.getTotalElements());
rs.setPages(page.getTotalPages());
rs.setPageSize(page.getSize());
rs.setPageCurrent(page.getNumber());
rs.setEngineers(engineers);
return Result.success(rs);
}
private List<EngineerCalendarDTO.Calendar> getOneEngineerCalendars(String engineerCode, String bdate, String edate) {
// 返回某一个技术员,日期范围内的日历列表
List<EngineerCalendarDTO.Calendar> calendars = new ArrayList<>();
List<String> teamIds = orgTeamEngineerDao.getTeamIdsByEngineerCode(engineerCode);
if (teamIds == null || teamIds.size() == 0) {
return new ArrayList<>();
}
LocalDate startDate = LocalDate.parse(bdate);
LocalDate endDate = LocalDate.parse(edate);
List<LocalDate> datesInRange = Stream.iterate(startDate, date -> date.plusDays(1))
.limit(ChronoUnit.DAYS.between(startDate, endDate.plusDays(1)))
.collect(Collectors.toList());
Map<String, List<CapacityEngineerCalendarEntity>> configs = capacityEngineerCalendarDao.findCalendarByEngineerCodeAndDateBetween(engineerCode, bdate, edate).stream()
.collect(Collectors.groupingBy(CapacityEngineerCalendarEntity::getWorkday));
for (LocalDate date : datesInRange) {
String sDate = LocalDateTimeUtil.format(date, PATTERN_DATE);
EngineerCalendarDTO.Calendar calander = null;
calander = getEmptyCalendar(teamIds.get(0), sDate);
if (configs.containsKey(sDate)) {
List<EngineerCalendarDTO.Content> contents = new ArrayList<>();
// 有配置
for (CapacityEngineerCalendarEntity e : configs.get(sDate)) {
EngineerCalendarDTO.Content content = new EngineerCalendarDTO.Content();
content.setType("leave");
content.setTitle(e.getType());
content.setValue(getCalendarDuration(e.getStartTime(), e.getEndTime()));
contents.add(content);
}
List<EngineerCalendarDTO.Content> mergedList = new ArrayList<>();
mergedList.addAll(calander.getContent());
mergedList.addAll(contents);
calander.setContent(mergedList);
}
calendars.add(calander);
}
return calendars;
}
private String getCalendarDuration(LocalDateTime btime, LocalDateTime etime) {
String b2 = LocalDateTimeUtil.format(btime, PATTERN_DATETIME);
String e2 = LocalDateTimeUtil.format(etime, PATTERN_DATETIME);
return getCalendarDuration(b2.substring(11), e2.substring(11));
}
private String getCalendarDuration(String btime, String etime) {
LocalTime t1 = LocalTime.parse(btime);
LocalTime t2 = LocalTime.parse(etime);
Duration duration = Duration.between(t1, t2);
long hours = duration.toHours();
long minutes = duration.toMinutesPart();
if (minutes > 0 && hours == 0) {
return String.format("%d分钟", minutes);
} else if (minutes == 0 && hours > 0) {
return String.format("%d小时", hours);
} else {
return String.format("%d小时%d分钟", hours, minutes);
}
}
private EngineerCalendarDTO.Calendar getEmptyCalendar(String teamId, String date) {
// 初始化一天的日历
OrgTeamEntity e = orgTeamDao.getByTeamId(teamId);
EngineerCalendarDTO.Calendar calendar = new EngineerCalendarDTO.Calendar();
calendar.setDate(date);
int dayOfWeek = LocalDate.parse(date).getDayOfWeek().getValue();
calendar.setWeek(DateUtil.toWeekChinese(dayOfWeek));
EngineerCalendarDTO.Content content = new EngineerCalendarDTO.Content();
List<String> workdays = Arrays.asList(e.getWorkdays().split(","));
if (workdays.contains(String.valueOf(dayOfWeek))) {
content.setType("woring");
content.setTitle(String.format("%s-%s", e.getWorkOn(), e.getWorkOff()));
content.setValue(getCalendarDuration(e.getWorkOn(), e.getWorkOff()));
} else {
content.setType("rest");
content.setTitle("休息");
}
calendar.setContent(Collections.singletonList(content));
return calendar;
}
}
package com.dituhui.pea.order.service.impl;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.common.EngineerUtil;
import com.dituhui.pea.order.dao.CapacityEngineerStatDao;
import com.dituhui.pea.order.dao.EngineerInfoDao;
import com.dituhui.pea.order.dao.OrderAppointmentDao;
import com.dituhui.pea.order.dao.OrderRequestDao;
import com.dituhui.pea.order.dto.EngineersGanttDTO;
import com.dituhui.pea.order.dto.LabelValueDTO;
import com.dituhui.pea.order.entity.CapacityEngineerStatEntity;
import com.dituhui.pea.order.entity.EngineerInfoEntity;
import com.dituhui.pea.order.entity.OrderAppointmentEntity;
import com.dituhui.pea.order.entity.OrderRequestEntity;
import com.dituhui.pea.order.service.EngineerGanttService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class EngineerGanttServiceImpl implements EngineerGanttService {
@Autowired
private OrderAppointmentDao orderAppointmentDao;
@Autowired
private CapacityEngineerStatDao capacityEngineerStatDao;
@Autowired
private EngineerInfoDao engineerInfoDao;
@Autowired
private OrderRequestDao orderRequestDao;
@Autowired
private EngineerUtil engineerUtil;
@Override
public Result<?> getEngineersGanttList(EngineersGanttDTO.Request reqDTO) {
// 按日期返回技术员们当天的服务甘特图,不需要翻页
log.info("getEngineersGanttList: {}", reqDTO);
List<String> engineerCodes = reqDTO.getEngineerCodes();
if (engineerCodes == null || engineerCodes.size() == 0) {
// 需要根据levelType/levelValue/brandIds/branchIds/groupIds/teamIds/key,后端查询匹配
engineerCodes = findEngineers(reqDTO.getLevelType(), reqDTO.getLevelValue(), reqDTO.getBranchIds(), reqDTO.getGroupIds(), reqDTO.getTeamIds(), reqDTO.getKey());
log.info("根据多条件,查询返回符合条件的技术员列表:{}", engineerCodes);
}
List<OrderAppointmentEntity> orderAppointments = orderAppointmentDao.findByDateAndEngineerCodeIn(reqDTO.getDate(), engineerCodes);
List<String> orderIds = orderAppointments.stream().map(OrderAppointmentEntity::getOrderId).collect(Collectors.toList());
Map<String, OrderRequestEntity> mapOrderRequest = getOrdersByOrderIds(orderIds);
HashMap<String, List<EngineersGanttDTO.Order>> mapEngineers = new HashMap<>();
for (OrderAppointmentEntity e : orderAppointments) {
log.info("===== order_id: [{}]", e.getOrderId());
EngineersGanttDTO.Order order = new EngineersGanttDTO.Order();
// todo 需要根据订单时间和状态,采用expectXXXX或者actualXXXX
order.setStartTime(e.getExpectStartTime()).setEndTime(e.getExpectEndTime());
order.setOrderId(e.getOrderId()).setPreStatus(e.getPreStatus());
order.setTips(getOrderTips(e.getOrderId()));
order.setAppointmentStatus(mapOrderRequest.get(e.getOrderId()).getAppointmentStatus());
List<EngineersGanttDTO.Order> orders = null;
if (mapEngineers.containsKey(e.getEngineerCode())) {
orders = mapEngineers.get(e.getEngineerCode());
} else {
orders = new ArrayList<>();
}
orders.add(order);
mapEngineers.put(e.getEngineerCode(), orders);
}
List<EngineersGanttDTO.GanttChart> engineers = new ArrayList<>();
for (String engineerCode : engineerCodes) {
EngineerInfoEntity engineerInfo = engineerInfoDao.getByEngineerCode(engineerCode);
EngineersGanttDTO.GanttChart engineer = new EngineersGanttDTO.GanttChart();
engineer.setEngineerCode(engineerCode)
.setStartTime(String.format("%s 08:00", reqDTO.getDate()))
.setEndTime(String.format("%s 18:00", reqDTO.getDate()))
.setHoliday(false) // todo
.setEngineerName(engineerInfo.getName())
.setGrade(engineerInfo.getGrade());
CapacityEngineerStatEntity capacityEngineerStat = capacityEngineerStatDao.getByEngineerCodeAndWorkday(engineerCode, reqDTO.getDate());
if (capacityEngineerStat == null) {
log.warn("技术员当日的容量数据不存在,{}{}", engineerCode, reqDTO.getDate());
} else {
engineer.setCapTotal(capacityEngineerStat.getCapTotal().toString()).setCapUsed(capacityEngineerStat.getCapUsed().toString());
}
if (mapEngineers.containsKey(engineerCode)) {
engineer.setOrders(mapEngineers.get(engineerCode));
}
// engineer.setErrorTip(); todo
engineers.add(engineer);
}
EngineersGanttDTO.Result res = new EngineersGanttDTO.Result();
res.setDate(reqDTO.getDate()).setEngineers(engineers);
return Result.success(res);
}
private List<String> findEngineers(String levelType, String levelValue, List<String> branchIds, List<String> groupIds, List<String> teamIds, String key) {
// brandIds, groupIds, teamIds, 以team -> group -> branch 为顺序判断,前者优先;
List<String> engineerCodes = new ArrayList<>();
if (teamIds != null && teamIds.size() > 0) {
for (String teamId : teamIds) {
engineerCodes.addAll(
engineerUtil.getEngineersByLevel("team", teamId).stream().map(EngineerInfoEntity::getEngineerCode).collect(Collectors.toList()));
}
} else if (groupIds != null && groupIds.size() > 0) {
for (String groupId : groupIds) {
engineerCodes.addAll(
engineerUtil.getEngineersByLevel("group", groupId).stream().map(EngineerInfoEntity::getEngineerCode).collect(Collectors.toList()));
}
} else if (branchIds != null && branchIds.size() > 0) {
for (String branchId : branchIds) {
engineerCodes.addAll(
engineerUtil.getEngineersByLevel("branch", branchId).stream().map(EngineerInfoEntity::getEngineerCode).collect(Collectors.toList()));
}
} else {
engineerCodes.addAll(engineerUtil.getEngineersByLevel(levelType, levelValue).stream().map(EngineerInfoEntity::getEngineerCode).collect(Collectors.toList()));
}
engineerCodes = new ArrayList<>(new HashSet<>(engineerCodes));
if (StringUtils.isBlank(key)) {
return engineerCodes;
} else {
// 最后,还需要根据key进行过滤(需要结合数据库表)
return engineerUtil.filterEngineersByKey(engineerCodes, key).stream().map(EngineerInfoEntity::getEngineerCode).collect(Collectors.toList());
}
}
public Map<String, OrderRequestEntity> getOrdersByOrderIds(List<String> orderIds) {
List<OrderRequestEntity> orders = orderRequestDao.findAllByOrderIdIn(orderIds);
return orders.stream()
.collect(Collectors.toMap(OrderRequestEntity::getOrderId, order -> order));
}
private List<?> getOrderTips(String orderId) {
log.info("==> getOrderTips: orderId[{}]", orderId);
OrderRequestEntity order = orderRequestDao.getByOrderId(orderId);
if (order == null) {
log.error("对应的订单不存在!{}", orderId);
return null;
}
List<LabelValueDTO> tips = new ArrayList<>();
tips.add(new LabelValueDTO().setLabel("工单号码").setValue(orderId));
tips.add(new LabelValueDTO().setLabel("类型/品牌").setValue(String.format("%s %s", order.getBrand(), order.getType())));
tips.add(new LabelValueDTO().setLabel("电话/地址").setValue(String.format("%s %s\n %s", order.getName(), order.getPhone(), order.getAddress())));
if (StringUtils.isNotBlank(order.getApplyNote())) {
tips.add(new LabelValueDTO().setLabel("备注").setValue(order.getApplyNote()));
}
tips.add(new LabelValueDTO().setLabel("标签").setValue(order.getTags()));
return tips;
}
}
...@@ -25,533 +25,456 @@ import java.util.stream.Collectors; ...@@ -25,533 +25,456 @@ import java.util.stream.Collectors;
@Service @Service
public class EngineerServiceImpl implements EngineerService { public class EngineerServiceImpl implements EngineerService {
@Autowired @Autowired
private EngineerInfoMPDao engineerInfoMPDao; private EngineerInfoMPDao engineerInfoMPDao;
@Autowired @Autowired
private EngineerSkillGroupMPDao engineerSkillGroupMPDao; private EngineerSkillGroupMPDao engineerSkillGroupMPDao;
@Autowired @Autowired
private OrgGroupMPDao orgGroupMPDao; private OrgGroupMPDao orgGroupMPDao;
@Autowired @Autowired
private EngineerBusinessMPDao engineerBusinessDao; private EngineerBusinessMPDao engineerBusinessDao;
@Autowired @Autowired
private OrderRequestDao orderRequestDao; private OrderRequestDao orderRequestDao;
@Autowired @Autowired
private OrderAppointmentDao orderAppointmentDao; private OrderAppointmentDao orderAppointmentDao;
@Autowired @Autowired
private EngineerInfoDao engineerInfoDao; private EngineerInfoDao engineerInfoDao;
@Autowired @Autowired
private CapacityEngineerStatDao capacityEngineerStatDao; private CapacityEngineerStatDao capacityEngineerStatDao;
@Transactional @Transactional
@Override @Override
public Result<?> getEngineerInfoList(String levelType, String levelValue, long page, long size, String kind, String key) { public Result<?> getEngineerInfoList(String levelType, String levelValue, long page, long size, String kind, String key) {
// 查询工程师信息 // 查询工程师信息
IPage<EngineerInfo> pg = this.queryEngineerInfoIPage(levelType, levelValue, page, size, kind, key); IPage<EngineerInfo> pg = this.queryEngineerInfoIPage(levelType, levelValue, page, size, kind, key);
List<EngineerInfo> records = pg.getRecords(); List<EngineerInfo> records = pg.getRecords();
// 获取groupIds // 获取groupIds
List<String> groupIds = records.stream().map(EngineerInfo::getGroupId).collect(Collectors.toList()); List<String> groupIds = records.stream().map(EngineerInfo::getGroupId).collect(Collectors.toList());
// 获取Map<groupId, groupName> // 获取Map<groupId, groupName>
HashMap<String, String> groupNames = this.queryGroupNames(groupIds); HashMap<String, String> groupNames = this.queryGroupNames(groupIds);
// 设置返回值 // 设置返回值
EngineerInfoListResp res = new EngineerInfoListResp(); EngineerInfoListResp res = new EngineerInfoListResp();
res.setContent(this.packEngineerInfos(records, groupNames)); res.setContent(this.packEngineerInfos(records, groupNames));
res.setTotal(pg.getTotal()); res.setTotal(pg.getTotal());
res.setPages(pg.getPages()); res.setPages(pg.getPages());
res.setPageCurrent(pg.getCurrent()); res.setPageCurrent(pg.getCurrent());
res.setPageSize(pg.getSize()); res.setPageSize(pg.getSize());
return Result.success(res); return Result.success(res);
} }
@Override @Override
public Result<?> getEngineerInfoDetail(String engineerCode) throws BusinessException { public Result<?> getEngineerInfoDetail(String engineerCode) throws BusinessException {
// 获取技术员基础信息详情 // 获取技术员基础信息详情
// 获取技术员列表 // 获取技术员列表
List<EngineerInfo> records = engineerInfoMPDao.selectByEngineerCode(engineerCode); List<EngineerInfo> records = engineerInfoMPDao.selectByEngineerCode(engineerCode);
if (records.isEmpty()) { if (records.isEmpty()) {
throw new BusinessException("技术员不存在"); throw new BusinessException("技术员不存在");
} }
List<String> groupIds = records.stream().map(EngineerInfo::getGroupId).collect(Collectors.toList()); List<String> groupIds = records.stream().map(EngineerInfo::getGroupId).collect(Collectors.toList());
HashMap<String, String> groupNames = this.queryGroupNames(groupIds); HashMap<String, String> groupNames = this.queryGroupNames(groupIds);
List<EngineerInfoListResp.EngineerInfo> items = this.packEngineerInfos(records, groupNames); List<EngineerInfoListResp.EngineerInfo> items = this.packEngineerInfos(records, groupNames);
if (items.isEmpty()) { if (items.isEmpty()) {
throw new BusinessException("技术员不存在"); throw new BusinessException("技术员不存在");
} }
return Result.success(items.get(0)); return Result.success(items.get(0));
} }
@Transactional @Transactional
@Override @Override
public Result<?> getEngineerSkillList(String levelType, String levelValue, long page, long size, String kind, String key) { public Result<?> getEngineerSkillList(String levelType, String levelValue, long page, long size, String kind, String key) {
// 获取技术员技能列表 // 获取技术员技能列表
IPage<EngineerInfo> pg = this.queryEngineerInfoIPage(levelType, levelValue, page, size, kind, key); IPage<EngineerInfo> pg = this.queryEngineerInfoIPage(levelType, levelValue, page, size, kind, key);
List<EngineerInfo> engineers = pg.getRecords(); List<EngineerInfo> engineers = pg.getRecords();
EngineerSkillListResp res = new EngineerSkillListResp(); EngineerSkillListResp res = new EngineerSkillListResp();
res.setTotal(pg.getTotal()); res.setTotal(pg.getTotal());
res.setPages(pg.getPages()); res.setPages(pg.getPages());
res.setPageCurrent(pg.getCurrent()); res.setPageCurrent(pg.getCurrent());
res.setPageSize(pg.getSize()); res.setPageSize(pg.getSize());
res.setContent(this.packEngineerSkills(engineers)); res.setContent(this.packEngineerSkills(engineers));
return Result.success(res); return Result.success(res);
} }
@Override @Override
public Result<?> getEngineerSkillDetail(String engineerCode) throws BusinessException { public Result<?> getEngineerSkillDetail(String engineerCode) throws BusinessException {
// 获取工程师技能详情 // 获取工程师技能详情
List<EngineerInfo> engineers = engineerInfoMPDao.selectByEngineerCode(engineerCode); List<EngineerInfo> engineers = engineerInfoMPDao.selectByEngineerCode(engineerCode);
if (engineers.isEmpty()) { if (engineers.isEmpty()) {
throw new BusinessException("技术员不存在"); throw new BusinessException("技术员不存在");
} }
List<EngineerSkillListResp.EngineerSkill> items = this.packEngineerSkills(engineers); List<EngineerSkillListResp.EngineerSkill> items = this.packEngineerSkills(engineers);
if (items.isEmpty()) { if (items.isEmpty()) {
throw new BusinessException("技术员不存在"); throw new BusinessException("技术员不存在");
} }
return Result.success(items.get(0)); return Result.success(items.get(0));
} }
@Transactional @Transactional
@Override @Override
public Result<?> engineerSkillUpdate(String engineerCode, List<String> skillGroupIds) { public Result<?> engineerSkillUpdate(String engineerCode, List<String> skillGroupIds) {
// 更新技术员技能 // 更新技术员技能
// 先将所有技能更新为0-不可用状态 // 先将所有技能更新为0-不可用状态
LambdaUpdateWrapper<EngineerSkillGroup> wrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<EngineerSkillGroup> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(EngineerSkillGroup::getEngineerCode, engineerCode).set(EngineerSkillGroup::getStatus, 0); wrapper.eq(EngineerSkillGroup::getEngineerCode, engineerCode).set(EngineerSkillGroup::getStatus, 0);
engineerSkillGroupMPDao.update(null, wrapper); engineerSkillGroupMPDao.update(null, wrapper);
if (skillGroupIds.isEmpty()) { if (skillGroupIds.isEmpty()) {
return null; return null;
} }
// 更新categoryIds状态为1 // 更新categoryIds状态为1
wrapper.eq(EngineerSkillGroup::getEngineerCode, engineerCode); wrapper.eq(EngineerSkillGroup::getEngineerCode, engineerCode);
wrapper.in(EngineerSkillGroup::getSkillGroupCode, skillGroupIds); wrapper.in(EngineerSkillGroup::getSkillGroupCode, skillGroupIds);
wrapper.set(EngineerSkillGroup::getStatus, 1); wrapper.set(EngineerSkillGroup::getStatus, 1);
int n = engineerSkillGroupMPDao.update(null, wrapper); int n = engineerSkillGroupMPDao.update(null, wrapper);
if (skillGroupIds.size() == n) { if (skillGroupIds.size() == n) {
// 更新记录条数等于提交记录条数 // 更新记录条数等于提交记录条数
return null; return null;
} }
// 可能存在engineerSkill表不存在的记录,需要补充录入 // 可能存在engineerSkill表不存在的记录,需要补充录入
List<Integer> statuses = new ArrayList<Integer>(Arrays.asList(1, 0)); List<Integer> statuses = new ArrayList<Integer>(Arrays.asList(1, 0));
List<String> engineerCodes = new ArrayList<>(Collections.singletonList(engineerCode)); List<String> engineerCodes = new ArrayList<>(Collections.singletonList(engineerCode));
HashMap<String, List<String>> engineerSkills = this.queryEngineerSkills(engineerCodes, statuses); HashMap<String, List<String>> engineerSkills = this.queryEngineerSkills(engineerCodes, statuses);
Set<String> sInput = new HashSet<>(skillGroupIds); Set<String> sInput = new HashSet<>(skillGroupIds);
Set<String> sDB = new HashSet<>(engineerSkills.getOrDefault(engineerCode, new ArrayList<>())); Set<String> sDB = new HashSet<>(engineerSkills.getOrDefault(engineerCode, new ArrayList<>()));
sInput.removeAll(sDB); sInput.removeAll(sDB);
for (String skillGroupId : sInput) { for (String skillGroupId : sInput) {
EngineerSkillGroup e = new EngineerSkillGroup(); EngineerSkillGroup e = new EngineerSkillGroup();
e.setEngineerCode(engineerCode); e.setEngineerCode(engineerCode);
e.setSkillGroupCode(skillGroupId); e.setSkillGroupCode(skillGroupId);
e.setDescription(""); e.setDescription("");
e.setStatus(1); e.setStatus(1);
engineerSkillGroupMPDao.insert(e); engineerSkillGroupMPDao.insert(e);
} }
return null; return null;
} }
@Transactional @Transactional
@Override @Override
public Result<?> getEngineerBusinessList(String levelType, String levelValue, long page, long size, String kind, String key) { public Result<?> getEngineerBusinessList(String levelType, String levelValue, long page, long size, String kind, String key) {
// 技术员业务属性配置列表 // 技术员业务属性配置列表
// 查询技术员列表 // 查询技术员列表
IPage<EngineerInfo> pg = this.queryEngineerInfoIPage(levelType, levelValue, page, size, kind, key); IPage<EngineerInfo> pg = this.queryEngineerInfoIPage(levelType, levelValue, page, size, kind, key);
List<EngineerInfo> engineers = pg.getRecords(); List<EngineerInfo> engineers = pg.getRecords();
// 查询技术员业务属性 // 查询技术员业务属性
EngineerBusinessListResp res = new EngineerBusinessListResp(); EngineerBusinessListResp res = new EngineerBusinessListResp();
res.setTotal(pg.getTotal()); res.setTotal(pg.getTotal());
res.setPages(pg.getPages()); res.setPages(pg.getPages());
res.setPageCurrent(pg.getCurrent()); res.setPageCurrent(pg.getCurrent());
res.setPageSize(pg.getSize()); res.setPageSize(pg.getSize());
res.setContent(this.packEngineerBusinesses(engineers)); res.setContent(this.packEngineerBusinesses(engineers));
return Result.success(res); return Result.success(res);
} }
@Override @Override
public Result<?> getEngineerBusinessDetail(String engineerCode) { public Result<?> getEngineerBusinessDetail(String engineerCode) {
// 获取技术员业务熟悉详情 // 获取技术员业务熟悉详情
List<EngineerInfo> engineers = engineerInfoMPDao.selectByEngineerCode(engineerCode); List<EngineerInfo> engineers = engineerInfoMPDao.selectByEngineerCode(engineerCode);
if (engineers.isEmpty()) { if (engineers.isEmpty()) {
throw new BusinessException("技术员不存在"); throw new BusinessException("技术员不存在");
} }
List<?> items = this.packEngineerBusinesses(engineers); List<?> items = this.packEngineerBusinesses(engineers);
if (items.isEmpty()) { if (items.isEmpty()) {
throw new BusinessException("技术员不存在"); throw new BusinessException("技术员不存在");
} }
return Result.success(items.get(0)); return Result.success(items.get(0));
} }
@Transactional @Transactional
@Override @Override
public Result<?> engineerBusinessUpdate(String engineerCode, Integer maxNum, Integer maxMinute, String departure, String priority) { public Result<?> engineerBusinessUpdate(String engineerCode, Integer maxNum, Integer maxMinute, String departure, String priority) {
// 技术员业务属性配置修改 // 技术员业务属性配置修改
LambdaUpdateWrapper<EngineerBusiness> wrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<EngineerBusiness> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(EngineerBusiness::getEngineerCode, engineerCode); wrapper.eq(EngineerBusiness::getEngineerCode, engineerCode);
wrapper.set(maxNum >= 0, EngineerBusiness::getMaxNum, maxNum); wrapper.set(maxNum >= 0, EngineerBusiness::getMaxNum, maxNum);
wrapper.set(maxMinute >= 0, EngineerBusiness::getMaxMinute, maxMinute); wrapper.set(maxMinute >= 0, EngineerBusiness::getMaxMinute, maxMinute);
Integer dep = (departure.equals("配件仓")) ? 1 : 2; Integer dep = (departure.equals("配件仓")) ? 1 : 2;
wrapper.set(EngineerBusiness::getDeparture, dep); wrapper.set(EngineerBusiness::getDeparture, dep);
int pri; int pri;
if (priority.equals("高")) { if (priority.equals("高")) {
pri = 3; pri = 3;
} else if (priority.equals("中")) { } else if (priority.equals("中")) {
pri = 2; pri = 2;
} else { } else {
pri = 1; pri = 1;
} }
wrapper.set(EngineerBusiness::getPriority, pri); wrapper.set(EngineerBusiness::getPriority, pri);
// 更新字段 // 更新字段
engineerBusinessDao.update(null, wrapper); engineerBusinessDao.update(null, wrapper);
return Result.success(null); return Result.success(null);
} }
private IPage<EngineerInfo> queryEngineerInfoIPage(String levelType, String levelValue, long page, long size, String kind, String key) { private IPage<EngineerInfo> queryEngineerInfoIPage(String levelType, String levelValue, long page, long size, String kind, String key) {
// 分页查询工程师基础信息 // 分页查询工程师基础信息
// 查询技术员所在的groupIds // 查询技术员所在的groupIds
LambdaQueryWrapper<OrgGroup> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<OrgGroup> wrapper = new LambdaQueryWrapper<>();
wrapper.select(OrgGroup::getGroupId); wrapper.select(OrgGroup::getGroupId);
wrapper.eq(levelType.equals("cluster"), OrgGroup::getClusterId, levelValue); wrapper.eq(levelType.equals("cluster"), OrgGroup::getClusterId, levelValue);
wrapper.eq(levelType.equals("branch"), OrgGroup::getBranchId, levelValue); wrapper.eq(levelType.equals("branch"), OrgGroup::getBranchId, levelValue);
wrapper.eq(levelType.equals("group"), OrgGroup::getGroupId, levelValue); wrapper.eq(levelType.equals("group"), OrgGroup::getGroupId, levelValue);
List<String> groupIds = orgGroupMPDao.selectList(wrapper).stream().map(OrgGroup::getGroupId).collect(Collectors.toList()); List<String> groupIds = orgGroupMPDao.selectList(wrapper).stream().map(OrgGroup::getGroupId).collect(Collectors.toList());
LambdaQueryWrapper<EngineerInfo> lqw = new LambdaQueryWrapper<>(); LambdaQueryWrapper<EngineerInfo> lqw = new LambdaQueryWrapper<>();
lqw.in(groupIds != null && !groupIds.isEmpty(), EngineerInfo::getGroupId, groupIds); lqw.in(groupIds != null && !groupIds.isEmpty(), EngineerInfo::getGroupId, groupIds);
if(StringUtils.isNotEmpty(kind)) { if(StringUtils.isNotEmpty(kind)) {
lqw.eq(EngineerInfo::getKind, (kind.equals("fullJob")) ? 1 : 2); lqw.eq(EngineerInfo::getKind, (kind.equals("fullJob")) ? 1 : 2);
} }
if (StringUtils.isNotEmpty(key)) { if (StringUtils.isNotEmpty(key)) {
lqw.and(w -> lqw.and(w ->
w.like(EngineerInfo::getPhone, key) w.like(EngineerInfo::getPhone, key)
.or() .or()
.like(EngineerInfo::getName, key) .like(EngineerInfo::getName, key)
.or() .or()
.like(EngineerInfo::getEngineerCode, key) .like(EngineerInfo::getEngineerCode, key)
); );
} }
lqw.orderByAsc(EngineerInfo::getGroupId); lqw.orderByAsc(EngineerInfo::getGroupId);
lqw.orderByAsc(EngineerInfo::getEngineerCode); lqw.orderByAsc(EngineerInfo::getEngineerCode);
IPage<EngineerInfo> pg = new Page(page, size); IPage<EngineerInfo> pg = new Page(page, size);
engineerInfoMPDao.selectPage(pg, lqw); engineerInfoMPDao.selectPage(pg, lqw);
return pg; return pg;
} }
private HashMap<String, String> queryGroupNames(List<String> groupIds) { private HashMap<String, String> queryGroupNames(List<String> groupIds) {
//查询小组名称映射关系 //查询小组名称映射关系
HashMap<String, String> map = new HashMap<>(); HashMap<String, String> map = new HashMap<>();
if (groupIds.isEmpty()) { if (groupIds.isEmpty()) {
return map; return map;
} }
LambdaQueryWrapper<OrgGroup> lqw = new LambdaQueryWrapper<>(); LambdaQueryWrapper<OrgGroup> lqw = new LambdaQueryWrapper<>();
lqw.select(OrgGroup::getGroupId, OrgGroup::getGroupName); lqw.select(OrgGroup::getGroupId, OrgGroup::getGroupName);
lqw.in(OrgGroup::getGroupId, groupIds); lqw.in(OrgGroup::getGroupId, groupIds);
List<OrgGroup> groups = orgGroupMPDao.selectList(lqw); List<OrgGroup> groups = orgGroupMPDao.selectList(lqw);
for (OrgGroup g : groups) { for (OrgGroup g : groups) {
map.put(g.getGroupId(), g.getGroupName()); map.put(g.getGroupId(), g.getGroupName());
} }
return map; return map;
} }
private HashMap<String, List<String>> queryEngineerSkills(List<String> engineerCodes, List<Integer> statuses) { private HashMap<String, List<String>> queryEngineerSkills(List<String> engineerCodes, List<Integer> statuses) {
// 获取engineerCode对应的技能表, HashMap<engineerCode, List<skillId>> // 获取engineerCode对应的技能表, HashMap<engineerCode, List<skillId>>
HashMap<String, List<String>> map = new HashMap<>(); HashMap<String, List<String>> map = new HashMap<>();
if (engineerCodes.isEmpty()) { if (engineerCodes.isEmpty()) {
return map; return map;
} }
LambdaQueryWrapper<EngineerSkillGroup> lqw = new LambdaQueryWrapper<>(); LambdaQueryWrapper<EngineerSkillGroup> lqw = new LambdaQueryWrapper<>();
lqw.in(EngineerSkillGroup::getEngineerCode, engineerCodes); lqw.in(EngineerSkillGroup::getEngineerCode, engineerCodes);
lqw.in(EngineerSkillGroup::getStatus, statuses); lqw.in(EngineerSkillGroup::getStatus, statuses);
List<EngineerSkillGroup> records = engineerSkillGroupMPDao.selectList(lqw); List<EngineerSkillGroup> records = engineerSkillGroupMPDao.selectList(lqw);
if(records == null || records.isEmpty()) { if(records == null || records.isEmpty()) {
return map; return map;
} }
Comparator<EngineerSkillGroup> ec = Comparator.comparing(EngineerSkillGroup::getEngineerCode, String.CASE_INSENSITIVE_ORDER); Comparator<EngineerSkillGroup> ec = Comparator.comparing(EngineerSkillGroup::getEngineerCode, String.CASE_INSENSITIVE_ORDER);
List<EngineerSkillGroup> results = records.stream().sorted(ec).collect(Collectors.toList()); List<EngineerSkillGroup> results = records.stream().sorted(ec).collect(Collectors.toList());
// 根据engineerCode分组 // 根据engineerCode分组
Map<String, List<EngineerSkillGroup>> g = results.stream().collect(Collectors.groupingBy(EngineerSkillGroup::getEngineerCode)); Map<String, List<EngineerSkillGroup>> g = results.stream().collect(Collectors.groupingBy(EngineerSkillGroup::getEngineerCode));
for (String engineerCode : g.keySet()) { for (String engineerCode : g.keySet()) {
// 技术员技能ID列表 // 技术员技能ID列表
List<String> skillGroupIds = g.get(engineerCode).stream().map(EngineerSkillGroup::getSkillGroupCode).collect(Collectors.toList()); List<String> skillGroupIds = g.get(engineerCode).stream().map(EngineerSkillGroup::getSkillGroupCode).collect(Collectors.toList());
map.put(engineerCode, skillGroupIds); map.put(engineerCode, skillGroupIds);
} }
return map; return map;
} }
private HashMap<String, EngineerBusiness> queryEngineerBusiness(List<String> engineerCodes) { private HashMap<String, EngineerBusiness> queryEngineerBusiness(List<String> engineerCodes) {
HashMap<String, EngineerBusiness> map = new HashMap<>(); HashMap<String, EngineerBusiness> map = new HashMap<>();
if (engineerCodes.isEmpty()) { if (engineerCodes.isEmpty()) {
return map; return map;
} }
LambdaQueryWrapper<EngineerBusiness> lqw = new LambdaQueryWrapper<>(); LambdaQueryWrapper<EngineerBusiness> lqw = new LambdaQueryWrapper<>();
lqw.in(EngineerBusiness::getEngineerCode, engineerCodes); lqw.in(EngineerBusiness::getEngineerCode, engineerCodes);
List<EngineerBusiness> records = engineerBusinessDao.selectList(lqw); List<EngineerBusiness> records = engineerBusinessDao.selectList(lqw);
for (EngineerBusiness r : records) { for (EngineerBusiness r : records) {
map.put(r.getEngineerCode(), r); map.put(r.getEngineerCode(), r);
} }
return map; return map;
} }
private List<EngineerInfoListResp.EngineerInfo> packEngineerInfos(List<EngineerInfo> engineers, HashMap<String, String> groups) { private List<EngineerInfoListResp.EngineerInfo> packEngineerInfos(List<EngineerInfo> engineers, HashMap<String, String> groups) {
String groupName, age, kind; String groupName, age, kind;
List<EngineerInfoListResp.EngineerInfo> items = new ArrayList<>(); List<EngineerInfoListResp.EngineerInfo> items = new ArrayList<>();
for (EngineerInfo e : engineers) { for (EngineerInfo e : engineers) {
EngineerInfoListResp.EngineerInfo item = new EngineerInfoListResp.EngineerInfo(); EngineerInfoListResp.EngineerInfo item = new EngineerInfoListResp.EngineerInfo();
item.setEngineerCode(e.getEngineerCode()); item.setEngineerCode(e.getEngineerCode());
item.setNumber(e.getEngineerCode()); item.setNumber(e.getEngineerCode());
item.setName(e.getName()); item.setName(e.getName());
item.setSex(e.getGender()); item.setSex(e.getGender());
item.setPhone(e.getPhone()); item.setPhone(e.getPhone());
item.setAddress(e.getAddress()); item.setAddress(e.getAddress());
item.setGrade(e.getGrade()); item.setGrade(e.getGrade());
// group name // group name
groupName = groups.getOrDefault(e.getGroupId(), ""); groupName = groups.getOrDefault(e.getGroupId(), "");
item.setGroupName(groupName); item.setGroupName(groupName);
// 年龄 // 年龄
age = this.getEngineerAge(e.getBirth()); age = this.getEngineerAge(e.getBirth());
item.setAge(age); item.setAge(age);
// 工作类型:全职/兼职 // 工作类型:全职/兼职
kind = (e.getKind() == 1) ? "fullJob" : "partJob"; kind = (e.getKind() == 1) ? "fullJob" : "partJob";
item.setKind(kind); item.setKind(kind);
if (e.getCredentials() != null) { if (e.getCredentials() != null) {
item.setCredentials(Arrays.asList(e.getCredentials().split("、"))); item.setCredentials(Arrays.asList(e.getCredentials().split("、")));
} else { } else {
item.setCredentials(new ArrayList<String>()); item.setCredentials(new ArrayList<String>());
} }
// 标签 // 标签
List<String> tags = new ArrayList<>(); List<String> tags = new ArrayList<>();
if (e.getTags() != null && !e.getTags().isEmpty()) { if (e.getTags() != null && !e.getTags().isEmpty()) {
for (Map.Entry<String, Object> entry : e.getTags().entrySet()) { for (Map.Entry<String, Object> entry : e.getTags().entrySet()) {
tags.add(String.format("%s+%s", entry.getKey(), entry.getValue().toString())); tags.add(String.format("%s+%s", entry.getKey(), entry.getValue().toString()));
} }
} }
item.setTags(tags); item.setTags(tags);
items.add(item); items.add(item);
} }
return items; return items;
} }
private List<EngineerSkillListResp.EngineerSkill> packEngineerSkills(List<EngineerInfo> engineers) { private List<EngineerSkillListResp.EngineerSkill> packEngineerSkills(List<EngineerInfo> engineers) {
// 获取groupId类表 // 获取groupId类表
List<String> groupIds = engineers.stream().map(EngineerInfo::getGroupId).collect(Collectors.toList()); List<String> groupIds = engineers.stream().map(EngineerInfo::getGroupId).collect(Collectors.toList());
HashMap<String, String> groupNames = this.queryGroupNames(groupIds); HashMap<String, String> groupNames = this.queryGroupNames(groupIds);
// 获取技术员code列表 // 获取技术员code列表
List<String> engineerCodes = engineers.stream().map(EngineerInfo::getEngineerCode).collect(Collectors.toList()); List<String> engineerCodes = engineers.stream().map(EngineerInfo::getEngineerCode).collect(Collectors.toList());
// 获取技术员的可用技能列表 // 获取技术员的可用技能列表
List<Integer> statuses = Collections.singletonList(1); List<Integer> statuses = Collections.singletonList(1);
HashMap<String, List<String>> engineerSkillGroups = this.queryEngineerSkills(engineerCodes, statuses); HashMap<String, List<String>> engineerSkillGroups = this.queryEngineerSkills(engineerCodes, statuses);
List<String> emptySkills = Collections.emptyList(); List<String> emptySkills = Collections.emptyList();
List<EngineerSkillListResp.EngineerSkill> items = new ArrayList<>(); List<EngineerSkillListResp.EngineerSkill> items = new ArrayList<>();
for (EngineerInfo e : engineers) { for (EngineerInfo e : engineers) {
EngineerSkillListResp.EngineerSkill skill = new EngineerSkillListResp.EngineerSkill(); EngineerSkillListResp.EngineerSkill skill = new EngineerSkillListResp.EngineerSkill();
skill.setEngineerCode(e.getEngineerCode()); skill.setEngineerCode(e.getEngineerCode());
skill.setEngineerName(e.getName()); skill.setEngineerName(e.getName());
skill.setGroupName(groupNames.getOrDefault(e.getGroupId(), "")); skill.setGroupName(groupNames.getOrDefault(e.getGroupId(), ""));
skill.setUpdateTime(TimeUtils.IsoTimestamp2DateTime(e.getUpdateTime())); skill.setUpdateTime(TimeUtils.IsoTimestamp2DateTime(e.getUpdateTime()));
// 获取一个工程师的技能列表 // 获取一个工程师的技能列表
skill.setSkillGroupIds(engineerSkillGroups.getOrDefault(e.getEngineerCode(), emptySkills)); skill.setSkillGroupIds(engineerSkillGroups.getOrDefault(e.getEngineerCode(), emptySkills));
items.add(skill); items.add(skill);
} }
return items; return items;
} }
private List<EngineerBusinessListResp.EngineerBusiness> packEngineerBusinesses(List<EngineerInfo> engineers) { private List<EngineerBusinessListResp.EngineerBusiness> packEngineerBusinesses(List<EngineerInfo> engineers) {
// 获取技术员code列表 // 获取技术员code列表
List<String> engineerCodes = engineers.stream().map(EngineerInfo::getEngineerCode).collect(Collectors.toList()); List<String> engineerCodes = engineers.stream().map(EngineerInfo::getEngineerCode).collect(Collectors.toList());
List<String> groupIds = engineers.stream().map(EngineerInfo::getGroupId).collect(Collectors.toList()); List<String> groupIds = engineers.stream().map(EngineerInfo::getGroupId).collect(Collectors.toList());
HashMap<String, String> groupNames = this.queryGroupNames(groupIds); HashMap<String, String> groupNames = this.queryGroupNames(groupIds);
HashMap<String, EngineerBusiness> buss = this.queryEngineerBusiness(engineerCodes); HashMap<String, EngineerBusiness> buss = this.queryEngineerBusiness(engineerCodes);
List<EngineerBusinessListResp.EngineerBusiness> items = new ArrayList<>(); List<EngineerBusinessListResp.EngineerBusiness> items = new ArrayList<>();
for (EngineerInfo e : engineers) { for (EngineerInfo e : engineers) {
EngineerBusinessListResp.EngineerBusiness item = new EngineerBusinessListResp.EngineerBusiness(); EngineerBusinessListResp.EngineerBusiness item = new EngineerBusinessListResp.EngineerBusiness();
item.setEngineerCode(e.getEngineerCode()); item.setEngineerCode(e.getEngineerCode());
item.setGroupName(groupNames.getOrDefault(e.getGroupId(), "")); item.setGroupName(groupNames.getOrDefault(e.getGroupId(), ""));
item.setEngineerName(e.getName()); item.setEngineerName(e.getName());
item.setKind((e.getKind() == 1) ? "fullJob" : "partJob"); item.setKind((e.getKind() == 1) ? "fullJob" : "partJob");
EngineerBusiness b = buss.getOrDefault(e.getEngineerCode(), null); EngineerBusiness b = buss.getOrDefault(e.getEngineerCode(), null);
if (b == null) { if (b == null) {
item.setAddress(""); item.setAddress("");
item.setLocation(""); item.setLocation("");
item.setDeparture(""); item.setDeparture("");
item.setMaxMinute(0); item.setMaxMinute(0);
item.setMaxNum(0); item.setMaxNum(0);
item.setPriority("低"); item.setPriority("低");
} else { } else {
item.setAddress(b.getAddress()); item.setAddress(b.getAddress());
item.setLocation(String.format("%s,%s", b.getX(), b.getY())); item.setLocation(String.format("%s,%s", b.getX(), b.getY()));
item.setDeparture((b.getDeparture() == 1) ? "配件仓" : "住址"); item.setDeparture((b.getDeparture() == 1) ? "配件仓" : "住址");
item.setMaxMinute(b.getMaxMinute()); item.setMaxMinute(b.getMaxMinute());
item.setMaxNum(b.getMaxNum()); item.setMaxNum(b.getMaxNum());
String priority; String priority;
if (b.getPriority() == 3) { if (b.getPriority() == 3) {
priority = "高"; priority = "高";
} else if (b.getPriority() == 2) { } else if (b.getPriority() == 2) {
priority = "中"; priority = "中";
} else { } else {
priority = "低"; priority = "低";
} }
item.setPriority(priority); item.setPriority(priority);
} }
items.add(item); items.add(item);
} }
return items; return items;
} }
private HashMap<String, Integer> getEngineerSkillIds(List<String> skillIds, HashMap<String, Integer> engineerSkillIds) { private HashMap<String, Integer> getEngineerSkillIds(List<String> skillIds, HashMap<String, Integer> engineerSkillIds) {
HashMap<String, Integer> map = new HashMap<>(); HashMap<String, Integer> map = new HashMap<>();
for (String skillId : skillIds) { for (String skillId : skillIds) {
map.put(skillId, engineerSkillIds.getOrDefault(skillId, 0)); map.put(skillId, engineerSkillIds.getOrDefault(skillId, 0));
} }
return map; return map;
} }
private String getEngineerAge(String birth) { private String getEngineerAge(String birth) {
// 获取工程师年龄 // 获取工程师年龄
if (birth.isEmpty()) { if (birth.isEmpty()) {
return ""; return "";
} }
int age; int age;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try { try {
Date birthDate = dateFormat.parse(birth); Date birthDate = dateFormat.parse(birth);
Calendar birthCalendar = Calendar.getInstance(); Calendar birthCalendar = Calendar.getInstance();
birthCalendar.setTime(birthDate); birthCalendar.setTime(birthDate);
Calendar nowCalendar = Calendar.getInstance(); Calendar nowCalendar = Calendar.getInstance();
age = nowCalendar.get(Calendar.YEAR) - birthCalendar.get(Calendar.YEAR); age = nowCalendar.get(Calendar.YEAR) - birthCalendar.get(Calendar.YEAR);
if (nowCalendar.get(Calendar.DAY_OF_YEAR) < birthCalendar.get(Calendar.DAY_OF_YEAR)) { if (nowCalendar.get(Calendar.DAY_OF_YEAR) < birthCalendar.get(Calendar.DAY_OF_YEAR)) {
age--; age--;
} }
} catch (Exception e) { } catch (Exception e) {
return ""; return "";
} }
return (age <= 0) ? "" : Integer.toString(age); return (age <= 0) ? "" : Integer.toString(age);
} }
@Override
public Result<?> getEngineersGanttList(EngineersGanttReqDTO reqDTO) {
// 按日期返回技术员们当天的服务甘特图,不需要翻页
log.info("getEngineersGanttList: {}", reqDTO);
List<OrderAppointmentEntity> orderAppointments = orderAppointmentDao.findByDateAndEngineerCodeIn(reqDTO.getDate(), reqDTO.getEngineerCodes());
List<String> orderIds = orderAppointments.stream().map(OrderAppointmentEntity::getOrderId).collect(Collectors.toList());
Map<String, OrderRequestEntity> mapOrderRequest = getOrdersByOrderIds(orderIds);
HashMap<String, List<EngineersGanttRespDTO.Order>> mapEngineers = new HashMap<>();
for (OrderAppointmentEntity e : orderAppointments) {
log.info("===== order_id: [{}]", e.getOrderId());
EngineersGanttRespDTO.Order order = new EngineersGanttRespDTO.Order();
// todo 需要根据订单时间和状态,采用expectXXXX或者actualXXXX
order.setStartTime(e.getExpectStartTime()).setEndTime(e.getExpectEndTime());
order.setOrderId(e.getOrderId()).setPreStatus(e.getPreStatus());
order.setTips(getOrderTips(e.getOrderId()));
order.setAppointmentStatus(mapOrderRequest.get(e.getOrderId()).getAppointmentStatus());
List<EngineersGanttRespDTO.Order> orders = null;
if (mapEngineers.containsKey(e.getEngineerCode())) {
orders = mapEngineers.get(e.getEngineerCode());
} else {
orders = new ArrayList<>();
}
orders.add(order);
mapEngineers.put(e.getEngineerCode(), orders);
}
List<EngineersGanttRespDTO.GanttChart> engineers = new ArrayList<>();
for (String engineerCode : reqDTO.getEngineerCodes()) {
EngineerInfoEntity engineerInfo = engineerInfoDao.getByEngineerCode(engineerCode);
EngineersGanttRespDTO.GanttChart engineer = new EngineersGanttRespDTO.GanttChart();
engineer.setEngineerCode(engineerCode)
.setStartTime(String.format("%s 08:00", reqDTO.getDate()))
.setEndTime(String.format("%s 18:00", reqDTO.getDate()))
.setHoliday(false) // todo
.setEngineerName(engineerInfo.getName())
.setGrade(engineerInfo.getGrade());
CapacityEngineerStatEntity capacityEngineerStat = capacityEngineerStatDao.getByEngineerCodeAndWorkday(engineerCode, reqDTO.getDate());
if (capacityEngineerStat == null) {
log.warn("技术员当日的容量数据不存在,{}{}", engineerCode, reqDTO.getDate());
} else {
engineer.setCapTotal(capacityEngineerStat.getCapTotal().toString()).setCapUsed(capacityEngineerStat.getCapUsed().toString());
}
if (mapEngineers.containsKey(engineerCode)) {
engineer.setOrders(mapEngineers.get(engineerCode));
}
// engineer.setErrorTip(); todo
engineers.add(engineer);
}
EngineersGanttRespDTO data = new EngineersGanttRespDTO().setDate(reqDTO.getDate()).setEngineers(engineers);
return Result.success(data);
}
public Map<String, OrderRequestEntity> getOrdersByOrderIds(List<String> orderIds) {
List<OrderRequestEntity> orders = orderRequestDao.findAllByOrderIdIn(orderIds);
return orders.stream()
.collect(Collectors.toMap(OrderRequestEntity::getOrderId, order -> order));
}
private List<?> getOrderTips(String orderId) {
log.info("==> getOrderTips: orderId[{}]", orderId);
OrderRequestEntity order = orderRequestDao.getByOrderId(orderId);
if (order == null) {
log.error("对应的订单不存在!{}", orderId);
return null;
}
List<LabelValueDTO> tips = new ArrayList<>();
tips.add(new LabelValueDTO().setLabel("工单号码").setValue(orderId));
tips.add(new LabelValueDTO().setLabel("类型/品牌").setValue(String.format("%s %s", order.getBrand(), order.getType())));
tips.add(new LabelValueDTO().setLabel("电话/地址").setValue(String.format("%s %s\n %s", order.getName(), order.getPhone(), order.getAddress())));
if (StringUtils.isNotBlank(order.getApplyNote())) {
tips.add(new LabelValueDTO().setLabel("备注").setValue(order.getApplyNote()));
}
tips.add(new LabelValueDTO().setLabel("标签").setValue(order.getTags()));
return tips;
}
} }
...@@ -4,23 +4,28 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; ...@@ -4,23 +4,28 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.dituhui.pea.common.BusinessException; import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result; import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.common.OrderAssignCheck;
import com.dituhui.pea.order.common.TimeUtils; import com.dituhui.pea.order.common.TimeUtils;
import com.dituhui.pea.order.dao.EngineerInfoMPDao; import com.dituhui.pea.order.dao.EngineerInfoMPDao;
import com.dituhui.pea.order.dao.OrderAppointmentMPDao; import com.dituhui.pea.order.dao.OrderAppointmentMPDao;
import com.dituhui.pea.order.dao.OrderEventMPDao;
import com.dituhui.pea.order.dao.OrderRequestMPDao; import com.dituhui.pea.order.dao.OrderRequestMPDao;
import com.dituhui.pea.order.dto.LabelValueDTO; import com.dituhui.pea.order.dto.LabelValueDTO;
import com.dituhui.pea.order.dto.OrderAssignRecommendResp; import com.dituhui.pea.order.dto.OrderAssignRecommendResp;
import com.dituhui.pea.order.dto.TimeLineDTO; import com.dituhui.pea.order.dto.TimeLineDTO;
import com.dituhui.pea.order.entity.EngineerInfo; import com.dituhui.pea.order.entity.EngineerInfo;
import com.dituhui.pea.order.entity.OrderAppointment; import com.dituhui.pea.order.entity.OrderAppointment;
import com.dituhui.pea.order.entity.OrderEvent;
import com.dituhui.pea.order.entity.OrderRequest; import com.dituhui.pea.order.entity.OrderRequest;
import com.dituhui.pea.order.service.CommonService; import com.dituhui.pea.order.service.CommonService;
import com.dituhui.pea.order.service.OrderAssign; import com.dituhui.pea.order.service.OrderAssign;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -30,6 +35,7 @@ import java.util.List; ...@@ -30,6 +35,7 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@Slf4j
public class OrderAssignImpl implements OrderAssign { public class OrderAssignImpl implements OrderAssign {
@Autowired @Autowired
...@@ -44,6 +50,12 @@ public class OrderAssignImpl implements OrderAssign { ...@@ -44,6 +50,12 @@ public class OrderAssignImpl implements OrderAssign {
@Autowired @Autowired
private CommonService commonService; private CommonService commonService;
@Autowired
private OrderEventMPDao orderEventMPDao;
@Autowired
private OrderAssignCheck orderAssignCheck;
@Transactional @Transactional
@Override @Override
public Result<?> getOrderAssignRecommendEngineers(String orderId, String key, String distance, String recommend) { public Result<?> getOrderAssignRecommendEngineers(String orderId, String key, String distance, String recommend) {
...@@ -111,26 +123,30 @@ public class OrderAssignImpl implements OrderAssign { ...@@ -111,26 +123,30 @@ public class OrderAssignImpl implements OrderAssign {
throw new BusinessException("订单不存在"); throw new BusinessException("订单不存在");
} }
if (!order.getAppointmentStatus().equals("NOT_ASSIGNED")) {
throw new BusinessException("订单已指派成功,不必重新指派");
}
EngineerInfo engineer = engineerInfoMPDao.getByEngineerCode(engineerCode); EngineerInfo engineer = engineerInfoMPDao.getByEngineerCode(engineerCode);
String date = TimeUtils.timestamp2DateTime(order.getExpectTimeBegin(), TimeUtils.DATE_GAP_FORMAT); boolean record = false;
List<OrderAppointment> orderAppointments = this.queryOrderAppointments(engineerCode, date); OrderAppointment op = orderAppointmentMPDao.getByOrderIdAndDt(orderId, order.getDt());
if(op != null) {
record = true;
}
OrderRecommend recommend = new OrderRecommend(); if(op != null && !order.getAppointmentStatus().equals("NOT_ASSIGNED") && op.getEngineerCode().equals(engineerCode)) {
RecommendResult rr = recommend.recommend(order, orderAppointments); throw new BusinessException(String.format("订单已指派个技术员[%s], 不必重复指派给同一个技术员", engineer.getName()));
if (rr.getIndex() == -1) {
throw new BusinessException("指派失败, 未能找到合适的时间段, 请选择其他技术员");
} }
LineSegment seg = rr.getSeg(); OrderAssignCheck.Result result = orderAssignCheck.orderAssignCheck(orderId, engineerCode);
Timestamp expectStartTime = recommend.linePoint2Timestamp(seg.start, date); log.info("指派检查结果:{}", result);
Timestamp expectEndTime = recommend.linePoint2Timestamp(seg.end, date); if(!result.getCanAssign()){
throw new BusinessException("指派失败, 未能找到合适的时间段, 请选择其他技术员");
}
Timestamp expectStartTime = Timestamp.valueOf(result.getStart());;
Timestamp expectEndTime = Timestamp.valueOf(result.getEnd());
OrderAppointment op = new OrderAppointment(); // 更新或插入指派单
if(!record){
op = new OrderAppointment();
}
op.setOrderId(orderId); op.setOrderId(orderId);
op.setSuborderId(Long.toString(System.currentTimeMillis())); op.setSuborderId(Long.toString(System.currentTimeMillis()));
op.setMainSub(1); op.setMainSub(1);
...@@ -139,12 +155,17 @@ public class OrderAssignImpl implements OrderAssign { ...@@ -139,12 +155,17 @@ public class OrderAssignImpl implements OrderAssign {
op.setEngineerAge(0); op.setEngineerAge(0);
op.setEngineerPhone(engineer.getPhone()); op.setEngineerPhone(engineer.getPhone());
op.setIsWorkshop(0); op.setIsWorkshop(0);
op.setDt(order.getDt());
op.setExpectStartTime(expectStartTime); op.setExpectStartTime(expectStartTime);
op.setExpectEndTime(expectEndTime); op.setExpectEndTime(expectEndTime);
op.setPreStatus("PRE"); op.setPreStatus("CONFIRM");
op.setStatus("ASSIGNED"); op.setStatus("ASSIGNED");
orderAppointmentMPDao.insert(op); if(!record) {
orderAppointmentMPDao.insert(op);
} else {
orderAppointmentMPDao.updateById(op);
}
// 更新order_request表状态 // 更新order_request表状态
LambdaUpdateWrapper<OrderRequest> wrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<OrderRequest> wrapper = new LambdaUpdateWrapper<>();
...@@ -159,6 +180,40 @@ public class OrderAssignImpl implements OrderAssign { ...@@ -159,6 +180,40 @@ public class OrderAssignImpl implements OrderAssign {
return Result.success(null); return Result.success(null);
} }
@Override
public Result<?> orderRevokeAssign(String orderId) throws BusinessException{
OrderRequest order = orderRequestMPDao.getByOrderId(orderId);
if (order == null){
throw new BusinessException("订单不存在");
}
// 更新order_request表为未指派
order.setAppointmentStatus("NOT_ASSIGNED");
orderRequestMPDao.updateById(order);
// 更新order_appointment表为未指派
LambdaUpdateWrapper<OrderAppointment> appWrapper = new LambdaUpdateWrapper<>();
appWrapper.set(OrderAppointment::getStatus, "NOT_ASSIGNED")
.eq(OrderAppointment::getOrderId, orderId).eq(OrderAppointment::getDt, order.getDt());
orderAppointmentMPDao.update(null, appWrapper);
// 登记事件
OrderEvent oe = new OrderEvent();
oe.setOrderId(orderId);
oe.setSuborderId("");
oe.setHappen(new Timestamp(System.currentTimeMillis()));
oe.setEvent("放回工单池");
oe.setOperator("123"); // 操作员ID TODO-用户系统
oe.setOperatorName("测试用户"); // 操作员姓名 TODO-用户系统
oe.setSource("PEA");
oe.setDescription("返回工单池");
oe.setMemo("");
oe.setCreateTime(new Timestamp(System.currentTimeMillis()));
orderEventMPDao.insert(oe);
return Result.success(null);
}
private List<OrderAppointment> queryOrderAppointments(String engineerCode, String date) { private List<OrderAppointment> queryOrderAppointments(String engineerCode, String date) {
LambdaQueryWrapper<OrderAppointment> lqw = new LambdaQueryWrapper<>(); LambdaQueryWrapper<OrderAppointment> lqw = new LambdaQueryWrapper<>();
lqw.eq(OrderAppointment::getEngineerCode, engineerCode); lqw.eq(OrderAppointment::getEngineerCode, engineerCode);
......
...@@ -51,6 +51,15 @@ public class OrderServiceDetailImpl implements OrderServiceDetail { ...@@ -51,6 +51,15 @@ public class OrderServiceDetailImpl implements OrderServiceDetail {
List<KV> items = this.packOrderDetail(order); List<KV> items = this.packOrderDetail(order);
// 设置订单详情信息
OrderServiceDetailResp.OrderDetail detail = new OrderServiceDetailResp.OrderDetail();
detail.setAddress(String.format("%s%s%s", order.getCity(), order.getCounty(), order.getAddress()));
detail.setLocation(String.format("%s,%s", order.getX(),order.getY()));
detail.setDate(TimeUtils.IsoLocalDate2String(order.getDt()));
detail.setBrand(order.getBrand());
detail.setType(order.getType());
detail.setSkill(order.getSkill());
OrderServiceDetailResp res = new OrderServiceDetailResp(); OrderServiceDetailResp res = new OrderServiceDetailResp();
res.setOrderId(orderId); res.setOrderId(orderId);
res.setRisk(""); res.setRisk("");
...@@ -59,6 +68,7 @@ public class OrderServiceDetailImpl implements OrderServiceDetail { ...@@ -59,6 +68,7 @@ public class OrderServiceDetailImpl implements OrderServiceDetail {
res.setStatus(order.getStatus()); res.setStatus(order.getStatus());
res.setAppointmentStatus(order.getAppointmentStatus()); res.setAppointmentStatus(order.getAppointmentStatus());
res.setLocation(String.format("%s,%s", order.getX(), order.getY())); res.setLocation(String.format("%s,%s", order.getX(), order.getY()));
res.setReschedulingParams(detail);
res.setItems(items); res.setItems(items);
return Result.success(res); return Result.success(res);
...@@ -92,7 +102,7 @@ public class OrderServiceDetailImpl implements OrderServiceDetail { ...@@ -92,7 +102,7 @@ public class OrderServiceDetailImpl implements OrderServiceDetail {
if (appoints.isEmpty()) { if (appoints.isEmpty()) {
// 没有指派单列表,返回 // 没有指派单列表,返回
res.setOrderId(orderId); res.setOrderId(orderId);
res.setOrders(List.of()); res.setOrders(new ArrayList<>());
return Result.success(res); return Result.success(res);
} }
......
...@@ -59,13 +59,8 @@ public class OrderServiceListServiceImpl implements OrderServiceListService { ...@@ -59,13 +59,8 @@ public class OrderServiceListServiceImpl implements OrderServiceListService {
lqw.in(ListUtils.isNotEmpty(reqDTO.getPriorities()), OrderRequest::getPriority, reqDTO.getPriorities()); lqw.in(ListUtils.isNotEmpty(reqDTO.getPriorities()), OrderRequest::getPriority, reqDTO.getPriorities());
lqw.in(ListUtils.isNotEmpty(reqDTO.getProductCategory()), OrderRequest::getType, reqDTO.getProductCategory()); lqw.in(ListUtils.isNotEmpty(reqDTO.getProductCategory()), OrderRequest::getType, reqDTO.getProductCategory());
lqw.in(ListUtils.isNotEmpty(reqDTO.getProductCategory()), OrderRequest::getSkill, reqDTO.getServiceCategory()); lqw.in(ListUtils.isNotEmpty(reqDTO.getProductCategory()), OrderRequest::getSkill, reqDTO.getServiceCategory());
lqw.in(ListUtils.isNotEmpty(reqDTO.getAppointmentType()), OrderRequest::getAppointmentMethod, reqDTO.getAppointmentType());
lqw.eq(StringUtils.isNotEmpty(reqDTO.getAppointmentType()), OrderRequest::getAppointmentMethod, reqDTO.getAppointmentType()); //指派状态 lqw.in(ListUtils.isNotEmpty(reqDTO.getAppointmentStatus()), OrderRequest::getAppointmentStatus, reqDTO.getAppointmentStatus());
if (StringUtils.isNotEmpty(reqDTO.getAppointmentStatus()) && reqDTO.getAppointmentStatus().equals("0")) {
lqw.eq(OrderRequest::getAppointmentStatus, "NOT_ASSIGNED");
} else if (StringUtils.isNotEmpty(reqDTO.getAppointmentStatus()) && reqDTO.getAppointmentStatus().equals("1")) {
lqw.ne(OrderRequest::getAppointmentStatus, "NOT_ASSIGNED");
}
if(ListUtils.isNotEmpty(reqDTO.getEngineerCodes())) { if(ListUtils.isNotEmpty(reqDTO.getEngineerCodes())) {
String engineerCodes = String.join(",", reqDTO.getEngineerCodes()); String engineerCodes = String.join(",", reqDTO.getEngineerCodes());
......
package com.dituhui.pea.order.service.impl; package com.dituhui.pea.order.service.impl;
import com.dituhui.pea.common.Result; import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.common.EngineerUtil;
import com.dituhui.pea.order.dao.*; import com.dituhui.pea.order.dao.*;
import com.dituhui.pea.order.dto.*; import com.dituhui.pea.order.dto.*;
import com.dituhui.pea.order.entity.*; import com.dituhui.pea.order.entity.*;
...@@ -31,6 +32,9 @@ public class OrganizationServiceImpl implements OrganizationService { ...@@ -31,6 +32,9 @@ public class OrganizationServiceImpl implements OrganizationService {
@Autowired @Autowired
private OrgTeamDao orgTeamDao; private OrgTeamDao orgTeamDao;
@Autowired
private EngineerUtil engineerUtil;
@Override @Override
public Result<?> getOrganizationTree(String levelType, String levelValue) { public Result<?> getOrganizationTree(String levelType, String levelValue) {
// 如果传递了精确的id,只返回对应的tree内容;如果没有传递,返回所有tree内容 // 如果传递了精确的id,只返回对应的tree内容;如果没有传递,返回所有tree内容
...@@ -111,30 +115,7 @@ public class OrganizationServiceImpl implements OrganizationService { ...@@ -111,30 +115,7 @@ public class OrganizationServiceImpl implements OrganizationService {
@Override @Override
public Result<?> getEngineersByLevel(String levelType, String levelValue) { public Result<?> getEngineersByLevel(String levelType, String levelValue) {
List<EngineerInfoEntity> engineers = null; List<EngineerInfoEntity> engineers = engineerUtil.getEngineersByLevel(levelType, levelValue);
List<String> groupIds = null;
assert "team".equals(levelType) || "group".equals(levelType) || "branch".equals(levelType) || "cluster".equals(levelType);
switch (levelType) {
case "team":
List<String> engineerCodes = orgTeamEngineerDao.findAllByTeamId(levelValue).stream()
.map(OrgTeamEngineerEntity::getEngineerCode).collect(Collectors.toList());
engineers = engineerInfoDao.findByEngineerCodeIn(engineerCodes);
break;
case "group":
engineers = engineerInfoDao.findByGroupId(levelValue);
break;
case "branch":
groupIds = orgGroupDao.findAllByBranchId(levelValue).stream()
.map(OrgGroupEntity::getGroupId).collect(Collectors.toList());
engineers = engineerInfoDao.findByGroupIdIn(groupIds);
break;
default:
// "cluster".equals(levelType)
groupIds = orgGroupDao.findAllByClusterId(levelValue).stream()
.map(OrgGroupEntity::getGroupId).collect(Collectors.toList());
engineers = engineerInfoDao.findByGroupIdIn(groupIds);
break;
}
List<OrganizationEngineersDTO.Engineer> engineers1 = engineers.stream().map(entity -> { List<OrganizationEngineersDTO.Engineer> engineers1 = engineers.stream().map(entity -> {
return new OrganizationEngineersDTO.Engineer() return new OrganizationEngineersDTO.Engineer()
.setEngineerCode(entity.getEngineerCode()) .setEngineerCode(entity.getEngineerCode())
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!