Commit ee9364cf by 刘鑫

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

2 parents b9858377 d3159ef8
Showing with 1042 additions and 825 deletions
package com.dituhui.pea.util;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.util.Assert;
import java.text.MessageFormat;
......@@ -493,6 +494,16 @@ public class DateUtil {
return MessageFormat.format("{}小时{}分{}秒", hours, minutes, second);
}
}
/**
* 获取小时
*
* @param date
* @return
*/
public static Integer getHour(Date date) {
return DateUtils.toCalendar(date).get(Calendar.HOUR_OF_DAY);
}
//CHECKSTYLE:ON
}
......@@ -2,6 +2,7 @@ package com.dituhui.pea.order.common;
import com.dituhui.pea.order.dao.*;
import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
......@@ -27,327 +28,327 @@ import java.util.stream.Collectors;
@Slf4j
public class OrderAssignCheck {
@Autowired
private SkillInfoDao skillInfoDao;
@Autowired
private EngineerBusinessDao engineerBusinessDao;
@Autowired
private EngineerInfoDao engineerInfoDao;
@Autowired
private OrgGroupDao orgGroupDao;
@Autowired
private OrderInfoDao orderInfoDao;
@Autowired
private EntityManager entityManager;
public Result orderAssignCheck(String orderId, LocalDate dt, String engineerCode) {
log.info("begin orderAssignCheck:orderId={}, engineerCode={}", orderId, engineerCode);
OrderInfoEntity order = orderInfoDao.getByOrderIdAndDt(orderId, dt);
double curX = Double.parseDouble(order.getX());
double curY = Double.parseDouble(order.getY());
// 获取技能需要的时长(分钟)
SkillInfoEntity skillInfo = skillInfoDao.getByBrandAndTypeAndSkill(order.getBrand(), order.getType(), order.getSkill());
int takeTime = skillInfo.getTakeTime();
// 获取客户期望时间段
int start = this.timestamp2Point(Timestamp.valueOf(order.getExpectTimeBegin()));
int end = this.timestamp2Point(Timestamp.valueOf(order.getExpectTimeEnd()));
log.info("客户期望的时间段:{}-{}, 技能所需时长:{}, 坐标:{},{}", start, end, takeTime, curX, curY);
// 获取技术员的已分配订单的时间段, 根据时间段排序
List<OrderSegment> orderSegments = getEngineerOrderSegments(engineerCode, order.getDt());
// 转化为SegmentInsertion需要的时间段
List<SegmentInsertion.Segment> segments = this.orderSegment2Segment(orderSegments);
log.info("技术员已分配时间段列表:{}", segments);
int index = SegmentInsertion.insertSegment(takeTime, start, end, segments);
if (index == -1) {
log.info("没有可连续插入的空间");
return new Result(-1, false, false, orderId, null,0,0, null, null, null);
}
log.info("插入位置为第{}单, 已分配单数(不包含本单):{}", index, orderSegments.size());
// 计算距离 & 时间
if (index == 0 && orderSegments.isEmpty()) {
// 第一订单为出发地, 没有其他订单
// 技术员出发地
double[] location = this.getEngineerDepartureLocation(engineerCode);
double preX = location[0];
double preY = location[1];
OrderSegment pre = new OrderSegment(480, 480, preX, preY, 0, 0, 0);
Pair p = this.getDistanceAndDuration(pre.getX(), pre.getY(), curX, curY);
// 最早可插入位置为技术员出发时间+行程时间
int startPos = pre.getEnd() + p.getDuration();
int startInsert = (startPos >= start) ? startPos : start; // 客户期望最早时间是start, 可最早插入时间是startPos
int endInsert = startInsert + takeTime;
LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, order.getDt());
LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, order.getDt());
// 当前节点信息
OrderNode curOrder = new OrderNode();
curOrder.setOrderId(orderId);
curOrder.setArriveElapsed(p.getDuration());
curOrder.setArriveDistance(p.getDistance());
curOrder.setTakeTime(takeTime);
curOrder.setPlanStartTime(startDateTime);
curOrder.setPlanEndTime(endDateTime);
return new Result(index, true, true, orderId, "", p.getDistance(), p.getDuration(), curOrder, null, null);
} else if (index == 0 && !orderSegments.isEmpty()) {
// 第一订单为出发地, 且有其他订单
double[] location = this.getEngineerDepartureLocation(engineerCode);
double preX = location[0];
double preY = location[1];
OrderSegment pre = new OrderSegment(480, 480, preX, preY, 0, 0, 0);
OrderSegment cur = new OrderSegment(-1, -1, curX, curY, takeTime, -1, -1);
OrderSegment post = orderSegments.get(0);
return this.getResult(index, cur, pre, post, order.getDt());
} else if (index == orderSegments.size()) {
// 有其他订单,最后一个订单出发
OrderSegment pre = orderSegments.get(index - 1);
Pair p = this.getDistanceAndDuration(pre.getX(), pre.getY(), curX, curY);
// 最早可插入位置为技术员上一单出发时间+行程时间
int startPos = pre.getEnd() + p.getDuration();
int startInsert = (startPos >= start) ? startPos : start; // 客户期望最早时间是start, 可最早插入时间是startPos
int endInsert = startInsert + takeTime;
LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, order.getDt());
LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, order.getDt());
// 当前节点信息
OrderNode curOrder = new OrderNode();
curOrder.setOrderId(orderId);
curOrder.setArriveElapsed(p.getDuration());
curOrder.setArriveDistance(p.getDistance());
curOrder.setTakeTime(takeTime);
curOrder.setPlanStartTime(startDateTime);
curOrder.setPlanEndTime(endDateTime);
return new Result(index, false, true, orderId, "", p.getDistance(), p.getDuration(), curOrder, null, null);
} else {
// 插入中间位置
OrderSegment pre = orderSegments.get(index - 1);
OrderSegment cur = new OrderSegment(-1, -1, curX, curY, takeTime, -1, -1);
OrderSegment post = orderSegments.get(index);
return this.getResult(index, cur, pre, post, order.getDt());
}
}
private List<OrderSegment> getEngineerOrderSegments(String engineerCode, LocalDate dt) {
List<OrderSegment> orderSegments = new ArrayList<>();
List<String> appointmentStatusList = Arrays.asList("PRE", "CONFIRM");
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<OrderInfoEntity> criteriaQuery = criteriaBuilder.createQuery(OrderInfoEntity.class);
Root<OrderInfoEntity> root = criteriaQuery.from(OrderInfoEntity.class);
Predicate dtPredicate = criteriaBuilder.equal(root.get("dt"), dt);
Predicate engineerCodePredicate = criteriaBuilder.equal(root.get("engineerCode"), engineerCode);
Predicate orderStatusPredicate = criteriaBuilder.equal(root.get("orderStatus"), "NORMAL");
Predicate appointmentStatusPredicate = root.get("appointmentStatus").in(appointmentStatusList);
criteriaQuery.where(dtPredicate, engineerCodePredicate, orderStatusPredicate, appointmentStatusPredicate);
List<OrderInfoEntity> appointments = entityManager.createQuery(criteriaQuery).getResultList();
if (appointments.isEmpty()) {
return orderSegments;
}
for (OrderInfoEntity o : appointments) {
OrderSegment seg = new OrderSegment();
seg.setOrderId(o.getOrderId());
seg.setX(Double.parseDouble(o.getX()));
seg.setY(Double.parseDouble(o.getY()));
seg.setStart(this.timestamp2Point(Timestamp.valueOf(o.getPlanStartTime())));
seg.setEnd(this.timestamp2Point(Timestamp.valueOf(o.getPlanEndTime())));
seg.setElapsed(o.getArriveElapsed());
seg.setDistance(o.getArriveDistance());
orderSegments.add(seg);
}
return orderSegments.stream().sorted(Comparator.comparing(OrderSegment::getStart)).collect(Collectors.toList());
}
private List<SegmentInsertion.Segment> orderSegment2Segment(List<OrderSegment> orderSegments) {
List<SegmentInsertion.Segment> segments = new ArrayList<>();
for (OrderSegment s : orderSegments) {
segments.add(new SegmentInsertion.Segment(s.getOrderId(), s.getStart(), s.getEnd()));
}
return segments;
}
private Result getResult(int index, OrderSegment cur, OrderSegment pre, OrderSegment post, LocalDate dt) {
Pair preCurPair = this.getDistanceAndDuration(pre.getX(), pre.getY(), cur.getX(), cur.getY());
Pair postCurPair = this.getDistanceAndDuration(post.getX(), post.getY(), cur.getX(), cur.getY());
Pair prePostPair = this.getDistanceAndDuration(post.getX(), post.getY(), pre.getX(), pre.getY());
log.info("pre-cur{}, post-cur:{}, pre-post:{}", preCurPair, postCurPair, prePostPair);
// 判断增加时间+距离后,时间是否重叠了
int distance = post.getStart() - postCurPair.getDuration() - (pre.getEnd() + preCurPair.getDuration());
if (distance < cur.getTakeTime()) {
// 不支持插入
return new Result(-1, false, false, "", "", 0, 0, null, null, null);
}
// 插入点(时间点)
int startInsert = pre.getEnd() + preCurPair.getDuration();
int endInsert = startInsert + cur.getTakeTime();
LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, dt);
LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, dt);
// 当前节点
OrderNode curOrder = new OrderNode();
curOrder.setOrderId(cur.getOrderId());
curOrder.setArriveElapsed(cur.getElapsed());
curOrder.setArriveDistance(cur.getDistance());
curOrder.setTakeTime(cur.getTakeTime());
curOrder.setPlanStartTime(startDateTime);
curOrder.setPlanEndTime(endDateTime);
//后一个节点最新变更情况
OrderNode postOrder = new OrderNode();
postOrder.setOrderId(post.getOrderId());
postOrder.setTakeTime(post.getTakeTime());
postOrder.setPlanStartTime(this.point2LocalDateTime(post.getStart(), dt));
postOrder.setPlanEndTime(this.point2LocalDateTime(post.getEnd(), dt));
postOrder.setArriveDistance(postCurPair.getDistance());
postOrder.setArriveElapsed(postCurPair.getDuration());
// 后一个节点之前的情况
OrderNode postOrderOrg = new OrderNode();
postOrder.setOrderId(post.getOrderId());
postOrder.setTakeTime(post.getTakeTime());
postOrder.setPlanStartTime(this.point2LocalDateTime(post.getStart(), dt));
postOrder.setPlanEndTime(this.point2LocalDateTime(post.getEnd(), dt));
postOrder.setArriveDistance(post.getDistance());
postOrder.setArriveElapsed(post.getElapsed());
int additionDistance = preCurPair.getDistance() + postCurPair.getDistance() - prePostPair.getDistance();
int additionElapsed = preCurPair.getDuration() + postCurPair.getDuration() - prePostPair.getDuration();
return new Result(index, false, false, cur.getOrderId(), post.getOrderId(), additionDistance, additionElapsed, curOrder, postOrder, postOrderOrg);
}
private double[] getEngineerDepartureLocation(String engineerCode) {
// 获取技术员出发坐标
// 从技术员配置中获取
EngineerBusinessEntity b = engineerBusinessDao.getByEngineerCode(engineerCode);
if (b != null && StringUtils.isNotEmpty(b.getX()) && StringUtils.isNotEmpty(b.getY())) {
return new double[]{Double.parseDouble(b.getX()), Double.parseDouble(b.getY())};
}
//从org_group中获取
EngineerInfoEntity e = engineerInfoDao.getByEngineerCode(engineerCode);
OrgGroupEntity g = orgGroupDao.getByGroupId(e.getGroupId());
return new double[]{Double.parseDouble(g.getX()), Double.parseDouble(g.getY())};
}
private int timestamp2Point(Timestamp t) {
LocalDateTime dt = t.toLocalDateTime();
return dt.getHour() * 60 + dt.getMinute();
}
private LocalTime point2LocalTime(int point) {
int hour = point / 60;
int minute = point % 60;
return LocalTime.of(hour, minute, 0);
}
private LocalDateTime point2LocalDateTime(int point, LocalDate dt) {
return LocalDateTime.of(dt, this.point2LocalTime(point));
}
private Pair getDistanceAndDuration(double x1, double y1, double x2, double y2) {
Distance cal = new Distance();
long distance = Math.round(cal.calculateDistance(x1, y1, x2, y2) * 1.4); // 单位为米
long duration = distance / (19 * 1000 / 60); // 时间为分钟,假设电动车速度为19km/h
return new Pair((int) distance, (int) duration);
}
@Data
public static class OrderNode {
private String orderId;
private LocalDateTime planStartTime;
private LocalDateTime planEndTime;
private int takeTime;
private int arriveDistance;
private int arriveElapsed;
}
@Data
public class Result {
private int index;
private boolean isHead;
private boolean isTail;
private String curOrderId;
private String postOrderId;
private int additionDistance;
private int additionElapsed;
private OrderNode curOrderNode;
private OrderNode postOrderNode;
private OrderNode postOrderNodeOrg;
public Result(int index, boolean isHead, boolean isTail, String curOrderId, String postOrderId, int additionDistance, int additionElapsed, OrderNode curOrderNode, OrderNode postOrderNode, OrderNode postOrderNodeOrg) {
this.index = index;
this.isHead = isHead;
this.isTail = isTail;
this.curOrderId = curOrderId;
this.postOrderId = postOrderId;
this.additionDistance = additionDistance;
this.additionElapsed = additionElapsed;
this.curOrderNode = curOrderNode;
this.postOrderNode = postOrderNode;
this.postOrderNodeOrg = postOrderNodeOrg;
}
}
@Autowired
private SkillInfoDao skillInfoDao;
@Autowired
private EngineerBusinessDao engineerBusinessDao;
@Autowired
private EngineerInfoDao engineerInfoDao;
@Autowired
private OrgGroupDao orgGroupDao;
@Autowired
private OrderInfoDao orderInfoDao;
@Autowired
private EntityManager entityManager;
public Result orderAssignCheck(String orderId, LocalDate dt, String engineerCode) {
log.info("begin orderAssignCheck:orderId={}, engineerCode={}", orderId, engineerCode);
OrderInfoEntity order = orderInfoDao.getByOrderIdAndDt(orderId, dt);
double curX = Double.parseDouble(order.getX());
double curY = Double.parseDouble(order.getY());
// 获取技能需要的时长(分钟)
SkillInfoEntity skillInfo = skillInfoDao.getByBrandAndTypeAndSkill(order.getBrand(), order.getType(), order.getSkill());
int takeTime = skillInfo.getTakeTime();
// 获取客户期望时间段
int start = this.timestamp2Point(Timestamp.valueOf(order.getExpectTimeBegin()));
int end = this.timestamp2Point(Timestamp.valueOf(order.getExpectTimeEnd()));
log.info("客户期望的时间段:{}-{}, 技能所需时长:{}, 坐标:{},{}", start, end, takeTime, curX, curY);
// 获取技术员的已分配订单的时间段, 根据时间段排序
List<OrderSegment> orderSegments = getEngineerOrderSegments(engineerCode, order.getDt());
// 转化为SegmentInsertion需要的时间段
List<SegmentInsertion.Segment> segments = this.orderSegment2Segment(orderSegments);
log.info("技术员已分配时间段列表:{}", segments);
int index = SegmentInsertion.insertSegment(takeTime, start, end, segments);
if (index == -1) {
log.info("没有可连续插入的空间");
return new Result(-1, false, false, orderId, null, 0, 0, null, null, null);
}
log.info("插入位置为第{}单, 已分配单数(不包含本单):{}", index, orderSegments.size());
// 计算距离 & 时间
if (index == 0 && orderSegments.isEmpty()) {
// 第一订单为出发地, 没有其他订单
// 技术员出发地
double[] location = this.getEngineerDepartureLocation(engineerCode);
double preX = location[0];
double preY = location[1];
OrderSegment pre = new OrderSegment(480, 480, preX, preY, 0, 0, 0);
Pair p = this.getDistanceAndDuration(pre.getX(), pre.getY(), curX, curY);
// 最早可插入位置为技术员出发时间+行程时间
int startPos = pre.getEnd() + p.getDuration();
int startInsert = (startPos >= start) ? startPos : start; // 客户期望最早时间是start, 可最早插入时间是startPos
int endInsert = startInsert + takeTime;
LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, order.getDt());
LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, order.getDt());
// 当前节点信息
OrderNode curOrder = new OrderNode();
curOrder.setOrderId(orderId);
curOrder.setArriveElapsed(p.getDuration());
curOrder.setArriveDistance(p.getDistance());
curOrder.setTakeTime(takeTime);
curOrder.setPlanStartTime(startDateTime);
curOrder.setPlanEndTime(endDateTime);
return new Result(index, true, true, orderId, "", p.getDistance(), p.getDuration(), curOrder, null, null);
} else if (index == 0 && !orderSegments.isEmpty()) {
// 第一订单为出发地, 且有其他订单
double[] location = this.getEngineerDepartureLocation(engineerCode);
double preX = location[0];
double preY = location[1];
OrderSegment pre = new OrderSegment(480, 480, preX, preY, 0, 0, 0);
OrderSegment cur = new OrderSegment(-1, -1, curX, curY, takeTime, -1, -1);
OrderSegment post = orderSegments.get(0);
return this.getResult(index, cur, pre, post, order.getDt());
} else if (index == orderSegments.size()) {
// 有其他订单,最后一个订单出发
OrderSegment pre = orderSegments.get(index - 1);
Pair p = this.getDistanceAndDuration(pre.getX(), pre.getY(), curX, curY);
// 最早可插入位置为技术员上一单出发时间+行程时间
int startPos = pre.getEnd() + p.getDuration();
int startInsert = (startPos >= start) ? startPos : start; // 客户期望最早时间是start, 可最早插入时间是startPos
int endInsert = startInsert + takeTime;
LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, order.getDt());
LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, order.getDt());
// 当前节点信息
OrderNode curOrder = new OrderNode();
curOrder.setOrderId(orderId);
curOrder.setArriveElapsed(p.getDuration());
curOrder.setArriveDistance(p.getDistance());
curOrder.setTakeTime(takeTime);
curOrder.setPlanStartTime(startDateTime);
curOrder.setPlanEndTime(endDateTime);
return new Result(index, false, true, orderId, "", p.getDistance(), p.getDuration(), curOrder, null, null);
} else {
// 插入中间位置
OrderSegment pre = orderSegments.get(index - 1);
OrderSegment cur = new OrderSegment(-1, -1, curX, curY, takeTime, -1, -1);
OrderSegment post = orderSegments.get(index);
return this.getResult(index, cur, pre, post, order.getDt());
}
}
private List<OrderSegment> getEngineerOrderSegments(String engineerCode, LocalDate dt) {
List<OrderSegment> orderSegments = new ArrayList<>();
List<String> appointmentStatusList = Arrays.asList(OrderFlowEnum.PRE.name(), OrderFlowEnum.CONFIRM.name());
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<OrderInfoEntity> criteriaQuery = criteriaBuilder.createQuery(OrderInfoEntity.class);
Root<OrderInfoEntity> root = criteriaQuery.from(OrderInfoEntity.class);
Predicate dtPredicate = criteriaBuilder.equal(root.get("dt"), dt);
Predicate engineerCodePredicate = criteriaBuilder.equal(root.get("engineerCode"), engineerCode);
Predicate orderStatusPredicate = criteriaBuilder.equal(root.get("orderStatus"), "NORMAL");
Predicate appointmentStatusPredicate = root.get("appointmentStatus").in(appointmentStatusList);
criteriaQuery.where(dtPredicate, engineerCodePredicate, orderStatusPredicate, appointmentStatusPredicate);
List<OrderInfoEntity> appointments = entityManager.createQuery(criteriaQuery).getResultList();
if (appointments.isEmpty()) {
return orderSegments;
}
for (OrderInfoEntity o : appointments) {
OrderSegment seg = new OrderSegment();
seg.setOrderId(o.getOrderId());
seg.setX(Double.parseDouble(o.getX()));
seg.setY(Double.parseDouble(o.getY()));
seg.setStart(this.timestamp2Point(Timestamp.valueOf(o.getPlanStartTime())));
seg.setEnd(this.timestamp2Point(Timestamp.valueOf(o.getPlanEndTime())));
seg.setElapsed(o.getArriveElapsed());
seg.setDistance(o.getArriveDistance());
orderSegments.add(seg);
}
return orderSegments.stream().sorted(Comparator.comparing(OrderSegment::getStart)).collect(Collectors.toList());
}
private List<SegmentInsertion.Segment> orderSegment2Segment(List<OrderSegment> orderSegments) {
List<SegmentInsertion.Segment> segments = new ArrayList<>();
for (OrderSegment s : orderSegments) {
segments.add(new SegmentInsertion.Segment(s.getOrderId(), s.getStart(), s.getEnd()));
}
return segments;
}
private Result getResult(int index, OrderSegment cur, OrderSegment pre, OrderSegment post, LocalDate dt) {
Pair preCurPair = this.getDistanceAndDuration(pre.getX(), pre.getY(), cur.getX(), cur.getY());
Pair postCurPair = this.getDistanceAndDuration(post.getX(), post.getY(), cur.getX(), cur.getY());
Pair prePostPair = this.getDistanceAndDuration(post.getX(), post.getY(), pre.getX(), pre.getY());
log.info("pre-cur{}, post-cur:{}, pre-post:{}", preCurPair, postCurPair, prePostPair);
// 判断增加时间+距离后,时间是否重叠了
int distance = post.getStart() - postCurPair.getDuration() - (pre.getEnd() + preCurPair.getDuration());
if (distance < cur.getTakeTime()) {
// 不支持插入
return new Result(-1, false, false, "", "", 0, 0, null, null, null);
}
// 插入点(时间点)
int startInsert = pre.getEnd() + preCurPair.getDuration();
int endInsert = startInsert + cur.getTakeTime();
LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, dt);
LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, dt);
// 当前节点
OrderNode curOrder = new OrderNode();
curOrder.setOrderId(cur.getOrderId());
curOrder.setArriveElapsed(cur.getElapsed());
curOrder.setArriveDistance(cur.getDistance());
curOrder.setTakeTime(cur.getTakeTime());
curOrder.setPlanStartTime(startDateTime);
curOrder.setPlanEndTime(endDateTime);
//后一个节点最新变更情况
OrderNode postOrder = new OrderNode();
postOrder.setOrderId(post.getOrderId());
postOrder.setTakeTime(post.getTakeTime());
postOrder.setPlanStartTime(this.point2LocalDateTime(post.getStart(), dt));
postOrder.setPlanEndTime(this.point2LocalDateTime(post.getEnd(), dt));
postOrder.setArriveDistance(postCurPair.getDistance());
postOrder.setArriveElapsed(postCurPair.getDuration());
// 后一个节点之前的情况
OrderNode postOrderOrg = new OrderNode();
postOrder.setOrderId(post.getOrderId());
postOrder.setTakeTime(post.getTakeTime());
postOrder.setPlanStartTime(this.point2LocalDateTime(post.getStart(), dt));
postOrder.setPlanEndTime(this.point2LocalDateTime(post.getEnd(), dt));
postOrder.setArriveDistance(post.getDistance());
postOrder.setArriveElapsed(post.getElapsed());
int additionDistance = preCurPair.getDistance() + postCurPair.getDistance() - prePostPair.getDistance();
int additionElapsed = preCurPair.getDuration() + postCurPair.getDuration() - prePostPair.getDuration();
return new Result(index, false, false, cur.getOrderId(), post.getOrderId(), additionDistance, additionElapsed, curOrder, postOrder, postOrderOrg);
}
private double[] getEngineerDepartureLocation(String engineerCode) {
// 获取技术员出发坐标
// 从技术员配置中获取
EngineerBusinessEntity b = engineerBusinessDao.getByEngineerCode(engineerCode);
if (b != null && StringUtils.isNotEmpty(b.getX()) && StringUtils.isNotEmpty(b.getY())) {
return new double[]{Double.parseDouble(b.getX()), Double.parseDouble(b.getY())};
}
//从org_group中获取
EngineerInfoEntity e = engineerInfoDao.getByEngineerCode(engineerCode);
OrgGroupEntity g = orgGroupDao.getByGroupId(e.getGroupId());
return new double[]{Double.parseDouble(g.getX()), Double.parseDouble(g.getY())};
}
private int timestamp2Point(Timestamp t) {
LocalDateTime dt = t.toLocalDateTime();
return dt.getHour() * 60 + dt.getMinute();
}
private LocalTime point2LocalTime(int point) {
int hour = point / 60;
int minute = point % 60;
return LocalTime.of(hour, minute, 0);
}
private LocalDateTime point2LocalDateTime(int point, LocalDate dt) {
return LocalDateTime.of(dt, this.point2LocalTime(point));
}
private Pair getDistanceAndDuration(double x1, double y1, double x2, double y2) {
Distance cal = new Distance();
long distance = Math.round(cal.calculateDistance(x1, y1, x2, y2) * 1.4); // 单位为米
long duration = distance / (19 * 1000 / 60); // 时间为分钟,假设电动车速度为19km/h
return new Pair((int) distance, (int) duration);
}
@Data
public static class OrderNode {
private String orderId;
private LocalDateTime planStartTime;
private LocalDateTime planEndTime;
private int takeTime;
private int arriveDistance;
private int arriveElapsed;
}
@Data
public class Result {
private int index;
private boolean isHead;
private boolean isTail;
private String curOrderId;
private String postOrderId;
private int additionDistance;
private int additionElapsed;
private OrderNode curOrderNode;
private OrderNode postOrderNode;
private OrderNode postOrderNodeOrg;
public Result(int index, boolean isHead, boolean isTail, String curOrderId, String postOrderId, int additionDistance, int additionElapsed, OrderNode curOrderNode, OrderNode postOrderNode, OrderNode postOrderNodeOrg) {
this.index = index;
this.isHead = isHead;
this.isTail = isTail;
this.curOrderId = curOrderId;
this.postOrderId = postOrderId;
this.additionDistance = additionDistance;
this.additionElapsed = additionElapsed;
this.curOrderNode = curOrderNode;
this.postOrderNode = postOrderNode;
this.postOrderNodeOrg = postOrderNodeOrg;
}
}
}
@Data
class OrderSegment {
private String orderId;
private int start;
private int end;
private double x;
private double y;
private int takeTime;
private int elapsed;
private int distance;
public OrderSegment() {
}
public OrderSegment(int start, int end, double x, double y, int takeTime, int elapsed, int distance) {
this.start = start;
this.end = end;
this.x = x;
this.y = y;
this.takeTime = takeTime;
this.elapsed = elapsed;
this.distance = distance;
}
private String orderId;
private int start;
private int end;
private double x;
private double y;
private int takeTime;
private int elapsed;
private int distance;
public OrderSegment() {
}
public OrderSegment(int start, int end, double x, double y, int takeTime, int elapsed, int distance) {
this.start = start;
this.end = end;
this.x = x;
this.y = y;
this.takeTime = takeTime;
this.elapsed = elapsed;
this.distance = distance;
}
}
@Data
class Pair {
private int distance;
private int duration;
private int distance;
private int duration;
public Pair(int distance, int duration) {
this.distance = distance;
this.duration = duration;
}
public Pair(int distance, int duration) {
this.distance = distance;
this.duration = duration;
}
}
......@@ -109,7 +109,7 @@ public class SaasUtils {
/**
* 根据提供的地址信息,获取对应的片区图层
*/
public List<AdministrativeDistrictResp> getAdminDistrict(AdministrativeDistrictReq districtReq) {
public AdministrativeDistrictResp getAdminDistrict(AdministrativeDistrictReq districtReq) {
String webResultStr = saasRemoteService.getAdminDistrict(ak, districtReq);
log.info("queryBlocksByXySingle返回结果: ===> {}", webResultStr);
SaasWebResult webResult = JSONObject.parseObject(webResultStr, SaasWebResult.class);
......@@ -117,8 +117,11 @@ public class SaasUtils {
if (!webResult.getCode().equals("S001")) {
return null;
}
List<AdministrativeDistrictResp> administrativeDistrictResp = JSONObject.parseObject(JSONObject.toJSONString(webResult.getResult()), List.class);
return administrativeDistrictResp;
List<AdministrativeDistrictResp> administrativeDistrictResp = JSONObject.parseArray(JSONObject.toJSONString(webResult.getResult()), AdministrativeDistrictResp.class);
if (CollectionUtils.isNotEmpty(administrativeDistrictResp)) {
return administrativeDistrictResp.get(0);
}
return null;
}
......
......@@ -4,6 +4,7 @@ import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dto.BusinessServiceBlockAddReqDTO;
import com.dituhui.pea.order.dto.BusinessServiceBlockRemoveReqDTO;
import com.dituhui.pea.order.dto.BusinessServiceBlockUpdateReqDTO;
import com.dituhui.pea.order.service.BusinessBlockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
......@@ -60,6 +61,25 @@ public class BusinessBlockController {
}
return res;
}
/**
* 更新saas区块id列表
*
* @param req::layerId 图层ID
* @param req::teamId 小队ID
* @return
*/
@PostMapping("/business/service/block/updateAreaIds")
public Result<?> businessServiceBlockUpdateAreaIds(@RequestBody BusinessServiceBlockUpdateReqDTO req) {
// 新增服务范围
Result<?> res = null;
try {
res = businessBlockService.businessServiceBlockUpdateAreaIds(req.getBlockId(), req.getAreaIds());
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
/**
* 新增服务区块
......
......@@ -33,7 +33,7 @@ public class FendanController {
}
@RequestMapping(value = "getAdminDistrict", method = RequestMethod.POST)
public Result<List<AdministrativeDistrictResp>> getAdminDistrict(@RequestBody AdministrativeDistrictReq req) {
public Result<AdministrativeDistrictResp> getAdminDistrict(@RequestBody AdministrativeDistrictReq req) {
return fendanService.getAdminDistrict(req);
}
}
......@@ -40,10 +40,12 @@ public class MsgController {
MsgQuery request) {
CommonUtil.setNullValue(request);
request.setUserId(userId);
if (!"isRead".equalsIgnoreCase(request.getSort())) {
request.setSort("create_time");
} else {
if ("isRead".equalsIgnoreCase(request.getSort())) {
request.setSort("is_read");
} if ("type".equalsIgnoreCase(request.getSort())) {
request.setSort("type");
} else {
request.setSort("create_time");
}
if (!"asc".equalsIgnoreCase(request.getSortType())) {
request.setSortType("desc");
......
......@@ -17,59 +17,57 @@ import java.time.LocalDateTime;
@RequestMapping("/pea-order")
public class OrderAssignController {
@Autowired
private OrderAssign orderAssign;
@Autowired
private OrderAssign orderAssign;
@GetMapping("/order/assign/recommend/engineers")
public Result<?> getOrderAssignRecommendEngineers(
@RequestParam String orderId, @RequestParam(required = false) String key,
@RequestParam(required = false) String distance, @RequestParam(required = false) String recommend) {
//服务单指派-推荐技术员列表
@GetMapping("/order/assign/recommend/engineers")
public Result<?> getOrderAssignRecommendEngineers(
@RequestParam String orderId, @RequestParam(required = false) String key,
@RequestParam(required = false) String distance, @RequestParam(required = false) String recommend) {
//服务单指派-推荐技术员列表
Result<?> res = null;
try {
res = orderAssign.getOrderAssignRecommendEngineers(orderId, key, distance, recommend);
}catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
Result<?> res = null;
try {
res = orderAssign.getOrderAssignRecommendEngineers(orderId, key, distance, recommend);
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
@PostMapping("/order/assign")
public Result<?> orderAssign(@RequestBody OrderAssignReq req) {
// 服务单指派-指派提交
Result<?> res = null;
try {
res = orderAssign.orderAssign(req.getOrderId(), req.getEngineerCode());
}catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
@PostMapping("/order/assign")
public Result<?> orderAssign(@RequestBody OrderAssignReq req) {
// 服务单指派-指派提交
Result<?> res = null;
try {
res = orderAssign.orderAssign(req);
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
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;
}
@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;
}
@PostMapping("/order/rescheduling")
public Result<?> orderRescheduling(@RequestBody OrderReschedule req){
// 订单改约
Result<?> res = null;
LocalDateTime expectBegin = TimeUtils.IsoDateTime2LocalDateTime(req.getExpectBegin());
LocalDateTime expectEnd = TimeUtils.IsoDateTime2LocalDateTime(req.getExpectEnd());
try{
res = orderAssign.orderReschedule(req.getOrderId(), expectBegin, expectEnd, req.getExpectDesc());
} catch (BusinessException e){
return Result.failed(e.getMessage());
}
return res;
}
@PostMapping("/order/rescheduling")
public Result<?> orderRescheduling(@RequestBody OrderReschedule req) {
// 订单改约
Result<?> res = null;
try {
res = orderAssign.orderReschedule(req);
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
}
......@@ -4,6 +4,7 @@ import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dto.OrderCreateReqDTO;
import com.dituhui.pea.order.dto.CapacityOrderQueryDTO;
import com.dituhui.pea.order.dto.param.OrderDTO;
import com.dituhui.pea.order.service.OrderCreateService;
import com.dituhui.pea.order.service.CapacityQueryService;
......@@ -22,7 +23,7 @@ public class OrderCreateController {
private CapacityQueryService capacityQueryService;
@PostMapping("/order/service/create")
public Result<?> createOrder(@Validated @RequestBody OrderCreateReqDTO orderCreateReqDTO) {
public Result<?> createOrder(@Validated @RequestBody OrderDTO.OrderCreateRequest orderCreateReqDTO) {
Result<?> res = null;
try {
res = orderCreateService.createOrder(orderCreateReqDTO);
......
......@@ -5,9 +5,11 @@ import com.dituhui.pea.order.common.jackson.DateUtil;
import com.dituhui.pea.order.common.jackson.JsonUtil;
import com.dituhui.pea.order.dto.param.*;
import com.dituhui.pea.order.service.EngineerCalendarService;
import com.dituhui.pea.order.service.OrderCreateService;
import com.dituhui.pea.order.service.PeaOuterAPIService;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
......@@ -30,6 +32,8 @@ public class PeaApiController {
private final EngineerCalendarService engineerCalendarService;
private final PeaOuterAPIService peaOuterAPIService;
@Autowired
private OrderCreateService orderCreateService;
private static final String capacity = "{\"groupId\": \"G100038\", \"params\": {\"beginDate\": \"2023-07-21\", \"endDate\": \"2023-07-27\", \"services\": [{\"brand\": \"博世\", \"productType\": \"多门冰箱\", \"serviceType\": \"商场样机安装\"}], \"location\": {\"addressId\":\"21231231\", \"latitude\": 120.608463, \"longitude\": 31.318442, \"name\": \"江苏省苏州市姑苏区蒋庙前\", \"address\": \"江苏省苏州市姑苏区解放大街123号\"}}, \"takeTime\": 720, \"datas\": [{\"date\": \"2023-07-21\", \"segments\": [{\"maxDuration\": 90, \"name\": \"全天\", \"beginTime\": \"2023-07-21 08:00:00\", \"endTime\": \"2023-07-21 17:59:59\", \"status\": 1, \"remain\": 3500}, {\"maxDuration\": 45, \"name\": \"上午\", \"beginTime\": \"2023-07-21 08:00:00\", \"endTime\": \"2023-07-21 11:59:59\", \"status\": 1, \"remain\": 2500}, {\"maxDuration\": 60, \"name\": \"下午\", \"beginTime\": \"2023-07-21 13:00:00\", \"endTime\": \"2023-07-21 17:59:59\", \"status\": 0, \"remain\": 1000}, {\"maxDuration\": 60, \"name\": \"时间段\", \"beginTime\": \"2023-07-21 13:00:00\", \"endTime\": \"2023-07-21 15:00:00\", \"status\": 1, \"remain\": 480}]}]}";
......@@ -113,7 +117,7 @@ public class PeaApiController {
@RequestParam("beginDate") Date beginDate,
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
Date endDate) throws IOException {
Date endDate) throws IOException {
ArrayList<String> strings = new ArrayList<>();
strings.add(half_capacity);
......@@ -160,8 +164,7 @@ public class PeaApiController {
*/
@PostMapping("/order/create")
public Result<?> orderCreate(@Validated @RequestBody OrderDTO.OrderCreateRequest request) {
return Result.success(null);
return orderCreateService.createOrder(request);
}
......
......@@ -24,8 +24,11 @@ public interface MapBlockInfoDao extends JpaRepository<MapBlockInfoEntity, Integ
List<MapBlockInfoEntity> findByAreaIdsIn(List<String> blockIds);
@Query(value = "select mbi.* from map_block_info mbi left join skill_info si on mbi.layer_id = si.layer_id left join map_layer_customize mlc on mlc.layer_id = mbi.layer_id " +
"where si.brand = :brand and si.`type` = :productType and si.skill = :skill and mbi.area_ids in ( :blockIds ) order by mlc.priority ", nativeQuery = true)
List<MapBlockInfoEntity> listTeamIdByBrandAndSkillAndBlockIds(@Param("brand") String brand, @Param("productType") String productType,
@Param("skill") String skill, @Param("blockIds") List<String> blockIds);
List<MapBlockInfoEntity> findByAreaIdsLike(String blockId);
@Query(value = "select mbi.* from map_block_info mbi left join map_layer_customize_skill mlcs on mlcs.layer_id = mbi.layer_id " +
"left join map_layer_customize mlc on mlc.layer_id = mbi.layer_id left join skill_info si on si.skill_code = mlcs.skill_code " +
"where si.brand = :brand and si.`type` = :productType and si.skill = :skill order by mlc.priority ", nativeQuery = true)
List<MapBlockInfoEntity> listTeamIdByBrandAndSkill(@Param("brand") String brand, @Param("productType") String productType,
@Param("skill") String skill);
}
......@@ -16,7 +16,7 @@ import java.util.Objects;
public interface MsgDao extends JpaRepository<MsgEntity, Integer> {
@Query(value = "select t.cluster_id,t.branch_id,t.group_id" +
" from (" +
" select tt.cluster_id,tt.branch_id,tt.group_id,min(tt.create_time) create_time,min(r.is_read) is_read" +
" select tt.cluster_id,tt.branch_id,tt.group_id,min(tt.create_time) create_time,min(r.is_read) is_read,min(tt.type) type" +
" from zzz_msg tt join zzz_msg_receiver r on r.msg_id=tt.id and r.user_id=:#{#req.userId}" +
" where IF(:#{#req.startDate} is not null, tt.create_time>=:#{#req.startDate}, 1=1)" +
" and IF(:#{#req.endDate} is not null, tt.create_time<:#{#req.endDate}, 1=1)" +
......@@ -28,7 +28,7 @@ public interface MsgDao extends JpaRepository<MsgEntity, Integer> {
") t",
countQuery = "select count(t.cluster_id)" +
" from (" +
" select tt.cluster_id,tt.branch_id,tt.group_id,min(tt.create_time) create_time,min(r.is_read) is_read" +
" select tt.cluster_id,tt.branch_id,tt.group_id,min(tt.create_time) create_time,min(r.is_read) is_read,min(tt.type) type" +
" from zzz_msg tt join zzz_msg_receiver r on r.msg_id=tt.id and r.user_id=:#{#req.userId}" +
" where IF(:#{#req.startDate} is not null, tt.create_time>=:#{#req.startDate}, 1=1)" +
" and IF(:#{#req.endDate} is not null, tt.create_time<:#{#req.endDate}, 1=1)" +
......
......@@ -34,7 +34,7 @@ public interface OrderInfoDao extends JpaRepository<OrderInfoEntity, Long>, JpaS
List<OrderInfoEntity> findByServiceStatusAndEngineerCode(String serviceStatus, String engineerCode);
List<OrderInfoEntity> findByDtAndAddressId(String dt, String addressId);
List<OrderInfoEntity> findByDtAndAddressId(LocalDate dt, String addressId);
List<OrderInfoEntity> findByMultipleOrders(String multipleOrders);
}
......@@ -41,4 +41,6 @@ public interface OrgGroupDao extends JpaRepository<OrgGroupEntity, Integer> {
@Query(value = "SELECT og.* FROM org_group og left join org_team ot ON ot.group_id = og.group_id "
+ "WHERE ot.team_id = :teamId",nativeQuery = true)
OrgGroupEntity queryGroupByTeam(String teamId);
OrgGroupEntity getByCitycodeListLike(String citycodeList);
}
......@@ -15,14 +15,16 @@ public class BusinessServerBlocksRespDTO {
@Data
public static class Block {
private String id;
private Integer id;
private String areaIds;
private String groupId;
private String groupName;
private String layerId;
private String layerName;
private String teamId;
private String teamName;
private String area;
private Integer areaCount;
private String saasUrl;
private String updateTime;
}
}
package com.dituhui.pea.order.dto;
import lombok.Data;
@Data
public class BusinessServiceBlockUpdateReqDTO {
private String blockId;
private String areaIds;
}
......@@ -29,7 +29,7 @@ public class MsgQuery {
private String userId;
/**
* 排序字段:create_time、is_read
* 排序字段:createTime、isRead、type
*/
private String sort;
......
......@@ -4,6 +4,11 @@ import lombok.Data;
@Data
public class OrderAssignReq {
private String engineerCode;
private String orderId;
private String engineerCode;
private String orderId;
/**
* 操作员
*/
private String operator;
}
......@@ -8,4 +8,9 @@ public class OrderReschedule {
private String expectBegin;
private String expectEnd;
private String expectDesc;
/**
* 操作员
*/
private String operator;
}
package com.dituhui.pea.order.dto.param;
import com.dituhui.pea.util.DateUtil;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
......@@ -101,6 +104,11 @@ public class OrderDTO {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date expectEnd;
public static void main(String[] args) {
Date date = new Date();
int hour = DateUtils.toCalendar(date).get(Calendar.HOUR_OF_DAY);
System.out.println("当前小时为:" + hour);
}
/**
* 预约描述时间(全天/上午/下午)
*/
......
......@@ -14,7 +14,7 @@ public class MapBlockInfoEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "area_ids", length = 1024, nullable = false)
@Column(name = "saas_area_ids", length = 1024)
private String areaIds;
@Column(name = "area_name", length = 50, nullable = false)
......@@ -32,7 +32,7 @@ public class MapBlockInfoEntity {
@Column(name = "city_code", nullable = true)
private String cityCode;
@Column(name = "areaCount")
@Column(name = "area_count")
private Long areaCount;
@Column(name = "area_data", nullable = true, columnDefinition = "json")
......@@ -47,11 +47,14 @@ public class MapBlockInfoEntity {
@Column(name = "layer_name", length = 50, nullable = false)
private String layerName;
@Column(name = "saas_layercode", length = 50, nullable = false)
@Column(name = "saas_layercode", length = 50)
private String saasLayercode;
@Column(name = "saas_layer_id", length = 50, nullable = false)
private String saasLayerName;
@Column(name = "saas_layer_id", length = 50)
private String saasLayerId;
@Column(name = "saas_url", length = 512)
private String saasUrl;
@Column(nullable = false)
private Boolean status;
......
package com.dituhui.pea.order.entity;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import lombok.Data;
import javax.persistence.*;
......@@ -131,7 +132,7 @@ public class OrderInfoEntity {
private String orderStatus = "NORMAL";
@Column(name = "service_status", nullable = true, length = 20, columnDefinition = "varchar(20) default 'INIT'")
private String serviceStatus = "INIT";
private String serviceStatus = OrderFlowEnum.INIT.name();
@Column(name = "engineer_code", nullable = true, length = 32, columnDefinition = "varchar(32) default ''")
private String engineerCode = "";
......@@ -217,7 +218,7 @@ public class OrderInfoEntity {
* 是否超派,0否 1是,默认0
*/
@Column(name = "transcend")
private Integer transcend;
private Integer transcend = 0;
/**
......
package com.dituhui.pea.order.enums;
/**
* 订单流程枚举类
*/
public enum OrderFlowEnum {
// 指派状态: INIT-待指派/PRE-预指派/CONFIRM-确认指派(通知BEAN)
INIT, PRE, CONFIRM,
}
package com.dituhui.pea.order.enums;
public enum OrderStatus {
CREATE("创建订单"),
NORMAL("正常"),
CANCELED("已取消"),
RESCHEDULED("已改约");
RESCHEDULED("已改约"),
ASSIGN("工单指派");
private final String description;
OrderStatus(String description){
......
package com.dituhui.pea.order.enums;
public enum ServiceStatus {
// 服务状态:INIT-初始化/PENDING待服务/CONTACTED已排期/STARTED-已开始/FINISHED已完成/UNFINISHED-已上门未完成
INIT("待服务"),
PENDING("待服务"),
CONTACTED("已排期"),
......
......@@ -7,6 +7,15 @@ public interface BusinessBlockService {
Result<?> businessServerBlocks(String levelType, String levelValue, int page, int size, String layerId, String teamId);
Result<?> businessServiceBlockAdd(String layerId, String teamId);
/**
* 更新saas区块id
*
* @param blockId
* @param areaIds
* @return
*/
Result<?> businessServiceBlockUpdateAreaIds(String blockId, String areaIds);
Result<?> businessServiceBlockRemove(String blockId);
......
......@@ -27,5 +27,5 @@ public interface FendanService {
*/
Result<List<OrgGroupInfo>> fendanToGroup(OrderDTO.OrderCreateRequest request);
Result<List<AdministrativeDistrictResp>> getAdminDistrict(AdministrativeDistrictReq req);
Result<AdministrativeDistrictResp> getAdminDistrict(AdministrativeDistrictReq req);
}
package com.dituhui.pea.order.service;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dto.OrderAssignReq;
import com.dituhui.pea.order.dto.OrderReschedule;
import org.bouncycastle.asn1.cms.TimeStampAndCRL;
import java.sql.Timestamp;
......@@ -13,9 +15,9 @@ public interface OrderAssign {
Result<?> getOrderAssignRecommendEngineers(String orderId, String key, String distance, String recommend);
// 服务单指派-指派提交
Result<?> orderAssign(String orderId, String engineerCode);
Result<?> orderAssign(OrderAssignReq req);
Result<?> orderRevokeAssign(String orderId);
Result<?> orderReschedule(String orderId, LocalDateTime expectBegin, LocalDateTime expectEnd, String expectDesc);
Result<?> orderReschedule(OrderReschedule req);
}
......@@ -19,12 +19,13 @@ package com.dituhui.pea.order.service;
import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dto.OrderCreateReqDTO;
import com.dituhui.pea.order.dto.param.OrderDTO;
public interface OrderCreateService {
Result<?> initParameter();
Result<?> createOrder(OrderCreateReqDTO orderCreateReqDTO)
Result<?> createOrder(OrderDTO.OrderCreateRequest orderCreateReqDTO)
throws BusinessException;
}
......@@ -2,6 +2,8 @@ package com.dituhui.pea.order.service;
import com.dituhui.pea.common.Result;
import java.time.LocalDate;
/**
* 订单相关
*/
......@@ -14,7 +16,7 @@ public interface OrderInfoService {
* @param addressId 地址id
* @return 有则返回多条订单关联id,没有则不是一家多单
*/
Result<String> addMultipleOrders(String dt, String addressId);
Result<String> addMultipleOrders(LocalDate dt, String addressId, String orderId);
/**
* 取消指定订单一家多台
......
......@@ -10,8 +10,9 @@ import com.dituhui.pea.order.dto.BusinessServerBlocksRespDTO;
import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.feign.ISaaSRemoteService;
import com.dituhui.pea.order.service.BusinessBlockService;
import com.dituhui.pea.order.utils.RegionUtils;
import com.dituhui.pea.order.utils.TypeUtils;
import com.google.gson.internal.LinkedTreeMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -38,6 +39,10 @@ public class BusinessBlockServiceImpl implements BusinessBlockService {
String ak;
@Value("${SaaS.url}")
String url;
@Value("${SaaS.userAccount}")
String userAccount;
@Value("${SaaS.userPassword}")
String password;
@Autowired
private OrgTeamDao orgTeamDao;
@Autowired
......@@ -120,14 +125,25 @@ public class BusinessBlockServiceImpl implements BusinessBlockService {
String groupId = team.getGroupId();
String groupName = groupMapping.get(groupId);
block.setId(b.getAreaIds());
block.setId(b.getId());
block.setAreaIds(b.getAreaIds());
if (StringUtils.isNotBlank(b.getAreaIds())) {
block.setAreaCount(b.getAreaIds().split(",").length);
} else {
block.setAreaCount(0);
}
block.setGroupId(groupId);
block.setGroupName(groupName);
block.setLayerId(b.getLayerId());
block.setLayerName(b.getLayerName());
block.setTeamId(b.getTeamId());
block.setTeamName(team.getTeamName());
// block.setArea(b.getArea().toString());
// 组装url
String saasUrl = url + "/mlAutoLogin?userAccount=" + userAccount + "&password=" + password
+ "&jump=basedata&navHidden=true&layerId=" + StringUtils.trimToEmpty(b.getSaasLayerId())
+ "&layercode=" + StringUtils.trimToEmpty(b.getSaasLayercode()) + "&area_ids="
+ StringUtils.trimToEmpty(b.getAreaIds());
block.setSaasUrl(saasUrl);
if(null != b.getUpdateTime()) {
block.setUpdateTime(TimeUtils.IsoLocalDateTime2String(b.getUpdateTime()));
}
......@@ -170,31 +186,24 @@ public class BusinessBlockServiceImpl implements BusinessBlockService {
// 重复检查layerId+teamId 注意:1个小队可以对应多个图层
MapBlockInfoEntity existBlock = mapBlockInfoDao.findByTeamIdAndLayerId(teamId, layerId);
if (null != existBlock) {
return Result.failure("区块已存在");
return Result.failure("该工作队图层服务范围已存在");
}
// 同步到saas,返回blockId
// 获取小队出发点,初始化区块
OrgGroupEntity group = orgGroupDao.getByGroupId(team.getGroupId());
String center = RegionUtils.constructCenter(group.getX(), group.getY());
// 获取saas图层id
String saasLayerId = getSaaSLayerId(team.getBranchId(), layerId);
if (StringUtils.isEmpty(saasLayerId)) {
return Result.failure(team.getTeamName() + " 图层未配置");
}
String result = saasRemoteService.addArea(ak, team.getTeamName(), saasLayerId, center);
log.info("params:{} {} {} {} result:{}", team.getTeamName(), saasLayerId, center, result);
Result<String> saasResult = TypeUtils.convertResult(result);
// 同步初始化saas区划图层,图层命名方式:分部id_图层id,先检查一下图层是否存在,不存在则新建。FIXME saas处理逻辑
String saasLayerName = team.getBranchId() + "_" + layerId;
String result = saasRemoteService.addLayer(ak, saasLayerName, 1, 1);
log.info("addLayer params:{} result:{}", layerName, result);
System.out.println(result);
Result<LinkedTreeMap<String, Object>> saasResult = TypeUtils.convertResult(result);
if (!ResultEnum.SUCCESS.getCode().equals(saasResult.getCode())) {
return Result.failure("区块已存在或者裁剪为空");
return Result.failure(saasResult.getMessage());
}
String blockId = saasResult.getResult();
String blockName = String.format("%s_%s", layerName, team.getTeamName()); //区块名称
// 返回layerid和code
String saasLayerId = (String) saasResult.getResult().get("id");// 存入pea
String saasLayercode = (String) saasResult.getResult().get("code");// 存入pea
MapBlockInfoEntity block = new MapBlockInfoEntity();
block.setAreaIds(blockId);
String blockName = String.format("%s_%s", layerName, team.getTeamName()); //区块名称
block.setAreaName(blockName);
block.setBranchId(team.getBranchId());
block.setGroupId(team.getGroupId());
......@@ -202,7 +211,9 @@ public class BusinessBlockServiceImpl implements BusinessBlockService {
block.setLayerId(layerId);
block.setLayerName(layerName);
block.setStatus(true);
//block.setArea(0L);
block.setAreaCount(0L);
block.setSaasLayerId(saasLayerId);
block.setSaasLayercode(saasLayercode);
block.setCreateTime(LocalDateTime.now());
block.setUpdateTime(block.getCreateTime());
entityManager.persist(block);
......@@ -210,6 +221,24 @@ public class BusinessBlockServiceImpl implements BusinessBlockService {
return Result.success(null);
}
@Transactional
@Override
public Result<?> businessServiceBlockUpdateAreaIds(String blockId, String areaIds) throws BusinessException {
MapBlockInfoEntity block = mapBlockInfoDao.getById(Integer.parseInt(blockId));
if (null != block) {
block.setAreaIds(areaIds);
if (StringUtils.isBlank(areaIds)) {
block.setAreaCount(0L);
} else {
block.setAreaCount((long) areaIds.split(",").length);
}
}
mapBlockInfoDao.save(block);
mapBlockInfoDao.flush();
return Result.success(null);
}
/**
* 获取saas图层id
*
......@@ -262,10 +291,6 @@ public class BusinessBlockServiceImpl implements BusinessBlockService {
throw new BusinessException("区块不存在");
}
// TODO 根据当前block转换成分部,再转换成对应账号信息
String userAccount = "sMvf3yZWA69lKcvlgKcOHQ==";
String password = "qjOHxpQPXLnJP+Jq1CZGBQ==";
// 跳转SaaS url
// 获取saas图层id
String saasLayerId = getSaaSLayerId(block.getBranchId(), block.getLayerId());
......
......@@ -10,6 +10,7 @@ import com.dituhui.pea.order.dto.DispatchEngineerOrderListResp;
import com.dituhui.pea.order.dto.DispatchOrderListReq;
import com.dituhui.pea.order.dto.DispatchOrderListResp;
import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.enums.OrderGroupEnum;
import com.dituhui.pea.order.enums.OrderStatus;
import com.dituhui.pea.order.service.DispatchService;
......@@ -298,7 +299,7 @@ public class DispatchServiceImpl implements DispatchService {
Root<OrderInfoEntity> root = update.from(OrderInfoEntity.class);
update.set(root.get("planStartTime"), planStartTime);
update.set(root.get("planEndTime"), planEndTime);
update.set(root.get("appointmentStatus"), "CONFIRM");
update.set(root.get("appointmentStatus"), OrderFlowEnum.CONFIRM.name());
update.set(root.get("appointmentMethod"), "MANUAL");
update.set(root.get("engineerCode"), engineerCode);
update.where(
......@@ -441,7 +442,7 @@ public class DispatchServiceImpl implements DispatchService {
List<Predicate> predicates = new ArrayList<>();
predicates.add(criteriaBuilder.equal(root.get("dt"), TimeUtils.IsoDate2LocalDate(reqDTO.getDate())));
predicates.add(criteriaBuilder.equal(root.get("appointmentStatus"), "INIT"));
predicates.add(criteriaBuilder.equal(root.get("appointmentStatus"), OrderFlowEnum.INIT.name()));
String levelType = reqDTO.getLevelType();
String levelValue = reqDTO.getLevelValue();
......@@ -775,7 +776,7 @@ class OrderRequestScheduler {
List<Line> newTasks = new ArrayList<>();
for (OrderInfoEntity o : orderRequests) {
if (!o.getAppointmentStatus().equals("INIT")) {
if (!o.getAppointmentStatus().equals(OrderFlowEnum.INIT.name())) {
continue;
}
Line t = new Line(o.getOrderId(), 30);
......
......@@ -7,6 +7,7 @@ import com.dituhui.pea.order.dao.*;
import com.dituhui.pea.order.dto.EngineersGanttDTO;
import com.dituhui.pea.order.dto.LabelValueDTO;
import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.service.EngineerGanttService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
......@@ -84,7 +85,7 @@ public class EngineerGanttServiceImpl implements EngineerGanttService {
slots = new ArrayList<>();
}
slot.setBgColor(getColor(order.getServiceStatus()));
if (!order.getAppointmentStatus().equals("CONFIRM")) {
if (!order.getAppointmentStatus().equals(OrderFlowEnum.CONFIRM.name())) {
slot.setBorderStyle("dashed"); // 未确认的指派,统一加上虚框
}
slots.add(slot);
......
......@@ -12,6 +12,7 @@ import com.dituhui.pea.order.entity.OrderEventEntity;
import com.dituhui.pea.order.entity.OrderInfoEntity;
import com.dituhui.pea.order.entity.OrgGroupEntity;
import com.dituhui.pea.order.entity.OrgWarehouseInfoEntity;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.service.EngineerTimelineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -88,7 +89,7 @@ public class EngineerTimelineServiceImpl implements EngineerTimelineService {
private List<OrderInfoEntity> selectEngineerOrders(String engineerCode, LocalDate dt){
List<OrderInfoEntity> orders = orderInfoDao.findByEngineerCodeAndDtAndAppointmentStatusIn(
engineerCode, dt, List.of("PRE", "CONFIRM"));
engineerCode, dt, List.of(OrderFlowEnum.PRE.name(), OrderFlowEnum.CONFIRM.name()));
return orders.stream().filter(o -> !o.getOrderStatus().equals("CANCEL")).collect(Collectors.toList());
}
......
......@@ -153,18 +153,23 @@ public class FendanServiceImpl implements FendanService {
//2:根据服务范围匹配工作队
String peaBrand = fixBrand(request.getBrand());
List<String> blockIds = blockInfos.stream().map(SaasUtils.BlockInfo::getBlockId).distinct().collect(Collectors.toList());
//区划所在范围并分配到具体技能的工作队
List<MapBlockInfoEntity> mapBlockInfoList = mapBlockInfoDao.listTeamIdByBrandAndSkillAndBlockIds(peaBrand, request.getProductType(), request.getServiceType(), blockIds);
List<MapBlockInfoEntity> mapBlockInBlockIdsList = new ArrayList<>();
//区划所在范围所有工作队
List<MapBlockInfoEntity> mapBlockInBlockIdsList = mapBlockInfoDao.findByAreaIdsIn(blockIds);
if (CollectionUtils.isEmpty(mapBlockInfoList) && CollectionUtils.isEmpty(mapBlockInBlockIdsList)) {
for (String blockId : blockIds) {
List<MapBlockInfoEntity> mapBlockInfoEntities = mapBlockInfoDao.findByAreaIdsLike(blockId);
mapBlockInBlockIdsList.addAll(mapBlockInfoEntities);
}
//区划所在范围并分配到具体技能的工作队
List<MapBlockInfoEntity> mapBlockSkillList = mapBlockInfoDao.listTeamIdByBrandAndSkill(peaBrand, request.getProductType(), request.getServiceType());
if (CollectionUtils.isEmpty(mapBlockSkillList) && CollectionUtils.isEmpty(mapBlockInBlockIdsList)) {
return Result.failed(StatusCodeEnum.FENDAN_TEAM_UNMATCHED);
}
List<Integer> mapBlockIdList = mapBlockInfoList.stream().map(MapBlockInfoEntity::getId).distinct().collect(Collectors.toList());
//筛选漏选工作队(处理全技能图层)
List<Integer> mapBlockAllList = mapBlockSkillList.stream().map(MapBlockInfoEntity::getId).distinct().collect(Collectors.toList());
//筛选漏选工作队(处理全技能图层)和查出多余图层
List<MapBlockInfoEntity> mapBlockInfoList = new ArrayList<>();
for (MapBlockInfoEntity mapBlockInfoEntity : mapBlockInBlockIdsList) {
if (mapBlockIdList.contains(mapBlockInfoEntity.getId())) {
continue;
if (mapBlockAllList.contains(mapBlockInfoEntity.getId())) {
mapBlockInfoList.add(mapBlockInfoEntity);
}
if (mapBlockInfoEntity.getLayerId().equals(allLayerId)) {
mapBlockInfoList.add(mapBlockInfoEntity);
......@@ -203,8 +208,9 @@ public class FendanServiceImpl implements FendanService {
}
@Override
public Result<List<AdministrativeDistrictResp>> getAdminDistrict(AdministrativeDistrictReq req) {
return Result.success(saasUtils.getAdminDistrict(req));
public Result<AdministrativeDistrictResp> getAdminDistrict(AdministrativeDistrictReq req) {
AdministrativeDistrictResp adminDistrict = saasUtils.getAdminDistrict(req);
return Result.success(adminDistrict);
}
......
......@@ -3,15 +3,18 @@ package com.dituhui.pea.order.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.common.ResultEnum;
import com.dituhui.pea.enums.StatusCodeEnum;
import com.dituhui.pea.order.common.OrderAssignCheck;
import com.dituhui.pea.order.common.TimeUtils;
import com.dituhui.pea.order.dao.*;
import com.dituhui.pea.order.dto.LabelValueDTO;
import com.dituhui.pea.order.dto.OrderAssignRecommendResp;
import com.dituhui.pea.order.dto.TimeLineDTO;
import com.dituhui.pea.order.dto.*;
import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.enums.OrderStatus;
import com.dituhui.pea.order.service.CommonService;
import com.dituhui.pea.order.service.OrderAssign;
import com.dituhui.pea.order.service.OrderInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -34,231 +37,252 @@ import java.util.stream.Collectors;
@Slf4j
public class OrderAssignImpl implements OrderAssign {
@Autowired
private OrderInfoDao orderInfoDao;
@Autowired
private OrderInfoDao orderInfoDao;
@Autowired
private EngineerInfoDao engineerInfoDao;
@Autowired
private EngineerInfoDao engineerInfoDao;
@Autowired
private CommonService commonService;
@Autowired
private OrderAssignCheck orderAssignCheck;
@Autowired
private OrgTeamDao orgTeamDao;
@Autowired
private OrgTeamEngineerDao orgTeamEngineerDao;
@Autowired
private SkillInfoDao skillInfoDao;
@Autowired
private EngineerSkillGroupDao engineerSkillGroupDao;
@Autowired
private EntityManager entityManager;
@Transactional
@Override
public Result<?> getOrderAssignRecommendEngineers(String orderId, String key, String distance, String recommend) {
// 服务单指派-推荐技术员列表
OrderInfoEntity order = orderInfoDao.getByOrderId(orderId);
if (order == null) {
throw new BusinessException("订单不存在");
}
String date = TimeUtils.IsoLocalDate2String(order.getDt());
// 获取符合筛选条件的技术员
List<String> engineerCodes = this.searchEngineerCodes(order, distance, key, recommend);
List<EngineerInfoEntity> engineers = engineerInfoDao.findByEngineerCodeIn(engineerCodes);
List<OrderAssignRecommendResp.Engineer> items = new ArrayList<>();
for (EngineerInfoEntity engineer : engineers) {
OrderAssignCheck.Result result = orderAssignCheck.orderAssignCheck(orderId, order.getDt(), engineer.getEngineerCode());
log.info("指派检查结果:{}", result);
if (result.getIndex() < 0) {
continue;
}
// 获取已技术员已指派订单列表
List<OrderInfoEntity> orderAppointments = orderInfoDao.findByEngineerCodeAndDtAndAppointmentStatusIn(
engineer.getEngineerCode(), order.getDt(), List.of("CONFIRM"));
// 获取订单tips
HashMap<String, List<LabelValueDTO>> orderTips = new HashMap<>();
List<String> orderIds = orderAppointments.stream().map(OrderInfoEntity::getOrderId).collect(Collectors.toList());
if (!orderIds.isEmpty()) {
List<OrderInfoEntity> orders = orderInfoDao.findAllByDtAndOrderIdIn(order.getDt(), orderIds);
orderTips = this.packOrderTips(orders);
}
OrderAssignRecommendResp.Engineer item = new OrderAssignRecommendResp.Engineer();
OrderAssignRecommendResp.InsertInfo insertInfo = new OrderAssignRecommendResp.InsertInfo();
insertInfo.setNumber(String.format("%d/%d", result.getIndex(), orderAppointments.size() + 1));
insertInfo.setTimeDesc(String.format("+%d分钟", result.getAdditionElapsed()));
insertInfo.setDistanceDesc(String.format("+%d公里", result.getAdditionDistance() / 1000));
item.setEngineerCode(engineer.getEngineerCode());
item.setEngineerName(engineer.getName());
item.setLocation(String.format("%s,%s", order.getX(), order.getY()));
item.setInsertInfo(insertInfo);
item.setDistanceDesc("");
item.setTimeDesc("");
int index = result.getIndex() + 1;
item.setDesc(String.format("将被插入在第%d单,受此影响原第%d单变化第%d单,第%d单将增加%d公里路程,比预计晚到%d分钟,建议调整;", index, index, index + 1, index + 1, result.getAdditionDistance() / 1000, result.getAdditionElapsed()));
item.setStartTime(String.format("%s 08:00:00", date));
item.setEndTime(String.format("%s 18:00:00", date));
item.setOrders(this.packTimelines(orderAppointments, orderTips));
items.add(item);
}
OrderAssignRecommendResp res = new OrderAssignRecommendResp();
res.setEngineers(items);
return Result.success(res);
}
@Transactional
@Override
public Result<?> orderAssign(String orderId, String engineerCode) throws BusinessException {
// 服务单指派-指派提交
OrderInfoEntity order = orderInfoDao.getByOrderId(orderId);
if (order == null) {
throw new BusinessException("订单不存在");
}
EngineerInfoEntity engineer = engineerInfoDao.getByEngineerCode(engineerCode);
boolean record = false;
OrderInfoEntity op = orderInfoDao.getByOrderIdAndDt(orderId, order.getDt());
if (op != null) {
record = true;
}
if (op != null && !order.getAppointmentStatus().equals("NOT_ASSIGNED") && op.getEngineerCode().equals(engineerCode)) {
throw new BusinessException(String.format("订单已指派个技术员[%s], 不必重复指派给同一个技术员", engineer.getName()));
}
OrderAssignCheck.Result result = orderAssignCheck.orderAssignCheck(orderId, order.getDt(), engineerCode);
log.info("指派检查结果:{}", result);
if (result.getIndex() < 0) {
throw new BusinessException("指派失败, 未能找到合适的时间段, 请选择其他技术员");
}
OrderAssignCheck.OrderNode insertNode = result.getCurOrderNode();
Timestamp planStartTime = Timestamp.valueOf(insertNode.getPlanStartTime());
Timestamp planEndTime = Timestamp.valueOf(insertNode.getPlanEndTime());
// 更新order_info表状态
String sql = "UPDATE OrderInfo e SET e.appointmentStatus = 'CONFIRM', e.appointmentMethod='MANUAL', e.planStartTime = :planStartTime, e.planEndTime = :panEndTime WHERE e.orderId = :orderId";
Query query = entityManager.createQuery(sql);
query.setParameter("planStartTime", planStartTime);
query.setParameter("planEndTime", planEndTime);
query.setParameter("orderId", orderId);
query.executeUpdate();
// 工单变更登记
commonService.addOrderEvent(orderId, "", "PEA-WEB", "API", "工单指派", "工单指派", "");
return Result.success(null);
}
@Override
public Result<?> orderRevokeAssign(String orderId) throws BusinessException {
// 放回工单池
OrderInfoEntity order = orderInfoDao.getByOrderId(orderId);
if (order == null) {
throw new BusinessException("订单不存在");
}
// 更新order_request表为未指派
order.setAppointmentStatus("INIT");
entityManager.merge(order);
// 操作员ID TODO-用户系统
// 登记事件
commonService.addOrderEvent(orderId, "", "PEA-WEB", "123", "放回工单池", "放回工单池", "");
return Result.success(null);
}
@Override
public Result<?> orderReschedule(String orderId, LocalDateTime expectBegin, LocalDateTime expectEnd, String expectDesc) throws BusinessException {
// 工单改约接口(当前同放回工单池处理)
OrderInfoEntity order = orderInfoDao.getByOrderId(orderId);
if (order == null) {
throw new BusinessException("订单不存在");
}
if (order.getDt().isEqual(expectBegin.toLocalDate())) {
throw new BusinessException("改约日期不应与之前日期相同");
}
if (LocalDate.now().isAfter(expectBegin.toLocalDate())) {
throw new BusinessException("改约日期不能小于今日");
}
LocalDate originDate = order.getDt(); // 改约前的日期
// 更新order_info表
String sql = "UPDATE OrderInfo e SET e.appointmentStatus = 'INIT', e.dt=:dt, e.expectTimeBegin = :expectTimeBegin, e.expectTimeEnd = :expectTimeEnd, e.expectTimeDesc = :expectTimeDesc WHERE e.orderId = :orderId";
Query query = entityManager.createQuery(sql);
query.setParameter("dt", expectBegin.toLocalDate());
query.setParameter("expectTimeBegin", expectBegin);
query.setParameter("expectTimeEnd", expectEnd);
query.setParameter("expectTimeDesc", expectDesc);
query.setParameter("orderId", orderId);
query.executeUpdate();
// 操作员ID TODO-用户系统
// 登记事件
commonService.addOrderEvent(orderId, "", "PEA-WEB", "123", "已改约", "已改约", "");
return Result.success(null);
}
private List<String> searchEngineerCodes(OrderInfoEntity order, String distance, String key, String recommend) {
Set<String> engineerCodes1 = this.searchEngineerByRecommend(order, recommend);
if (engineerCodes1.isEmpty()) {
log.info("recommend:{}筛选条件未找到技术员", recommend);
return new ArrayList<>();
}
if (StringUtils.isNotEmpty(key)) {
Set<String> engineerCodes2 = this.searchEngineerByKey(key);
if (engineerCodes2.isEmpty()) {
log.info("key:{}筛选条件未找到技术员", key);
return new ArrayList<>();
}
engineerCodes1.retainAll(engineerCodes2);
if (engineerCodes1.isEmpty()) {
log.info("recommend:{} 与 key:{}筛选条件交集未找到技术员", recommend, key);
return new ArrayList<>();
}
}
// 匹配技能
SkillInfoEntity skill = skillInfoDao.getByBrandAndTypeAndSkill(order.getBrand(), order.getType(), order.getSkill());
if (skill == null) {
log.info("skill_info表没有匹配到技能配置:{}-{}-{}", order.getBrand(), order.getY(), order.getSkill());
return new ArrayList<>();
}
Set<String> engineerCodes3 = engineerSkillGroupDao.findBySkillGroupCode(skill.getSkillGroupCode()).stream().map(
EngineerSkillGroupEntity::getEngineerCode).collect(Collectors.toSet());
if (engineerCodes3.isEmpty()) {
log.info("没有匹配到技能相匹配的技术员:{}-{}-{}", order.getBrand(), order.getType(), order.getSkill());
return new ArrayList<>();
}
engineerCodes1.retainAll(engineerCodes3);
if (engineerCodes1.isEmpty()) {
log.info("recommend:{} 与 key:{}筛选条件, 与技术员所需要的技能:{}-{}-{}交集未找到技术员", recommend, key, order.getBrand(), order.getType(), order.getSkill());
return new ArrayList<>();
}
@Autowired
private CommonService commonService;
@Autowired
private OrderAssignCheck orderAssignCheck;
@Autowired
private OrgTeamDao orgTeamDao;
@Autowired
private OrgTeamEngineerDao orgTeamEngineerDao;
@Autowired
private SkillInfoDao skillInfoDao;
@Autowired
private EngineerSkillGroupDao engineerSkillGroupDao;
@Autowired
private EntityManager entityManager;
@Autowired
private OrderInfoService orderInfoService;
@Transactional
@Override
public Result<?> getOrderAssignRecommendEngineers(String orderId, String key, String distance, String recommend) {
// 服务单指派-推荐技术员列表
OrderInfoEntity order = orderInfoDao.getByOrderId(orderId);
if (order == null) {
throw new BusinessException("订单不存在");
}
String date = TimeUtils.IsoLocalDate2String(order.getDt());
// 获取符合筛选条件的技术员
List<String> engineerCodes = this.searchEngineerCodes(order, distance, key, recommend);
List<EngineerInfoEntity> engineers = engineerInfoDao.findByEngineerCodeIn(engineerCodes);
List<OrderAssignRecommendResp.Engineer> items = new ArrayList<>();
for (EngineerInfoEntity engineer : engineers) {
OrderAssignCheck.Result result = orderAssignCheck.orderAssignCheck(orderId, order.getDt(), engineer.getEngineerCode());
log.info("指派检查结果:{}", result);
if (result.getIndex() < 0) {
continue;
}
// 获取已技术员已指派订单列表
List<OrderInfoEntity> orderAppointments = orderInfoDao.findByEngineerCodeAndDtAndAppointmentStatusIn(
engineer.getEngineerCode(), order.getDt(), List.of(OrderFlowEnum.CONFIRM.name()));
// 获取订单tips
HashMap<String, List<LabelValueDTO>> orderTips = new HashMap<>();
List<String> orderIds = orderAppointments.stream().map(OrderInfoEntity::getOrderId).collect(Collectors.toList());
if (!orderIds.isEmpty()) {
List<OrderInfoEntity> orders = orderInfoDao.findAllByDtAndOrderIdIn(order.getDt(), orderIds);
orderTips = this.packOrderTips(orders);
}
OrderAssignRecommendResp.Engineer item = new OrderAssignRecommendResp.Engineer();
OrderAssignRecommendResp.InsertInfo insertInfo = new OrderAssignRecommendResp.InsertInfo();
insertInfo.setNumber(String.format("%d/%d", result.getIndex(), orderAppointments.size() + 1));
insertInfo.setTimeDesc(String.format("+%d分钟", result.getAdditionElapsed()));
insertInfo.setDistanceDesc(String.format("+%d公里", result.getAdditionDistance() / 1000));
item.setEngineerCode(engineer.getEngineerCode());
item.setEngineerName(engineer.getName());
item.setLocation(String.format("%s,%s", order.getX(), order.getY()));
item.setInsertInfo(insertInfo);
item.setDistanceDesc("");
item.setTimeDesc("");
int index = result.getIndex() + 1;
item.setDesc(String.format("将被插入在第%d单,受此影响原第%d单变化第%d单,第%d单将增加%d公里路程,比预计晚到%d分钟,建议调整;", index, index, index + 1, index + 1, result.getAdditionDistance() / 1000, result.getAdditionElapsed()));
item.setStartTime(String.format("%s 08:00:00", date));
item.setEndTime(String.format("%s 18:00:00", date));
item.setOrders(this.packTimelines(orderAppointments, orderTips));
items.add(item);
}
OrderAssignRecommendResp res = new OrderAssignRecommendResp();
res.setEngineers(items);
return Result.success(res);
}
@Transactional
@Override
public Result<?> orderAssign(OrderAssignReq req) throws BusinessException {
// 服务单指派-指派提交
OrderInfoEntity order = orderInfoDao.getByOrderId(req.getOrderId());
if (order == null) {
throw new BusinessException("订单不存在");
}
EngineerInfoEntity engineer = engineerInfoDao.getByEngineerCode(req.getEngineerCode());
boolean record = false;
OrderInfoEntity op = orderInfoDao.getByOrderIdAndDt(req.getOrderId(), order.getDt());
if (op != null) {
record = true;
}
if (op != null && !order.getAppointmentStatus().equals("NOT_ASSIGNED") && op.getEngineerCode().equals(req.getEngineerCode())) {
throw new BusinessException(String.format("订单已指派个技术员[%s], 不必重复指派给同一个技术员", engineer.getName()));
}
// OrderAssignCheck.Result result = orderAssignCheck.orderAssignCheck(orderId, order.getDt(), engineerCode);
// log.info("指派检查结果:{}", result);
// if (result.getIndex() < 0) {
// throw new BusinessException("指派失败, 未能找到合适的时间段, 请选择其他技术员");
// }
// OrderAssignCheck.OrderNode insertNode = result.getCurOrderNode();
// Timestamp planStartTime = Timestamp.valueOf(insertNode.getPlanStartTime());
// Timestamp planEndTime = Timestamp.valueOf(insertNode.getPlanEndTime());
// 更新order_info表状态
// String sql = "UPDATE OrderInfo e SET e.appointmentStatus = 'CONFIRM', e.appointmentMethod='MANUAL', e.planStartTime = :planStartTime, e.planEndTime = :panEndTime WHERE e.orderId = :orderId";
// Query query = entityManager.createQuery(sql);
// query.setParameter("planStartTime", planStartTime);
// query.setParameter("planEndTime", planEndTime);
// query.setParameter("orderId", orderId);
// query.executeUpdate();
order.setEngineerCode(engineer.getEngineerCode());
orderInfoDao.save(order);
// 工单变更登记
commonService.addOrderEvent(req.getOrderId(), "", "PEA-WEB", req.getOperator(), OrderStatus.ASSIGN.getDescription(), OrderStatus.ASSIGN.getDescription(), "");
return Result.success(null);
}
@Override
public Result<?> orderRevokeAssign(String orderId) throws BusinessException {
// 放回工单池
OrderInfoEntity order = orderInfoDao.getByOrderId(orderId);
if (order == null) {
throw new BusinessException("订单不存在");
}
// 更新order_request表为未指派
order.setAppointmentStatus(OrderFlowEnum.INIT.name());
entityManager.merge(order);
// 操作员ID TODO-用户系统
// 登记事件
commonService.addOrderEvent(orderId, "", "PEA-WEB", "123", "放回工单池", "放回工单池", "");
return Result.success(null);
}
@Override
public Result<?> orderReschedule(OrderReschedule req) throws BusinessException {
// 工单改约接口(当前同放回工单池处理)
LocalDateTime expectBegin = TimeUtils.IsoDateTime2LocalDateTime(req.getExpectBegin());
LocalDateTime expectEnd = TimeUtils.IsoDateTime2LocalDateTime(req.getExpectEnd());
OrderInfoEntity order = orderInfoDao.getByOrderId(req.getOrderId());
if (order == null) {
throw new BusinessException("订单不存在");
}
if (order.getDt().isEqual(expectBegin.toLocalDate())) {
throw new BusinessException("改约日期不应与之前日期相同");
}
if (LocalDate.now().isAfter(expectBegin.toLocalDate())) {
throw new BusinessException("改约日期不能小于今日");
}
LocalDate originDate = order.getDt(); // 改约前的日期
// 更新order_info表
// String sql = "UPDATE OrderInfo e SET e.appointmentStatus = 'INIT', e.dt=:dt, e.expectTimeBegin = :expectTimeBegin, e.expectTimeEnd = :expectTimeEnd, e.expectTimeDesc = :expectTimeDesc WHERE e.orderId = :orderId";
// Query query = entityManager.createQuery(sql);
// query.setParameter("dt", expectBegin.toLocalDate());
// query.setParameter("expectTimeBegin", expectBegin);
// query.setParameter("expectTimeEnd", expectEnd);
// query.setParameter("expectTimeDesc", expectDesc);
// query.setParameter("orderId", orderId);
// query.executeUpdate();
order.setAppointmentStatus(OrderFlowEnum.INIT.name());
order.setDt(expectBegin.toLocalDate());
order.setExpectTimeBegin(expectBegin);
order.setExpectTimeEnd(expectEnd);
order.setExpectTimeDesc(req.getExpectDesc());
//处理一家多单逻辑
Result<String> deleteMultipleOrders = orderInfoService.deleteMultipleOrders(order.getMultipleOrders(), order.getAddressId());
if (!deleteMultipleOrders.getCode().equals(ResultEnum.SUCCESS.getCode())) {
throw new BusinessException("改约日期失败");
}
Result<String> multipleOrdersResult = orderInfoService.addMultipleOrders(expectBegin.toLocalDate(), order.getAddressId(), req.getOrderId());
if (!multipleOrdersResult.getCode().equals(ResultEnum.SUCCESS.getCode())) {
throw new BusinessException("改约日期失败");
}
order.setMultipleOrders(multipleOrdersResult.getResult());
orderInfoDao.save(order);
// 操作员ID TODO-用户系统
// 登记事件
commonService.addOrderEvent(req.getOrderId(), "", "PEA-WEB", req.getOperator(), OrderStatus.RESCHEDULED.getDescription(), OrderStatus.RESCHEDULED.getDescription(), "");
return Result.success(null);
}
private List<String> searchEngineerCodes(OrderInfoEntity order, String distance, String key, String recommend) {
Set<String> engineerCodes1 = this.searchEngineerByRecommend(order, recommend);
if (engineerCodes1.isEmpty()) {
log.info("recommend:{}筛选条件未找到技术员", recommend);
return new ArrayList<>();
}
if (StringUtils.isNotEmpty(key)) {
Set<String> engineerCodes2 = this.searchEngineerByKey(key);
if (engineerCodes2.isEmpty()) {
log.info("key:{}筛选条件未找到技术员", key);
return new ArrayList<>();
}
engineerCodes1.retainAll(engineerCodes2);
if (engineerCodes1.isEmpty()) {
log.info("recommend:{} 与 key:{}筛选条件交集未找到技术员", recommend, key);
return new ArrayList<>();
}
}
// 匹配技能
SkillInfoEntity skill = skillInfoDao.getByBrandAndTypeAndSkill(order.getBrand(), order.getType(), order.getSkill());
if (skill == null) {
log.info("skill_info表没有匹配到技能配置:{}-{}-{}", order.getBrand(), order.getY(), order.getSkill());
return new ArrayList<>();
}
Set<String> engineerCodes3 = engineerSkillGroupDao.findBySkillGroupCode(skill.getSkillGroupCode()).stream().map(
EngineerSkillGroupEntity::getEngineerCode).collect(Collectors.toSet());
if (engineerCodes3.isEmpty()) {
log.info("没有匹配到技能相匹配的技术员:{}-{}-{}", order.getBrand(), order.getType(), order.getSkill());
return new ArrayList<>();
}
engineerCodes1.retainAll(engineerCodes3);
if (engineerCodes1.isEmpty()) {
log.info("recommend:{} 与 key:{}筛选条件, 与技术员所需要的技能:{}-{}-{}交集未找到技术员", recommend, key, order.getBrand(), order.getType(), order.getSkill());
return new ArrayList<>();
}
/*
if (StringUtils.isEmpty(distance)) {
......@@ -267,91 +291,91 @@ public class OrderAssignImpl implements OrderAssign {
//进行距离匹配TODO
*/
return new ArrayList<>(engineerCodes1);
}
private Set<String> searchEngineerByRecommend(OrderInfoEntity order, String recommend) {
if (StringUtils.isNotEmpty(recommend) && recommend.equals("team")) {
return orgTeamEngineerDao.findAllByTeamId(order.getOrgTeamId()).stream().map(
OrgTeamEngineerEntity::getEngineerCode).collect(Collectors.toSet());
}
String levelType;
String levelValue;
if (StringUtils.isEmpty(recommend) || recommend.equals("branch")) {
levelType = "branch";
levelValue = order.getOrgBranchId();
} else if (recommend.equals("group")) {
levelType = "group";
levelValue = order.getOrgGroupId();
} else {
return new HashSet<>();
}
List<OrgTeamEntity> teams = new ArrayList<>();
if(levelType.equals("cluster")){
teams = orgTeamDao.findAllByClusterId(levelValue);
} else if (levelType.equals("branch")){
teams = orgTeamDao.findAllByBranchId(levelValue);
} else if (levelType.equals("group")){
teams = orgTeamDao.findAllByGroupId(levelValue);
} else if (levelType.equals("team")){
teams = orgTeamDao.findAllByTeamId(levelValue);
}
List<String> groupIds = teams.stream().map(OrgTeamEntity::getGroupId).collect(Collectors.toList());
return engineerInfoDao.findByGroupIdIn(groupIds).stream().map(EngineerInfoEntity::getEngineerCode).collect(Collectors.toSet());
}
private Set<String> searchEngineerByKey(String key) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<EngineerInfoEntity> criteriaQuery = criteriaBuilder.createQuery(EngineerInfoEntity.class);
Root<EngineerInfoEntity> root = criteriaQuery.from(EngineerInfoEntity.class);
Predicate predicate = criteriaBuilder.equal(root.get("beanStatus"), 1);
if (StringUtils.isNotEmpty(key)) {
Predicate keyPredicate = criteriaBuilder.or(
criteriaBuilder.like(root.get("phone"), "%" + key + "%"),
criteriaBuilder.like(root.get("name"), "%" + key + "%"),
criteriaBuilder.like(root.get("engineerCode"), "%" + key + "%")
);
predicate = criteriaBuilder.and(predicate, keyPredicate);
}
criteriaQuery.where(predicate);
CriteriaQuery<EngineerInfoEntity> selectQuery = criteriaQuery.select(root);
return entityManager.createQuery(selectQuery).getResultList().stream().map(
EngineerInfoEntity::getEngineerCode).collect(Collectors.toSet());
}
private List<TimeLineDTO> packTimelines(List<OrderInfoEntity> orders, HashMap<String, List<LabelValueDTO>> orderTips) {
List<LabelValueDTO> empty = new ArrayList<>();
List<TimeLineDTO> items = new ArrayList<>();
for (OrderInfoEntity order : orders) {
TimeLineDTO item = new TimeLineDTO();
item.setOrderId(order.getOrderId());
item.setAppointmentStatus(order.getAppointmentStatus());
item.setStartTime(TimeUtils.IsoLocalDateTime2String(order.getPlanStartTime()));
item.setEndTime(TimeUtils.IsoLocalDateTime2String(order.getPlanEndTime()));
item.setTips(orderTips.getOrDefault(order.getOrderId(), empty));
items.add(item);
}
return items;
}
private HashMap<String, List<LabelValueDTO>> packOrderTips(List<OrderInfoEntity> orders) {
return orders.stream().collect(Collectors.toMap(
OrderInfoEntity::getOrderId, this::packOrderTip, (l1, l2) -> l1, HashMap::new));
}
private List<LabelValueDTO> packOrderTip(OrderInfoEntity order) {
// pack订单tips
List<LabelValueDTO> items = new ArrayList<>();
items.add(new LabelValueDTO("类型/品牌", String.format("%s %s %s", order.getSkill(), order.getType(), order.getBrand())));
items.add(new LabelValueDTO("电话/地址", String.format("%s %s\n%s", order.getName(), order.getPhone(), order.getAddress())));
items.add(new LabelValueDTO("备注", order.getDescription()));
items.add(new LabelValueDTO("标签", order.getTags()));
return items;
}
return new ArrayList<>(engineerCodes1);
}
private Set<String> searchEngineerByRecommend(OrderInfoEntity order, String recommend) {
if (StringUtils.isNotEmpty(recommend) && recommend.equals("team")) {
return orgTeamEngineerDao.findAllByTeamId(order.getOrgTeamId()).stream().map(
OrgTeamEngineerEntity::getEngineerCode).collect(Collectors.toSet());
}
String levelType;
String levelValue;
if (StringUtils.isEmpty(recommend) || recommend.equals("branch")) {
levelType = "branch";
levelValue = order.getOrgBranchId();
} else if (recommend.equals("group")) {
levelType = "group";
levelValue = order.getOrgGroupId();
} else {
return new HashSet<>();
}
List<OrgTeamEntity> teams = new ArrayList<>();
if (levelType.equals("cluster")) {
teams = orgTeamDao.findAllByClusterId(levelValue);
} else if (levelType.equals("branch")) {
teams = orgTeamDao.findAllByBranchId(levelValue);
} else if (levelType.equals("group")) {
teams = orgTeamDao.findAllByGroupId(levelValue);
} else if (levelType.equals("team")) {
teams = orgTeamDao.findAllByTeamId(levelValue);
}
List<String> groupIds = teams.stream().map(OrgTeamEntity::getGroupId).collect(Collectors.toList());
return engineerInfoDao.findByGroupIdIn(groupIds).stream().map(EngineerInfoEntity::getEngineerCode).collect(Collectors.toSet());
}
private Set<String> searchEngineerByKey(String key) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<EngineerInfoEntity> criteriaQuery = criteriaBuilder.createQuery(EngineerInfoEntity.class);
Root<EngineerInfoEntity> root = criteriaQuery.from(EngineerInfoEntity.class);
Predicate predicate = criteriaBuilder.equal(root.get("beanStatus"), 1);
if (StringUtils.isNotEmpty(key)) {
Predicate keyPredicate = criteriaBuilder.or(
criteriaBuilder.like(root.get("phone"), "%" + key + "%"),
criteriaBuilder.like(root.get("name"), "%" + key + "%"),
criteriaBuilder.like(root.get("engineerCode"), "%" + key + "%")
);
predicate = criteriaBuilder.and(predicate, keyPredicate);
}
criteriaQuery.where(predicate);
CriteriaQuery<EngineerInfoEntity> selectQuery = criteriaQuery.select(root);
return entityManager.createQuery(selectQuery).getResultList().stream().map(
EngineerInfoEntity::getEngineerCode).collect(Collectors.toSet());
}
private List<TimeLineDTO> packTimelines(List<OrderInfoEntity> orders, HashMap<String, List<LabelValueDTO>> orderTips) {
List<LabelValueDTO> empty = new ArrayList<>();
List<TimeLineDTO> items = new ArrayList<>();
for (OrderInfoEntity order : orders) {
TimeLineDTO item = new TimeLineDTO();
item.setOrderId(order.getOrderId());
item.setAppointmentStatus(order.getAppointmentStatus());
item.setStartTime(TimeUtils.IsoLocalDateTime2String(order.getPlanStartTime()));
item.setEndTime(TimeUtils.IsoLocalDateTime2String(order.getPlanEndTime()));
item.setTips(orderTips.getOrDefault(order.getOrderId(), empty));
items.add(item);
}
return items;
}
private HashMap<String, List<LabelValueDTO>> packOrderTips(List<OrderInfoEntity> orders) {
return orders.stream().collect(Collectors.toMap(
OrderInfoEntity::getOrderId, this::packOrderTip, (l1, l2) -> l1, HashMap::new));
}
private List<LabelValueDTO> packOrderTip(OrderInfoEntity order) {
// pack订单tips
List<LabelValueDTO> items = new ArrayList<>();
items.add(new LabelValueDTO("类型/品牌", String.format("%s %s %s", order.getSkill(), order.getType(), order.getBrand())));
items.add(new LabelValueDTO("电话/地址", String.format("%s %s\n%s", order.getName(), order.getPhone(), order.getAddress())));
items.add(new LabelValueDTO("备注", order.getDescription()));
items.add(new LabelValueDTO("标签", order.getTags()));
return items;
}
}
\ No newline at end of file
......@@ -18,19 +18,28 @@ package com.dituhui.pea.order.service.impl;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.common.ResultEnum;
import com.dituhui.pea.order.common.*;
import com.dituhui.pea.order.dao.*;
import com.dituhui.pea.order.dto.LabelValueDTO;
import com.dituhui.pea.order.dto.LocationDTO;
import com.dituhui.pea.order.dto.OrderCreateReqDTO;
import com.dituhui.pea.order.dto.ParameterRespDTO;
import com.dituhui.pea.order.dto.*;
import com.dituhui.pea.order.dto.param.Location;
import com.dituhui.pea.order.dto.param.OrderDTO;
import com.dituhui.pea.order.dto.param.OrgGroupInfo;
import com.dituhui.pea.order.dto.param.OrgTeamInfo;
import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.service.CommonService;
import com.dituhui.pea.order.service.OrderCreateService;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.enums.OrderStatus;
import com.dituhui.pea.order.service.*;
import com.dituhui.pea.pojo.saas.req.AdministrativeDistrictReq;
import com.dituhui.pea.pojo.saas.resp.AdministrativeDistrictResp;
import com.dituhui.pea.util.DateUtil;
import io.seata.core.context.RootContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.weaver.ast.Var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
......@@ -38,6 +47,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
......@@ -79,6 +89,18 @@ public class OrderCreateServiceImpl implements OrderCreateService {
@Autowired
private SkillInfoDao skillInfoDao;
@Autowired
private FendanService fendanService;
@Autowired
private OrgGroupDao orgGroupDao;
@Autowired
private MsgService msgService;
@Autowired
private OrderInfoService orderInfoService;
private List<LabelValueDTO> getPriorities() {
String[] priorities = {"紧急", "正常"};
List<LabelValueDTO> listPriorities = new ArrayList<>();
......@@ -107,7 +129,7 @@ public class OrderCreateServiceImpl implements OrderCreateService {
@Override
@Transactional
public Result<?> createOrder(OrderCreateReqDTO req) {
public Result<?> createOrder(OrderDTO.OrderCreateRequest req) {
log.info("[createOrder] current XID: {}", RootContext.getXID());
OrderInfoEntity entity = new OrderInfoEntity();
String orderId = req.getOrderId();
......@@ -115,86 +137,102 @@ public class OrderCreateServiceImpl implements OrderCreateService {
String s = UUID.randomUUID().toString().replace("-", "");
orderId = s.substring(s.length() - 9);
}
entity.setSource("PEA");
// 分单处理
String peaBrand = fixBrand(req.getBrand());
// location
Location location = req.getLocation();
//获取省市区
AdministrativeDistrictReq administrativeDistrictReq = new AdministrativeDistrictReq();
administrativeDistrictReq.setPoints(location.getLongitude() + "," + location.getLatitude());
Result<AdministrativeDistrictResp> adminDistrict = fendanService.getAdminDistrict(administrativeDistrictReq);
if (ObjectUtil.isNotEmpty(adminDistrict) && ObjectUtil.isNotEmpty(adminDistrict.getResult())) {
entity.setProvince(adminDistrict.getResult().getSubNames().getProvince());
entity.setCity(adminDistrict.getResult().getSubNames().getCity());
entity.setCounty(adminDistrict.getResult().getSubNames().getCounty());
}
Result<List<OrgGroupInfo>> fendanResult = fendanService.fendanToGroup(req);
//todo 根据容量筛选出一个工作队,分单失败则存数据库然后发送消息
if (!fendanResult.getCode().equals(ResultEnum.SUCCESS.getCode()) || CollectionUtils.isEmpty(fendanResult.getResult())) {
OrgGroupEntity groupDaoByCitycodeListLike = orgGroupDao.getByCitycodeListLike(adminDistrict.getResult().getSubNames().getCounty());
entity.setOrgClusterId(groupDaoByCitycodeListLike.getClusterId());
entity.setOrgBranchId(groupDaoByCitycodeListLike.getBranchId());
entity.setOrgGroupId(groupDaoByCitycodeListLike.getGroupId());
//发送通知分部消息
MsgDTO msgDTO = new MsgDTO();
msgDTO.setGroupId(groupDaoByCitycodeListLike.getGroupId());
msgDTO.setType(0);
msgDTO.setOrderIds(orderId);
msgDTO.setContent("有1条预约日期在" + entity.getExpectTimeBegin().toLocalDate() + "的工单需人工外理");
msgService.add(msgDTO);
} else {
OrgTeamInfo teamInfo = fendanResult.getResult().get(0).getTeamInfos().get(0);
// 根据分单,填写clusterId/branchId/groupId/teamId等
entity.setOrgClusterId(teamInfo.getClusterId());
entity.setOrgBranchId(teamInfo.getBranchId());
entity.setOrgGroupId(teamInfo.getGroupId());
entity.setOrgTeamId(teamInfo.getTeamId());
//处理超派,特殊时间段
Integer startHourOrder = DateUtil.getHour(req.getExpectBegin());
Integer endHourOrder = DateUtil.getHour(req.getExpectEnd());
Integer startHourTeam = Integer.valueOf(teamInfo.getWorkOn().split(":")[0]);
Integer endHourTeam = Integer.valueOf(teamInfo.getWorkOff().split(":")[0]);
if (startHourOrder < startHourTeam || endHourOrder > endHourTeam) {
entity.setIsSpecialTime(1);
}
}
entity.setSource(req.getSource());
entity.setOrderId(orderId);
entity.setName(req.getName());
entity.setPhone(req.getPhone());
entity.setBeanBrand(req.getBrand());
String peaBrand = fixBrand(req.getBrand());
entity.setBrand(peaBrand);
entity.setType(req.getType());
entity.setSkill(req.getSkill());
entity.setType(req.getProductType());
entity.setSkill(req.getServiceType());
entity.setFaultDescribe(req.getFaultDescribe());
entity.setExpectTimeBegin(LocalDateTimeUtil.parse(req.getExpectBegin(), PATTERN_DATETIME));
entity.setExpectTimeEnd(LocalDateTimeUtil.parse(req.getExpectEnd(), PATTERN_DATETIME));
entity.setExpectTimeBegin(DateUtil.fromDate(req.getExpectBegin()));
entity.setExpectTimeEnd(DateUtil.fromDate(req.getExpectEnd()));
entity.setExpectTimeDesc(req.getExpectDesc());
// 使用期望时间来初始化计划时间,后面在指派环节更新为真正的有效的计划时间
entity.setPlanStartTime(entity.getExpectTimeBegin());
entity.setPlanEndTime(entity.getExpectTimeEnd());
entity.setApplyNote(req.getDescription()); // order_request的description字段,仅仅用于内部备注,不对外
entity.setDt(LocalDateTimeUtil.parseDate(req.getExpectBegin().substring(0, 10), PATTERN_DATE));
entity.setDt(entity.getExpectTimeBegin().toLocalDate());
entity.setSubId(newSubId(entity.getOrderId(), entity.getDt()));
// location
LocationDTO location = req.getLocation();
entity.setProvince(location.getProvince());
entity.setCity(location.getCity());
entity.setCounty(location.getDistrict());
if (req.getAddress() != null) {
entity.setAddress(req.getAddress());
} else {
entity.setAddress(location.getFormattedAddress());
}
entity.setX(req.getLocation().getLongitude().toString());
entity.setY(req.getLocation().getLatitude().toString());
entity.setAddress(location.getAddress());
entity.setAddressId(location.getAddressId());
// 默认值
entity.setAppointmentStatus("INIT");
entity.setAppointmentStatus(OrderFlowEnum.INIT.name());
entity.setBeanStatus("OPEN");
entity.setBeanSubStatus("");
entity.setAppointmentStatus("NOT_ASSIGNED");
entity.setAppointmentMethod("AUTO_NOW");
entity.setWorkshop(false);
SkillInfoEntity skillInfoEntity = skillInfoDao.getByBrandAndTypeAndSkill(peaBrand, req.getType(), req.getSkill());
entity.setIsAppointEngineer(req.getIsAppointEngineer());
String appointEngineerCodes = CollectionUtils.isEmpty(req.getAppointEngineerCodes()) ? "" : String.join(",", req.getAppointEngineerCodes());
entity.setAppointEngineerCodes(appointEngineerCodes);
SkillInfoEntity skillInfoEntity = skillInfoDao.getByBrandAndTypeAndSkill(peaBrand, req.getProductType(), req.getServiceType());
assert skillInfoEntity != null;
entity.setTakeTime(skillInfoEntity.getTakeTime());
// 基础保存
orderInfoDao.save(entity);
// 分单处理
List<String> blockIds = null;
List<String> layerIds = capacityUtils.getLayers(peaBrand, req.getType(), req.getSkill());
if (req.getLocation() != null) {
String loc = String.format("%f,%f", req.getLocation().getLng(), req.getLocation().getLat());
blockIds = saasUtils.queryBlocksByLocation(loc).stream().map(SaasUtils.BlockInfo::getBlockId).collect(Collectors.toList());
} else {
blockIds = saasUtils.queryBlocksByAddress(req.getAddress()).stream().map(SaasUtils.BlockInfo::getBlockId).collect(Collectors.toList());
}
if (blockIds.isEmpty()) {
log.error("分单接口没有查到对应的结果");
return Result.failed(String.format("分单接口(address:%s)(location:%s) 没有查到配置区块", req.getAddress(), req.getLocation()));
}
List<String> teamIds = capacityUtils.getTeamIdsByBlockIdsAndLayerIds(blockIds, layerIds);
if (teamIds == null || teamIds.isEmpty()) {
return Result.failed("没有找到匹配的工作队");
}
// 选择一个工作队(理论上,只有1个合适的工作队),然后遍历下面的符合技能的技术员
// 遍历工作队,每个工作队
String teamId = teamIds.get(0);
OrgTeamEntity teamEntity = orgTeamDao.getByTeamId(teamId);
// 根据分单,填写clusterId/branchId/groupId/teamId等
entity.setOrgClusterId(teamEntity.getClusterId());
entity.setOrgBranchId(teamEntity.getBranchId());
entity.setOrgGroupId(teamEntity.getGroupId());
entity.setOrgTeamId(teamId);
entity.setX(req.getLocation().getLng().toString());
entity.setY(req.getLocation().getLat().toString());
entity.setBeanTags(String.join(",", req.getOrderTags()));
String joinTags = CollectionUtils.isEmpty(req.getOrderTags()) ? "" : String.join(",", req.getOrderTags());
entity.setBeanTags(joinTags);
entity.setBeanPriority(req.getPriority());
entity.setIsMultiple(joinTags.contains("重物搬运") ? 1 : 0);
//一家多单
Result<String> addMultipleOrders = orderInfoService.addMultipleOrders(entity.getDt(), location.getAddressId(), orderId);
entity.setMultipleOrders(addMultipleOrders.getResult());
// todo 服务单状态、预约状态等
orderInfoDao.save(entity);
// 登记
commonService.addOrderEvent(orderId, "", req.getSource(), "API", "创建订单", "创建订单", "");
commonService.addOrderEvent(orderId, "", req.getSource(), "API", OrderStatus.CREATE.getDescription(), OrderStatus.CREATE.getDescription(), "");
// 指派检查,简单处理,遇到第一个可以指派的就停止检查
tryVirtualAppointment(entity, req.getSource(), teamId);
// tryVirtualAppointment(entity, req.getSource(), teamId);
return Result.success(null);
}
......@@ -226,7 +264,7 @@ public class OrderCreateServiceImpl implements OrderCreateService {
EngineerInfoEntity engineerInfo = engineerInfoDao.getByEngineerCode(assignEngineerCode);
thisOrderEntity.setEngineerName(engineerInfo.getName());
thisOrderEntity.setEngineerPhone(engineerInfo.getPhone());
thisOrderEntity.setAppointmentStatus("PRE");
thisOrderEntity.setAppointmentStatus(OrderFlowEnum.PRE.name());
thisOrderEntity.setDispatcher("AUTO_NOW");
thisOrderEntity.setPlanStartTime(insertNode.getPlanStartTime());
thisOrderEntity.setPlanEndTime(insertNode.getPlanEndTime());
......
......@@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
......@@ -32,14 +33,22 @@ public class OrderInfoServiceImpl implements OrderInfoService {
*/
@Override
@Transactional
public Result<String> addMultipleOrders(String dt, String addressId) {
public Result<String> addMultipleOrders(LocalDate dt, String addressId, String orderId) {
List<OrderInfoEntity> infoList = orderInfoDao.findByDtAndAddressId(dt, addressId);
if (CollectionUtils.isEmpty(infoList)) {
return Result.success(null);
}
List<String> multipleOrdersList = infoList.stream().filter(e -> StringUtils.isNotEmpty(e.getMultipleOrders())).map(OrderInfoEntity::getMultipleOrders).distinct().collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(multipleOrdersList)) {
return Result.success(multipleOrdersList.get(0));
//排除自己
List<String> multipleOrdersList = infoList.stream().filter(e -> !e.getOrderId().equals(orderId))
.map(OrderInfoEntity::getMultipleOrders).distinct().collect(Collectors.toList());
if (CollectionUtils.isEmpty(multipleOrdersList)) {
return Result.success(null);
}
//查看是否已存在一家多单id存在则返回
List<String> multipleOrdersFilterList = infoList.stream().filter(e -> StringUtils.isNotEmpty(e.getMultipleOrders()))
.map(OrderInfoEntity::getMultipleOrders).distinct().collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(multipleOrdersFilterList)) {
return Result.success(multipleOrdersFilterList.get(0));
}
String uuid = UUIDUtil.getUuid();
for (OrderInfoEntity orderInfoEntity : infoList) {
......@@ -59,6 +68,9 @@ public class OrderInfoServiceImpl implements OrderInfoService {
@Override
@Transactional
public Result deleteMultipleOrders(String multipleOrders, String orderId) {
if (StringUtils.isBlank(multipleOrders)) {
return Result.success();
}
List<OrderInfoEntity> infoList = orderInfoDao.findByMultipleOrders(multipleOrders);
for (OrderInfoEntity infoEntity : infoList) {
if (infoEntity.getOrderId().equals(orderId)) {
......
......@@ -9,6 +9,7 @@ import com.dituhui.pea.order.dto.param.Order;
import com.dituhui.pea.order.dto.param.OrderDTO;
import com.dituhui.pea.order.entity.OrderInfoEntity;
import com.dituhui.pea.order.entity.OrgGroupEntity;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.service.PeaOuterAPIService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
......@@ -61,7 +62,7 @@ public class PeaOuterAPIServiceImpl implements PeaOuterAPIService {
@Override
public Order orderIncreaseQuery(String engineerCode, Location location, Integer idleDuration) {
OrderInfoEntity sss = orderInfoDao.findTopBySkillAndAppointmentStatus("标准安装", "INIT");
OrderInfoEntity sss = orderInfoDao.findTopBySkillAndAppointmentStatus("标准安装", OrderFlowEnum.INIT.name());
Order order = new Order();
order.setOrderId(sss.getOrderId());
......
......@@ -8,6 +8,7 @@ import com.dituhui.pea.order.common.TimeUtils;
import com.dituhui.pea.order.dao.*;
import com.dituhui.pea.order.dto.*;
import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.service.ScheduleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
......@@ -94,7 +95,7 @@ public class ScheduleServiceImpl implements ScheduleService {
team.setLevel("team");
// 获取改team订单列表
List<OrderInfoEntity> orders = orderInfoDao.findByDtAndOrgTeamIdAndAppointmentStatusIn(date, t.getTeamId(), List.of("PRE", "CONFIRM"));
List<OrderInfoEntity> orders = orderInfoDao.findByDtAndOrgTeamIdAndAppointmentStatusIn(date, t.getTeamId(), List.of(OrderFlowEnum.PRE.name(), OrderFlowEnum.CONFIRM.name()));
team.setOrder(this.getTeamOrderSum(orders, skillMapping));
// 技术员指派单列表
......@@ -159,7 +160,7 @@ public class ScheduleServiceImpl implements ScheduleService {
List<LabelValueDTO> emptyTips = new ArrayList<>();
List<OrderInfoEntity> orderAppointments = orderInfoDao.findByEngineerCodeAndDtAndAppointmentStatusIn(
engineerCode, date, List.of("PRE", "CONFIRM"));
engineerCode, date, List.of(OrderFlowEnum.PRE.name(), OrderFlowEnum.CONFIRM.name()));
List<TimeLineDTO> timelines = new ArrayList<>();
for (OrderInfoEntity o : orderAppointments) {
TimeLineDTO item = new TimeLineDTO();
......
......@@ -10,6 +10,7 @@ import com.dituhui.pea.order.dto.OrderChangeListDTO;
import com.dituhui.pea.order.dto.WorkbenchSummaryResp;
import com.dituhui.pea.order.entity.OrderEventEntity;
import com.dituhui.pea.order.entity.OrderInfoEntity;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.service.WorkbenchService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -240,7 +241,7 @@ public class WorkbenchServiceImpl implements WorkbenchService {
Long autoTotal = summary.getOrDefault("autoTotal", 0L);
Long total = summary.getOrDefault("total", 0L);
HashMap<String, List<String>> p = this.packParams("appointmentStatus", "INIT");
HashMap<String, List<String>> p = this.packParams("appointmentStatus", OrderFlowEnum.INIT.name());
HashMap<String, List<String>> p1 = this.packParams("appointmentType", "MANUAL");
p1.putAll(p);
......
......@@ -63,6 +63,8 @@ sentry:
SaaS:
url: https://pea-test.bshg.com.cn
ak: 64e1cde3f9144bfb850b7d37c51af559
userAccount: sMvf3yZWA69lKcvlgKcOHQ==
userPassword: qjOHxpQPXLnJP+Jq1CZGBQ==
bean:
server: https://bean-test.bshg.com.cn
app-key: eDZEhTCxAcM9paRfwPjAM7RGkfmbf15S_PEA
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!