Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
yangxiujun
/
paidan_demo
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit 102701f5
authored
Dec 08, 2023
by
Ren Ping
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:自动排版优化
1 parent
2c85e672
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
250 additions
and
94 deletions
project-dispatch/src/main/java/com/dituhui/pea/dispatch/constraint/ConstraintNameEnum.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/constraint/DispatchConstraintProvider.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/DispatchOrderRepository.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/OrderEventRepository.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/OrderInfoRepository.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/DispatchOrder.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/pojo/Customer.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/quartz/dispatch/AutoDispatchJob.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/BatchServiceImpl.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/ExtractServiceImpl.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/SolveServiceImpl.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/utils/DispatchSolutionUtils.java
project-dispatch/src/main/resources/application-dev.yaml
project-dispatch/src/main/java/com/dituhui/pea/dispatch/constraint/ConstraintNameEnum.java
View file @
102701f
...
...
@@ -2,46 +2,53 @@ package com.dituhui.pea.dispatch.constraint;
/**
* 约束枚举
*
* @author zhangguoping
*
* @author zhangguoping
*/
public
enum
ConstraintNameEnum
{
// 硬约束
/**
* 技术员技能跟订单相匹配
*/
skillMatch
,
/**
* 订单到达时间跟时间窗吻合
*/
customerTimeWindowsMatch
,
/**
* 技术员不加班
*/
technicianTimeWindowsMatch
,
/**
* 技术员订单数量不超过最大值
*/
technicianCapacityMatch
,
/**
* 已分配和已排除技术员匹配
*/
dispatchedMatch
,
// 软约束
/**
* 订单数量均衡
*/
technicianBalanceSoft
,
/**
* 总路程最小
*/
totalDistance
,
/**
* 技术员中心点偏好
*/
preferredTotalDistance
// 硬约束
/**
* 技术员技能跟订单相匹配
*/
skillMatch
,
/**
* 订单到达时间跟时间窗吻合
*/
customerTimeWindowsMatch
,
/**
* 工单副工程师和主工程师必须同时存在
*/
customerSubAndMainEngineerMustCoexist
,
/**
* 技术员不加班
*/
technicianTimeWindowsMatch
,
/**
* 技术员订单数量不超过最大值
*/
technicianCapacityMatch
,
/**
* 已分配和已排除技术员匹配
*/
dispatchedMatch
,
// 软约束
/**
* 订单数量均衡
*/
technicianBalanceSoft
,
/**
* 总路程最小
*/
totalDistance
,
/**
* 技术员中心点偏好
*/
preferredTotalDistance
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/constraint/DispatchConstraintProvider.java
View file @
102701f
...
...
@@ -3,6 +3,7 @@ package com.dituhui.pea.dispatch.constraint;
import
java.util.List
;
import
cn.hutool.core.util.StrUtil
;
import
com.dituhui.pea.dispatch.quartz.dispatch.AutoDispatchJob
;
import
org.optaplanner.core.api.score.buildin.hardsoftlong.HardSoftLongScore
;
import
org.optaplanner.core.api.score.stream.Constraint
;
import
org.optaplanner.core.api.score.stream.ConstraintFactory
;
...
...
@@ -26,6 +27,8 @@ public class DispatchConstraintProvider implements ConstraintProvider {
technicianCapacityMatch
(
factory
),
skillMatch
(
factory
),
dispatchedMatch
(
factory
),
//工单副工程师和主工程师必须同时存在
customerSubAndMainEngineerMustCoexist
(
factory
),
// 软约束
technicianBalanceSoft
(
factory
),
...
...
@@ -55,6 +58,15 @@ public class DispatchConstraintProvider implements ConstraintProvider {
.
asConstraint
(
ConstraintNameEnum
.
customerTimeWindowsMatch
.
name
());
}
//工单副工程师和主工程师必须同时存在
public
Constraint
customerSubAndMainEngineerMustCoexist
(
ConstraintFactory
factory
)
{
return
factory
.
forEach
(
Customer
.
class
).
filter
(
customer
->
customer
.
getCode
().
endsWith
(
AutoDispatchJob
.
SUB_ORDER_ID_SUFFIX
)
&&
null
!=
customer
.
getTechnician
()
&&
null
!=
customer
.
getMainCustomer
()
&&
null
==
customer
.
getMainCustomer
().
getTechnician
())
.
penalizeLong
(
HardSoftLongScore
.
ONE_HARD
,
Customer
->
1
).
asConstraint
(
ConstraintNameEnum
.
customerSubAndMainEngineerMustCoexist
.
name
());
}
protected
Constraint
technicianTimeWindowsMatch
(
ConstraintFactory
factory
)
{
return
factory
.
forEach
(
Technician
.
class
).
filter
(
technician
->
{
...
...
@@ -129,7 +141,9 @@ public class DispatchConstraintProvider implements ConstraintProvider {
protected
Constraint
skillMatch
(
ConstraintFactory
factory
)
{
return
factory
.
forEach
(
Customer
.
class
)
.
filter
(
customer
->
customer
.
getTechnician
()
!=
null
&&
!
customer
.
getCode
().
endsWith
(
"_sub"
)
&&
!
customer
.
getTechnician
().
getSkills
().
contains
(
customer
.
getRequiredSkill
()))
.
penalizeLong
(
HardSoftLongScore
.
ONE_HARD
,
// 技能匹配跟时间窗匹配存在很明显的跷跷板效应,权重小于3就会存在技能匹配问题
// 3-技能匹配问题1个,时间窗问题8个
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/DispatchOrderRepository.java
View file @
102701f
...
...
@@ -2,6 +2,7 @@ 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.quartz.dispatch.AutoDispatchJob
;
import
org.springframework.data.jpa.repository.JpaRepository
;
import
org.springframework.data.jpa.repository.Query
;
import
org.springframework.data.repository.CrudRepository
;
...
...
@@ -58,8 +59,21 @@ public interface DispatchOrderRepository extends CrudRepository<DispatchOrder, L
" where a.org_team_id=?3 and a.dt = ?4 and bean_status='OPEN'\n"
+
" and (appointment_method like 'AUTO%' or appointment_method='MANUAL') and a.appointment_status in ('CONFIRM')\n"
+
" and order_status in ('NORMAL','RESCHEDULED') and service_status='INIT'\n"
+
" and (a.is_multiple<>1 or a.engineer_code_sub is null)"
+
//指定了辅助工程师的不参与自动派单
" order by a.expect_time_begin asc "
,
nativeQuery
=
true
)
List
<
Map
<
String
,
Object
>>
getNewDispatchConfirmOrder
(
String
groupId
,
String
batchNo
,
String
teamId
,
String
batchDay
);
@Query
(
value
=
" select ?1 group_id, ?2 batch_no, a.org_team_id team_id, concat(a.order_id,'"
+
AutoDispatchJob
.
SUB_ORDER_ID_SUFFIX
+
"')order_id, date_format(a.dt,'%Y-%m-%d') dt, a.x, a.y , \n"
+
" a.expect_time_begin, DATE_ADD(a.expect_time_end, INTERVAL 15 MINUTE) expect_time_end, a.tags, a.priority , \n"
+
" '' skills , 15 take_time, a.appointment_status status, \n"
+
" a.engineer_code_sub engineer_code, date_format(a.sub_plan_start_time,'%Y-%m-%d %H:%i:%s') time_begin, date_format(a.sub_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%' or appointment_method='MANUAL') and a.appointment_status in ('INIT', 'PRE', 'CONFIRM')\n"
+
" and order_status in ('NORMAL','RESCHEDULED') and service_status='INIT'\n"
+
" and (a.is_multiple=1 and a.engineer_code is not null and a.engineer_code !='' and a.engineer_code_sub is not null and a.engineer_code_sub !='')\n"
+
" order by a.expect_time_begin asc "
,
nativeQuery
=
true
)
List
<
Map
<
String
,
Object
>>
getNewDispatchSubOrder
(
String
groupId
,
String
batchNo
,
String
teamId
,
String
batchDay
);
}
\ No newline at end of file
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/OrderEventRepository.java
View file @
102701f
...
...
@@ -3,9 +3,12 @@ package com.dituhui.pea.dispatch.dao;
import
java.util.List
;
import
com.dituhui.pea.dispatch.entity.OrderEvent
;
import
org.springframework.data.jpa.repository.JpaRepository
;
import
org.springframework.data.repository.CrudRepository
;
import
com.fasterxml.jackson.annotation.JsonFormat
;
public
interface
OrderEventRepository
extends
CrudRepository
<
OrderEvent
,
Long
>
{
public
interface
OrderEventRepository
extends
CrudRepository
<
OrderEvent
,
Long
>,
JpaRepository
<
OrderEvent
,
Long
>
{
long
countByOrderIdAndEventLike
(
String
orderId
,
String
event
);
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/OrderInfoRepository.java
View file @
102701f
package
com
.
dituhui
.
pea
.
dispatch
.
dao
;
import
com.dituhui.pea.dispatch.entity.OrderInfo
;
import
org.springframework.data.jpa.repository.JpaRepository
;
import
org.springframework.data.jpa.repository.Query
;
import
org.springframework.data.repository.CrudRepository
;
...
...
@@ -9,16 +10,16 @@ import java.util.List;
import
java.util.Optional
;
public
interface
OrderInfoRepository
extends
CrudRepository
<
OrderInfo
,
Long
>
{
public
interface
OrderInfoRepository
extends
CrudRepository
<
OrderInfo
,
Long
>
,
JpaRepository
<
OrderInfo
,
Long
>
{
// @Query(value = "SELECT * FROM order_info WHERE order_id=:orderId ORDER BY dt DESC LIMIT 1",nativeQuery = true)
Optional
<
OrderInfo
>
findOrderInfoByOrderIdAndDt
(
String
orderId
,
LocalDate
dt
);
List
<
OrderInfo
>
findByOrderId
(
String
orderId
);
List
<
OrderInfo
>
findByOrgTeamIdAndDt
(
String
teamId
,
LocalDate
dt
);
List
<
OrderInfo
>
findByOrgGroupIdAndDt
(
String
groupId
,
LocalDate
dt
);
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/DispatchOrder.java
View file @
102701f
...
...
@@ -26,7 +26,7 @@ public class DispatchOrder implements Serializable {
@Column
(
name
=
"group_id"
)
private
String
groupId
;
@Column
(
name
=
"batch_no"
)
private
String
batchNo
;
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/pojo/Customer.java
View file @
102701f
...
...
@@ -55,6 +55,11 @@ public class Customer {
private
boolean
isInTechnicianTimeWindows
=
true
;
/**
* 主工程师工单
*/
private
Customer
mainCustomer
;
public
Customer
()
{
}
...
...
@@ -164,7 +169,8 @@ public class Customer {
@Override
public
int
hashCode
()
{
return
Long
.
valueOf
(
this
.
id
).
hashCode
();
//return Long.valueOf(this.id).hashCode();
return
this
.
code
.
hashCode
();
}
@Override
...
...
@@ -175,7 +181,8 @@ public class Customer {
return
false
;
if
(
obj
==
this
)
return
true
;
return
this
.
id
==
((
Customer
)
obj
).
getId
();
//return this.id == ((Customer) obj).getId();
return
this
.
code
.
equals
(((
Customer
)
obj
).
getCode
());
}
@Override
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/quartz/dispatch/AutoDispatchJob.java
View file @
102701f
...
...
@@ -26,6 +26,8 @@ public class AutoDispatchJob extends QuartzJobBean {
public
static
final
String
TEAM_JOB_PREFIX
=
"BOXI_TEAM_"
;
public
static
final
String
SUB_ORDER_ID_SUFFIX
=
"_sub"
;
@Resource
private
SchedulerService
schedulerService
;
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/BatchServiceImpl.java
View file @
102701f
...
...
@@ -279,10 +279,14 @@ public class BatchServiceImpl implements BatchService {
dispatchOrderRepository
.
saveAll
(
JSONObject
.
parseArray
(
JSONObject
.
toJSONString
(
orderConfirmList
),
DispatchOrder
.
class
));
int
orderConfirmCount
=
orderConfirmList
.
size
();
log
.
info
(
"准备批次数据 engCount:{}, orderCount:{}, orderConfirmCount:{}"
,
engCount
,
orderCount
,
orderConfirmCount
);
List
<
Map
<
String
,
Object
>>
orderSubList
=
dispatchOrderRepository
.
getNewDispatchSubOrder
(
groupId
,
batchNo
,
teamId
,
batchDay
);
dispatchOrderRepository
.
saveAll
(
JSONObject
.
parseArray
(
JSONObject
.
toJSONString
(
orderSubList
),
DispatchOrder
.
class
));
int
orderSubCount
=
orderSubList
.
size
();
log
.
info
(
"准备批次数据 engCount:{}, orderCount:{}, orderConfirmCount:{}, orderSubCount:{}"
,
engCount
,
orderCount
,
orderConfirmCount
,
orderSubCount
);
if
(
orderCount
+
orderConfirmCount
>
0
)
{
if
(
orderCount
+
orderConfirmCount
+
orderSubCount
>
0
)
{
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
{
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/ExtractServiceImpl.java
View file @
102701f
package
com
.
dituhui
.
pea
.
dispatch
.
service
.
impl
;
import
cn.hutool.core.date.DateTime
;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.date.LocalDateTimeUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
com.alibaba.fastjson.JSONObject
;
import
com.alibaba.nacos.common.utils.CollectionUtils
;
import
com.dituhui.pea.bean.AllotResultParam
;
import
com.dituhui.pea.bean.Reason
;
import
com.dituhui.pea.bean.RemoteBeanApi
;
import
com.dituhui.pea.bean.Rescheduled
;
import
com.dituhui.pea.dispatch.dao.*
;
import
com.dituhui.pea.dispatch.entity.*
;
import
com.dituhui.pea.dispatch.pojo.Customer
;
import
com.dituhui.pea.dispatch.pojo.DispatchSolution
;
import
com.dituhui.pea.dispatch.quartz.dispatch.AutoDispatchJob
;
import
com.dituhui.pea.dispatch.service.ExtractService
;
import
com.dituhui.pea.enums.OrderEventEnum
;
import
com.dituhui.pea.util.DateUtil
;
import
com.google.common.collect.Maps
;
import
cn.hutool.core.util.StrUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
org.aspectj.weaver.ast.Or
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.jdbc.core.JdbcTemplate
;
...
...
@@ -31,11 +30,9 @@ import java.time.LocalDate;
import
java.time.LocalDateTime
;
import
java.time.ZoneId
;
import
java.time.format.DateTimeFormatter
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Optional
;
import
java.util.Set
;
import
java.util.*
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
import
static
org
.
springframework
.
transaction
.
annotation
.
Isolation
.
READ_COMMITTED
;
...
...
@@ -219,6 +216,7 @@ public class ExtractServiceImpl implements ExtractService {
}
List
<
DispatchOrder
>
dispatchOrderList
=
dispatchOrderRepo
.
findAllWithoutConfirm2
(
teamId
,
batchNo
);
Map
<
String
,
DispatchOrder
>
orderIdMap
=
dispatchOrderList
.
stream
().
collect
(
Collectors
.
toMap
(
DispatchOrder:
:
getOrderId
,
Function
.
identity
()));
log
.
info
(
"算法结果更新到工单, step1-开始处理, teamId:{}, batchNo:{}, order-size:{}"
,
teamId
,
batchNo
,
dispatchOrderList
.
size
());
...
...
@@ -226,6 +224,10 @@ public class ExtractServiceImpl implements ExtractService {
dispatchOrderList
.
forEach
(
dispatchOrder
->
{
int
idx
=
atomicInteger
.
getAndIncrement
();
String
orderId
=
dispatchOrder
.
getOrderId
();
if
(
orderId
.
endsWith
(
AutoDispatchJob
.
SUB_ORDER_ID_SUFFIX
))
{
return
;
}
String
dt
=
dispatchOrder
.
getDt
();
String
engCode
=
dispatchOrder
.
getEngineerCode
();
...
...
@@ -281,23 +283,28 @@ public class ExtractServiceImpl implements ExtractService {
}
orderInfo
.
setDispatcher
(
"AUTO_BATCH"
);
orderInfo
.
setUpdateTime
(
LocalDateTime
.
now
());
orderInfoRepo
.
save
(
orderInfo
);
if
(
cutOff
)
{
AllotResultParam
allotResultParam
=
new
AllotResultParam
();
allotResultParam
.
setRisId
(
orderInfo
.
getOrderId
());
allotResultParam
.
setExecutorWorkNo
(
engineerInfo
.
getCosmosId
());
allotResultParam
.
setAssistantWorkNo
(
null
);
allotResultParam
.
setReason
(
"自动派单"
);
String
format
=
"yyyy-MM-dd HH:mm:ss"
;
allotResultParam
.
setAppointmentStartTime
(
orderInfo
.
getPlanStartTime
().
atZone
(
ZoneId
.
systemDefault
()).
toInstant
().
toEpochMilli
());
allotResultParam
.
setAppointmentEndTime
(
orderInfo
.
getPlanEndTime
().
atZone
(
ZoneId
.
systemDefault
()).
toInstant
().
toEpochMilli
());
boolean
result
=
remoteBeanApi
.
allotResultUpdate
(
allotResultParam
);
log
.
info
(
">>> 【服务工单派单结果更新】请求参数:{}, 响应结果:{}"
,
JSONObject
.
toJSON
(
allotResultParam
),
result
);
DispatchOrder
subDispatchOrder
=
orderIdMap
.
get
(
orderId
+
AutoDispatchJob
.
SUB_ORDER_ID_SUFFIX
);
if
(
Objects
.
nonNull
(
subDispatchOrder
))
{
orderInfo
.
setEngineerCodeSub
(
subDispatchOrder
.
getEngineerCode
());
orderInfo
.
setSubElapsed
(
subDispatchOrder
.
getPathTime
());
orderInfo
.
setSubDistance
(
subDispatchOrder
.
getPathDistance
());
orderInfo
.
setSubPlanStartTime
(
subDispatchOrder
.
getTimeBegin
());
orderInfo
.
setSubPlanEndTime
(
subDispatchOrder
.
getTimeEnd
());
}
else
{
orderInfo
.
setEngineerCodeSub
(
null
);
orderInfo
.
setSubElapsed
(
null
);
orderInfo
.
setSubDistance
(
null
);
orderInfo
.
setSubPlanStartTime
(
null
);
orderInfo
.
setSubPlanEndTime
(
null
);
}
entityManager
.
merge
(
orderInfo
);
if
(
cutOff
)
{
//同步自动派单结果到Bean
syncOrderToBean
(
orderInfo
,
engineerInfoMap
);
OrderEvent
orderEvent
=
new
OrderEvent
().
setOrderId
(
orderId
).
setSuborderId
(
orderInfo
.
getSubId
()).
setHappen
(
LocalDateTime
.
now
())
.
setEvent
(
"批量自动指派"
).
setOperator
(
"DISPATCH"
).
setOperatorName
(
"算法批量指派"
).
setSource
(
"PEA-DISPATCH"
)
.
setEvent
(
OrderEventEnum
.
reassignment
.
getEvent
()
).
setOperator
(
"DISPATCH"
).
setOperatorName
(
"算法批量指派"
).
setSource
(
"PEA-DISPATCH"
)
.
setDescription
(
String
.
format
(
"批量自动指派:<%s,%s>"
,
engCode
,
engName
)).
setMemo
(
""
)
.
setCreateTime
(
LocalDateTime
.
now
()).
setUpdateTime
(
LocalDateTime
.
now
());
orderEventRepo
.
save
(
orderEvent
);
...
...
@@ -311,24 +318,32 @@ public class ExtractServiceImpl implements ExtractService {
}
else
{
log
.
warn
(
"算法结果更新到工单, step1.2-loop, 未能分配到技术员, teamId:{}, batchNo:{}, orderId:{}, dt:{}"
,
teamId
,
batchNo
,
orderId
,
dt
);
orderInfo
.
setEngineerCode
(
""
);
orderInfo
.
setEngineerName
(
""
);
orderInfo
.
setEngineerPhone
(
""
);
orderInfo
.
setEngineerCode
(
null
);
orderInfo
.
setEngineerName
(
null
);
orderInfo
.
setEngineerPhone
(
null
);
orderInfo
.
setPlanStartTime
(
orderInfo
.
getExpectTimeBegin
());
orderInfo
.
setPlanEndTime
(
orderInfo
.
getExpectTimeEnd
());
orderInfo
.
setArriveElapsed
(
0
);
orderInfo
.
setArriveDistance
(
0
);
if
(
ObjectUtil
.
equals
(
1
,
orderInfo
.
getIsMultiple
()))
{
orderInfo
.
setEngineerCodeSub
(
null
);
orderInfo
.
setSubElapsed
(
0
);
orderInfo
.
setSubDistance
(
0
);
orderInfo
.
setSubPlanStartTime
(
orderInfo
.
getExpectTimeBegin
());
orderInfo
.
setSubPlanEndTime
(
orderInfo
.
getExpectTimeBegin
().
plusMinutes
(
15
));
}
orderInfo
.
setAppointmentStatus
(
"INIT"
);
if
(
cutOff
)
{
orderInfo
.
setAppointmentMethod
(
"MANUAL"
);
orderInfo
.
setDispatcher
(
"MANUAL"
);
log
.
info
(
"算法结果更新
到
工单为人工, teamId:{}, batchNo:{}, orderId:{}"
,
teamId
,
batchNo
,
orderId
);
}
else
{
log
.
info
(
"算法结果更新工单为人工, teamId:{}, batchNo:{}, orderId:{}"
,
teamId
,
batchNo
,
orderId
);
}
else
if
(
null
!=
orderInfo
.
getDispatcher
()
&&
!
orderInfo
.
getDispatcher
().
startsWith
(
"MANUAL"
))
{
orderInfo
.
setDispatcher
(
"AUTO_BATCH"
);
}
orderInfo
.
setUpdateTime
(
LocalDateTime
.
now
());
orderInfoRepo
.
save
(
orderInfo
);
entityManager
.
merge
(
orderInfo
);
OrderLog
orderLog
=
new
OrderLog
().
setOrderId
(
orderId
).
setSuborderId
(
orderInfo
.
getSubId
()).
setSource
(
"PEA-DISPATCH"
).
setOperator
(
"DISPATCH"
)
.
setContent
(
String
.
format
(
"批量自动指派:<%s,%s>"
,
""
,
"抹掉技术员"
)).
setContentOld
(
""
)
...
...
@@ -341,5 +356,57 @@ public class ExtractServiceImpl implements ExtractService {
log
.
info
(
"算法结果更新到工单完成, teamId:{}, batchNo:{}"
,
teamId
,
batchNo
);
}
private
void
syncOrderToBean
(
OrderInfo
orderInfo
,
Map
<
String
,
EngineerInfo
>
engineerInfoMap
)
{
if
(
orderEventRepo
.
countByOrderIdAndEventLike
(
orderInfo
.
getOrderId
(),
"%"
+
OrderEventEnum
.
reassignment
.
getEvent
()
+
"%"
)
==
0
)
{
AllotResultParam
allotResultParam
=
new
AllotResultParam
();
allotResultParam
.
setRisId
(
orderInfo
.
getOrderId
());
allotResultParam
.
setExecutorWorkNo
(
engineerInfoMap
.
get
(
orderInfo
.
getEngineerCode
()).
getCosmosId
());
if
(
null
!=
orderInfo
.
getEngineerCodeSub
())
{
EngineerInfo
subEngineerInfo
=
engineerInfoMap
.
get
(
orderInfo
.
getEngineerCodeSub
());
allotResultParam
.
setAssistantWorkNo
(
subEngineerInfo
.
getCosmosId
());
}
allotResultParam
.
setReason
(
"自动派单"
);
String
format
=
"yyyy-MM-dd HH:mm:ss"
;
allotResultParam
.
setAppointmentStartTime
(
orderInfo
.
getPlanStartTime
().
atZone
(
ZoneId
.
systemDefault
()).
toInstant
().
toEpochMilli
());
allotResultParam
.
setAppointmentEndTime
(
orderInfo
.
getPlanEndTime
().
atZone
(
ZoneId
.
systemDefault
()).
toInstant
().
toEpochMilli
());
boolean
result
=
remoteBeanApi
.
allotResultUpdate
(
allotResultParam
);
log
.
info
(
">>> 同步自动派单结果到Bean,【服务工单派单结果更新】请求参数:{}, 响应结果:{}"
,
JSONObject
.
toJSON
(
allotResultParam
),
result
);
}
else
{
OrderInfo
oldOrderInfo
=
orderInfoRepo
.
findByOrderId
(
orderInfo
.
getOrderId
()).
get
(
0
);
Rescheduled
rescheduled
=
new
Rescheduled
();
rescheduled
.
setRisId
(
orderInfo
.
getOrderId
());
rescheduled
.
setInitiatorOfRescheduling
(
""
);
rescheduled
.
setReasonForRescheduling
(
new
Reason
());
rescheduled
.
setRescheduledDate
(
DateUtil
.
toMilliseconds
(
orderInfo
.
getPlanStartTime
()));
rescheduled
.
setRequireApprove
(
Boolean
.
FALSE
);
if
(
StrUtil
.
isNotEmpty
(
orderInfo
.
getEngineerCode
()))
{
String
engineerCode
=
orderInfo
.
getEngineerCode
();
EngineerInfo
engineerInfo
=
engineerInfoMap
.
get
(
engineerCode
);
rescheduled
.
setExecutorWorkNo
(
engineerInfo
.
getCosmosId
());
rescheduled
.
setOrgUnitId
(
engineerInfo
.
getGroupId
());
}
if
(
StrUtil
.
isNotEmpty
(
orderInfo
.
getEngineerCodeSub
()))
{
EngineerInfo
engineerInfo
=
engineerInfoMap
.
get
(
orderInfo
.
getEngineerCodeSub
());
rescheduled
.
setAssistantWorkNo
(
engineerInfo
.
getCosmosId
());
rescheduled
.
setAssOrgUnitId
(
engineerInfo
.
getGroupId
());
}
//判断是否是改派
if
((
StrUtil
.
isNotEmpty
(
orderInfo
.
getEngineerCode
())
&&
!
Objects
.
equals
(
orderInfo
.
getEngineerCode
(),
oldOrderInfo
.
getEngineerCode
()))
||
(
StrUtil
.
isNotEmpty
(
orderInfo
.
getEngineerCodeSub
())
&&
!
Objects
.
equals
(
orderInfo
.
getEngineerCodeSub
(),
oldOrderInfo
.
getEngineerCodeSub
())))
{
rescheduled
.
setReassignment
(
Boolean
.
TRUE
);
}
else
{
rescheduled
.
setReassignment
(
Boolean
.
FALSE
);
}
boolean
result
=
remoteBeanApi
.
orderRescheduled
(
rescheduled
);
log
.
info
(
">>> 同步自动派单结果到Bean,【服务工单改约】请求参数:{}, 响应结果:{}"
,
JSONObject
.
toJSON
(
rescheduled
),
result
);
}
}
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/SolveServiceImpl.java
View file @
102701f
...
...
@@ -10,6 +10,7 @@ import com.dituhui.pea.dispatch.dao.*;
import
com.dituhui.pea.dispatch.entity.*
;
import
com.dituhui.pea.dispatch.enums.DepartureEnum
;
import
com.dituhui.pea.dispatch.pojo.*
;
import
com.dituhui.pea.dispatch.quartz.dispatch.AutoDispatchJob
;
import
com.dituhui.pea.dispatch.service.EngineerCalendarService
;
import
com.dituhui.pea.dispatch.service.ExtractService
;
import
com.dituhui.pea.dispatch.service.SolveService
;
...
...
@@ -35,6 +36,7 @@ import java.time.LocalDateTime;
import
java.time.format.DateTimeFormatter
;
import
java.util.*
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
import
java.util.stream.Stream
;
...
...
@@ -260,26 +262,36 @@ public class SolveServiceImpl implements SolveService {
}
Customer
customer
=
new
Customer
(
order
.
getId
(),
order
.
getOrderId
(),
order
.
getDt
(),
location
,
start
,
end
,
order
.
getSkills
(),
order
.
getTakeTime
(),
order
.
getStatus
());
OrderInfo
orderInfo
=
orderInfoRepository
.
findByOrderId
(
order
.
getOrderId
()).
get
(
0
);
if
((
StrUtil
.
equals
(
"MANUAL"
,
orderInfo
.
getAppointmentMethod
())
&&
StrUtil
.
equals
(
"CONFIRM"
,
orderInfo
.
getAppointmentStatus
()))
||
ObjectUtil
.
equal
(
1
,
orderInfo
.
getIsAppointEngineer
()))
{
customer
.
setDispatchedTechnicianCode
(
orderInfo
.
getEngineerCode
());
}
if
(!
order
.
getOrderId
().
endsWith
(
"_sub"
))
{
OrderInfo
orderInfo
=
orderInfoRepository
.
findByOrderId
(
order
.
getOrderId
()).
get
(
0
);
if
((
StrUtil
.
equals
(
"MANUAL"
,
orderInfo
.
getAppointmentMethod
())
&&
StrUtil
.
equals
(
"CONFIRM"
,
orderInfo
.
getAppointmentStatus
()))
||
ObjectUtil
.
equal
(
1
,
orderInfo
.
getIsAppointEngineer
()))
{
customer
.
setDispatchedTechnicianCode
(
orderInfo
.
getEngineerCode
());
}
if
(
ObjectUtil
.
equal
(
2
,
orderInfo
.
getIsAppointEngineer
()))
{
customer
.
setExclusiveTechnicianCode
(
Objects
.
nonNull
(
orderInfo
.
getAppointEngineerCodes
())
?
orderInfo
.
getAppointEngineerCodes
().
trim
()
:
null
);
}
if
(
ObjectUtil
.
equal
(
2
,
orderInfo
.
getIsAppointEngineer
()))
{
customer
.
setExclusiveTechnicianCode
(
Objects
.
nonNull
(
orderInfo
.
getAppointEngineerCodes
())
?
orderInfo
.
getAppointEngineerCodes
().
trim
()
:
null
);
}
log
.
info
(
"订单指定排除工程师, teamId:{}, batchNo:{}, orderId:{}, dispatchedTechnicianCode:{}, exclusiveTechnicianCode:{}"
,
teamId
,
batchNo
,
order
.
getOrderId
(),
customer
.
getDispatchedTechnicianCode
(),
customer
.
getExclusiveTechnicianCode
());
log
.
info
(
"订单指定排除工程师, teamId:{}, batchNo:{}, orderId:{}, dispatchedTechnicianCode:{}, exclusiveTechnicianCode:{}"
,
teamId
,
batchNo
,
order
.
getOrderId
(),
customer
.
getDispatchedTechnicianCode
(),
customer
.
getExclusiveTechnicianCode
());
}
customerList
.
add
(
customer
);
});
Map
<
String
,
Customer
>
customerCodeMap
=
customerList
.
stream
().
collect
(
Collectors
.
toMap
(
Customer:
:
getCode
,
Function
.
identity
()));
customerList
.
forEach
(
customer
->
{
if
(
customer
.
getCode
().
endsWith
(
AutoDispatchJob
.
SUB_ORDER_ID_SUFFIX
)){
String
code
=
customer
.
getCode
();
customer
.
setMainCustomer
(
customerCodeMap
.
get
(
code
.
substring
(
0
,
code
.
length
()-
AutoDispatchJob
.
SUB_ORDER_ID_SUFFIX
.
length
())));
}
});
log
.
info
(
"组织问题对象, customer-list, teamId:{}, batchNo:{}, customer-list:{}"
,
teamId
,
batchNo
,
customerList
.
size
());
// technicianList
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/utils/DispatchSolutionUtils.java
View file @
102701f
...
...
@@ -443,6 +443,30 @@ public class DispatchSolutionUtils {
}
}
break
;
case
customerSubAndMainEngineerMustCoexist:
for
(
Object
indictedObject
:
constraintMatch
.
getIndictedObjectList
())
{
// 违反硬约束对象,根据具体约束返回不同类型对象
if
(
indictedObject
instanceof
Customer
)
{
Customer
customer
=
(
Customer
)
indictedObject
;
log
.
warn
(
">>> 副工单({})违背 customerSubAndMainEngineerMustCoexist 硬约束: 主工单:{}, 主工程师: {}, 副工程师: {}, arriveTime: {},departureTime: {}"
,
customer
.
getCode
(),
customer
.
getMainCustomer
().
getCode
(),
null
!=
customer
.
getMainCustomer
().
getTechnician
()
?
customer
.
getMainCustomer
().
getTechnician
().
getCode
()
:
null
,
null
!=
customer
.
getTechnician
()
?
customer
.
getTechnician
().
getCode
()
:
null
,
customer
.
getArrivalTime
(),
customer
.
getDepartureTime
());
List
<
Customer
>
removeCustomers
=
CollectionUtil
.
toList
(
customer
,
customer
.
getMainCustomer
());
removeCustomers
.
forEach
(
customer1
->
{
// 更新shadow变量
updateShadowVariable
(
customer1
);
// 移除技术员
customer1
.
getTechnician
().
getCustomerList
().
remove
(
customer1
);
solution
.
getUnDispatchedCustomers
().
add
(
customer1
);
});
}
}
break
;
default
:
break
;
}
...
...
project-dispatch/src/main/resources/application-dev.yaml
View file @
102701f
...
...
@@ -3,7 +3,7 @@ server:
dispatch
:
cron
:
expr
:
0
57
8-23 * * ?
expr
:
0
22
8-23 * * ?
next-day-limit
:
2
scheduler
:
...
...
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment