Commit 1d2f96cf by wangli

修改

1 parent dc306930
package com.dituhui.pea.order.common; package com.dituhui.pea.order.common;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dituhui.pea.order.dao.*; import com.dituhui.pea.order.dao.*;
import com.dituhui.pea.order.entity.*; import com.dituhui.pea.order.entity.*;
import lombok.Data; import lombok.Data;
...@@ -9,14 +8,19 @@ import org.apache.commons.lang3.StringUtils; ...@@ -9,14 +8,19 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.LocalTime; import java.time.LocalTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Component @Component
...@@ -24,55 +28,37 @@ import java.util.stream.Collectors; ...@@ -24,55 +28,37 @@ import java.util.stream.Collectors;
public class OrderAssignCheck { public class OrderAssignCheck {
@Autowired @Autowired
SkillInfoMPDao skillInfoMPDao; private SkillInfoDao skillInfoDao;
@Autowired @Autowired
EngineerBusinessMPDao engineerBusinessMPDao; private EngineerBusinessDao engineerBusinessDao;
@Autowired @Autowired
EngineerInfoMPDao engineerInfoMPDao; private EngineerInfoDao engineerInfoDao;
@Autowired @Autowired
OrgGroupMPDao orgGroupMPDao; private OrgGroupDao orgGroupDao;
@Autowired @Autowired
OrderInfoMPDao orderInfoMPDao; private OrderInfoDao orderInfoDao;
@Data @Autowired
public class Result { private EntityManager entityManager;
private Boolean canAssign;
private String message;
private int minuteAddition;
private int distanceAddition;
private LocalDateTime start;
private LocalDateTime end;
private int index;
public Result(boolean canAssign, String message, int minuteAddition, int distanceAddition, LocalDateTime start, LocalDateTime end, int index){
this.canAssign = canAssign;
this.message = message;
this.minuteAddition = minuteAddition;
this.distanceAddition = distanceAddition;
this.start = start;
this.end = end;
this.index = index;
}
}
public Result orderAssignCheck(String orderId, String engineerCode) { public Result orderAssignCheck(String orderId, LocalDate dt, String engineerCode) {
log.info("begin orderAssignCheck:orderId={}, engineerCode={}", orderId, engineerCode); log.info("begin orderAssignCheck:orderId={}, engineerCode={}", orderId, engineerCode);
OrderInfo order = orderInfoMPDao.getByOrderId(orderId); OrderInfoEntity order = orderInfoDao.getByOrderIdAndDt(orderId, dt);
double curX = Double.parseDouble(order.getX()); double curX = Double.parseDouble(order.getX());
double curY = Double.parseDouble(order.getY()); double curY = Double.parseDouble(order.getY());
// 获取技能需要的时长(分钟) // 获取技能需要的时长(分钟)
SkillInfo skillInfo = skillInfoMPDao.getByBrandAndTypeAndSkill(order.getBrand(), order.getType(), order.getSkill()); SkillInfoEntity skillInfo = skillInfoDao.getByBrandAndTypeAndSkill(order.getBrand(), order.getType(), order.getSkill());
int takeTime = skillInfo.getTakeTime(); int takeTime = skillInfo.getTakeTime();
// 获取客户期望时间段 // 获取客户期望时间段
int start = this.timestamp2Point(order.getExpectTimeBegin()); int start = this.timestamp2Point(Timestamp.valueOf(order.getExpectTimeBegin()));
int end = this.timestamp2Point(order.getExpectTimeEnd()); int end = this.timestamp2Point(Timestamp.valueOf(order.getExpectTimeEnd()));
log.info("客户期望的时间段:{}-{}, 技能所需时长:{}, 坐标:{},{}", start, end, takeTime, curX, curY); log.info("客户期望的时间段:{}-{}, 技能所需时长:{}, 坐标:{},{}", start, end, takeTime, curX, curY);
// 获取技术员的已分配订单的时间段, 根据时间段排序 // 获取技术员的已分配订单的时间段, 根据时间段排序
...@@ -84,18 +70,20 @@ public class OrderAssignCheck { ...@@ -84,18 +70,20 @@ public class OrderAssignCheck {
int index = SegmentInsertion.insertSegment(takeTime, start, end, segments); int index = SegmentInsertion.insertSegment(takeTime, start, end, segments);
if (index == -1) { if (index == -1) {
log.info("没有可连续插入的空间"); log.info("没有可连续插入的空间");
return new Result(false, "没有连续可插入空间(没计算时间)", 0, 0, null, null, index); return new Result(-1, false, false, orderId, null,0,0, null, null, null);
} }
log.info("插入位置为第{}单, 已分配单数(不包含本单):{}", index, orderSegments.size()); log.info("插入位置为第{}单, 已分配单数(不包含本单):{}", index, orderSegments.size());
// 计算距离 & 时间 // 计算距离 & 时间
if(index == 0 && orderSegments.isEmpty()) { if (index == 0 && orderSegments.isEmpty()) {
// 第一订单为出发地, 没有其他订单 // 第一订单为出发地, 没有其他订单
// 技术员出发地
double[] location = this.getEngineerDepartureLocation(engineerCode); double[] location = this.getEngineerDepartureLocation(engineerCode);
double preX = location[0]; double preX = location[0];
double preY = location[1]; double preY = location[1];
OrderSegment pre = new OrderSegment(480, 480, preX, preY); OrderSegment pre = new OrderSegment(480, 480, preX, preY, 0, 0, 0);
Pair p = this.getDistanceAndDuration(pre.getX(), pre.getY(), curX, curY); Pair p = this.getDistanceAndDuration(pre.getX(), pre.getY(), curX, curY);
// 最早可插入位置为技术员出发时间+行程时间 // 最早可插入位置为技术员出发时间+行程时间
...@@ -106,21 +94,29 @@ public class OrderAssignCheck { ...@@ -106,21 +94,29 @@ public class OrderAssignCheck {
LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, order.getDt()); LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, order.getDt());
LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, order.getDt()); LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, order.getDt());
return new Result(true, "success", 0, 0, startDateTime, endDateTime, index); // 当前节点信息
} OrderNode curOrder = new OrderNode();
else if(index == 0 && !orderSegments.isEmpty()) { 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[] location = this.getEngineerDepartureLocation(engineerCode);
double preX = location[0]; double preX = location[0];
double preY = location[1]; 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); OrderSegment post = orderSegments.get(0);
OrderSegment pre = new OrderSegment(480, 480, preX, preY); return this.getResult(index, cur, pre, post, order.getDt());
return this.getResult(curX, curY, pre, post, takeTime, order.getDt(), index); } else if (index == orderSegments.size()) {
} // 有其他订单,最后一个订单出发
else if(index == orderSegments.size()) { OrderSegment pre = orderSegments.get(index - 1);
// 最后一个订单出发
OrderSegment pre = orderSegments.get(index-1);
Pair p = this.getDistanceAndDuration(pre.getX(), pre.getY(), curX, curY); Pair p = this.getDistanceAndDuration(pre.getX(), pre.getY(), curX, curY);
// 最早可插入位置为技术员上一单出发时间+行程时间 // 最早可插入位置为技术员上一单出发时间+行程时间
int startPos = pre.getEnd() + p.getDuration(); int startPos = pre.getEnd() + p.getDuration();
...@@ -129,83 +125,134 @@ public class OrderAssignCheck { ...@@ -129,83 +125,134 @@ public class OrderAssignCheck {
LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, order.getDt()); LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, order.getDt());
LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, order.getDt()); LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, order.getDt());
return new Result(true, "success", 0, 0, startDateTime, endDateTime, index);
// 当前节点信息
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 { } else {
OrderSegment pre = orderSegments.get(index-1); // 插入中间位置
OrderSegment pre = orderSegments.get(index - 1);
OrderSegment cur = new OrderSegment(-1, -1, curX, curY, takeTime, -1, -1);
OrderSegment post = orderSegments.get(index); OrderSegment post = orderSegments.get(index);
return this.getResult(curX, curY, pre, post, takeTime, order.getDt(), index); return this.getResult(index, cur, pre, post, order.getDt());
} }
} }
private List<OrderSegment> getEngineerOrderSegments(String engineerCode, LocalDate dt) { private List<OrderSegment> getEngineerOrderSegments(String engineerCode, LocalDate dt) {
List<OrderSegment> orderSegments = new ArrayList<>(); List<OrderSegment> orderSegments = new ArrayList<>();
LambdaQueryWrapper<OrderInfo> lqw = new LambdaQueryWrapper<>(); List<String> appointmentStatusList = Arrays.asList("PRE", "CONFIRM");
lqw.eq(OrderInfo::getDt, dt); CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
lqw.eq(OrderInfo::getEngineerCode, engineerCode); CriteriaQuery<OrderInfoEntity> criteriaQuery = criteriaBuilder.createQuery(OrderInfoEntity.class);
lqw.eq(OrderInfo::getOrderStatus, "NORMAL"); Root<OrderInfoEntity> root = criteriaQuery.from(OrderInfoEntity.class);
lqw.in(OrderInfo::getAppointmentStatus, List.of("PRE", "CONFIRM"));
List<OrderInfo> appointments = orderInfoMPDao.selectList(lqw); Predicate dtPredicate = criteriaBuilder.equal(root.get("dt"), dt);
if(appointments.isEmpty()){ 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; return orderSegments;
} }
for(OrderInfo o: appointments) {
for (OrderInfoEntity o : appointments) {
OrderSegment seg = new OrderSegment(); OrderSegment seg = new OrderSegment();
seg.setOrderId(o.getOrderId()); seg.setOrderId(o.getOrderId());
seg.setX(Double.parseDouble(o.getX())); seg.setX(Double.parseDouble(o.getX()));
seg.setY(Double.parseDouble(o.getY())); seg.setY(Double.parseDouble(o.getY()));
seg.setStart(this.timestamp2Point(o.getPlanStartTime())); seg.setStart(this.timestamp2Point(Timestamp.valueOf(o.getPlanStartTime())));
seg.setEnd(this.timestamp2Point(o.getPlanEndTime())); seg.setEnd(this.timestamp2Point(Timestamp.valueOf(o.getPlanEndTime())));
seg.setElapsed(o.getArriveElapsed());
seg.setDistance(o.getArriveDistance());
orderSegments.add(seg); orderSegments.add(seg);
} }
return orderSegments.stream().sorted(Comparator.comparing(OrderSegment::getStart)).collect(Collectors.toList()); return orderSegments.stream().sorted(Comparator.comparing(OrderSegment::getStart)).collect(Collectors.toList());
} }
private List<SegmentInsertion.Segment> orderSegment2Segment(List<OrderSegment> orderSegments) { private List<SegmentInsertion.Segment> orderSegment2Segment(List<OrderSegment> orderSegments) {
List<SegmentInsertion.Segment> segments = new ArrayList<>(); List<SegmentInsertion.Segment> segments = new ArrayList<>();
for (OrderSegment s: orderSegments) { for (OrderSegment s : orderSegments) {
segments.add(new SegmentInsertion.Segment(s.getOrderId(), s.getStart(), s.getEnd())); segments.add(new SegmentInsertion.Segment(s.getOrderId(), s.getStart(), s.getEnd()));
} }
return segments; return segments;
} }
private Result getResult(double curX, double curY, OrderSegment pre, OrderSegment post, int takeTime, LocalDate dt, int index) { private Result getResult(int index, OrderSegment cur, OrderSegment pre, OrderSegment post, LocalDate dt) {
Pair preCurPair = this.getDistanceAndDuration(pre.getX(), pre.getY(), curX, curY); Pair preCurPair = this.getDistanceAndDuration(pre.getX(), pre.getY(), cur.getX(), cur.getY());
Pair postCurPair = this.getDistanceAndDuration(post.getX(), post.getY(), curX, curY); Pair postCurPair = this.getDistanceAndDuration(post.getX(), post.getY(), cur.getX(), cur.getY());
Pair prePostPair = this.getDistanceAndDuration(post.getX(), post.getY(), pre.getX(), pre.getY()); Pair prePostPair = this.getDistanceAndDuration(post.getX(), post.getY(), pre.getX(), pre.getY());
log.info("pre-cur{}, post-cur:{}, pre-post:{}", preCurPair, postCurPair, prePostPair); log.info("pre-cur{}, post-cur:{}, pre-post:{}", preCurPair, postCurPair, prePostPair);
// 判断增加时间+距离后,时间是否重叠了 // 判断增加时间+距离后,时间是否重叠了
int distance = post.getStart() - postCurPair.getDuration() - (pre.getEnd() + preCurPair.getDuration()); int distance = post.getStart() - postCurPair.getDuration() - (pre.getEnd() + preCurPair.getDuration());
if(distance < takeTime) { if (distance < cur.getTakeTime()) {
// 不支持插入 // 不支持插入
return new Result(false, "增加时间路程后,不支持插入", 0, 0, null, null, index); return new Result(-1, false, false, "", "", 0, 0, null, null, null);
} }
// 插入点(时间点) // 插入点(时间点)
int startInsert = pre.getEnd() + preCurPair.getDuration(); int startInsert = pre.getEnd() + preCurPair.getDuration();
int endInsert = startInsert + takeTime; int endInsert = startInsert + cur.getTakeTime();
LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, dt); LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, dt);
LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, dt); LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, dt);
int minuteAddition = preCurPair.getDuration() + postCurPair.getDuration() - prePostPair.getDuration(); // 当前节点
int distanceAddition = preCurPair.getDistance() + postCurPair.getDistance() - prePostPair.getDistance(); OrderNode curOrder = new OrderNode();
return new Result(true, "success", minuteAddition, distanceAddition, startDateTime, endDateTime, index); 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){ private double[] getEngineerDepartureLocation(String engineerCode) {
// 获取技术员出发坐标 // 获取技术员出发坐标
// 从技术员配置中获取 // 从技术员配置中获取
EngineerBusiness b = engineerBusinessMPDao.getByEngineerCode(engineerCode); EngineerBusinessEntity b = engineerBusinessDao.getByEngineerCode(engineerCode);
if( b != null && StringUtils.isNotEmpty(b.getX()) && StringUtils.isNotEmpty(b.getY())){ if (b != null && StringUtils.isNotEmpty(b.getX()) && StringUtils.isNotEmpty(b.getY())) {
return new double[]{Double.parseDouble(b.getX()), Double.parseDouble(b.getY())}; return new double[]{Double.parseDouble(b.getX()), Double.parseDouble(b.getY())};
} }
//从org_group中获取 //从org_group中获取
EngineerInfo e = engineerInfoMPDao.getByEngineerCode(engineerCode); EngineerInfoEntity e = engineerInfoDao.getByEngineerCode(engineerCode);
OrgGroup g = orgGroupMPDao.getByGroupId(e.getGroupId()); OrgGroupEntity g = orgGroupDao.getByGroupId(e.getGroupId());
return new double[]{Double.parseDouble(g.getX()), Double.parseDouble(g.getY())}; return new double[]{Double.parseDouble(g.getX()), Double.parseDouble(g.getY())};
} }
...@@ -224,40 +271,82 @@ public class OrderAssignCheck { ...@@ -224,40 +271,82 @@ public class OrderAssignCheck {
return LocalDateTime.of(dt, this.point2LocalTime(point)); return LocalDateTime.of(dt, this.point2LocalTime(point));
} }
private Pair getDistanceAndDuration(double x1, double y1, double x2, double y2){ private Pair getDistanceAndDuration(double x1, double y1, double x2, double y2) {
Distance cal= new Distance(); Distance cal = new Distance();
long distance = Math.round(cal.calculateDistance(x1, y1, x2, y2) * 1.4); // 单位为米 long distance = Math.round(cal.calculateDistance(x1, y1, x2, y2) * 1.4); // 单位为米
long duration = distance / (19 * 1000 / 60); // 时间为分钟,假设电动车速度为19km/h long duration = distance / (19 * 1000 / 60); // 时间为分钟,假设电动车速度为19km/h
return new Pair((int)distance, (int)duration); 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 @Data
class OrderSegment{ class OrderSegment {
private String orderId; private String orderId;
private int start; private int start;
private int end; private int end;
private double x; private double x;
private double y; private double y;
private int takeTime;
private int elapsed;
private int distance;
public OrderSegment(){ public OrderSegment() {
} }
public OrderSegment(int start, int end, double x, double y){ public OrderSegment(int start, int end, double x, double y, int takeTime, int elapsed, int distance) {
this.start = start; this.start = start;
this.end = end; this.end = end;
this.x = x; this.x = x;
this.y = y; this.y = y;
this.takeTime = takeTime;
this.elapsed = elapsed;
this.distance = distance;
} }
} }
@Data @Data
class Pair{ class Pair {
private int distance; private int distance;
private int duration; private int duration;
public Pair(int distance, int duration){ public Pair(int distance, int duration) {
this.distance = distance; this.distance = distance;
this.duration = duration; this.duration = duration;
} }
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!