Commit f93ab0af by Ren Ping

feat:优化自动派单任务,支持如下功能

3.1,算法运行截止时间是动态的,根据工作队的cutoff配置来的,cutoff时间之后需要将订单'指派状态'改成'已指派'
3.3,算法需要根据工作队的网点指派策略/指派到人才进行自动派单
1 parent 04cc1926
......@@ -209,7 +209,6 @@ public class InitEngineerCapacityScheduler {
statEntity.setMaxDuration((int) stats.getRemain());
statEntity.setUpdateTime(LocalDateTime.now());
capacityEngineerStatDao.save(statEntity);
log.info("====== 处理完毕 ======");
}
public void initOneEngineerByDays(String bdate, String edate, String branchId) {
......
......@@ -69,7 +69,7 @@ public class BatchScheduler {
String currDay = LocalDate.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE);
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);
log.info("dispatchRun teamId:{}, day:{}, batch:{}, problemId:{}", teamId, currDay, batchNo, problemId);
......
......@@ -24,7 +24,7 @@ public interface BatchService {
void saveDispatchBatch(DispatchBatch batchInfo);
// 小队id
public String buildBatchData2(String teamId, String day);
public String buildBatchData2(String teamId, String day, boolean cutOff);
public DispatchBatch queryBatchInfoByDay2(String teamId, String day);
......
......@@ -192,7 +192,7 @@ public class BatchServiceImpl implements BatchService {
// 检查给定小队、日期是否有在运行的批次任务,没则返回,没有则创建
@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
@Override
public String buildBatchData2(String teamId, String day) {
public String buildBatchData2(String teamId, String day, boolean cutOff) {
OrgTeamEntity orgTeamEntity = orgTeamDao.findByTeamId(teamId);
String groupId = orgTeamEntity.getGroupId();
entityManager.clear();
......@@ -283,11 +283,11 @@ public class BatchServiceImpl implements BatchService {
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=?",
engCount, orderCount + orderConfirmCount, LocalDateTime.now(), teamId, batchNo);
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(), cutOff ? LocalDateTime.now() : null, teamId, batchNo);
} else {
jdbcTemplate.update("update dispatch_batch set engineer_num=? , order_num=?, start_time=?, end_time=?, status='DONE' where team_id=? and batch_no=?",
engCount, 0, LocalDateTime.now(), LocalDateTime.now(), teamId, batchNo);
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(), cutOff ? LocalDateTime.now() : null, teamId, batchNo);
}
log.info("准备批次数据完成, teamId:{}, day:{}, batchNo:{}", teamId, batchDay, batchNo);
......
package com.dituhui.pea.dispatch.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.dituhui.pea.dispatch.dao.DispatchBatchRepository;
import com.dituhui.pea.dispatch.dao.OrgTeamDao;
import com.dituhui.pea.dispatch.entity.DispatchBatch;
import com.dituhui.pea.dispatch.entity.OrgTeamEntity;
import com.dituhui.pea.dispatch.pojo.DispatchSolution;
import com.dituhui.pea.dispatch.service.BatchService;
......@@ -18,10 +22,13 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
/**
......@@ -34,6 +41,9 @@ import java.util.UUID;
@Slf4j
public class SchedulerServiceImpl implements SchedulerService {
//默认指派策略
public static final String DEFAULT_STRATEGY_APPOINTMENT = "指派给信息员";
@Value("${dispatch.cron.next-day-limit}")
int nextDaysLimit = 2;
......@@ -50,6 +60,9 @@ public class SchedulerServiceImpl implements SchedulerService {
OrgTeamDao orgTeamDao;
private DefaultSolverFactory<DispatchSolution> solverFactory;
@Resource
private DispatchBatchRepository dispatchBatchRepository;
//private Solver<DispatchSolution> solver;
public SchedulerServiceImpl() {
......@@ -65,14 +78,42 @@ public class SchedulerServiceImpl implements SchedulerService {
return;
}
if (StrUtil.equals(DEFAULT_STRATEGY_APPOINTMENT, orgTeamEntity.getStrategyAppointment())) {
log.error(">>> teamId:{} " + DEFAULT_STRATEGY_APPOINTMENT, 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();
log.info("dispatchRun group:{}, team:{} done", groupId, teamId);
for (int i = 1; i <= nextDaysLimit; i++) {
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 {
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);
log.info("dispatchRun teamId:{}, day:{}, batch:{}, problemId:{}", teamId, currDay, batchNo, problemId);
......@@ -88,7 +129,7 @@ public class SchedulerServiceImpl implements SchedulerService {
DispatchSolutionUtils.removeHardConstraintCustomer(solution, solverFactory);
log.info("dispatchRun solve done, teamId:{}, day:{}, batch:{}, problemId:{}, score:{}", teamId, currDay, batchNo, problemId, solution.getScore().toShortString());
this.solveService.saveSolutionWrp2(solution);
this.extractService.extractDispatchToOrder2(teamId, batchNo, false);
this.extractService.extractDispatchToOrder2(teamId, batchNo, cutOff);
log.info("dispatchRun done ------ teamId:{}, day:{}", teamId, currDay);
JacksonSolutionFileIO<DispatchSolution> exporter = new JacksonSolutionFileIO<DispatchSolution>(DispatchSolution.class);
......
......@@ -3,7 +3,7 @@ server:
dispatch:
cron:
expr: 0 47 8-22 * * ?
expr: 0 45 8-22 * * ?
next-day-limit: 2
# expr: 0 */10 8-18 * * ?
......@@ -49,12 +49,12 @@ spring:
enabled: false
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://127.0.0.1:3306/saas_aftersale_test?serverTimezone=Asia/Shanghai
# username: root
# password: 123456
url: jdbc:mysql://localhost:32306/saas_aftersale_test?serverTimezone=Asia/Shanghai
username: boxi
password: boxi_dev_0725
url: jdbc:mysql://127.0.0.1:3306/saas_aftersale_test?serverTimezone=Asia/Shanghai
username: root
password: 123456
# url: jdbc:mysql://localhost:32306/saas_aftersale_test?serverTimezone=Asia/Shanghai
# username: boxi
# password: boxi_dev_0725
type: com.alibaba.druid.pool.DruidDataSource
jpa:
......
......@@ -20,7 +20,7 @@
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
<level>DEBUG</level>
</filter>
<!-- 日志输出编码 -->
<encoder>
......@@ -111,9 +111,10 @@
</appender>
<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="FileAppender"/>
<appender-ref ref="FILE_ERROR"/>
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!