Commit 4517df72 by 刘鑫

Merge branch 'develop' of https://gitlab.dituhui.com/bsh/project/project into develop-16542

2 parents 6b2a36a7 ee922485
Showing with 1104 additions and 309 deletions
......@@ -11,6 +11,8 @@ import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
......@@ -59,13 +61,13 @@ public class GeoDistanceCalculator {
}
}
private Map<Location, Map<Location, Pair>> calculateBulkDistanceDuration(Collection<Location> fromLocations, Collection<Location> toLocations) {
private Map<Location, Map<Location, Pair>> calculateBulkDistanceDuration(Collection<Location> fromLocations, Collection<Location> toLocations, Integer vehicleType) {
return fromLocations.stream().collect(Collectors.toMap(
Function.identity(),
from -> toLocations.stream().collect(Collectors.toMap(
Function.identity(),
to -> {
Distance distance = RoadDistanceUtils.getDistance(from, to);
Distance distance = RoadDistanceUtils.getDistance(from, to, vehicleType);
long path = (long) distance.getDis();
long time = distance.getTime();
return new Pair(path, time);
......@@ -74,18 +76,17 @@ public class GeoDistanceCalculator {
));
}
public void initDistanceMaps(Collection<Location> locationList) {
Map<Location, Map<Location, Pair>> distanceMatrix = calculateBulkDistanceDuration(locationList, locationList);
locationList.forEach(location -> {
Map<Location, Pair> mapPair = distanceMatrix.get(location);
mapPair.forEach((loc2, pair) -> {
location.getDistanceMap().put(loc2, pair.Distance);
location.getDistanceTimeMap().put(loc2, pair.Duration);
public void initDistanceMaps(Collection<Location> locationList, List<Integer> vehicleTypes) {
for (Integer vehicleType: vehicleTypes) {
Map<Location, Map<Location, Pair>> distanceMatrix = calculateBulkDistanceDuration(locationList, locationList, vehicleType);
locationList.forEach(location -> {
Map<Location, Pair> mapPair = distanceMatrix.get(location);
mapPair.forEach((loc2, pair) -> {
location.getDistanceMap(vehicleType).put(loc2, pair.Distance);
location.getDistanceTimeMap(vehicleType).put(loc2, pair.Duration);
});
});
});
}
}
}
......
......@@ -51,6 +51,9 @@ public class DispatchEngineer implements Serializable {
@Column(name = "max_distance")
private Integer maxDistance;
@Column(name = "vehicle_type")
private Integer vehicleType;
private String ext = "";
......
......@@ -131,9 +131,9 @@ public class Customer {
// throw new IllegalStateException("This method must not be called when the shadow variables are not initialized yet.");
}
if (previousCustomer == null) {
return technician.getDepot().getLocation().getDistanceTo(location);
return technician.getDepot().getLocation().getDistanceTo(technician.getVehicleType(),location);
}
return previousCustomer.getLocation().getDistanceTo(location);
return previousCustomer.getLocation().getDistanceTo(technician.getVehicleType(),location);
}
/**
......@@ -147,9 +147,9 @@ public class Customer {
// throw new IllegalStateException("This method must not be called when the shadow variables are not initialized yet.");
}
if (previousCustomer == null) {
return technician.getDepot().getLocation().getPathTimeTo(location);
return technician.getDepot().getLocation().getPathTimeTo(technician.getVehicleType(),location);
}
return previousCustomer.getLocation().getPathTimeTo(location);
return previousCustomer.getLocation().getPathTimeTo(technician.getVehicleType(),location);
}
@Override
......
......@@ -24,10 +24,26 @@ public class Location {
private double latitude;
private double longitude;
// 汽车路网矩阵
@JsonIgnore
private Map<Location, Long> distanceMap = new HashMap<Location, Long>();// 路网距离矩阵
private Map<Location, Long> carDistanceMap = new HashMap<Location, Long>();// 路网距离矩阵
@JsonIgnore
private Map<Location, Long> distanceTimeMap = new HashMap<Location, Long>();// 路网时间矩阵
private Map<Location, Long> carDistanceTimeMap = new HashMap<Location, Long>();// 路网时间矩阵
// 电动车路网矩阵
@JsonIgnore
private Map<Location, Long> electricBicycleDistanceMap = new HashMap<Location, Long>();// 路网距离矩阵
@JsonIgnore
private Map<Location, Long> electricBicycleDistanceTimeMap = new HashMap<Location, Long>();// 路网时间矩阵
// 自行车路网矩阵
@JsonIgnore
private Map<Location, Long> bicycleDistanceMap = new HashMap<Location, Long>();// 路网距离矩阵
@JsonIgnore
private Map<Location, Long> bicycleDistanceTimeMap = new HashMap<Location, Long>();// 路网时间矩阵
// 步行路网矩阵
@JsonIgnore
private Map<Location, Long> walkDistanceMap = new HashMap<Location, Long>();// 路网距离矩阵
@JsonIgnore
private Map<Location, Long> walkDistanceTimeMap = new HashMap<Location, Long>();// 路网时间矩阵
public Location(long id) {
this.id = id;
......@@ -47,36 +63,101 @@ public class Location {
this.latitude = latitude;
}
/**
* Set the distance map. Distances are in meters.
*
* @param distanceMap a map containing distances from here to other locations
*/
public void setDistanceMap(Map<Location, Long> distanceMap) {
this.distanceMap = distanceMap;
}
/**
* Distance to the given location in meters.
*
* @param location other location
* @return distance in meters
* 根据不同交通方式返回不同距离
*
* @param vehicleType
* @param location
* @return
*/
public long getDistanceTo(Location location) {
return distanceMap.get(location);
}
public long getDistanceTo(Integer vehicleType, Location location) {
if (null == vehicleType) {
return carDistanceMap.get(location);
}
switch (vehicleType) {
case 1:
return carDistanceMap.get(location);
case 2:
return electricBicycleDistanceMap.get(location);
case 3:
return bicycleDistanceMap.get(location);
case 4:
return walkDistanceMap.get(location);
}
return carDistanceMap.get(location);
}
public Map<Location, Long> getDistanceMap(Integer vehicleType) {
if (null == vehicleType) {
return carDistanceMap;
}
switch (vehicleType) {
case 1:
return carDistanceMap;
case 2:
return electricBicycleDistanceMap;
case 3:
return bicycleDistanceMap;
case 4:
return walkDistanceMap;
}
return carDistanceMap;
}
public Map<Location, Long> getDistanceTimeMap(Integer vehicleType) {
if (null == vehicleType) {
return carDistanceTimeMap;
}
switch (vehicleType) {
case 1:
return carDistanceTimeMap;
case 2:
return electricBicycleDistanceTimeMap;
case 3:
return bicycleDistanceTimeMap;
case 4:
return walkDistanceTimeMap;
}
return carDistanceTimeMap;
}
public int getPathTimeTo(Integer vehicleType, Location location) {
if (null == vehicleType) {
return carDistanceTimeMap.get(location).intValue() / 60;
}
switch (vehicleType) {
case 1:
return carDistanceTimeMap.get(location).intValue() / 60;
case 2:
return electricBicycleDistanceTimeMap.get(location).intValue() / 60;
case 3:
return bicycleDistanceTimeMap.get(location).intValue() / 60;
case 4:
return walkDistanceTimeMap.get(location).intValue() / 60;
}
return carDistanceTimeMap.get(location).intValue() / 60;
}
/**
* time to the given location in minutes.
*
* @param location other location
* @return time in minutes
*/
public int getPathTimeTo(Location location) {
return distanceTimeMap.get(location).intValue()/60;
public int getCarPathTimeTo(Location location) {
return carDistanceTimeMap.get(location).intValue() / 60;
}
public int getElectricBicyclePathTimeTo(Location location) {
return electricBicycleDistanceTimeMap.get(location).intValue() / 60;
}
public int getBicyclePathTimeTo(Location location) {
return bicycleDistanceTimeMap.get(location).intValue() / 60;
}
public int getWalkDathTimeTo(Location location) {
return walkDistanceTimeMap.get(location).intValue() / 60;
}
// ************************************************************************
......@@ -110,5 +191,4 @@ public class Location {
'}';
}
}
......@@ -44,6 +44,9 @@ public class Technician {
// 单位是米,这里要注意
private int maxDistanceMeter;
// 交通方式 1汽车;2电动车;3自行车;4步行 默认是汽车
private Integer vehicleType;
@PlanningListVariable
private List<Customer> customerList = new ArrayList<>();
......@@ -76,6 +79,20 @@ public class Technician {
this.maxDistanceMeter = maxDistanceMeter;
this.preferredlocationDistanceMap = preferredlocationDistanceMap;
}
public Technician(long id, String code, int maxCount, int maxMinute, int maxDistanceMeter, Integer vehicleType, Depot depot,
int startTime, int endTime, Set<String> skills, Map<String, Long> preferredlocationDistanceMap) {
this.id = id;
this.code = code;
this.depot = depot;
this.startTime = startTime;
this.endTime = endTime;
this.skills = skills;
this.maxCount = maxCount;
this.maxMinute = maxMinute;
this.maxDistanceMeter = maxDistanceMeter;
this.preferredlocationDistanceMap = preferredlocationDistanceMap;
}
// ************************************************************************
// Complex methods
......@@ -114,10 +131,10 @@ public class Technician {
Location previousLocation = depot.getLocation();
for (Customer customer : customerList) {
totalDistance += previousLocation.getDistanceTo(customer.getLocation());
totalDistance += previousLocation.getDistanceTo(this.getVehicleType(),customer.getLocation());
previousLocation = customer.getLocation();
}
totalDistance += previousLocation.getDistanceTo(depot.getLocation());
totalDistance += previousLocation.getDistanceTo(this.getVehicleType(), depot.getLocation());
return totalDistance;
}
......
......@@ -210,8 +210,8 @@ public class BatchServiceImpl implements BatchService {
jdbcTemplate.update("delete from dispatch_order where team_id=? and batch_no=?", teamId, batchNo);
log.info("写入新批次技术员、工单数据, teamId:{}, day:{}, batchNo:{}", teamId, batchDay, batchNo);
String sqlEngineer = "INSERT INTO dispatch_engineer (team_id, batch_no, engineer_code, engineer_name, x, y, max_num, max_minute, max_distance)\n"
+ "SELECT o.team_id,?,o.engineer_code, a.name , b.x, b.y , max_num, max_minute, max_distance FROM `org_team_engineer` o,engineer_info a,engineer_business b \r\n"
String sqlEngineer = "INSERT INTO dispatch_engineer (team_id, batch_no, engineer_code, engineer_name, x, y, max_num, max_minute, max_distance, vehicle_type)\n"
+ "SELECT o.team_id,?,o.engineer_code, a.name , b.x, b.y , max_num, max_minute, max_distance, b.vehicle FROM `org_team_engineer` o,engineer_info a,engineer_business b \r\n"
+ " WHERE o.team_id=? AND `status`=1\r\n"
+ " AND o.engineer_code=a.engineer_code AND a.engineer_code = b.engineer_code \r\n"
+ " AND b.x IS NOT NULL AND b.x !=''" + " order by a.engineer_code asc";
......
......@@ -85,107 +85,108 @@ public class SolveServiceImpl implements SolveService {
// 按小组、批次号组装问题对象
@Override
public DispatchSolution prepareSolution(String groupId, String batchNo) {
log.info("组织问题对象, groupId:{}, batchNo:{}", groupId, batchNo);
entityManager.clear();
// 统一出发地
Depot oneDepot;
Optional<OrgGroup> optional = groupRepository.findByGroupId(groupId);
if (optional.isEmpty()) {
log.error("组织问题对象, 未查询到组织信息 ,groupId:{}, batchNo:{}", groupId, batchNo);
throw new RuntimeException(String.format("组织问题对象, 未查询到组织信息 ,groupId:%s, batchNo:%s", groupId, batchNo));
}
OrgGroup oneGroup = optional.get();
Location deptLocation = new Location(oneGroup.getId(), oneGroup.getGroupId(), "起点", Double.parseDouble(oneGroup.getX()), Double.parseDouble(oneGroup.getY()));
oneDepot = new Depot(oneGroup.getId(), oneGroup.getGroupId(), deptLocation, 60 * 8, 60 * 18);
// customerlist
ArrayList<Customer> customerList = new ArrayList<>();
// 已分配和未分配一起排班,因为已分配会影响整体排班结果
List<DispatchOrder> dispatchOrderList = dispatchOrderRepo.findAll(groupId, batchNo);
// List<DispatchOrder> dispatchOrderList = dispatchOrderRepo.findNotAssigned(groupId, batchNo);
log.info("组织问题对象, dispatchorder-list, groupId:{}, batchNo:{}, dispatchorder-size:{}", groupId, batchNo, dispatchOrderList.size());
if (dispatchOrderList.isEmpty()) {
log.error("组织问题对象, 未查询到工单信息 ,groupId:{}, batchNo:{}", groupId, batchNo);
}
dispatchOrderList.forEach(order -> {
Location location = new Location(order.getId(), order.getOrderId(), "工单", Double.parseDouble(order.getX()), Double.parseDouble(order.getY()));
LocalDateTime ldt1 = dateToLocalDateTime(order.getExpectTimeBegin());
LocalDateTime ldt2 = dateToLocalDateTime(order.getExpectTimeEnd());
int start = 60 * 8;
int end = 60 * 18;
if (ldt1 != null) {
start = ldt1.getHour() * 60 + ldt1.getMinute();
}
if (ldt2 != null) {
end = ldt2.getHour() * 60 + ldt2.getMinute();
}
// 40分钟兜低(技能未能正确匹配原因) FIXME 需要跟客户沟通
if (null == order.getTakeTime()) {
order.setTakeTime(40);
}
if (null == order.getTags()) {
order.setTags("");
}
if (null == order.getPriority()) {
order.setPriority(0);
}
Customer customer = new Customer(order.getId(), order.getOrderId(), order.getDt(), location, start, end, order.getSkills(), order.getTakeTime());
customerList.add(customer);
});
log.info("组织问题对象, customer-list, groupId:{}, batchNo:{}, customer-list:{}", groupId, batchNo, customerList.size());
// technicianList
ArrayList<Technician> technicianList = new ArrayList<>();
dispatchEngineerRepo.findByGroupIdAndBatchNo(groupId, batchNo).forEach(engineer -> {
Location location = new Location(engineer.getId(), engineer.getEngineerCode(), "中心点", Double.parseDouble(engineer.getX()), Double.parseDouble(engineer.getY()));
// Depot depot = new Depot(engineer.getId(), engineer.getEngineerCode(), location, 60 * 8, 60 * 18);
// depotList.add(depot);
// log.debug("组织问题对象, technicianList groupId:{}, batchNo:{}, engineer-code:{}", groupId, batchNo, engineer.getEngineerCode());
List<String> skillList = queryEngineerSkills(engineer.getEngineerCode());
// log.debug("组织问题对象, technicianList groupId:{}, batchNo:{}, engineer-code:{} , skills:{}", groupId, batchNo, engineer.getEngineerCode(), String.join(";", skillList));
// 距离偏好map
Map<String, Long> preferedLoctionDistanceMap = new HashMap<String, Long>();
customerList.forEach(customer -> {
long distance = distanceCalculator.calculateDistance(location, customer.getLocation());
preferedLoctionDistanceMap.put(customer.getCode(), distance);
});
Technician vehicle = new Technician(engineer.getId(), engineer.getEngineerCode(), engineer.getMaxNum(), engineer.getMaxMinute(), engineer.getMaxDistance() * 1000, oneDepot, 60 * 8, 60 * 18, Set.copyOf(skillList), preferedLoctionDistanceMap);
technicianList.add(vehicle);
});
log.info("组织问题对象, depotList-list, groupId:{}, batchNo:{}", groupId, batchNo);
log.info("组织问题对象, technician-list, groupId:{}, batchNo:{}, technician-list:{}", groupId, batchNo, technicianList.size());
// locationlist 起点+订单地点
List<Location> locationList = Stream.concat(Lists.newArrayList(oneDepot).stream().map(Depot::getLocation), customerList.stream().map(Customer::getLocation)).collect(Collectors.toList());
DispatchSolution solution = new DispatchSolution(groupId, batchNo, locationList, oneDepot, technicianList, customerList);
// path 路网数据初始化,FIXME 需要专门路网数据缓存库
long time1 = System.currentTimeMillis();
distanceCalculator.initDistanceMaps(locationList);
long time2 = System.currentTimeMillis();
log.info("组织问题对象 done, groupId:{}, batchNo:{}, technician-size:{}, customer-size:{}, location-size:{}, 路网耗时path:{}ms", groupId, batchNo, technicianList.size(), customerList.size(), locationList.size(), time2-time1);
return solution;
return null;
// log.info("组织问题对象, groupId:{}, batchNo:{}", groupId, batchNo);
//
// entityManager.clear();
//
// // 统一出发地
// Depot oneDepot;
// Optional<OrgGroup> optional = groupRepository.findByGroupId(groupId);
// if (optional.isEmpty()) {
// log.error("组织问题对象, 未查询到组织信息 ,groupId:{}, batchNo:{}", groupId, batchNo);
// throw new RuntimeException(String.format("组织问题对象, 未查询到组织信息 ,groupId:%s, batchNo:%s", groupId, batchNo));
// }
//
// OrgGroup oneGroup = optional.get();
// Location deptLocation = new Location(oneGroup.getId(), oneGroup.getGroupId(), "起点", Double.parseDouble(oneGroup.getX()), Double.parseDouble(oneGroup.getY()));
// oneDepot = new Depot(oneGroup.getId(), oneGroup.getGroupId(), deptLocation, 60 * 8, 60 * 18);
//
//
// // customerlist
// ArrayList<Customer> customerList = new ArrayList<>();
// // 已分配和未分配一起排班,因为已分配会影响整体排班结果
// List<DispatchOrder> dispatchOrderList = dispatchOrderRepo.findAll(groupId, batchNo);
// // List<DispatchOrder> dispatchOrderList = dispatchOrderRepo.findNotAssigned(groupId, batchNo);
//
// log.info("组织问题对象, dispatchorder-list, groupId:{}, batchNo:{}, dispatchorder-size:{}", groupId, batchNo, dispatchOrderList.size());
//
// if (dispatchOrderList.isEmpty()) {
// log.error("组织问题对象, 未查询到工单信息 ,groupId:{}, batchNo:{}", groupId, batchNo);
// }
//
// dispatchOrderList.forEach(order -> {
// Location location = new Location(order.getId(), order.getOrderId(), "工单", Double.parseDouble(order.getX()), Double.parseDouble(order.getY()));
//
// LocalDateTime ldt1 = dateToLocalDateTime(order.getExpectTimeBegin());
// LocalDateTime ldt2 = dateToLocalDateTime(order.getExpectTimeEnd());
// int start = 60 * 8;
// int end = 60 * 18;
// if (ldt1 != null) {
// start = ldt1.getHour() * 60 + ldt1.getMinute();
// }
// if (ldt2 != null) {
// end = ldt2.getHour() * 60 + ldt2.getMinute();
// }
//
//
// // 40分钟兜低(技能未能正确匹配原因) FIXME 需要跟客户沟通
// if (null == order.getTakeTime()) {
// order.setTakeTime(40);
// }
// if (null == order.getTags()) {
// order.setTags("");
// }
// if (null == order.getPriority()) {
// order.setPriority(0);
// }
//
// Customer customer = new Customer(order.getId(), order.getOrderId(), order.getDt(), location, start, end, order.getSkills(), order.getTakeTime());
//
// customerList.add(customer);
// });
//
// log.info("组织问题对象, customer-list, groupId:{}, batchNo:{}, customer-list:{}", groupId, batchNo, customerList.size());
//
// // technicianList
// ArrayList<Technician> technicianList = new ArrayList<>();
// dispatchEngineerRepo.findByGroupIdAndBatchNo(groupId, batchNo).forEach(engineer -> {
// Location location = new Location(engineer.getId(), engineer.getEngineerCode(), "中心点", Double.parseDouble(engineer.getX()), Double.parseDouble(engineer.getY()));
//// Depot depot = new Depot(engineer.getId(), engineer.getEngineerCode(), location, 60 * 8, 60 * 18);
//// depotList.add(depot);
//
//// log.debug("组织问题对象, technicianList groupId:{}, batchNo:{}, engineer-code:{}", groupId, batchNo, engineer.getEngineerCode());
// List<String> skillList = queryEngineerSkills(engineer.getEngineerCode());
//
//// log.debug("组织问题对象, technicianList groupId:{}, batchNo:{}, engineer-code:{} , skills:{}", groupId, batchNo, engineer.getEngineerCode(), String.join(";", skillList));
//
// // 距离偏好map
// Map<String, Long> preferedLoctionDistanceMap = new HashMap<String, Long>();
// customerList.forEach(customer -> {
// long distance = distanceCalculator.calculateDistance(location, customer.getLocation());
// preferedLoctionDistanceMap.put(customer.getCode(), distance);
// });
//
// Technician vehicle = new Technician(engineer.getId(), engineer.getEngineerCode(), engineer.getMaxNum(), engineer.getMaxMinute(), engineer.getMaxDistance() * 1000, oneDepot, 60 * 8, 60 * 18, Set.copyOf(skillList), preferedLoctionDistanceMap);
// technicianList.add(vehicle);
// });
//
// log.info("组织问题对象, depotList-list, groupId:{}, batchNo:{}", groupId, batchNo);
// log.info("组织问题对象, technician-list, groupId:{}, batchNo:{}, technician-list:{}", groupId, batchNo, technicianList.size());
//
// // locationlist 起点+订单地点
// List<Location> locationList = Stream.concat(Lists.newArrayList(oneDepot).stream().map(Depot::getLocation), customerList.stream().map(Customer::getLocation)).collect(Collectors.toList());
//
// DispatchSolution solution = new DispatchSolution(groupId, batchNo, locationList, oneDepot, technicianList, customerList);
//
// // path 路网数据初始化,FIXME 需要专门路网数据缓存库
// long time1 = System.currentTimeMillis();
// distanceCalculator.initDistanceMaps(locationList);
// long time2 = System.currentTimeMillis();
//
// log.info("组织问题对象 done, groupId:{}, batchNo:{}, technician-size:{}, customer-size:{}, location-size:{}, 路网耗时path:{}ms", groupId, batchNo, technicianList.size(), customerList.size(), locationList.size(), time2-time1);
//
// return solution;
}
......@@ -275,9 +276,12 @@ public class SolveServiceImpl implements SolveService {
preferedLoctionDistanceMap.put(customer.getCode(), distance);
});
// FIXME 硬约束:电动车固定40km上限,其他无限制
Technician vehicle = new Technician(engineer.getId(), engineer.getEngineerCode(), engineer.getMaxNum(), engineer.getMaxMinute(), engineer.getMaxDistance() * 1000, oneDepot, 60 * 8, 60 * 18, Set.copyOf(skillList), preferedLoctionDistanceMap);
// 硬约束:电动车固定40km上限,其他无限制
int maxDistance = engineer.getMaxDistance() * 1000;
if (engineer.getVehicleType() != null && engineer.getVehicleType() == 2) {
maxDistance = 40 * 1000;
}
Technician vehicle = new Technician(engineer.getId(), engineer.getEngineerCode(), engineer.getMaxNum(), engineer.getMaxMinute(), maxDistance, engineer.getVehicleType() , oneDepot, 60 * 8, 60 * 18, Set.copyOf(skillList), preferedLoctionDistanceMap);
technicianList.add(vehicle);
});
......@@ -291,8 +295,12 @@ public class SolveServiceImpl implements SolveService {
// path 路网数据初始化,FIXME 需要专门路网数据缓存库
long time1 = System.currentTimeMillis();
distanceCalculator.initDistanceMaps(locationList);
long time2 = System.currentTimeMillis();
// 根据不同的交通工具,初始化不同的路网数据
List<Integer> vehicleTypes = technicianList.stream()
.map(tec -> tec.getVehicleType() == null ? 1 : tec.getVehicleType()).distinct()
.collect(Collectors.toList());
distanceCalculator.initDistanceMaps(locationList, vehicleTypes);
long time2 = System.currentTimeMillis();
log.info("组织问题对象 done, teamId:{}, batchNo:{}, technician-size:{}, customer-size:{}, location-size:{}, 路网耗时path:{}ms", teamId, batchNo, technicianList.size(), customerList.size(), locationList.size(), time2-time1);
......
......@@ -240,7 +240,7 @@ public class DataUtils {
Location locationi = locationIndex.get(i + 1);
for (int j = 0; j < pathMatrix[i].length; j++) {
Location locationj = locationIndex.get(j + 1);
locationi.getDistanceMap().put(locationj, pathMatrix[i][j]);
locationi.getDistanceMap(1).put(locationj, pathMatrix[i][j]);
}
}
......@@ -259,7 +259,7 @@ public class DataUtils {
Location locationi = locationIndex.get(i + 1);
for (int j = 0; j < pathTimeMatrix[i].length; j++) {
Location locationj = locationIndex.get(j + 1);
locationi.getDistanceTimeMap().put(locationj, pathTimeMatrix[i][j]);
locationi.getDistanceTimeMap(1).put(locationj, pathTimeMatrix[i][j]);
}
}
......
......@@ -72,12 +72,12 @@ public class DispatchSolutionUtils {
startPath = technician.getDepot().getStartTime();
// endPath = startPath +
// customer.getLocation().getPathTimeTo(technician.getDepot().getLocation());
endPath = startPath + technician.getDepot().getLocation().getPathTimeTo(customer.getLocation());
endPath = startPath + technician.getDepot().getLocation().getPathTimeTo(technician.getVehicleType(),customer.getLocation());
} else {
startPath = previousCustomer.getDepartureTime();
// endPath = startPath +
// customer.getLocation().getPathTimeTo(previousCustomer.getLocation());
endPath = startPath + previousCustomer.getLocation().getPathTimeTo(customer.getLocation());
endPath = startPath + previousCustomer.getLocation().getPathTimeTo(technician.getVehicleType(),customer.getLocation());
}
if (customer.getArrivalTime() > customer.getEndTime()) {
......
......@@ -26,7 +26,7 @@ import lombok.Data;
*/
public class RoadDistanceUtils {
public static String URL = "https://api.map.baidu.com/routematrix/v2/riding?";
public static String URL = "https://api.map.baidu.com/routematrix/v2/";
public static String AK = "doR30pE7R0I7ivGLwMpkpsTT4bos9Akg";
/**
......@@ -42,20 +42,21 @@ public class RoadDistanceUtils {
*
* @param from
* @param to
* @param vehicleType 不能为空
* @return
*/
public static Distance getDistance(Location from, Location to) {
public static Distance getDistance(Location from, Location to, int vehicleType) {
try {
String key = from.getLongitude() + "," + from.getLatitude() + ";" + to.getLongitude() + ","
+ to.getLatitude();
+ to.getLatitude() + "|" + vehicleType;
Distance distance = distanceCache.get(key);
if (null == distance) {
distance = getDistance(from.getLatitude() + "," + from.getLongitude(),
to.getLatitude() + "," + to.getLongitude());
if(null == distance) {
to.getLatitude() + "," + to.getLongitude(), vehicleType);
if (null == distance) {
Distance dis = new Distance();
return dis;
}else {
} else {
distanceCache.put(key, distance);
}
return distance;
......@@ -68,14 +69,34 @@ public class RoadDistanceUtils {
}
}
private static Distance getDistance(String yx1, String yx2) throws Exception {
private static Distance getDistance(String yx1, String yx2, int vehicleType) throws Exception {
Map<String, String> params = new HashMap<String, String>();
params.put("origins", yx1);
params.put("destinations", yx2);
params.put("ak", AK);
params.put("riding_type", "1");// 电动自行车
params.put("coord_type", "gcj02");
String text = requestGetAK(URL, params);
String url = "";
switch (vehicleType) {
case 1:
url = URL + "driving?";
break;
case 2:
params.put("riding_type", "1");// 电动自行车
url = URL + "riding?";
break;
case 3:
params.put("riding_type", "0");// 普通自行车
url = URL + "riding?";
break;
case 4:
url = URL + "walking?";
break;
}
String text = requestGetAK(url, params);
BDResult webResult = gson.fromJson(text, BDResult.class);
float dis = webResult.getResult().get(0).getDistance().getValue() / 1000F;
int time = webResult.getResult().get(0).getDuration().getValue();
......
......@@ -130,7 +130,9 @@ public enum StatusCodeEnum {
FENDAN_AREA_UNMATCHED("023", "分单接口没有查到配置区块", false),
FENDAN_ENGINEER_UNMATCHED("023", "分单接口没有查到配置工程师", false);
FENDAN_ENGINEER_UNMATCHED("023", "分单接口没有查到配置工程师", false),
FENDAN_IS_TRANSCEND("024", "分单超派", false);
/**
* 状态码
......
......@@ -5,6 +5,7 @@ import org.apache.commons.lang3.time.DateUtils;
import org.springframework.util.Assert;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
......@@ -16,10 +17,7 @@ import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAmount;
import java.time.temporal.TemporalQuery;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.*;
/**
* 日期工具类
......@@ -46,6 +44,11 @@ public class DateUtil {
* java 8 时间格式化
*/
public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATETIME);
/**
* java 8 时间格式化
*/
public static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat(DateUtil.PATTERN_DATETIME);
/**
* 日期 yyyy-MM-dd格式
*/
......@@ -61,6 +64,15 @@ public class DateUtil {
*
* @return 当前日期
*/
public static String datetimeFormatter(Date date) {
return SIMPLE_DATE_FORMAT.format(date);
}
/**
* 获取当前日期
*
* @return 当前日期
*/
public static Date now() {
return new Date();
}
......@@ -504,6 +516,58 @@ public class DateUtil {
public static Integer getHour(Date date) {
return DateUtils.toCalendar(date).get(Calendar.HOUR_OF_DAY);
}
/**
* date转localDate
*
* @param date
* @return
*/
public static LocalDate getLocalDateByDate(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
/**
* 判断目标时间是否是今天
*/
public static boolean judgeIsToday(Date date) {
if (Objects.isNull(date)) {
return false;
}
ZoneId zoneId = ZoneId.systemDefault();
LocalDate inputDate = date.toInstant().atZone(zoneId).toLocalDate();
LocalDate today = LocalDate.now();
return inputDate.equals(today);
}
/***
* @param localDateTime
* @return: boolean
* @Description: 根据LocalDateTime来判断是否是今天
*/
public boolean judgeTimeIsToday(LocalDateTime localDateTime) {
LocalDateTime startTime = LocalDate.now().atTime(0, 0, 0);
LocalDateTime endTime = LocalDate.now().atTime(23, 59, 59);
//如果大于今天的开始日期,小于今天的结束日期
if (localDateTime.isAfter(startTime) && localDateTime.isBefore(endTime)) {
return true;
}
return false;
}
/**
* 根据日期转换到指定时间
* 2023-10-30+2023-10-22 21:21:12 -> 2023-10-30 21:21:12
*
* @param localDateTime
* @return: boolean
* @Description: 根据LocalDateTime来判断是否是今天
*/
public String handleDate(String date, LocalDateTime localDateTime) {
String format = localDateTime.format(TIME_FORMATTER);
return date + " " + format;
}
//CHECKSTYLE:ON
}
......@@ -7,6 +7,7 @@ import com.dituhui.pea.order.dto.OrderAssignReq;
import com.dituhui.pea.order.dto.OrderReschedule;
import com.dituhui.pea.order.dto.OrderRevokeAssign;
import com.dituhui.pea.order.service.OrderAssign;
import com.dituhui.pea.order.service.OrderInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
......@@ -19,6 +20,8 @@ public class OrderAssignController {
@Autowired
private OrderAssign orderAssign;
@Autowired
private OrderInfoService orderInfoService;
@GetMapping("/order/assign/recommend/engineers")
public Result<?> getOrderAssignRecommendEngineers(
......@@ -64,7 +67,7 @@ public class OrderAssignController {
// 订单改约
Result<?> res = null;
try {
res = orderAssign.orderReschedule(req);
res = orderInfoService.orderReschedule(req);
} catch (BusinessException e) {
return Result.failed(e.getMessage());
}
......
package com.dituhui.pea.order.controller;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.enums.StatusCodeEnum;
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.enums.OrderStatusEnum;
import com.dituhui.pea.order.enums.ServiceStatusEnum;
import com.dituhui.pea.order.dao.TableCodeCheckDao;
import com.dituhui.pea.order.dto.param.BaseDistance;
import com.dituhui.pea.order.dto.param.BaseDistanceParam;
......@@ -18,9 +22,12 @@ import com.dituhui.pea.order.entity.TypeCodeCheckTableEntity;
import com.dituhui.pea.order.service.CapacityQueryService;
import com.dituhui.pea.order.service.EngineerCalendarService;
import com.dituhui.pea.order.service.OrderCreateService;
import com.dituhui.pea.order.service.OrderInfoService;
import com.dituhui.pea.order.service.PeaOuterAPIService;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
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.GetMapping;
......@@ -54,8 +61,11 @@ public class PeaApiController {
private final EngineerCalendarService engineerCalendarService;
private final PeaOuterAPIService peaOuterAPIService;
@Autowired
private OrderCreateService orderCreateService;
@Autowired
private OrderInfoService orderInfoService;
private final CapacityQueryService capacityQueryService;
private final OrderCreateService orderCreateService;
private final TableCodeCheckDao tableCodeCheckDao;
......@@ -228,8 +238,10 @@ public class PeaApiController {
*/
@PostMapping("/order/stage/change")
public Result<?> orderStageChanged(@Validated @RequestBody OrderDTO.StageChangeRequest request) {
return Result.success(null);
if (StringUtils.isBlank(request.getOrderId())) {
return Result.failed(StatusCodeEnum.COMMON_PARAM_EMPTY);
}
return orderInfoService.orderStageChanged(request);
}
/**
......
......@@ -16,4 +16,6 @@ public interface OrgBranchDao extends JpaRepository<OrgBranchEntity, Integer> {
OrgBranchEntity getByBranchId(String branchId);
public List<OrgBranchEntity> findByBranchIdIn(List<String> ids);
public OrgBranchEntity findByCitycodeListLike(String citycodeList);
}
......@@ -23,6 +23,14 @@ public class BusinessTeamDetailDTO {
private String groupName;
private String warehouseId;
private List<String> workdays;
/**
* 下班时间
*/
private String workOff;
/**
* 上班时间
*/
private String workOn;
}
......
package com.dituhui.pea.order.dto;
import com.dituhui.pea.order.dto.param.Location;
import lombok.Data;
@Data
public class OrderReschedule {
private String orderId;
private String expectBegin;
private String expectEnd;
private String expectDesc;
private String orderId;
private String expectBegin;
private String expectEnd;
private String expectDesc;
/**
* 操作员
*/
private String operator;
/**
* 操作员
*/
private String operator;
/**
* 地址坐标信息
*/
private Location happenLocation;
/**
* 备注
*/
private String description;
}
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;
......@@ -109,6 +108,7 @@ public class OrderDTO {
int hour = DateUtils.toCalendar(date).get(Calendar.HOUR_OF_DAY);
System.out.println("当前小时为:" + hour);
}
/**
* 预约描述时间(全天/上午/下午)
*/
......@@ -136,7 +136,7 @@ public class OrderDTO {
/**
* 是否指定某个工程师/是否排除某个工程师 0:否 1:指定 2:排除 默认0
*/
private int isAppointEngineer;
private Integer isAppointEngineer;
/**
* 指定某个工程师/排除某个工程师 codes
......@@ -185,9 +185,9 @@ public class OrderDTO {
/**
* 新预约时间, 特殊状态的时候填写:orderStatus为改约的时候填写
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date newReservationTime;
// @DateTimeFormat(pattern = "yyyy-MM-dd")
// @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private String newReservationTime;
/**
* 描述信息
......
package com.dituhui.pea.order.enums;
import org.apache.commons.lang3.StringUtils;
/**
* bean 服务状态枚举
*/
public enum BeanServiceFlowEnum {
//bean 已联系/准备服务/开始服务/结束服务等
//pea 服务状态:INIT-初始化/PENDING待服务/CONTACTED已排期/STARTED-已开始/FINISHED已完成/UNFINISHED-已上门未完成
PENDING("已联系", "PENDING"),
CONTACTED("准备服务", "CONTACTED"),
STARTED("开始服务", "STARTED"),
FINISHED("结束服务", "FINISHED");
private String name;
private String status;
BeanServiceFlowEnum(String name, String status) {
this.name = name;
this.status = status;
}
public String getName() {
return name;
}
public String getStatus() {
return status;
}
public static String getStatusByName(String name) {
if (StringUtils.isBlank(name)) {
return null;
}
for (BeanServiceFlowEnum value : BeanServiceFlowEnum.values()) {
if (name.equals(value.name)) {
return value.status;
}
}
return null;
}
}
package com.dituhui.pea.order.enums;
public enum OrderStatus {
CREATE("创建订单"),
NORMAL("正常"),
CANCELED("已取消"),
RESCHEDULED("已改约"),
ASSIGN("工单指派");
private final String description;
OrderStatus(String description){
this.description = description;
};
public String getDescription() {
return description;
}
public static String getEnumName(OrderStatus orderStatus){
return orderStatus.toString();
}
}
package com.dituhui.pea.order.enums;
public enum OrderStatusEnum {
CREATE("创建订单", "CREATE"),
NORMAL("正常", "NORMAL"),
CANCELED("已取消", "CANCELED"),
RESCHEDULED("已改约", "RESCHEDULED"),
ASSIGN("工单指派", "ASSIGN");
private final String description;
private final String code;
OrderStatusEnum(String description, String code) {
this.description = description;
this.code = code;
}
public String getDescription() {
return description;
}
public String getCode() {
return code;
}
public static String getEnumName(OrderStatusEnum orderStatus) {
return orderStatus.toString();
}
}
package com.dituhui.pea.order.enums;
public enum ServiceStatus {
// 服务状态:INIT-初始化/PENDING待服务/CONTACTED已排期/STARTED-已开始/FINISHED已完成/UNFINISHED-已上门未完成
INIT("待服务"),
PENDING("待服务"),
CONTACTED("已排期"),
STARTED("已开始"),
FINISHED("已完成"),
UNFINISHED("已上门未完成");
public enum ServiceStatusEnum {
// 服务状态:INIT-初始化/PENDING待服务/CONTACTED已排期/STARTED-已开始/FINISHED已完成/UNFINISHED-已上门未完成
INIT("INIT", "待服务"),
PENDING("PENDING", "待服务"),
CONTACTED("CONTACTED", "已排期"),
STARTED("STARTED", "已开始"),
FINISHED("FINISHED", "已完成"),
UNFINISHED("UNFINISHED", "已上门未完成");
private final String description;
private final String code;
ServiceStatus(String description) {
this.description = description;
}
private final String description;
public String getDescription() {
return description;
}
ServiceStatusEnum(String code, String description) {
this.code = code;
this.description = description;
}
public static String getEnumName(ServiceStatus serviceStatus){
return serviceStatus.toString();
}
public String getDescription() {
return description;
}
public String getCode() {
return code;
}
public static String getEnumName(ServiceStatusEnum serviceStatus) {
return serviceStatus.toString();
}
}
......@@ -2,11 +2,14 @@ package com.dituhui.pea.order.service;
import com.dituhui.pea.order.dto.LabelValueDTO;
import java.time.LocalDateTime;
import java.util.List;
public interface CommonService {
void addOrderEvent(String orderId, String subOrderId, String source, String operator, String event, String content, String memo);
void addOrderEvent(String orderId, String subOrderId, String source, String operator, String event, String content, String memo, LocalDateTime createTime);
List<LabelValueDTO> getSpecialParams(String catalog, String biztype);
}
......@@ -7,6 +7,8 @@ import com.dituhui.pea.order.dto.param.OrgTeamInfo;
import com.dituhui.pea.pojo.saas.req.AdministrativeDistrictReq;
import com.dituhui.pea.pojo.saas.resp.AdministrativeDistrictResp;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;
public interface FendanService {
......@@ -27,5 +29,17 @@ public interface FendanService {
*/
Result<List<OrgGroupInfo>> fendanToGroup(OrderDTO.OrderCreateRequest request);
/**
* 分单到工作队
*
* @param request
* @param isDate 是否是日期,0 :false 1:是
* @param targetDate 日期
* @param startTime 开始时间
* @param endTime 结束时间
* @return
*/
Result<OrgTeamInfo> fendanToGroupCapacity(OrderDTO.OrderCreateRequest request, Integer isDate, LocalDate targetDate, LocalTime startTime, LocalTime endTime);
Result<AdministrativeDistrictResp> getAdminDistrict(AdministrativeDistrictReq req);
}
package com.dituhui.pea.order.service;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dto.OrderReschedule;
import com.dituhui.pea.order.dto.param.OrderDTO;
import java.time.LocalDate;
......@@ -26,4 +28,20 @@ public interface OrderInfoService {
* @return 有则返回多条订单关联id,没有则不是一家多单
*/
Result deleteMultipleOrders(String multipleOrders, String orderId);
/**
* 工单变更处理
*
* @param request
* @return
*/
Result<?> orderStageChanged(OrderDTO.StageChangeRequest request);
/**
* 改约
*
* @param req
* @return
*/
Result<?> orderReschedule(OrderReschedule req);
}
......@@ -266,7 +266,7 @@ public class BusinessBlockServiceImpl implements BusinessBlockService {
@Transactional
@Override
public Result<?> businessServiceBlockRemove(String blockId) throws BusinessException {
MapBlockInfoEntity block = mapBlockInfoDao.findByAreaIds(blockId);
MapBlockInfoEntity block = mapBlockInfoDao.getById(Integer.parseInt(blockId));
if (block == null) {
throw new BusinessException("区块不存在");
}
......@@ -274,12 +274,12 @@ public class BusinessBlockServiceImpl implements BusinessBlockService {
entityManager.merge(block);
// 同步删除saas区块
String result = saasRemoteService.deleteArea(ak, blockId);
log.info("params:{} result:{}", blockId, result);
Result<Boolean> saasResult = TypeUtils.convertResult(result);
if (!ResultEnum.SUCCESS.getCode().equals(saasResult.getCode())) {
return Result.failure("删除失败,请联系管理员");
}
// String result = saasRemoteService.deleteArea(ak, blockId);
// log.info("params:{} result:{}", blockId, result);
// Result<Boolean> saasResult = TypeUtils.convertResult(result);
// if (!ResultEnum.SUCCESS.getCode().equals(saasResult.getCode())) {
// return Result.failure("删除失败,请联系管理员");
// }
return Result.success(null);
}
......
......@@ -258,6 +258,8 @@ public class BusinessTeamServiceImpl implements BusinessTeamService {
.setGroupId(g.getGroupId())
.setGroupName(g.getGroupName())
.setWarehouseId(teamEntity.getWarehouseId())
.setWorkOff(teamEntity.getWorkOff())
.setWorkOn(teamEntity.getWorkOn())
.setWorkdays(Arrays.asList(teamEntity.getWorkdays().split(",")));
List<String> engineerCodes = orgTeamEngineerDao.findAllByTeamId(teamEntity.getTeamId()).stream()
.map(OrgTeamEngineerEntity::getEngineerCode).collect(Collectors.toList());
......
......@@ -39,10 +39,10 @@ public class CommonServiceImpl implements CommonService {
public void addOrderEvent(String orderId, String subOrderId, String source, String operator, String event, String content, String memo) {
OrderEventEntity entity = new OrderEventEntity();
if (StringUtils.isBlank(source)){
if (StringUtils.isBlank(source)) {
source = "SYSTEM";
}
if (StringUtils.isBlank(operator)){
if (StringUtils.isBlank(operator)) {
operator = "PEA-WEB";
}
entity.setOrderId(orderId).setSuborderId(subOrderId).setSource(source).setOperator(operator).setOperatorName(operator);
......@@ -52,9 +52,24 @@ public class CommonServiceImpl implements CommonService {
}
@Override
public void addOrderEvent(String orderId, String subOrderId, String source, String operator, String event, String content, String memo, LocalDateTime createTime) {
OrderEventEntity entity = new OrderEventEntity();
if (StringUtils.isBlank(source)) {
source = "SYSTEM";
}
if (StringUtils.isBlank(operator)) {
operator = "PEA-WEB";
}
entity.setOrderId(orderId).setSuborderId(subOrderId).setSource(source).setOperator(operator).setOperatorName(operator);
entity.setEvent(event).setDescription(content).setMemo(memo);
entity.setCreateTime(createTime).setUpdateTime(createTime);
orderEventDao.save(entity);
}
@Override
public List<LabelValueDTO> getSpecialParams(String catalog, String biztype) {
List<PubParamsEntity> params = pubParamsDao.findByCatalogAndBiztype(catalog, biztype);
return params.stream().map(entity ->{
return params.stream().map(entity -> {
return new LabelValueDTO()
.setLabel(entity.getPlabel())
.setValue(entity.getPvalue());
......
......@@ -12,7 +12,7 @@ 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.enums.OrderStatusEnum;
import com.dituhui.pea.order.service.DispatchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
......@@ -242,7 +242,7 @@ public class DispatchServiceImpl implements DispatchService {
item.setAppointmentStatus(o.getAppointmentStatus());
item.setOrderStatus(o.getOrderStatus()); // 订单状态
item.setServiceStatus(o.getServiceStatus());
item.setOrderStatusDesc(OrderStatus.valueOf(o.getOrderStatus()).getDescription());
item.setOrderStatusDesc(OrderStatusEnum.valueOf(o.getOrderStatus()).getDescription());
item.setCreateTime(TimeUtils.IsoLocalDateTime2String(o.getCreateTime()));
item.setMultipleOrders(o.getMultipleOrders());
......
package com.dituhui.pea.order.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.enums.StatusCodeEnum;
import com.dituhui.pea.order.common.SaasUtils;
import com.dituhui.pea.order.dao.*;
import com.dituhui.pea.order.dto.param.CapacityQueryDTO;
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.CapacityQueryService;
import com.dituhui.pea.order.service.FendanService;
import com.dituhui.pea.pojo.fendan.FendanDTO;
import com.dituhui.pea.pojo.saas.req.AdministrativeDistrictReq;
import com.dituhui.pea.pojo.saas.resp.AdministrativeDistrictResp;
import com.dituhui.pea.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
......@@ -37,6 +43,10 @@ public class FendanServiceImpl implements FendanService {
private EngineerInfoDao engineerInfoDao;
@Autowired
private OrgTeamEngineerDao orgTeamEngineerDao;
@Autowired
private SkillInfoDao skillInfoDao;
@Autowired
private CapacityQueryService capacityQueryService;
private static String allLayerId = "ALL";
......@@ -207,6 +217,96 @@ public class FendanServiceImpl implements FendanService {
return Result.success(orgGroupTeamInfos);
}
/**
* 派工到工作队
*
* @param request
* @return
*/
@Override
public Result<OrgTeamInfo> fendanToGroupCapacity(OrderDTO.OrderCreateRequest request, Integer isDate, LocalDate targetDate, LocalTime startTime, LocalTime endTime) {
List<OrgGroupInfo> orgGroupTeamInfos = new ArrayList<>();
//1:根据经纬度分单获取面
FendanDTO fendanDTO = new FendanDTO();
fendanDTO.setXy(request.getLocation().getLongitude() + "," + request.getLocation().getLatitude());
List<SaasUtils.BlockInfo> blockInfos = saasUtils.queryBlocksByXy(fendanDTO);
if (blockInfos.isEmpty()) {
return Result.failed(StatusCodeEnum.FENDAN_AREA_UNMATCHED);
}
//2:根据服务范围匹配工作队
String peaBrand = fixBrand(request.getBrand());
List<String> blockIds = blockInfos.stream().map(SaasUtils.BlockInfo::getBlockId).distinct().collect(Collectors.toList());
List<MapBlockInfoEntity> mapBlockInBlockIdsList = new ArrayList<>();
//区划所在范围所有工作队
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> mapBlockAllList = mapBlockSkillList.stream().map(MapBlockInfoEntity::getId).distinct().collect(Collectors.toList());
//筛选漏选工作队(处理全技能图层)和查出多余图层
List<MapBlockInfoEntity> mapBlockInfoList = new ArrayList<>();
for (MapBlockInfoEntity mapBlockInfoEntity : mapBlockInBlockIdsList) {
if (mapBlockAllList.contains(mapBlockInfoEntity.getId())) {
mapBlockInfoList.add(mapBlockInfoEntity);
}
if (mapBlockInfoEntity.getLayerId().equals(allLayerId)) {
mapBlockInfoList.add(mapBlockInfoEntity);
}
}
if (CollectionUtils.isEmpty(mapBlockInfoList)) {
return Result.failed(StatusCodeEnum.FENDAN_TEAM_UNMATCHED);
}
//3:按照派工顺序组装工作队数据
List<String> teamIdList = mapBlockInfoList.stream().map(MapBlockInfoEntity::getTeamId).distinct().collect(Collectors.toList());
List<OrgTeamEntity> teamList = orgTeamDao.findByTeamIdIn(teamIdList);
Map<String, OrgTeamEntity> teamMap = teamList.stream().collect(Collectors.toMap(OrgTeamEntity::getTeamId, e -> e));
List<OrgGroupEntity> orgGroupList = orgGroupDao.findByTeamIdIn(teamIdList);
for (OrgGroupEntity orgGroupEntity : orgGroupList) {
OrgGroupInfo orgGroup = BeanUtil.copyProperties(orgGroupEntity, OrgGroupInfo.class);
MapBlockInfoEntity allLayer = null;
for (int i = 0; i < mapBlockInfoList.size(); i++) {
if (!mapBlockInfoList.get(i).getGroupId().equals(orgGroupEntity.getGroupId())) {
continue;
}
OrgTeamEntity orgTeamEntity = teamMap.get(mapBlockInfoList.get(i).getTeamId());
//全技能数据放在最后
if (mapBlockInfoList.get(i).getLayerId().equals(allLayerId)) {
allLayer = mapBlockInfoList.get(i);
} else {
OrgTeamInfo orgTeamInfo = BeanUtil.copyProperties(orgTeamEntity, OrgTeamInfo.class);
orgGroup.setTeamInfos(Arrays.asList(orgTeamInfo));
}
//最后处理全技能数据
if (i == mapBlockInfoList.size() - 1 && null != allLayer) {
OrgTeamInfo orgTeamInfoAll = BeanUtil.copyProperties(orgTeamEntity, OrgTeamInfo.class);
orgGroup.setTeamInfos(Arrays.asList(orgTeamInfoAll));
allLayer = null;
}
}
orgGroupTeamInfos.add(orgGroup);
}
CapacityQueryDTO.Service service = new CapacityQueryDTO.Service();
service.setBrand(peaBrand);
service.setProductType(request.getProductType());
service.setServiceType(request.getServiceType());
SkillInfoEntity skillInfo = skillInfoDao.getByBrandAndTypeAndSkill(peaBrand, request.getProductType(), request.getServiceType());
for (OrgGroupInfo orgGroupInfo : orgGroupTeamInfos) {
CapacityQueryDTO.Segment capacity = isDate == 1 ? capacityQueryService.queryCapacityByTeam(orgGroupInfo.getTeamInfos().get(0).getTeamId(), service, targetDate) :
capacityQueryService.queryCapacityByTeam(orgGroupInfo.getTeamInfos().get(0).getTeamId(), service, targetDate, startTime, endTime);
if (ObjectUtil.isNotNull(capacity) && capacity.getStatus() == 1 && capacity.getMaxDuration() > skillInfo.getTakeTime()) {
return Result.success(orgGroupInfo.getTeamInfos().get(0));
}
}
return Result.failed(StatusCodeEnum.FENDAN_IS_TRANSCEND);
}
@Override
public Result<AdministrativeDistrictResp> getAdminDistrict(AdministrativeDistrictReq req) {
AdministrativeDistrictResp adminDistrict = saasUtils.getAdminDistrict(req);
......
package com.dituhui.pea.order.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.hutool.core.util.ObjectUtil;
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.*;
import com.dituhui.pea.order.dto.param.CapacityQueryDTO;
import com.dituhui.pea.order.dto.param.Location;
import com.dituhui.pea.order.dto.param.OrderDTO;
import com.dituhui.pea.order.dto.param.OrgTeamInfo;
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 com.dituhui.pea.order.enums.OrderStatusEnum;
import com.dituhui.pea.order.enums.ServiceStatusEnum;
import com.dituhui.pea.order.service.*;
import com.dituhui.pea.order.utils.CommonUtil;
import com.dituhui.pea.pojo.saas.req.AdministrativeDistrictReq;
import com.dituhui.pea.pojo.saas.resp.AdministrativeDistrictResp;
import com.dituhui.pea.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -22,12 +28,10 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.Query;
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.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
......@@ -67,6 +71,21 @@ public class OrderAssignImpl implements OrderAssign {
@Autowired
private OrderInfoService orderInfoService;
@Autowired
private OrgGroupDao orgGroupDao;
@Autowired
private FendanService fendanService;
@Autowired
private OrgBranchDao orgBranchDao;
@Autowired
private MsgService msgService;
@Autowired
private CapacityQueryService capacityQueryService;
@Transactional
@Override
public Result<?> getOrderAssignRecommendEngineers(String orderId, String key, String distance, String recommend) {
......@@ -171,7 +190,7 @@ public class OrderAssignImpl implements OrderAssign {
order.setEngineerCode(engineer.getEngineerCode());
orderInfoDao.save(order);
// 工单变更登记
commonService.addOrderEvent(req.getOrderId(), "", "PEA-WEB", req.getOperator(), OrderStatus.ASSIGN.getDescription(), OrderStatus.ASSIGN.getDescription(), "");
commonService.addOrderEvent(req.getOrderId(), "", "PEA-WEB", req.getOperator(), OrderStatusEnum.ASSIGN.getDescription(), OrderStatusEnum.ASSIGN.getDescription(), "");
return Result.success(null);
}
......@@ -198,53 +217,32 @@ public class OrderAssignImpl implements OrderAssign {
@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("改约日期不能小于今日");
}
return null;
}
LocalDate originDate = order.getDt(); // 改约前的日期
private void sendMsg(String branchId, String orderId, String reservationTime) {
//发送通知分部消息
MsgDTO msgDTO = new MsgDTO();
msgDTO.setBranchId(branchId);
msgDTO.setType(0);
msgDTO.setOrderIds(orderId);
msgDTO.setTag(1);
msgDTO.setContent("有1条预约日期在" + reservationTime + "的工单需人工外理");
msgService.add(msgDTO);
}
// 更新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());
private OrderInfoEntity handleMultipleOrders(OrderInfoEntity order) {
//处理一家多单逻辑
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());
Result<String> multipleOrdersResult = orderInfoService.addMultipleOrders(order.getDt(), order.getAddressId(), order.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);
return order;
}
private List<String> searchEngineerCodes(OrderInfoEntity order, String distance, String key, String recommend) {
......
......@@ -16,11 +16,10 @@
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.enums.StatusCodeEnum;
import com.dituhui.pea.order.common.*;
import com.dituhui.pea.order.dao.*;
import com.dituhui.pea.order.dto.*;
......@@ -30,8 +29,9 @@ 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.enums.OrderFlowEnum;
import com.dituhui.pea.order.enums.OrderStatus;
import com.dituhui.pea.order.enums.OrderStatusEnum;
import com.dituhui.pea.order.service.*;
import com.dituhui.pea.order.utils.CommonUtil;
import com.dituhui.pea.pojo.saas.req.AdministrativeDistrictReq;
import com.dituhui.pea.pojo.saas.resp.AdministrativeDistrictResp;
import com.dituhui.pea.util.DateUtil;
......@@ -39,7 +39,6 @@ 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;
......@@ -47,14 +46,10 @@ 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;
import static com.dituhui.pea.order.config.OrderConfig.PATTERN_DATE;
import static com.dituhui.pea.order.config.OrderConfig.PATTERN_DATETIME;
@Slf4j
@Service
public class OrderCreateServiceImpl implements OrderCreateService {
......@@ -142,6 +137,9 @@ public class OrderCreateServiceImpl implements OrderCreateService {
String peaBrand = fixBrand(req.getBrand());
// location
Location location = req.getLocation();
//先处理时间,后面用
entity.setExpectTimeBegin(DateUtil.fromDate(req.getExpectBegin()));
entity.setExpectTimeEnd(DateUtil.fromDate(req.getExpectEnd()));
//获取省市区
AdministrativeDistrictReq administrativeDistrictReq = new AdministrativeDistrictReq();
administrativeDistrictReq.setPoints(location.getLongitude() + "," + location.getLatitude());
......@@ -151,9 +149,11 @@ public class OrderCreateServiceImpl implements OrderCreateService {
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())) {
Result<OrgTeamInfo> fendanResult = fendanService.fendanToGroupCapacity(req, 2, entity.getExpectTimeBegin().toLocalDate(), entity.getExpectTimeBegin().toLocalTime(), entity.getExpectTimeEnd().toLocalTime());
if (!fendanResult.getCode().equals(ResultEnum.SUCCESS.getCode()) || ObjectUtil.isNull(fendanResult.getResult())) {
if (fendanResult.getCode().equals(StatusCodeEnum.FENDAN_IS_TRANSCEND.getCode())) {
entity.setTranscend(1);
}
OrgGroupEntity groupDaoByCitycodeListLike = orgGroupDao.getByCitycodeListLike(adminDistrict.getResult().getSubNames().getCounty());
entity.setOrgClusterId(groupDaoByCitycodeListLike.getClusterId());
entity.setOrgBranchId(groupDaoByCitycodeListLike.getBranchId());
......@@ -166,20 +166,15 @@ public class OrderCreateServiceImpl implements OrderCreateService {
msgDTO.setContent("有1条预约日期在" + entity.getExpectTimeBegin().toLocalDate() + "的工单需人工外理");
msgService.add(msgDTO);
} else {
OrgTeamInfo teamInfo = fendanResult.getResult().get(0).getTeamInfos().get(0);
// 根据分单,填写clusterId/branchId/groupId/teamId等
// 根据分单工作队,填写clusterId/branchId/groupId/teamId等
OrgTeamInfo teamInfo = fendanResult.getResult();
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.setIsSpecialTime(CommonUtil.isSpecial(entity.getExpectTimeBegin().toLocalTime(),
entity.getExpectTimeEnd().toLocalTime(), teamInfo.getWorkOn(), teamInfo.getWorkOff()));
}
entity.setSource(req.getSource());
entity.setOrderId(orderId);
......@@ -190,8 +185,6 @@ public class OrderCreateServiceImpl implements OrderCreateService {
entity.setType(req.getProductType());
entity.setSkill(req.getServiceType());
entity.setFaultDescribe(req.getFaultDescribe());
entity.setExpectTimeBegin(DateUtil.fromDate(req.getExpectBegin()));
entity.setExpectTimeEnd(DateUtil.fromDate(req.getExpectEnd()));
entity.setExpectTimeDesc(req.getExpectDesc());
// 使用期望时间来初始化计划时间,后面在指派环节更新为真正的有效的计划时间
entity.setPlanStartTime(entity.getExpectTimeBegin());
......@@ -229,7 +222,7 @@ public class OrderCreateServiceImpl implements OrderCreateService {
// todo 服务单状态、预约状态等
orderInfoDao.save(entity);
// 登记
commonService.addOrderEvent(orderId, "", req.getSource(), "API", OrderStatus.CREATE.getDescription(), OrderStatus.CREATE.getDescription(), "");
commonService.addOrderEvent(orderId, "", req.getSource(), "API", OrderStatusEnum.CREATE.getDescription(), OrderStatusEnum.CREATE.getDescription(), "");
// 指派检查,简单处理,遇到第一个可以指派的就停止检查
// tryVirtualAppointment(entity, req.getSource(), teamId);
......
package com.dituhui.pea.order.service.impl;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
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.TimeUtils;
import com.dituhui.pea.order.dao.OrderInfoDao;
import com.dituhui.pea.order.dao.OrgBranchDao;
import com.dituhui.pea.order.dao.OrgGroupDao;
import com.dituhui.pea.order.dao.SkillInfoDao;
import com.dituhui.pea.order.dto.MsgDTO;
import com.dituhui.pea.order.dto.OrderReschedule;
import com.dituhui.pea.order.dto.param.*;
import com.dituhui.pea.order.entity.OrderInfoEntity;
import com.dituhui.pea.order.service.OrderInfoService;
import com.dituhui.pea.order.entity.OrgBranchEntity;
import com.dituhui.pea.order.entity.OrgGroupEntity;
import com.dituhui.pea.order.entity.SkillInfoEntity;
import com.dituhui.pea.order.enums.BeanServiceFlowEnum;
import com.dituhui.pea.order.enums.OrderStatusEnum;
import com.dituhui.pea.order.enums.ServiceStatusEnum;
import com.dituhui.pea.order.service.*;
import com.dituhui.pea.order.utils.CommonUtil;
import com.dituhui.pea.pojo.saas.req.AdministrativeDistrictReq;
import com.dituhui.pea.pojo.saas.resp.AdministrativeDistrictResp;
import com.dituhui.pea.util.DateUtil;
import com.dituhui.pea.util.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
......@@ -13,6 +35,9 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
......@@ -23,6 +48,27 @@ public class OrderInfoServiceImpl implements OrderInfoService {
@Autowired
private OrderInfoDao orderInfoDao;
@Autowired
private CommonService commonService;
@Autowired
private FendanService fendanService;
@Autowired
private OrgBranchDao orgBranchDao;
@Autowired
private MsgService msgService;
@Autowired
private CapacityQueryService capacityQueryService;
@Autowired
private SkillInfoDao skillInfoDao;
@Autowired
private OrgGroupDao orgGroupDao;
/**
* 新增订单处理一家多单逻辑
......@@ -34,6 +80,9 @@ public class OrderInfoServiceImpl implements OrderInfoService {
@Override
@Transactional
public Result<String> addMultipleOrders(LocalDate dt, String addressId, String orderId) {
if (StringUtils.isEmpty(addressId)) {
return Result.success(null);
}
List<OrderInfoEntity> infoList = orderInfoDao.findByDtAndAddressId(dt, addressId);
if (CollectionUtils.isEmpty(infoList)) {
return Result.success(null);
......@@ -84,4 +133,290 @@ public class OrderInfoServiceImpl implements OrderInfoService {
}
return Result.success();
}
/**
* 工单变更处理
*
* @param request
* @return
*/
@Override
@Transactional
public Result<?> orderStageChanged(OrderDTO.StageChangeRequest request) {
OrderInfoEntity orderInfo = orderInfoDao.getByOrderId(request.getOrderId());
//判断是否是正常流程,正常流程只需要更新状态
if (request.getOrderStatus().equalsIgnoreCase(OrderStatusEnum.NORMAL.getCode())) {
orderInfo.setServiceStatus(BeanServiceFlowEnum.getStatusByName(request.getStage()));
if (StringUtils.isNotBlank(request.getDescription())) {
orderInfo.setDescription(request.getDescription());
}
orderInfoDao.save(orderInfo);
//记录流程
commonService.addOrderEvent(request.getOrderId(), "", "BEAN", "BEAN", OrderStatusEnum.NORMAL.getDescription(), request.getStage(), "", LocalDateTimeUtil.of(request.getHappen()));
} else if (request.getOrderStatus().equalsIgnoreCase(OrderStatusEnum.CANCELED.getCode())) {
orderInfo.setServiceStatus(BeanServiceFlowEnum.FINISHED.getStatus());
orderInfo.setOrderStatus(OrderStatusEnum.CANCELED.getDescription());
if (StringUtils.isBlank(request.getDescription())) {
orderInfo.setDescription(request.getDescription());
}
orderInfoDao.save(orderInfo);
//记录流程
commonService.addOrderEvent(request.getOrderId(), "", "BEAN", "BEAN", OrderStatusEnum.CANCELED.getDescription(), request.getStage(), "", LocalDateTimeUtil.of(request.getHappen()));
} else if (request.getOrderStatus().equalsIgnoreCase(OrderStatusEnum.RESCHEDULED.getCode())) {
//组装改约接口
OrderReschedule reschedule = new OrderReschedule();
reschedule.setOrderId(orderInfo.getOrderId());
reschedule.setExpectBegin(DateUtil.handleDate(request.getNewReservationTime(), orderInfo.getExpectTimeBegin()));
reschedule.setExpectEnd(DateUtil.handleDate(request.getNewReservationTime(), orderInfo.getExpectTimeEnd()));
Location location = request.getHappenLocation();
if (ObjectUtil.isNull(location)) {
location = new Location();
location.setLongitude(Double.valueOf(orderInfo.getX()));
location.setLatitude(Double.valueOf(orderInfo.getY()));
location.setAddress(orderInfo.getAddress());
location.setAddressId(orderInfo.getAddressId());
} else {
orderInfo.setX(location.getLongitude().toString());
orderInfo.setY(location.getLongitude().toString());
orderInfo.setAddress(location.getAddress());
orderInfo.setAddressId(location.getAddressId());
}
reschedule.setHappenLocation(location);
if (StringUtils.isNotBlank(request.getDescription())) {
orderInfo.setDescription(request.getDescription());
}
return this.orderReschedule(reschedule);
// orderInfo.setServiceStatus(ServiceStatusEnum.INIT.getCode());
// orderInfo.setOrderStatus(OrderStatusEnum.RESCHEDULED.getCode());
// if (StringUtils.isBlank(request.getDescription())) {
// orderInfo.setDescription(request.getDescription());
// }
// Location location = request.getHappenLocation();
// if (ObjectUtil.isNull(location)) {
// location = new Location();
// location.setLongitude(Double.valueOf(orderInfo.getX()));
// location.setLatitude(Double.valueOf(orderInfo.getY()));
// location.setAddress(orderInfo.getAddress());
// location.setAddressId(orderInfo.getAddressId());
// } else {
// orderInfo.setX(location.getLongitude().toString());
// orderInfo.setY(location.getLongitude().toString());
// orderInfo.setAddress(location.getAddress());
// orderInfo.setAddressId(location.getAddressId());
// }
// //获取省市区
// AdministrativeDistrictReq administrativeDistrictReq = new AdministrativeDistrictReq();
// administrativeDistrictReq.setPoints(location.getLongitude() + "," + location.getLatitude());
// Result<AdministrativeDistrictResp> adminDistrict = fendanService.getAdminDistrict(administrativeDistrictReq);
// if (ObjectUtil.isNotEmpty(adminDistrict) && ObjectUtil.isNotEmpty(adminDistrict.getResult())) {
// orderInfo.setProvince(adminDistrict.getResult().getSubNames().getProvince());
// orderInfo.setCity(adminDistrict.getResult().getSubNames().getCity());
// orderInfo.setCounty(adminDistrict.getResult().getSubNames().getCounty());
// }
// // 分单处理
// String peaBrand = CommonUtil.fixBrand(orderInfo.getBrand());
// OrderDTO.OrderCreateRequest req = new OrderDTO.OrderCreateRequest();
// req.setBrand(peaBrand);
// req.setProductType(orderInfo.getType());
// req.setServiceType(orderInfo.getSkill());
// req.setLocation(location);
// Result<OrgTeamInfo> fendanResult = fendanService.fendanToGroupCapacity(req, 1, DateUtil.getLocalDateByDate(request.getNewReservationTime()), null, null);
// String branchId = "";
// String clusterId = "";
// if (!fendanResult.getCode().equals(ResultEnum.SUCCESS.getCode()) || ObjectUtil.isNull(fendanResult.getResult())) {
// OrgBranchEntity branchEntity = orgBranchDao.findByCitycodeListLike("%" + adminDistrict.getResult().getSubNames().getCounty() + "%");
// clusterId = branchEntity.getClusterId();
// branchId = branchEntity.getBranchId();
// sendMsg(branchEntity, orderInfo.getOrderId(), request.getNewReservationTime());
// } else {
// OrgTeamInfo teamInfo = fendanResult.getResult();
// clusterId = teamInfo.getClusterId();
// branchId = teamInfo.getBranchId();
// orderInfo.setOrgGroupId(teamInfo.getGroupId());
// orderInfo.setOrgTeamId(teamInfo.getTeamId());
// }
// orderInfo.setOrgClusterId(clusterId);
// orderInfo.setOrgBranchId(branchId);
// orderInfo.setDt(DateUtil.getLocalDateByDate(request.getNewReservationTime()));
// //一家多单
// Result<String> deleteMultipleOrders = this.deleteMultipleOrders(orderInfo.getMultipleOrders(), orderInfo.getAddressId());
// if (!deleteMultipleOrders.getCode().equals(ResultEnum.SUCCESS.getCode())) {
// return Result.failed("改约日期失败");
// }
// Result<String> addMultipleOrders = this.addMultipleOrders(orderInfo.getDt(), location.getAddressId(), orderInfo.getOrderId());
// if (!addMultipleOrders.getCode().equals(ResultEnum.SUCCESS.getCode())) {
// return Result.failed("改约日期失败");
// }
// orderInfo.setMultipleOrders(addMultipleOrders.getResult());
// orderInfoDao.save(orderInfo);
// //记录流程
// commonService.addOrderEvent(request.getOrderId(), "", "BEAN", "BEAN", OrderStatusEnum.CANCELED.getDescription(), request.getStage(), "", LocalDateTimeUtil.of(request.getHappen()));
}
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());
order.setDt(expectBegin.toLocalDate());
order.setExpectTimeBegin(expectBegin);
order.setExpectTimeEnd(expectEnd);
order.setExpectTimeDesc(req.getExpectDesc());
if (order == null) {
throw new BusinessException("订单不存在");
}
OrgGroupEntity groupEntity = orgGroupDao.getByGroupId(order.getOrgGroupId());
//是否今天
boolean isToday = DateUtil.judgeTimeIsToday(expectBegin);
//是否到人
boolean isBelong = StringUtils.isNotEmpty(order.getEngineerCode());
// 是否网点
boolean isNetwork = ObjectUtil.isNull(groupEntity) ? false : groupEntity.getCategory() == 2;
String branchId = order.getOrgBranchId();
String clusterId = order.getOrgClusterId();
//网点都需要重新指派
// a.已派人-改约到未来
// i.自有:优先改约指派给当前工程师
// ii.网点:优先改约指派给当前网点
// (不给当前工程师)
if (!isToday && isBelong) {
order = handleMultipleOrders(order);
} else if (isToday && isBelong) {
// b.已派人-改约到当天
// i.自有:优先改约指派给当前工程师
// (会影响该工程师当天后续工单的时
// 间窗),若超派则人工改派其他工程
// 师,辅助工程师同样需要人工重新指
// 派
// ii.网点:优先改约指派给当前网点
// (不给当前工程师)
if (!isNetwork) {
order.setServiceStatus(ServiceStatusEnum.INIT.getCode());
order.setOrderStatus(OrderStatusEnum.RESCHEDULED.getCode());
CapacityQueryDTO.Service service = new CapacityQueryDTO.Service();
service.setBrand(order.getBrand());
service.setProductType(order.getType());
service.setServiceType(order.getSkill());
CapacityQueryDTO.Segment capacity = capacityQueryService.queryEngineerCapacity(order.getEngineerCode(), service, order.getDt(), expectBegin.toLocalTime(), expectEnd.toLocalTime());
SkillInfoEntity skillInfo = skillInfoDao.getByBrandAndTypeAndSkill(order.getBrand(), order.getType(), order.getSkill());
if (ObjectUtil.isNull(capacity) || capacity.getStatus() != 1 || capacity.getMaxDuration() > skillInfo.getTakeTime()) {
order.setTranscend(1);
order.setOrgGroupId(null);
order.setOrgTeamId(null);
order.setEngineerCode(null);
clusterId = order.getOrgClusterId();
branchId = order.getOrgBranchId();
sendMsg(order.getOrgBranchId(), order.getOrderId(), req.getExpectBegin());
}
}
} else if (!isToday && !isBelong) {
// a.未派人-改约到未来
// i.动态排班
order.setServiceStatus(ServiceStatusEnum.INIT.getCode());
order.setOrderStatus(OrderStatusEnum.RESCHEDULED.getCode());
if (StringUtils.isBlank(req.getDescription())) {
order.setDescription(order.getDescription());
}
Location location = req.getHappenLocation();
if (ObjectUtil.isNull(location)) {
location = new Location();
location.setLongitude(Double.valueOf(order.getX()));
location.setLatitude(Double.valueOf(order.getY()));
location.setAddress(order.getAddress());
location.setAddressId(order.getAddressId());
} else {
order.setX(location.getLongitude().toString());
order.setY(location.getLongitude().toString());
order.setAddress(location.getAddress());
order.setAddressId(location.getAddressId());
}
//获取省市区
AdministrativeDistrictReq administrativeDistrictReq = new AdministrativeDistrictReq();
administrativeDistrictReq.setPoints(location.getLongitude() + "," + location.getLatitude());
Result<AdministrativeDistrictResp> adminDistrict = fendanService.getAdminDistrict(administrativeDistrictReq);
if (ObjectUtil.isNotEmpty(adminDistrict) && ObjectUtil.isNotEmpty(adminDistrict.getResult())) {
order.setProvince(adminDistrict.getResult().getSubNames().getProvince());
order.setCity(adminDistrict.getResult().getSubNames().getCity());
order.setCounty(adminDistrict.getResult().getSubNames().getCounty());
}
// 分单处理
String peaBrand = CommonUtil.fixBrand(order.getBrand());
OrderDTO.OrderCreateRequest fendanReq = new OrderDTO.OrderCreateRequest();
fendanReq.setBrand(peaBrand);
fendanReq.setProductType(order.getType());
fendanReq.setServiceType(order.getSkill());
fendanReq.setLocation(location);
Result<OrgTeamInfo> fendanResult = fendanService.fendanToGroupCapacity(fendanReq, 2, order.getDt(), expectBegin.toLocalTime(), expectEnd.toLocalTime());
if (!fendanResult.getCode().equals(ResultEnum.SUCCESS.getCode()) || ObjectUtil.isNull(fendanResult.getResult())) {
if (fendanResult.getCode().equals(StatusCodeEnum.FENDAN_IS_TRANSCEND.getCode())) {
order.setTranscend(1);
}
OrgBranchEntity branchEntity = orgBranchDao.findByCitycodeListLike("%" + adminDistrict.getResult().getSubNames().getCounty() + "%");
clusterId = branchEntity.getClusterId();
branchId = branchEntity.getBranchId();
sendMsg(branchEntity.getBranchId(), order.getOrderId(), req.getExpectBegin());
} else {
// 根据分单工作队,填写clusterId/branchId/groupId/teamId等
OrgTeamInfo teamInfo = fendanResult.getResult();
clusterId = teamInfo.getClusterId();
branchId = teamInfo.getBranchId();
order.setOrgGroupId(teamInfo.getGroupId());
order.setOrgTeamId(teamInfo.getTeamId());
//处理超派,特殊时间段
order.setIsSpecialTime(CommonUtil.isSpecial(order.getExpectTimeBegin().toLocalTime(),
order.getExpectTimeEnd().toLocalTime(), teamInfo.getWorkOn(), teamInfo.getWorkOff()));
}
//处理一家多单
order = handleMultipleOrders(order);
} else if (isToday && !isBelong) {
// b.未派人-改约到当天
// i.人工指派
OrgBranchEntity branchEntity = orgBranchDao.getByBranchId(order.getOrgBranchId());
clusterId = branchEntity.getClusterId();
branchId = branchEntity.getBranchId();
order.setOrgTeamId(null);
order.setOrgGroupId(null);
sendMsg(branchEntity.getBranchId(), order.getOrderId(), req.getExpectBegin());
}
order.setOrgClusterId(clusterId);
order.setOrgBranchId(branchId);
orderInfoDao.save(order);
// 登记事件
commonService.addOrderEvent(req.getOrderId(), "", "PEA-WEB", req.getOperator(), OrderStatusEnum.RESCHEDULED.getDescription(), OrderStatusEnum.RESCHEDULED.getDescription(), "");
return Result.success(null);
}
private void sendMsg(String branchId, String orderId, String reservationTime) {
//发送通知分部消息
MsgDTO msgDTO = new MsgDTO();
msgDTO.setBranchId(branchId);
msgDTO.setType(0);
msgDTO.setOrderIds(orderId);
msgDTO.setTag(1);
msgDTO.setContent("有1条预约日期在" + reservationTime + "的工单需人工外理");
msgService.add(msgDTO);
}
private OrderInfoEntity handleMultipleOrders(OrderInfoEntity order) {
//处理一家多单逻辑
Result<String> deleteMultipleOrders = this.deleteMultipleOrders(order.getMultipleOrders(), order.getAddressId());
if (!deleteMultipleOrders.getCode().equals(ResultEnum.SUCCESS.getCode())) {
throw new BusinessException("改约日期失败");
}
Result<String> multipleOrdersResult = this.addMultipleOrders(order.getDt(), order.getAddressId(), order.getOrderId());
if (!multipleOrdersResult.getCode().equals(ResultEnum.SUCCESS.getCode())) {
throw new BusinessException("改约日期失败");
}
order.setMultipleOrders(multipleOrdersResult.getResult());
return order;
}
}
......@@ -54,7 +54,9 @@ public class OrderServiceListServiceImpl implements OrderServiceListService {
lqw.le(OrderInfo::getDt, endDate); //预约开始日期
//筛选项
lqw.eq(StringUtils.isNotEmpty(reqDTO.getPhone()), OrderInfo::getPhone, reqDTO.getPhone());
lqw.eq(StringUtils.isNotEmpty(reqDTO.getOrderId()), OrderInfo::getOrderId, reqDTO.getOrderId());
if (StringUtils.isNotBlank(reqDTO.getOrderId())) {
lqw.in(StringUtils.isNotEmpty(reqDTO.getOrderId()), OrderInfo::getOrderId, reqDTO.getOrderId().split(","));
}
lqw.in(ListUtils.isNotEmpty(reqDTO.getBranchIds()), OrderInfo::getOrgBranchId, reqDTO.getBranchIds());
lqw.in(ListUtils.isNotEmpty(reqDTO.getGroupIds()), OrderInfo::getOrgGroupId, reqDTO.getGroupIds());
lqw.in(ListUtils.isNotEmpty(reqDTO.getTeamIds()), OrderInfo::getOrgTeamId, reqDTO.getTeamIds());
......
package com.dituhui.pea.order.utils;
import cn.hutool.core.util.StrUtil;
import com.dituhui.pea.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalTime;
import java.util.*;
@Slf4j
......@@ -63,4 +65,28 @@ public class CommonUtil {
calendar.add(Calendar.DATE, days);
return calendar.getTime();
}
/**
* 判断是否特殊时间段
*
* @return
*/
public static Integer isSpecial(LocalTime expectBegin, LocalTime expectEnd, String strOn, String strOff) {
LocalTime workOn = LocalTime.parse(strOn + ":00", DateUtil.TIME_FORMATTER);
LocalTime workOff = LocalTime.parse(strOff + ":00", DateUtil.TIME_FORMATTER);
if (expectBegin.isBefore(workOn) || expectEnd.isAfter(workOff)) {
return 1;
}
return 0;
}
public static String fixBrand(String brand) {
if (!brand.equals("嘉格纳")) {
return "博世/西门子以及其他品牌";
} else {
return brand;
}
}
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!