Commit a5572131 by 刘鑫

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

2 parents 03b4a352 8905fedb
Showing with 485 additions and 293 deletions
...@@ -26,7 +26,7 @@ public enum ConstraintNameEnum { ...@@ -26,7 +26,7 @@ public enum ConstraintNameEnum {
*/ */
technicianCapacityMatch, technicianCapacityMatch,
/** /**
* 已分配匹配 * 已分配和已排除技术员匹配
*/ */
dispatchedMatch, dispatchedMatch,
......
...@@ -93,10 +93,14 @@ public class DispatchConstraintProvider implements ConstraintProvider { ...@@ -93,10 +93,14 @@ public class DispatchConstraintProvider implements ConstraintProvider {
} }
protected Constraint dispatchedMatch(ConstraintFactory factory) { protected Constraint dispatchedMatch(ConstraintFactory factory) {
return factory.forEach(Customer.class) return factory.forEach(Customer.class).filter(customer ->
.filter(customer -> customer.getDispatchedTechnicianCode() != null // 已分配
&& ((customer.getTechnician() == null) || (!StringUtils (customer.getDispatchedTechnicianCode() != null && ((customer.getTechnician() == null)
.equals(customer.getDispatchedTechnicianCode(), customer.getTechnician().getCode())))) || (!StringUtils.equals(customer.getDispatchedTechnicianCode(), customer.getTechnician().getCode()))))
||
// 已排除
(customer.getExclusiveTechnicianCode() != null && ((customer.getTechnician() == null) || (StringUtils
.equals(customer.getExclusiveTechnicianCode(), customer.getTechnician().getCode())))))
.penalizeLong(HardSoftLongScore.ONE_HARD, customer -> 50) .penalizeLong(HardSoftLongScore.ONE_HARD, customer -> 50)
.asConstraint(ConstraintNameEnum.dispatchedMatch.name()); .asConstraint(ConstraintNameEnum.dispatchedMatch.name());
} }
......
...@@ -2,15 +2,24 @@ package com.dituhui.pea.dispatch.dao; ...@@ -2,15 +2,24 @@ package com.dituhui.pea.dispatch.dao;
import com.dituhui.pea.dispatch.entity.DispatchEngineer; import com.dituhui.pea.dispatch.entity.DispatchEngineer;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import java.util.List; import java.util.List;
import java.util.Map;
public interface DispatchEngineerRepository extends CrudRepository<DispatchEngineer, Long>, JpaRepository<DispatchEngineer, Long> { public interface DispatchEngineerRepository extends CrudRepository<DispatchEngineer, Long>, JpaRepository<DispatchEngineer, Long> {
List<DispatchEngineer> findByGroupId(String groupId); List<DispatchEngineer> findByGroupId(String groupId);
List<DispatchEngineer> findByGroupIdAndBatchNo(String groupId, String batchNo); List<DispatchEngineer> findByGroupIdAndBatchNo(String groupId, String batchNo);
List<DispatchEngineer> findByTeamIdAndBatchNo(String teamId, String batchNo); List<DispatchEngineer> findByTeamIdAndBatchNo(String teamId, String batchNo);
@Query(value = "SELECT ?1 group_id, o.team_id,?2 batch_no,o.engineer_code, a.name engineer_name, b.x, b.y , max_num, max_minute, max_distance, b.vehicle vehicle_type FROM `org_team_engineer` o\n"
+ " join engineer_info a on o.engineer_code=a.engineer_code\n"
+ " left join engineer_business b on a.engineer_code = b.engineer_code\n"
+ " WHERE o.team_id=?3 AND o.`status`=1\n",
nativeQuery = true)
List<Map<String,Object>> getNewDispatchEngineer(String groupId, String batchNo, String teamId);
} }
\ No newline at end of file
package com.dituhui.pea.dispatch.dao; package com.dituhui.pea.dispatch.dao;
import com.dituhui.pea.dispatch.entity.DispatchEngineer;
import com.dituhui.pea.dispatch.entity.DispatchOrder; import com.dituhui.pea.dispatch.entity.DispatchOrder;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
public interface DispatchOrderRepository extends CrudRepository<DispatchOrder, Long>, JpaRepository<DispatchOrder, Long> { public interface DispatchOrderRepository extends CrudRepository<DispatchOrder, Long>, JpaRepository<DispatchOrder, Long> {
...@@ -34,4 +36,30 @@ public interface DispatchOrderRepository extends CrudRepository<DispatchOrder, L ...@@ -34,4 +36,30 @@ public interface DispatchOrderRepository extends CrudRepository<DispatchOrder, L
Optional<DispatchOrder> findByGroupIdAndBatchNoAndOrderIdAndDt(String groupId, String batchNo, String orderId, String dt); Optional<DispatchOrder> findByGroupIdAndBatchNoAndOrderIdAndDt(String groupId, String batchNo, String orderId, String dt);
List<DispatchOrder> findByTeamIdAndBatchNo(String teamId, String batchNo); List<DispatchOrder> findByTeamIdAndBatchNo(String teamId, String batchNo);
@Query(value = " SELECT ?1 group_id, ?2 batch_no, a.org_team_id team_id, a.order_id, date_format(a.dt,'%Y-%m-%d') dt, a.x, a.y , \n"
+ " a.expect_time_begin, a.expect_time_end, a.tags, a.priority , \n"
+ " CONCAT(a.brand, '-', a.type, '-', a.skill) skills , a.take_time , a.appointment_status status\n"
+ " FROM order_info a \n" + " WHERE a.org_team_id=?3 AND a.dt = ?4 AND bean_status='OPEN'\n"
+ " AND appointment_method LIKE 'AUTO%' AND a.appointment_status IN ('INIT', 'PRE')\n"
+ " AND order_status ='NORMAL' AND service_status='INIT'\n"
+ " ORDER BY a.expect_time_begin ASC \n",
nativeQuery = true)
List<Map<String,Object>> getNewDispatchOrder(String groupId, String batchNo, String teamId, String batchDay);
@Query(value = " select ?1 group_id, ?2 batch_no, a.org_team_id team_id, a.order_id, date_format(a.dt,'%Y-%m-%d') dt, a.x, a.y , \n" +
" a.expect_time_begin, a.expect_time_end, a.tags, a.priority , \n" +
" concat(a.brand, '-', a.type, '-', a.skill) skills , a.take_time, a.appointment_status status, \n" +
" a.engineer_code, date_format(a.plan_start_time,'%Y-%m-%d %H:%i:%s') time_begin, date_format(a.plan_end_time,'%Y-%m-%d %H:%i:%s') time_end \n" +
" from order_info a \n" +
" where a.org_team_id=?3 and a.dt = ?4 and bean_status='OPEN'\n" +
" and appointment_method like 'AUTO%' and a.appointment_status in ('CONFIRM')\n" +
" and order_status ='NORMAL' and service_status='INIT'\n" +
" order by a.expect_time_begin asc ",
nativeQuery = true)
List<Map<String,Object>> getNewDispatchConfirmOrder(String groupId, String batchNo, String teamId, String batchDay);
} }
\ No newline at end of file
...@@ -21,8 +21,12 @@ public class Customer { ...@@ -21,8 +21,12 @@ public class Customer {
private long id; private long id;
private String code; private String code;
// 已分配 // 已分配
private String dispatchedTechnicianCode; private String dispatchedTechnicianCode;
// 已排除
private String exclusiveTechnicianCode;
// orderid(code)+dt 确定唯一一条工单 // orderid(code)+dt 确定唯一一条工单
private String dt; private String dt;
@JsonIgnore @JsonIgnore
......
...@@ -19,202 +19,203 @@ import lombok.Data; ...@@ -19,202 +19,203 @@ import lombok.Data;
@PlanningEntity @PlanningEntity
public class Technician { public class Technician {
@PlanningId @PlanningId
private long id; private long id;
private String code; private String code;
@JsonIgnore @JsonIgnore
private Depot depot; private Depot depot;
// 上班时间窗 分钟480-1080 8-18点 // 上班时间窗 分钟480-1080 8-18点
// private int startTime; // private int startTime;
// private int endTime; // private int endTime;
/** /**
* 上班多时间窗 * 上班多时间窗
* 时间窗格式:[[起始时间段1,结束时间段1],[起始时间段2,结束时间段2]...] * 时间窗格式:[[起始时间段1,结束时间段1],[起始时间段2,结束时间段2]...]
* 时间格式:从0点开始的分钟数,如早上8点为480. * 时间格式:从0点开始的分钟数,如早上8点为480.
*/ */
private int[][] timeWindows; private int[][] timeWindows;
// 技能 // 技能
private Set<String> skills; private Set<String> skills;
// 偏好坐标 // 偏好坐标
private Location preferredlocation; private Location preferredlocation;
// technician code : customer code , distance // technician code : customer code , distance
@JsonIgnore @JsonIgnore
private Map<String, Long> preferredlocationDistanceMap = new HashMap<String, Long>(); private Map<String, Long> preferredlocationDistanceMap = new HashMap<String, Long>();
// 每日最大单量 // 每日最大单量
private int maxCount; private int maxCount;
// 每日最大工作时长 // 每日最大工作时长
private int maxMinute; private int maxMinute;
// 单位是米,这里要注意 // 单位是米,这里要注意
private int maxDistanceMeter; private int maxDistanceMeter;
// 交通方式 1汽车;2电动车;3自行车;4步行 默认是汽车 // 交通方式 1汽车;2电动车;3自行车;4步行 默认是汽车
private Integer vehicleType; private Integer vehicleType;
@PlanningListVariable @PlanningListVariable
private List<Customer> customerList = new ArrayList<>(); private List<Customer> customerList = new ArrayList<>();
public Technician() { public Technician() {
} }
public Technician(long id, String code, Depot depot, int startTime, int endTime, Set<String> skills, public Technician(long id, String code, Depot depot, int startTime, int endTime, Set<String> skills,
Map<String, Long> preferredlocationDistanceMap, Location preferredlocation) { Map<String, Long> preferredlocationDistanceMap, Location preferredlocation) {
this.id = id; this.id = id;
this.code = code; this.code = code;
this.depot = depot; this.depot = depot;
this.timeWindows = new int[][] { new int[] { startTime, endTime } }; this.timeWindows = new int[][]{new int[]{startTime, endTime}};
this.skills = skills; this.skills = skills;
this.preferredlocationDistanceMap = preferredlocationDistanceMap; this.preferredlocationDistanceMap = preferredlocationDistanceMap;
this.preferredlocation = preferredlocation; this.preferredlocation = preferredlocation;
} }
public Technician(long id, String code, int maxCount, int maxMinute, int maxDistanceMeter, Depot depot, public Technician(long id, String code, int maxCount, int maxMinute, int maxDistanceMeter, Depot depot,
int startTime, int endTime, Set<String> skills, Map<String, Long> preferredlocationDistanceMap) { int startTime, int endTime, Set<String> skills, Map<String, Long> preferredlocationDistanceMap) {
this.id = id; this.id = id;
this.code = code; this.code = code;
this.depot = depot; this.depot = depot;
this.timeWindows = new int[][] { new int[] { startTime, endTime } }; this.timeWindows = new int[][]{new int[]{startTime, endTime}};
this.skills = skills; this.skills = skills;
this.maxCount = maxCount;
this.maxMinute = maxMinute;
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.maxCount = maxCount; this.maxCount = maxCount;
this.maxMinute = maxMinute; this.maxMinute = maxMinute;
this.maxDistanceMeter = maxDistanceMeter; this.maxDistanceMeter = maxDistanceMeter;
this.preferredlocationDistanceMap = preferredlocationDistanceMap; this.vehicleType = vehicleType;
} this.depot = depot;
this.timeWindows = new int[][]{new int[]{startTime, endTime}};
public Technician(long id, String code, int maxCount, int maxMinute, int maxDistanceMeter, Integer vehicleType, Depot depot, this.skills = skills;
int startTime, int endTime, Set<String> skills, Map<String, Long> preferredlocationDistanceMap) { this.preferredlocationDistanceMap = preferredlocationDistanceMap;
this.id = id; }
this.code = code;
this.depot = depot; // ************************************************************************
this.timeWindows = new int[][] { new int[] { startTime, endTime } }; // Complex methods
this.skills = skills; // ************************************************************************
this.maxCount = maxCount;
this.maxMinute = maxMinute; /**
this.maxDistanceMeter = maxDistanceMeter; * @return route of the vehicle
this.preferredlocationDistanceMap = preferredlocationDistanceMap; */
} @JsonIgnore
public List<Location> getRoute() {
// ************************************************************************ if (customerList.isEmpty()) {
// Complex methods return Collections.emptyList();
// ************************************************************************ }
/** List<Location> route = new ArrayList<Location>();
* @return route of the vehicle
*/ route.add(depot.getLocation());
@JsonIgnore for (Customer customer : customerList) {
public List<Location> getRoute() { route.add(customer.getLocation());
if (customerList.isEmpty()) { }
return Collections.emptyList();
} return route;
}
List<Location> route = new ArrayList<Location>();
/**
route.add(depot.getLocation()); * 总路线距离
for (Customer customer : customerList) { *
route.add(customer.getLocation()); * @return
} */
public long getTotalDistanceMeters() {
return route; if (customerList.isEmpty()) {
} return 0;
}
/**
* 总路线距离 long totalDistance = 0;
* Location previousLocation = depot.getLocation();
* @return
*/ for (Customer customer : customerList) {
public long getTotalDistanceMeters() { totalDistance += previousLocation.getDistanceTo(this.getVehicleType(), customer.getLocation());
if (customerList.isEmpty()) { previousLocation = customer.getLocation();
return 0; }
} totalDistance += previousLocation.getDistanceTo(this.getVehicleType(), depot.getLocation());
long totalDistance = 0; return totalDistance;
Location previousLocation = depot.getLocation(); }
for (Customer customer : customerList) { /**
totalDistance += previousLocation.getDistanceTo(this.getVehicleType(),customer.getLocation()); * 获取偏好总距离 所有customer与该技术员的PreferredLocation距离之和
previousLocation = customer.getLocation(); *
} * @return
totalDistance += previousLocation.getDistanceTo(this.getVehicleType(), depot.getLocation()); */
public long getPreferredTotalDistanceMeters() {
return totalDistance; if (customerList.isEmpty()) {
} return 0;
}
/**
* 获取偏好总距离 所有customer与该技术员的PreferredLocation距离之和 long totalDistance = 0;
* for (Customer customer : customerList) {
* @return totalDistance += preferredlocationDistanceMap.get(customer.getCode());
*/ }
public long getPreferredTotalDistanceMeters() { return totalDistance;
if (customerList.isEmpty()) { }
return 0;
} public int getCustomerSize() {
return customerList.size();
long totalDistance = 0; }
for (Customer customer : customerList) {
totalDistance += preferredlocationDistanceMap.get(customer.getCode()); /**
} * 获取总上班时间,第一个订单到最后一个订单时间跨度
return totalDistance; *
} * @return
*/
public int getCustomerSize() { public int getWorkTime() {
return customerList.size(); int size = customerList.size();
} if (0 == size) {
return 0;
/** } else {
* 获取总上班时间,第一个订单到最后一个订单时间跨度 return customerList.get(size - 1).getArrivalTime() + customerList.get(size - 1).getServiceDuration()
* - customerList.get(0).getArrivalTime();
* @return }
*/ }
public int getWorkTime() {
int size = customerList.size(); /**
if (0 == size) { * 获取下班时间,最后一个订单完成时间
return 0; *
} else { * @return
return customerList.get(size - 1).getArrivalTime() + customerList.get(size - 1).getServiceDuration() */
- customerList.get(0).getArrivalTime(); public int getOffWorkTime() {
} int size = customerList.size();
} if (0 == size) {
return 0;
/** } else {
* 获取下班时间,最后一个订单完成时间 Customer lastCustomer = customerList.get(size - 1);
* return lastCustomer.getDepartureTime();
* @return }
*/ }
public int getOffWorkTime() {
int size = customerList.size(); @Override
if (0 == size) { public int hashCode() {
return 0; return Long.valueOf(this.id).hashCode();
} else { }
Customer lastCustomer = customerList.get(size - 1);
return lastCustomer.getDepartureTime(); @Override
} public boolean equals(Object obj) {
} if (obj == null)
return false;
@Override if (!(obj instanceof Technician))
public int hashCode() { return false;
return Long.valueOf(this.id).hashCode(); if (obj == this)
} return true;
return this.id == ((Technician) obj).getId();
@Override }
public boolean equals(Object obj) {
if (obj == null) @Override
return false; public String toString() {
if (!(obj instanceof Technician)) return "Technician{" + "id=" + id + ", code='" + code + '\'' + ", depot=" + depot + ", timeWindows=" + timeWindows
return false; + ", skills=" + skills + ", maxCount=" + maxCount + ", maxMinute=" + maxMinute
if (obj == this) + ", maxDistanceMeter=" + maxDistanceMeter + '}';
return true; }
return this.id == ((Technician) obj).getId();
}
@Override
public String toString() {
return "Technician{" + "id=" + id + ", code='" + code + '\'' + ", depot=" + depot + ", timeWindows=" + timeWindows
+ ", skills=" + skills + ", maxCount=" + maxCount + ", maxMinute=" + maxMinute
+ ", maxDistanceMeter=" + maxDistanceMeter + '}';
}
} }
...@@ -209,7 +209,6 @@ public class InitEngineerCapacityScheduler { ...@@ -209,7 +209,6 @@ public class InitEngineerCapacityScheduler {
statEntity.setMaxDuration((int) stats.getRemain()); statEntity.setMaxDuration((int) stats.getRemain());
statEntity.setUpdateTime(LocalDateTime.now()); statEntity.setUpdateTime(LocalDateTime.now());
capacityEngineerStatDao.save(statEntity); capacityEngineerStatDao.save(statEntity);
log.info("====== 处理完毕 ======");
} }
public void initOneEngineerByDays(String bdate, String edate, String branchId) { public void initOneEngineerByDays(String bdate, String edate, String branchId) {
......
...@@ -69,7 +69,7 @@ public class BatchScheduler { ...@@ -69,7 +69,7 @@ public class BatchScheduler {
String currDay = LocalDate.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE); String currDay = LocalDate.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE);
log.info("dispatchRun begin----- teamId:{}, day:{}", teamId, currDay); log.info("dispatchRun begin----- teamId:{}, day:{}", teamId, currDay);
String batchNo = batchService.buildBatchData2(teamId, currDay); String batchNo = batchService.buildBatchData2(teamId, currDay, false);
UUID problemId = solveService.generateProblemId(teamId, batchNo); UUID problemId = solveService.generateProblemId(teamId, batchNo);
log.info("dispatchRun teamId:{}, day:{}, batch:{}, problemId:{}", teamId, currDay, batchNo, problemId); log.info("dispatchRun teamId:{}, day:{}, batch:{}, problemId:{}", teamId, currDay, batchNo, problemId);
......
...@@ -24,7 +24,7 @@ public interface BatchService { ...@@ -24,7 +24,7 @@ public interface BatchService {
void saveDispatchBatch(DispatchBatch batchInfo); void saveDispatchBatch(DispatchBatch batchInfo);
// 小队id // 小队id
public String buildBatchData2(String teamId, String day); public String buildBatchData2(String teamId, String day, boolean cutOff);
public DispatchBatch queryBatchInfoByDay2(String teamId, String day); public DispatchBatch queryBatchInfoByDay2(String teamId, String day);
......
...@@ -192,7 +192,7 @@ public class BatchServiceImpl implements BatchService { ...@@ -192,7 +192,7 @@ public class BatchServiceImpl implements BatchService {
// 检查给定小队、日期是否有在运行的批次任务,没则返回,没有则创建 // 检查给定小队、日期是否有在运行的批次任务,没则返回,没有则创建
@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class) @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
@Override @Override
public String buildBatchData2(String teamId, String day) { public String buildBatchData2(String teamId, String day, boolean cutOff) {
OrgTeamEntity orgTeamEntity = orgTeamDao.findByTeamId(teamId); OrgTeamEntity orgTeamEntity = orgTeamDao.findByTeamId(teamId);
String groupId = orgTeamEntity.getGroupId(); String groupId = orgTeamEntity.getGroupId();
entityManager.clear(); entityManager.clear();
...@@ -230,50 +230,64 @@ public class BatchServiceImpl implements BatchService { ...@@ -230,50 +230,64 @@ public class BatchServiceImpl implements BatchService {
//dispatchOrderRepository.deleteAllInBatch(dispatchOrderRepository.findByTeamIdAndBatchNo(teamId,batchNo)); //dispatchOrderRepository.deleteAllInBatch(dispatchOrderRepository.findByTeamIdAndBatchNo(teamId,batchNo));
log.info("写入新批次技术员、工单数据, teamId:{}, day:{}, batchNo:{}", teamId, batchDay, batchNo); log.info("写入新批次技术员、工单数据, teamId:{}, day:{}, batchNo:{}", teamId, batchDay, batchNo);
String sqlEngineer = "INSERT INTO dispatch_engineer (group_id, team_id, batch_no, engineer_code, engineer_name, x, y, max_num, max_minute, max_distance, vehicle_type)\n" // String sqlEngineer = "INSERT INTO dispatch_engineer (group_id, 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\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\n"
+ " join engineer_info a on o.engineer_code=a.engineer_code\n" // + " join engineer_info a on o.engineer_code=a.engineer_code\n"
+ " left join engineer_business b on a.engineer_code = b.engineer_code\n" // + " left join engineer_business b on a.engineer_code = b.engineer_code\n"
+ " WHERE o.team_id=? AND o.`status`=1\n" // + " WHERE o.team_id=? AND o.`status`=1\n"
//+ " AND b.x IS NOT NULL AND b.x !=''" // //+ " AND b.x IS NOT NULL AND b.x !=''"
+ " order by a.engineer_code asc"; // + " order by a.engineer_code asc";
int engCount = jdbcTemplate.update(sqlEngineer, groupId, batchNo, teamId); // int engCount = jdbcTemplate.update(sqlEngineer, groupId, batchNo, teamId);
List<Map<String, Object>> engMapList = dispatchEngineerRepository.getNewDispatchEngineer(groupId, batchNo, teamId);
List<DispatchEngineer> engList = JSONObject.parseArray(JSONObject.toJSONString(engMapList), DispatchEngineer.class);
engList.forEach(eng -> eng.setExt(null));
dispatchEngineerRepository.saveAll(engList);
int engCount = engList.size();
// 未派过的工单(已派过PRE状态还可以再次派) // 未派过的工单(已派过PRE状态还可以再次派)
String sqlOrder = "INSERT INTO dispatch_order (group_id, batch_no, team_id, order_id , dt, x, y, \n" // String sqlOrder = "INSERT INTO dispatch_order (group_id, batch_no, team_id, order_id , dt, x, y, \n"
+ " expect_time_begin, expect_time_end, tags, priority , skills , take_time, status )\n" // + " expect_time_begin, expect_time_end, tags, priority , skills , take_time, status )\n"
+ " SELECT ?, ?, a.org_team_id , a.order_id, ?, a.x, a.y , \n" // + " SELECT ? group_id, ? batch_no, a.org_team_id team_id, a.order_id, a.dt dt, a.x, a.y , \n"
+ " a.expect_time_begin, a.expect_time_end, a.tags, a.priority , \n" // + " a.expect_time_begin, a.expect_time_end, a.tags, a.priority , \n"
+ " CONCAT(a.brand, '-', a.type, '-', a.skill) skills , a.take_time , a.appointment_status\n" // + " CONCAT(a.brand, '-', a.type, '-', a.skill) skills , a.take_time , a.appointment_status status\n"
+ " FROM order_info a \n" + " WHERE a.org_team_id=? AND a.dt = ? AND bean_status='OPEN'\n" // + " FROM order_info a \n" + " WHERE a.org_team_id=? AND a.dt = ? AND bean_status='OPEN'\n"
+ " AND appointment_method LIKE 'AUTO%' AND a.appointment_status IN ('INIT', 'PRE')\n" // + " AND appointment_method LIKE 'AUTO%' AND a.appointment_status IN ('INIT', 'PRE')\n"
+ " AND order_status ='NORMAL' AND service_status='INIT'\n" // + " AND order_status ='NORMAL' AND service_status='INIT'\n"
+ " ORDER BY a.expect_time_begin ASC \n"; // + " ORDER BY a.expect_time_begin ASC \n";
int orderCount = jdbcTemplate.update(sqlOrder, groupId, batchNo, batchDay, teamId, batchDay); // int orderCount = jdbcTemplate.update(sqlOrder, groupId, batchNo, batchDay, teamId, batchDay);
List<Map<String, Object>> orderList = dispatchOrderRepository.getNewDispatchOrder(groupId, batchNo, teamId, batchDay);
dispatchOrderRepository.saveAll(JSONObject.parseArray(JSONObject.toJSONString(orderList), DispatchOrder.class));
int orderCount = orderList.size();
// confirm的要做预占用,所以也加入进来 // confirm的要做预占用,所以也加入进来
String sqlOrderConfirm = "INSERT INTO dispatch_order (group_id, batch_no, team_id, order_id , dt, x, y, \n" + // String sqlOrderConfirm = "INSERT INTO dispatch_order (group_id, batch_no, team_id, order_id , dt, x, y, \n" +
" expect_time_begin, expect_time_end, tags, priority , skills , take_time, status, engineer_code, time_begin, time_end )\n" + // " expect_time_begin, expect_time_end, tags, priority , skills , take_time, status, engineer_code, time_begin, time_end )\n" +
" select ?, ?, a.org_team_id , a.order_id, a.dt, a.x, a.y , \n" + // " select ? group_id, ? batch_no, a.org_team_id team_id, a.order_id, a.dt, a.x, a.y , \n" +
" a.expect_time_begin, a.expect_time_end, a.tags, a.priority , \n" + // " a.expect_time_begin, a.expect_time_end, a.tags, a.priority , \n" +
" concat(a.brand, '-', a.type, '-', a.skill) skills , a.take_time, a.appointment_status, \n" + // " concat(a.brand, '-', a.type, '-', a.skill) skills , a.take_time, a.appointment_status status, \n" +
" a.engineer_code, a.plan_start_time, a.plan_end_time \n" + // " a.engineer_code, a.plan_start_time time_begin, a.plan_end_time time_end \n" +
" from order_info a \n" + // " from order_info a \n" +
" where a.org_team_id=? and a.dt = ? and bean_status='OPEN'\n" + // " where a.org_team_id=? and a.dt = ? and bean_status='OPEN'\n" +
" and appointment_method like 'AUTO%' and a.appointment_status in ('CONFIRM')\n" + // " and appointment_method like 'AUTO%' and a.appointment_status in ('CONFIRM')\n" +
" and order_status ='NORMAL' and service_status='INIT'\n" + // " and order_status ='NORMAL' and service_status='INIT'\n" +
" order by a.expect_time_begin asc "; // " order by a.expect_time_begin asc ";
int orderConfirmCount = jdbcTemplate.update(sqlOrderConfirm, groupId, batchNo, teamId, batchDay); // int orderConfirmCount = jdbcTemplate.update(sqlOrderConfirm, groupId, batchNo, teamId, batchDay);
List<Map<String, Object>> orderConfirmList = dispatchOrderRepository.getNewDispatchConfirmOrder(groupId, batchNo, teamId, batchDay);
dispatchOrderRepository.saveAll(JSONObject.parseArray(JSONObject.toJSONString(orderConfirmList), DispatchOrder.class));
int orderConfirmCount = orderConfirmList.size();
log.info("准备批次数据 engCount:{}, orderCount:{}, orderConfirmCount:{}", engCount, orderCount, orderConfirmCount); log.info("准备批次数据 engCount:{}, orderCount:{}, orderConfirmCount:{}", engCount, orderCount, orderConfirmCount);
if (orderCount + orderConfirmCount > 0) { if (orderCount + orderConfirmCount > 0) {
jdbcTemplate.update("update dispatch_batch set engineer_num=? , order_num=?, start_time=?, end_time=null, status='RUNNING' where team_id=? and batch_no=?", jdbcTemplate.update("update dispatch_batch set engineer_num=? , order_num=?, start_time=?, end_time=null, status='RUNNING', cutoffed_time=? where team_id=? and batch_no=?",
engCount, orderCount + orderConfirmCount, LocalDateTime.now(), teamId, batchNo); engCount, orderCount + orderConfirmCount, LocalDateTime.now(), cutOff ? LocalDateTime.now() : null, teamId, batchNo);
} else { } else {
jdbcTemplate.update("update dispatch_batch set engineer_num=? , order_num=?, start_time=?, end_time=?, status='DONE' where team_id=? and batch_no=?", jdbcTemplate.update("update dispatch_batch set engineer_num=? , order_num=?, start_time=?, end_time=?, status='DONE', cutoffed_time=? where team_id=? and batch_no=?",
engCount, 0, LocalDateTime.now(), LocalDateTime.now(), teamId, batchNo); engCount, 0, LocalDateTime.now(), LocalDateTime.now(), cutOff ? LocalDateTime.now() : null, teamId, batchNo);
} }
log.info("准备批次数据完成, teamId:{}, day:{}, batchNo:{}", teamId, batchDay, batchNo); log.info("准备批次数据完成, teamId:{}, day:{}, batchNo:{}", teamId, batchDay, batchNo);
......
package com.dituhui.pea.dispatch.service.impl; package com.dituhui.pea.dispatch.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.dituhui.pea.dispatch.dao.DispatchBatchRepository;
import com.dituhui.pea.dispatch.dao.OrgGroupRepository;
import com.dituhui.pea.dispatch.dao.OrgTeamDao; import com.dituhui.pea.dispatch.dao.OrgTeamDao;
import com.dituhui.pea.dispatch.entity.DispatchBatch;
import com.dituhui.pea.dispatch.entity.OrgGroup;
import com.dituhui.pea.dispatch.entity.OrgTeamEntity; import com.dituhui.pea.dispatch.entity.OrgTeamEntity;
import com.dituhui.pea.dispatch.pojo.DispatchSolution; import com.dituhui.pea.dispatch.pojo.DispatchSolution;
import com.dituhui.pea.dispatch.service.BatchService; import com.dituhui.pea.dispatch.service.BatchService;
...@@ -18,10 +25,13 @@ import org.springframework.stereotype.Service; ...@@ -18,10 +25,13 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.File; import java.io.File;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
/** /**
...@@ -34,6 +44,9 @@ import java.util.UUID; ...@@ -34,6 +44,9 @@ import java.util.UUID;
@Slf4j @Slf4j
public class SchedulerServiceImpl implements SchedulerService { public class SchedulerServiceImpl implements SchedulerService {
//默认指派策略
public static final String DEFAULT_STRATEGY_APPOINTMENT = "指派给信息员";
@Value("${dispatch.cron.next-day-limit}") @Value("${dispatch.cron.next-day-limit}")
int nextDaysLimit = 2; int nextDaysLimit = 2;
...@@ -49,7 +62,13 @@ public class SchedulerServiceImpl implements SchedulerService { ...@@ -49,7 +62,13 @@ public class SchedulerServiceImpl implements SchedulerService {
@Autowired @Autowired
OrgTeamDao orgTeamDao; OrgTeamDao orgTeamDao;
@Autowired
OrgGroupRepository orgGroupRepository;
private DefaultSolverFactory<DispatchSolution> solverFactory; private DefaultSolverFactory<DispatchSolution> solverFactory;
@Resource
private DispatchBatchRepository dispatchBatchRepository;
//private Solver<DispatchSolution> solver; //private Solver<DispatchSolution> solver;
public SchedulerServiceImpl() { public SchedulerServiceImpl() {
...@@ -65,14 +84,44 @@ public class SchedulerServiceImpl implements SchedulerService { ...@@ -65,14 +84,44 @@ public class SchedulerServiceImpl implements SchedulerService {
return; return;
} }
OrgGroup orgGroup=orgGroupRepository.findByGroupId(orgTeamEntity.getGroupId()).get();
if (ObjectUtil.equals(2, orgGroup.getCategory())) {
log.error(">>> teamId:{} 来自网点,不自动派工", teamId);
return;
}
String cutOffTime = orgTeamEntity.getCuteOff();
if (StrUtil.isEmpty(cutOffTime)) {
cutOffTime = "18:00";
}
LocalDateTime now = LocalDateTime.now();
String nowTime = DateUtil.format(now, "HH:mm");
String nowTimePlus30 = DateUtil.format(now.plusMinutes(30), "HH:mm");
boolean cutOff = false;
//当前时间大于等于截止时间,或者当前时间+30分钟大于截止时间,运行停止
if (nowTime.compareTo(cutOffTime) >= 0 || nowTimePlus30.compareTo(cutOffTime) > 0) {
cutOff = true;
}
String groupId = orgTeamEntity.getGroupId(); String groupId = orgTeamEntity.getGroupId();
log.info("dispatchRun group:{}, team:{} done", groupId, teamId); log.info("dispatchRun group:{}, team:{} done", groupId, teamId);
for (int i = 1; i <= nextDaysLimit; i++) { for (int i = 1; i <= nextDaysLimit; i++) {
String currDay = LocalDate.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE); String currDay = LocalDate.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE);
Optional<DispatchBatch> optional = dispatchBatchRepository.findByTeamIdAndBatchDate(teamId, currDay);
if (optional.isPresent() && Objects.nonNull(optional.get().getCutoffedTime())) {
//自动任务截止
log.error(">>> teamId:{}, day:{} 自动任务已截止", teamId, currDay);
continue;
}
try { try {
log.info("dispatchRun begin----- teamId:{}, day:{}", teamId, currDay); log.info("dispatchRun begin----- teamId:{}, day:{}", teamId, currDay);
String batchNo = batchService.buildBatchData2(teamId, currDay); String batchNo = batchService.buildBatchData2(teamId, currDay, cutOff);
UUID problemId = solveService.generateProblemId(teamId, batchNo); UUID problemId = solveService.generateProblemId(teamId, batchNo);
log.info("dispatchRun teamId:{}, day:{}, batch:{}, problemId:{}", teamId, currDay, batchNo, problemId); log.info("dispatchRun teamId:{}, day:{}, batch:{}, problemId:{}", teamId, currDay, batchNo, problemId);
...@@ -88,7 +137,7 @@ public class SchedulerServiceImpl implements SchedulerService { ...@@ -88,7 +137,7 @@ public class SchedulerServiceImpl implements SchedulerService {
DispatchSolutionUtils.removeHardConstraintCustomer(solution, solverFactory); DispatchSolutionUtils.removeHardConstraintCustomer(solution, solverFactory);
log.info("dispatchRun solve done, teamId:{}, day:{}, batch:{}, problemId:{}, score:{}", teamId, currDay, batchNo, problemId, solution.getScore().toShortString()); log.info("dispatchRun solve done, teamId:{}, day:{}, batch:{}, problemId:{}, score:{}", teamId, currDay, batchNo, problemId, solution.getScore().toShortString());
this.solveService.saveSolutionWrp2(solution); this.solveService.saveSolutionWrp2(solution);
this.extractService.extractDispatchToOrder2(teamId, batchNo, false); this.extractService.extractDispatchToOrder2(teamId, batchNo, cutOff);
log.info("dispatchRun done ------ teamId:{}, day:{}", teamId, currDay); log.info("dispatchRun done ------ teamId:{}, day:{}", teamId, currDay);
JacksonSolutionFileIO<DispatchSolution> exporter = new JacksonSolutionFileIO<DispatchSolution>(DispatchSolution.class); JacksonSolutionFileIO<DispatchSolution> exporter = new JacksonSolutionFileIO<DispatchSolution>(DispatchSolution.class);
......
...@@ -3,7 +3,7 @@ server: ...@@ -3,7 +3,7 @@ server:
dispatch: dispatch:
cron: cron:
expr: 0 10 8-22 * * ? expr: 0 14 8-22 * * ?
next-day-limit: 2 next-day-limit: 2
# expr: 0 */10 8-18 * * ? # expr: 0 */10 8-18 * * ?
...@@ -49,12 +49,12 @@ spring: ...@@ -49,12 +49,12 @@ spring:
enabled: false enabled: false
datasource: datasource:
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://127.0.0.1:3306/saas_aftersale_test?serverTimezone=Asia/Shanghai url: jdbc:mysql://127.0.0.1:3306/saas_aftersale_test?serverTimezone=Asia/Shanghai
# username: root username: root
# password: 123456 password: 123456
url: jdbc:mysql://localhost:32306/saas_aftersale_test?serverTimezone=Asia/Shanghai # url: jdbc:mysql://localhost:32306/saas_aftersale_test?serverTimezone=Asia/Shanghai
username: boxi # username: boxi
password: boxi_dev_0725 # password: boxi_dev_0725
type: com.alibaba.druid.pool.DruidDataSource type: com.alibaba.druid.pool.DruidDataSource
jpa: jpa:
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<!-- 控制台输出 --> <!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level> <level>DEBUG</level>
</filter> </filter>
<!-- 日志输出编码 --> <!-- 日志输出编码 -->
<encoder> <encoder>
...@@ -111,9 +111,10 @@ ...@@ -111,9 +111,10 @@
</appender> </appender>
<logger name="org.optaplanner" level="info"/> <logger name="org.optaplanner" level="info"/>
<logger name="org.springframework.jdbc.core.JdbcTemplate" level="debug" />
<!-- 日志输出级别 --> <!-- 日志输出级别 -->
<root level="debug"> <root level="info">
<appender-ref ref="console"/> <appender-ref ref="console"/>
<appender-ref ref="FileAppender"/> <appender-ref ref="FileAppender"/>
<appender-ref ref="FILE_ERROR"/> <appender-ref ref="FILE_ERROR"/>
......
...@@ -140,7 +140,10 @@ public enum StatusCodeEnum { ...@@ -140,7 +140,10 @@ public enum StatusCodeEnum {
ORDER_SKILL_NOT_EXISTS("027", "订单所需技能不存在,请核对!", false), ORDER_SKILL_NOT_EXISTS("027", "订单所需技能不存在,请核对!", false),
ORDER_RESCHEDULE_BEFORE_TIME("028", "订单不能改约到当前时间以前!", false); ORDER_RESCHEDULE_BEFORE_TIME("028", "订单不能改约到当前时间以前!", false),
TEAM_UNMATCHED("029", "工程师没有匹配到工作队", false),
;
/** /**
* 状态码 * 状态码
......
package com.dituhui.pea.order.enums;
public enum OrderEventEnum {
// 建单,首次指派,改派,取消,改约,放回工单池
createOrder("建单", "%s通过%s创建服务工单:%s"),
firstAssignment("首次指派", "通过PEA派工给工程师%s"),
reassignment("改派", "通过PEA派工给工程师%s"),
cancel("取消", "%s在线指导解决"),
recontracting("改约", "工程师%s/%s已改约,改约时间%s,改约原因:%s"),
backOrderPool("放回工单池", "取消派工"),
;
private String event;
private String msg;
OrderEventEnum(String event, String msg) {
this.event = event;
this.msg = msg;
}
public String getEvent() {
return event;
}
public String getMsg() {
return msg;
}
}
...@@ -161,7 +161,7 @@ public class BeanRemoteServiceImpl { ...@@ -161,7 +161,7 @@ public class BeanRemoteServiceImpl {
return Result.failed(beanR.getMessage()); return Result.failed(beanR.getMessage());
} }
for (Department department : beanR.getData()) { for (Department department : beanR.getData()) {
if (StringUtils.isBlank(department.getBsDeptId())) { if (StringUtils.isNotBlank(department.getCode()) && department.getCode().contains("beanTest")) {
continue; continue;
} }
log.info("处理部门详情---->{}", department.getBsDeptId()); log.info("处理部门详情---->{}", department.getBsDeptId());
...@@ -193,8 +193,8 @@ public class BeanRemoteServiceImpl { ...@@ -193,8 +193,8 @@ public class BeanRemoteServiceImpl {
*/ */
private void disposeChildren(Department departments, String accessToken, Boolean isDisposeData, String parentId) { private void disposeChildren(Department departments, String accessToken, Boolean isDisposeData, String parentId) {
for (Department department : departments.getChildren()) { for (Department department : departments.getChildren()) {
if (StringUtils.isBlank(department.getBsDeptId())) { if (StringUtils.isNotBlank(department.getCode()) && department.getCode().contains("beanTest")) {
return; continue;
} }
log.info("处理部门详情---->{}", department.getBsDeptId()); log.info("处理部门详情---->{}", department.getBsDeptId());
if (!BeanRegionIdEnum.getEnumByRegionId(department.getBsDeptId())) { if (!BeanRegionIdEnum.getEnumByRegionId(department.getBsDeptId())) {
...@@ -212,7 +212,7 @@ public class BeanRemoteServiceImpl { ...@@ -212,7 +212,7 @@ public class BeanRemoteServiceImpl {
} }
disposeChildren(department, accessToken, isDisposeData, departments.getBsDeptId()); disposeChildren(department, accessToken, isDisposeData, departments.getBsDeptId());
//大区数据处理完重置 //大区数据处理完重置
if (department.getDeptLevel().equals(BeanOrgLevelEnum.REGION.getCode())) { if (StringUtils.isBlank(department.getDeptLevel()) || department.getDeptLevel().equals(BeanOrgLevelEnum.REGION.getCode())) {
isDisposeData = false; isDisposeData = false;
} }
} }
...@@ -293,15 +293,15 @@ public class BeanRemoteServiceImpl { ...@@ -293,15 +293,15 @@ public class BeanRemoteServiceImpl {
groupEntity.setWarehouseEnabled(data.getPeripheralWarehouseEnabled()); groupEntity.setWarehouseEnabled(data.getPeripheralWarehouseEnabled());
groupEntity.setReserveTimeMax(data.getPartReserveTimeMax()); groupEntity.setReserveTimeMax(data.getPartReserveTimeMax());
//处理clusterId和branchId //处理clusterId和branchId
OrgBranchEntity branchEntity = branchMap.get(data.getParentId()); OrgBranchEntity branchEntity = branchMap.get(data.getBelongedBranch());
if (ObjUtil.isNull(branchEntity)) { if (ObjUtil.isNull(branchEntity)) {
branchEntity = orgBranchDao.getByBranchId(data.getParentId()); branchEntity = orgBranchDao.getByBranchId(data.getBelongedBranch());
if (ObjUtil.isNull(branchEntity)) { if (ObjUtil.isNull(branchEntity)) {
return Result.failed(); return Result.failed();
} }
branchMap.put(data.getParentId(), branchEntity); branchMap.put(data.getBelongedBranch(), branchEntity);
} }
groupEntity.setBranchId(data.getParentId()); groupEntity.setBranchId(data.getBelongedBranch());
groupEntity.setClusterId(branchEntity.getClusterId()); groupEntity.setClusterId(branchEntity.getClusterId());
//处理分站外围 //处理分站外围
if (data.getDeptType().equals(BeanOrgLevelEnum.PERIPHERY.getCode())) { if (data.getDeptType().equals(BeanOrgLevelEnum.PERIPHERY.getCode())) {
......
...@@ -2,6 +2,7 @@ package com.dituhui.pea.order.service.impl; ...@@ -2,6 +2,7 @@ package com.dituhui.pea.order.service.impl;
import com.dituhui.pea.common.BusinessException; import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result; import com.dituhui.pea.common.Result;
import com.dituhui.pea.enums.StatusCodeEnum;
import com.dituhui.pea.order.common.ListUtils; import com.dituhui.pea.order.common.ListUtils;
import com.dituhui.pea.order.common.TimeUtils; import com.dituhui.pea.order.common.TimeUtils;
import com.dituhui.pea.order.dao.*; import com.dituhui.pea.order.dao.*;
...@@ -10,10 +11,12 @@ import com.dituhui.pea.order.dto.DispatchEngineerOrderListResp; ...@@ -10,10 +11,12 @@ import com.dituhui.pea.order.dto.DispatchEngineerOrderListResp;
import com.dituhui.pea.order.dto.DispatchOrderListReq; import com.dituhui.pea.order.dto.DispatchOrderListReq;
import com.dituhui.pea.order.dto.DispatchOrderListResp; import com.dituhui.pea.order.dto.DispatchOrderListResp;
import com.dituhui.pea.order.entity.*; import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.enums.AppointmentMethodEnum;
import com.dituhui.pea.order.enums.OrderFlowEnum; import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.enums.OrderGroupEnum; import com.dituhui.pea.order.enums.OrderGroupEnum;
import com.dituhui.pea.order.enums.OrderStatusEnum; import com.dituhui.pea.order.enums.OrderStatusEnum;
import com.dituhui.pea.order.service.DispatchService; import com.dituhui.pea.order.service.DispatchService;
import com.dituhui.pea.order.utils.CommonUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
...@@ -61,6 +64,9 @@ public class DispatchServiceImpl implements DispatchService { ...@@ -61,6 +64,9 @@ public class DispatchServiceImpl implements DispatchService {
@Autowired @Autowired
private OrgGroupDao orgGroupDao; private OrgGroupDao orgGroupDao;
@Autowired
private OrgTeamEngineerDao orgTeamEngineerDao;
@Transactional @Transactional
@Override @Override
public Result<?> getDispatchOrderList(DispatchOrderListReq reqDTO) { public Result<?> getDispatchOrderList(DispatchOrderListReq reqDTO) {
...@@ -279,35 +285,57 @@ public class DispatchServiceImpl implements DispatchService { ...@@ -279,35 +285,57 @@ public class DispatchServiceImpl implements DispatchService {
throw new BusinessException("订单不存在"); throw new BusinessException("订单不存在");
} }
// 已经指派的订单 List<OrgTeamEngineerEntity> orgTeamEngineers = orgTeamEngineerDao.findByEngineerCode(engineer.getEngineerCode());
List<OrderInfoEntity> engineerOrders = orderInfoDao.findByDtAndEngineerCode(localDate, engineerCode); if (CollectionUtils.isEmpty(orgTeamEngineers)) {
engineerOrders.sort(Comparator.comparing(OrderInfoEntity::getPlanStartTime)); // 按照planStartTime排序 return Result.failed(StatusCodeEnum.TEAM_UNMATCHED);
List<OrderInfoEntity> orderAppointments = engineerOrders.stream() }
.filter(o -> o.getOrderStatus().equals("NORMAL")) OrgTeamEntity byTeamId = orgTeamDao.getByTeamId(orgTeamEngineers.get(0).getTeamId());
.collect(Collectors.toList()); // 过滤,只有NORMAL订单才需要处理,取消订单不需要处理
for (OrderInfoEntity entity : orders) {
// TODO,临时处理方案,后续调用派单引擎处理 SkillInfoEntity skill = skillInfoDao.getByBrandAndTypeAndSkill(CommonUtil.fixBrand(entity.getBrand()), entity.getType(), entity.getSkill());
OrderRequestScheduler scheduler = new OrderRequestScheduler(); entity.setTakeTime(skill.getTakeTime());
List<LineSegment> results = scheduler.scheduler(orders, orderAppointments); entity.setPlanStartTime(entity.getExpectTimeBegin());
for (LineSegment r : results) { entity.setPlanEndTime(entity.getExpectTimeBegin().plusMinutes(skill.getTakeTime()));
String orderId = r.id; entity.setEngineerCode(engineer.getEngineerCode());
LocalDateTime planStartTime = scheduler.linePoint2DateTime(r.start, date); entity.setEngineerName(engineer.getName());
LocalDateTime planEndTime = scheduler.linePoint2DateTime(r.end, date); entity.setEngineerPhone(engineer.getPhone());
entity.setAppointmentStatus(OrderFlowEnum.CONFIRM.name());
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); entity.setAppointmentMethod(AppointmentMethodEnum.MANUAL.name());
CriteriaUpdate<OrderInfoEntity> update = criteriaBuilder.createCriteriaUpdate(OrderInfoEntity.class); entity.setOrgTeamId(byTeamId.getTeamId());
Root<OrderInfoEntity> root = update.from(OrderInfoEntity.class); entity.setOrgBranchId(byTeamId.getBranchId());
update.set(root.get("planStartTime"), planStartTime); entity.setOrgClusterId(byTeamId.getClusterId());
update.set(root.get("planEndTime"), planEndTime); orderInfoDao.save(entity);
update.set(root.get("appointmentStatus"), OrderFlowEnum.CONFIRM.name()); }
update.set(root.get("appointmentMethod"), "MANUAL"); //
update.set(root.get("engineerCode"), engineerCode); // // 已经指派的订单
update.where( // List<OrderInfoEntity> engineerOrders = orderInfoDao.findByDtAndEngineerCode(localDate, engineerCode);
criteriaBuilder.equal(root.get("orderId"), orderId), // engineerOrders.sort(Comparator.comparing(OrderInfoEntity::getPlanStartTime)); // 按照planStartTime排序
criteriaBuilder.equal(root.get("dt"), localDate) // List<OrderInfoEntity> orderAppointments = engineerOrders.stream()
); // .filter(o -> o.getOrderStatus().equals("NORMAL"))
entityManager.createQuery(update).executeUpdate(); // .collect(Collectors.toList()); // 过滤,只有NORMAL订单才需要处理,取消订单不需要处理
} //
// // TODO,临时处理方案,后续调用派单引擎处理
// OrderRequestScheduler scheduler = new OrderRequestScheduler();
// List<LineSegment> results = scheduler.scheduler(orders, orderAppointments);
// for (LineSegment r : results) {
// String orderId = r.id;
// LocalDateTime planStartTime = scheduler.linePoint2DateTime(r.start, date);
// LocalDateTime planEndTime = scheduler.linePoint2DateTime(r.end, date);
//
// CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// CriteriaUpdate<OrderInfoEntity> update = criteriaBuilder.createCriteriaUpdate(OrderInfoEntity.class);
// Root<OrderInfoEntity> root = update.from(OrderInfoEntity.class);
// update.set(root.get("planStartTime"), planStartTime);
// update.set(root.get("planEndTime"), planEndTime);
// update.set(root.get("appointmentStatus"), OrderFlowEnum.CONFIRM.name());
// update.set(root.get("appointmentMethod"), "MANUAL");
// update.set(root.get("engineerCode"), engineerCode);
// update.where(
// criteriaBuilder.equal(root.get("orderId"), orderId),
// criteriaBuilder.equal(root.get("dt"), localDate)
// );
// entityManager.createQuery(update).executeUpdate();
// }
return Result.success(null); return Result.success(null);
} }
......
...@@ -52,6 +52,7 @@ import com.dituhui.pea.order.entity.OrgTeamEngineerEntity; ...@@ -52,6 +52,7 @@ import com.dituhui.pea.order.entity.OrgTeamEngineerEntity;
import com.dituhui.pea.order.entity.OrgTeamEntity; import com.dituhui.pea.order.entity.OrgTeamEntity;
import com.dituhui.pea.order.entity.SkillInfoEntity; import com.dituhui.pea.order.entity.SkillInfoEntity;
import com.dituhui.pea.order.enums.AppointmentMethodEnum; import com.dituhui.pea.order.enums.AppointmentMethodEnum;
import com.dituhui.pea.order.enums.OrderEventEnum;
import com.dituhui.pea.order.enums.OrderFlowEnum; import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.enums.OrderStatusEnum; import com.dituhui.pea.order.enums.OrderStatusEnum;
import com.dituhui.pea.order.service.CommonService; import com.dituhui.pea.order.service.CommonService;
...@@ -308,14 +309,17 @@ public class OrderCreateServiceImpl implements OrderCreateService { ...@@ -308,14 +309,17 @@ public class OrderCreateServiceImpl implements OrderCreateService {
entity.setIsAppointEngineer(req.getIsAppointEngineer()); entity.setIsAppointEngineer(req.getIsAppointEngineer());
String appointEngineerCodes = CollectionUtils.isEmpty(req.getAppointEngineerCodes()) ? null : String.join(",", req.getAppointEngineerCodes()); String appointEngineerCodes = CollectionUtils.isEmpty(req.getAppointEngineerCodes()) ? null : String.join(",", req.getAppointEngineerCodes());
entity.setAppointEngineerCodes(appointEngineerCodes); entity.setAppointEngineerCodes(appointEngineerCodes);
OrgTeamEntity byTeamId = null;
String engineerName = null;
if (req.getIsAppointEngineer() == 1) { if (req.getIsAppointEngineer() == 1) {
EngineerInfoEntity engineerInfo = engineerInfoDao.getByEngineerCode(req.getAppointEngineerCodes().get(0)); EngineerInfoEntity engineerInfo = engineerInfoDao.getByEngineerCode(req.getAppointEngineerCodes().get(0));
List<OrgTeamEngineerEntity> orgTeamEngineers = orgTeamEngineerDao.findByEngineerCode(req.getAppointEngineerCodes().get(0)); List<OrgTeamEngineerEntity> orgTeamEngineers = orgTeamEngineerDao.findByEngineerCode(req.getAppointEngineerCodes().get(0));
if (CollectionUtils.isEmpty(orgTeamEngineers)) { if (CollectionUtils.isEmpty(orgTeamEngineers)) {
return Result.failed(StatusCodeEnum.FENDAN_TEAM_UNMATCHED); return Result.failed(StatusCodeEnum.FENDAN_TEAM_UNMATCHED);
} }
OrgTeamEntity byTeamId = orgTeamDao.getByTeamId(orgTeamEngineers.get(0).getTeamId()); byTeamId = orgTeamDao.getByTeamId(orgTeamEngineers.get(0).getTeamId());
entity.setEngineerCode(engineerInfo.getEngineerCode()); entity.setEngineerCode(engineerInfo.getEngineerCode());
engineerName = engineerInfo.getName();
entity.setEngineerName(engineerInfo.getName()); entity.setEngineerName(engineerInfo.getName());
entity.setEngineerPhone(engineerInfo.getPhone()); entity.setEngineerPhone(engineerInfo.getPhone());
entity.setEngineerPhone(engineerInfo.getPhone()); entity.setEngineerPhone(engineerInfo.getPhone());
...@@ -348,6 +352,9 @@ public class OrderCreateServiceImpl implements OrderCreateService { ...@@ -348,6 +352,9 @@ public class OrderCreateServiceImpl implements OrderCreateService {
entity.setAppointmentMethod(AppointmentMethodEnum.MANUAL.name()); entity.setAppointmentMethod(AppointmentMethodEnum.MANUAL.name());
//发送通知分部消息 //发送通知分部消息
sendMsg(branchEntity.getBranchId(), orderId, entity.getExpectTimeBegin().toLocalDate()); sendMsg(branchEntity.getBranchId(), orderId, entity.getExpectTimeBegin().toLocalDate());
Integer cutoff = CommonUtil.isCutoff(LocalDateTime.now(), null);
entity.setIsCutoff(cutoff);
} else { } else {
// 根据分单工作队,填写clusterId/branchId/groupId/teamId等 // 根据分单工作队,填写clusterId/branchId/groupId/teamId等
OrgTeamInfo teamInfo = fendanResult.getResult(); OrgTeamInfo teamInfo = fendanResult.getResult();
...@@ -361,10 +368,13 @@ public class OrderCreateServiceImpl implements OrderCreateService { ...@@ -361,10 +368,13 @@ public class OrderCreateServiceImpl implements OrderCreateService {
entity.getExpectTimeEnd().toLocalTime(), teamInfo.getWorkOn(), teamInfo.getWorkOff()); entity.getExpectTimeEnd().toLocalTime(), teamInfo.getWorkOn(), teamInfo.getWorkOff());
Integer cutoff = CommonUtil.isCutoff(LocalDateTime.now(), teamInfo.getWorkOff()); Integer cutoff = CommonUtil.isCutoff(LocalDateTime.now(), teamInfo.getWorkOff());
// 处理cutoff 动态排班结束后创建的当日单和次日单 // 处理cutoff 动态排班结束后创建的当日单和次日单
boolean isToday = DateUtil.judgeTimeIsToday(entity.getExpectTimeBegin());
boolean isTomorrow = DateUtil.judgeTimeIsisTomorrow(entity.getExpectTimeBegin()); boolean isTomorrow = DateUtil.judgeTimeIsisTomorrow(entity.getExpectTimeBegin());
//次日单自动批量
if (isTomorrow) {
entity.setAppointmentMethod(AppointmentMethodEnum.AUTO_BATCH.name());
}
// 特殊时间段,当天单,cutoff需要人工处理 // 特殊时间段,当天单,cutoff需要人工处理
if (isToday || (isTomorrow && cutoff == 1) || special == 1) { if (cutoff == 1 || special == 1) {
//判断是否在今天cutoff之后 //判断是否在今天cutoff之后
entity.setIsCutoff(cutoff); entity.setIsCutoff(cutoff);
entity.setIsSpecialTime(special); entity.setIsSpecialTime(special);
...@@ -414,7 +424,7 @@ public class OrderCreateServiceImpl implements OrderCreateService { ...@@ -414,7 +424,7 @@ public class OrderCreateServiceImpl implements OrderCreateService {
if (req.getPriority().equals("1")) { if (req.getPriority().equals("1")) {
entity.setAppointmentMethod(AppointmentMethodEnum.AUTO_NOW.name()); entity.setAppointmentMethod(AppointmentMethodEnum.AUTO_NOW.name());
//发送通知分部消息 //发送通知分部消息
sendMsg(entity.getOrgBranchId(), orderId, entity.getExpectTimeBegin().toLocalDate()); // sendMsg(entity.getOrgBranchId(), orderId, entity.getExpectTimeBegin().toLocalDate());
} }
entity.setIsMultiple(joinTags.contains("重物搬运") ? 1 : 0); entity.setIsMultiple(joinTags.contains("重物搬运") ? 1 : 0);
...@@ -424,7 +434,11 @@ public class OrderCreateServiceImpl implements OrderCreateService { ...@@ -424,7 +434,11 @@ public class OrderCreateServiceImpl implements OrderCreateService {
// 记录订单和节点 // 记录订单和节点
orderInfoDao.save(entity); orderInfoDao.save(entity);
commonService.addOrderEvent(orderId, "", req.getSource(), "API", OrderStatusEnum.CREATE.getDescription(), OrderStatusEnum.CREATE.getDescription(), ""); commonService.addOrderEvent(orderId, "", req.getSource(), "API", OrderEventEnum.createOrder.getEvent(), String.format(OrderEventEnum.createOrder.getMsg(), req.getSource(), "BEAN", req.getOrderId()), "");
if (req.getIsAppointEngineer() == 1) {
commonService.addOrderEvent(orderId, "", req.getSource(), "PEA", OrderEventEnum.firstAssignment.getEvent(), String.format(OrderEventEnum.firstAssignment.getMsg(), engineerName + "-" + byTeamId.getTeamName()), "");
}
return Result.success(null); return Result.success(null);
} }
......
...@@ -3,6 +3,7 @@ package com.dituhui.pea.order.utils; ...@@ -3,6 +3,7 @@ package com.dituhui.pea.order.utils;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.dituhui.pea.util.DateUtil; import com.dituhui.pea.util.DateUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
...@@ -88,6 +89,12 @@ public class CommonUtil { ...@@ -88,6 +89,12 @@ public class CommonUtil {
* @return * @return
*/ */
public static Integer isCutoff(LocalDateTime localTime, String strOff) { public static Integer isCutoff(LocalDateTime localTime, String strOff) {
if (DateUtil.judgeTimeIsToday(localTime)) {
return 1;
}
if (StringUtils.isBlank(strOff)) {
return 0;
}
LocalDateTime workOff = LocalDate.now().atTime(Integer.parseInt(strOff.split(":")[0]), Integer.parseInt(strOff.split(":")[1]), 0); LocalDateTime workOff = LocalDate.now().atTime(Integer.parseInt(strOff.split(":")[0]), Integer.parseInt(strOff.split(":")[1]), 0);
if (localTime.isAfter(workOff)) { if (localTime.isAfter(workOff)) {
return 1; return 1;
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!