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 3f1796c1
authored
Oct 30, 2023
by
chamberone
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 算法任务调整成按照小队运行算法
1 parent
a90ab818
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
716 additions
and
7 deletions
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/DispatchBatchRepository.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/DispatchEngineerRepository.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/DispatchOrderRepository.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/EngineerInfoRepository.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/OldSkillMapperDao.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/OrgTeamDao.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/OrgTeamEngineerDao.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/DispatchBatch.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/DispatchEngineer.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/DispatchOrder.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/OldSkillMapper.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/OrgTeamEngineerEntity.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/OrgTeamEntity.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/pojo/DispatchSolution.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/scheduler/BatchScheduler.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/BatchService.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/ExtractService.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/SolveService.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/dao/DispatchBatchRepository.java
View file @
3f1796c
...
...
@@ -17,8 +17,10 @@ public interface DispatchBatchRepository extends CrudRepository<DispatchBatch, L
Optional
<
DispatchBatch
>
findByGroupIdAndBatchDate
(
String
groupId
,
String
batchDay
);
@Query
(
value
=
"from DispatchBatch where groupId = ?1 and batchNo=?2 "
)
Optional
<
DispatchBatch
>
findByGroupIdAndBatchNo
(
String
groupId
,
String
batchNo
);
Optional
<
DispatchBatch
>
findByTeamIdAndBatchDate
(
String
teamId
,
String
batchDay
);
}
\ No newline at end of file
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/DispatchEngineerRepository.java
View file @
3f1796c
...
...
@@ -10,4 +10,6 @@ public interface DispatchEngineerRepository extends CrudRepository<DispatchEngin
List
<
DispatchEngineer
>
findByGroupId
(
String
groupId
);
List
<
DispatchEngineer
>
findByGroupIdAndBatchNo
(
String
groupId
,
String
batchNo
);
List
<
DispatchEngineer
>
findByTeamIdAndBatchNo
(
String
teamId
,
String
batchNo
);
}
\ No newline at end of file
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/DispatchOrderRepository.java
View file @
3f1796c
...
...
@@ -18,9 +18,17 @@ public interface DispatchOrderRepository extends CrudRepository<DispatchOrder, L
@Query
(
"from DispatchOrder where groupId=?1 and batchNo=?2"
)
List
<
DispatchOrder
>
findAll
(
String
groupId
,
String
batchNo
);
// 查看未指派非confirm的,供算法计算
@Query
(
"from DispatchOrder where teamId=?1 and batchNo=?2"
)
List
<
DispatchOrder
>
findAll2
(
String
teamId
,
String
batchNo
);
// 查看算法指派成功(也有抹掉技术员、时间情况),非confirm状态的
@Query
(
"from DispatchOrder where groupId=?1 and batchNo=?2 and status !='CONFIRM' "
)
List
<
DispatchOrder
>
findAllWithoutConfirm
(
String
groupId
,
String
batchNo
);
// 查看算法指派成功(也有抹掉技术员、时间情况),非confirm状态的
@Query
(
"from DispatchOrder where teamId=?1 and batchNo=?2 and status !='CONFIRM' "
)
List
<
DispatchOrder
>
findAllWithoutConfirm2
(
String
teamId
,
String
batchNo
);
Optional
<
DispatchOrder
>
findByGroupIdAndBatchNoAndOrderIdAndDt
(
String
groupId
,
String
batchNo
,
String
orderId
,
String
dt
);
}
\ No newline at end of file
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/EngineerInfoRepository.java
View file @
3f1796c
...
...
@@ -11,4 +11,7 @@ public interface EngineerInfoRepository extends CrudRepository<EngineerInfo, Lon
List
<
EngineerInfo
>
findByGroupId
(
String
groupId
);
Optional
<
EngineerInfo
>
findByEngineerCode
(
String
engineerCode
);
List
<
EngineerInfo
>
findByEngineerCodeIn
(
List
<
String
>
engineerCodes
);
}
\ No newline at end of file
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/OldSkillMapperDao.java
0 → 100644
View file @
3f1796c
package
com
.
dituhui
.
pea
.
dispatch
.
dao
;
import
org.springframework.data.jpa.repository.JpaRepository
;
import
org.springframework.data.jpa.repository.JpaSpecificationExecutor
;
import
org.springframework.stereotype.Repository
;
import
com.dituhui.pea.dispatch.entity.OldSkillMapper
;
@Repository
public
interface
OldSkillMapperDao
extends
JpaRepository
<
OldSkillMapper
,
Integer
>,
JpaSpecificationExecutor
<
OldSkillMapper
>
{
OldSkillMapper
findByBrandAndTypeAndSkill
(
String
brand
,
String
type
,
String
skill
);
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/OrgTeamDao.java
0 → 100644
View file @
3f1796c
package
com
.
dituhui
.
pea
.
dispatch
.
dao
;
import
java.util.List
;
import
org.springframework.data.jpa.repository.JpaRepository
;
import
org.springframework.data.jpa.repository.JpaSpecificationExecutor
;
import
org.springframework.stereotype.Repository
;
import
com.dituhui.pea.dispatch.entity.OrgTeamEntity
;
@Repository
public
interface
OrgTeamDao
extends
JpaRepository
<
OrgTeamEntity
,
Integer
>,
JpaSpecificationExecutor
<
OrgTeamEntity
>
{
OrgTeamEntity
findByTeamNameAndGroupId
(
String
teamName
,
String
groupId
);
List
<
OrgTeamEntity
>
findByGroupId
(
String
groupId
);
OrgTeamEntity
findByTeamId
(
String
teamId
);
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/dao/OrgTeamEngineerDao.java
0 → 100644
View file @
3f1796c
package
com
.
dituhui
.
pea
.
dispatch
.
dao
;
import
org.hibernate.annotations.Where
;
import
org.springframework.data.jpa.repository.JpaRepository
;
import
org.springframework.data.jpa.repository.Modifying
;
import
org.springframework.data.jpa.repository.Query
;
import
org.springframework.stereotype.Repository
;
import
com.dituhui.pea.dispatch.entity.OrgTeamEngineerEntity
;
import
java.util.List
;
@Repository
public
interface
OrgTeamEngineerDao
extends
JpaRepository
<
OrgTeamEngineerEntity
,
Integer
>
{
@Query
(
"select t from OrgTeamEngineerEntity t where t.teamId = :teamId and t.status=1"
)
List
<
OrgTeamEngineerEntity
>
findAllByTeamId
(
String
teamId
);
@Query
(
"select t from OrgTeamEngineerEntity t where t.teamId = :teamId and t.engineerCode=:engineerCode"
)
OrgTeamEngineerEntity
findByTeamIdAndEngineerCode
(
String
teamId
,
String
engineerCode
);
@Query
(
"select t from OrgTeamEngineerEntity t where t.teamId in :teamIds and t.status=1"
)
List
<
OrgTeamEngineerEntity
>
findAllByTeamIdIn
(
List
<
String
>
teamIds
);
@Query
(
"select a.teamId from OrgTeamEngineerEntity a where a.engineerCode=:engineerCode"
)
List
<
String
>
getTeamIdsByEngineerCode
(
String
engineerCode
);
@Modifying
@Query
(
"UPDATE OrgTeamEngineerEntity tt SET tt.status = :status WHERE tt.teamId = :teamId"
)
void
updateStatusAllEngineers
(
String
teamId
,
int
status
);
@Modifying
@Query
(
"UPDATE OrgTeamEngineerEntity tt SET tt.status = :status WHERE tt.teamId = :teamId AND tt.engineerCode IN :engineerCodes"
)
void
updateStatusByEngineerCodes
(
String
teamId
,
List
<
String
>
engineerCodes
,
int
status
);
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/DispatchBatch.java
View file @
3f1796c
...
...
@@ -30,6 +30,9 @@ public class DispatchBatch implements Serializable {
@Column
(
name
=
"group_id"
)
private
String
groupId
;
@Column
(
name
=
"team_id"
)
private
String
teamId
;
/**
* 批次号
*/
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/DispatchEngineer.java
View file @
3f1796c
...
...
@@ -25,6 +25,9 @@ public class DispatchEngineer implements Serializable {
@Column
(
name
=
"group_id"
)
private
String
groupId
;
@Column
(
name
=
"team_id"
)
private
String
teamId
;
@Column
(
name
=
"batch_no"
)
private
String
batchNo
;
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/DispatchOrder.java
View file @
3f1796c
...
...
@@ -27,6 +27,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/entity/OldSkillMapper.java
0 → 100644
View file @
3f1796c
package
com
.
dituhui
.
pea
.
dispatch
.
entity
;
import
java.time.LocalDateTime
;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.GeneratedValue
;
import
javax.persistence.GenerationType
;
import
javax.persistence.Id
;
import
javax.persistence.Table
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
@Entity
@Table
(
name
=
"old_skill_mapper"
)
@Data
@Accessors
(
chain
=
true
)
public
class
OldSkillMapper
{
@Id
@GeneratedValue
(
strategy
=
GenerationType
.
IDENTITY
)
private
Integer
id
;
@Column
(
name
=
"brand"
,
nullable
=
false
)
private
String
brand
;
@Column
(
name
=
"type"
,
nullable
=
false
)
private
String
type
;
@Column
(
name
=
"skill"
,
nullable
=
false
)
private
String
skill
;
@Column
(
name
=
"brand2"
,
nullable
=
false
)
private
String
brand2
;
@Column
(
name
=
"type2"
,
nullable
=
false
)
private
String
type2
;
@Column
(
name
=
"skill2"
,
nullable
=
false
)
private
String
skill2
;
@Column
(
name
=
"memo"
,
nullable
=
false
)
private
String
memo
;
@Column
(
name
=
"create_time"
,
nullable
=
false
,
updatable
=
false
,
columnDefinition
=
"timestamp default current_timestamp"
)
private
LocalDateTime
createTime
;
@Column
(
name
=
"update_time"
,
nullable
=
false
,
columnDefinition
=
"timestamp default current_timestamp on update current_timestamp"
)
private
LocalDateTime
updateTime
;
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/OrgTeamEngineerEntity.java
0 → 100644
View file @
3f1796c
package
com
.
dituhui
.
pea
.
dispatch
.
entity
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
javax.persistence.*
;
import
java.time.LocalDateTime
;
import
java.util.Date
;
@Entity
@Data
@Accessors
(
chain
=
true
)
@Table
(
name
=
"org_team_engineer"
)
public
class
OrgTeamEngineerEntity
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* id
*/
@Id
@GeneratedValue
(
strategy
=
GenerationType
.
IDENTITY
)
private
Integer
id
;
/**
* 工作队id
*/
private
String
teamId
;
/**
* 工程师工号
*/
private
String
engineerCode
;
/**
* 状态(0无效 1有效)
*/
private
Integer
status
;
/**
* 备注
*/
private
String
memo
;
/**
* 创建时间
*/
private
LocalDateTime
createTime
=
LocalDateTime
.
now
();
/**
* 更新时间
*/
private
LocalDateTime
updateTime
=
LocalDateTime
.
now
();
public
OrgTeamEngineerEntity
()
{
}
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/entity/OrgTeamEntity.java
0 → 100644
View file @
3f1796c
package
com
.
dituhui
.
pea
.
dispatch
.
entity
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
javax.persistence.*
;
import
java.time.LocalDateTime
;
@Entity
@Table
(
name
=
"org_team"
)
@Data
@Accessors
(
chain
=
true
)
public
class
OrgTeamEntity
{
@Id
@GeneratedValue
(
strategy
=
GenerationType
.
IDENTITY
)
private
Integer
id
;
@Column
(
name
=
"team_id"
,
nullable
=
false
,
unique
=
true
)
private
String
teamId
;
@Column
(
name
=
"team_name"
,
nullable
=
false
)
private
String
teamName
;
@Column
(
name
=
"team_type"
,
columnDefinition
=
"int default 1"
)
private
Integer
teamType
=
1
;
@Column
(
name
=
"cluster_id"
,
nullable
=
false
)
private
String
clusterId
;
@Column
(
name
=
"branch_id"
,
nullable
=
false
)
private
String
branchId
;
@Column
(
name
=
"group_id"
,
nullable
=
false
)
private
String
groupId
;
@Column
(
name
=
"warehouse_id"
,
nullable
=
false
)
private
String
warehouseId
;
@Column
(
name
=
"workdays"
,
nullable
=
false
,
columnDefinition
=
"varchar(30) default '1,2,3,4,5,6,7'"
)
private
String
workdays
=
"1,2,3,4,5,6,7"
;
@Column
(
nullable
=
false
)
private
String
memo
;
@Column
(
name
=
"create_time"
,
nullable
=
false
,
updatable
=
false
,
columnDefinition
=
"timestamp default current_timestamp"
)
private
LocalDateTime
createTime
;
@Column
(
name
=
"update_time"
,
nullable
=
false
,
columnDefinition
=
"timestamp default current_timestamp on update current_timestamp"
)
private
LocalDateTime
updateTime
;
@Column
(
name
=
"work_on"
,
nullable
=
false
,
columnDefinition
=
"varchar(5) default '08:00'"
)
private
String
workOn
=
"08:00"
;
@Column
(
name
=
"work_off"
,
nullable
=
false
,
columnDefinition
=
"varchar(5) default '18:00'"
)
private
String
workOff
=
"18:00"
;
@Column
(
name
=
"work_duration"
,
nullable
=
false
,
columnDefinition
=
"int default 600"
)
private
Integer
workDuration
=
600
;
@Column
(
name
=
"transport_mode"
,
columnDefinition
=
"varchar(10) default '电动车'"
)
private
String
transportMode
=
"电动车"
;
@Column
(
name
=
"strategy_schedule"
,
columnDefinition
=
"varchar(10) default '营销优先'"
)
private
String
strategySchedule
=
"营销优先"
;
@Column
(
name
=
"strategy_appointment"
,
columnDefinition
=
"varchar(10) default '指派给信息员'"
)
private
String
strategyAppointment
=
"指派给信息员"
;
@Column
(
name
=
"interval_schedule"
,
nullable
=
false
,
columnDefinition
=
"int default 100"
)
private
Integer
intervalSchedule
=
100
;
@Column
(
name
=
"interval_schedule_next"
,
nullable
=
false
,
columnDefinition
=
"int default 200"
)
private
Integer
intervalScheduleNext
=
200
;
@Column
(
name
=
"cute_off"
,
nullable
=
false
,
columnDefinition
=
"varchar(5) default '18:00'"
)
private
String
cuteOff
=
"18:00"
;
@Column
(
nullable
=
false
,
columnDefinition
=
"int default 1"
)
private
Integer
status
=
1
;
// 其他字段和关联关系的定义
// ...
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/pojo/DispatchSolution.java
View file @
3f1796c
...
...
@@ -19,6 +19,8 @@ public class DispatchSolution {
private
String
groupId
;
private
String
teamId
;
private
String
batchNo
;
private
String
name
;
...
...
@@ -66,6 +68,16 @@ public class DispatchSolution {
this
.
customerList
=
customerList
;
}
public
DispatchSolution
(
String
groupId
,
String
teamId
,
String
batchNo
,
List
<
Location
>
locationList
,
Depot
depot
,
List
<
Technician
>
technicianList
,
List
<
Customer
>
customerList
)
{
this
.
groupId
=
groupId
;
this
.
teamId
=
teamId
;
this
.
batchNo
=
batchNo
;
this
.
locationList
=
locationList
;
this
.
depot
=
depot
;
this
.
technicianList
=
technicianList
;
this
.
customerList
=
customerList
;
}
// ************************************************************************
// Complex methods
// ************************************************************************
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/scheduler/BatchScheduler.java
View file @
3f1796c
...
...
@@ -3,6 +3,8 @@ package com.dituhui.pea.dispatch.scheduler;
import
java.io.File
;
import
java.time.LocalDate
;
import
java.time.format.DateTimeFormatter
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.UUID
;
import
org.optaplanner.core.api.solver.Solver
;
...
...
@@ -13,6 +15,8 @@ import org.springframework.beans.factory.annotation.Value;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Component
;
import
com.dituhui.pea.dispatch.dao.OrgTeamDao
;
import
com.dituhui.pea.dispatch.entity.OrgTeamEntity
;
import
com.dituhui.pea.dispatch.pojo.DispatchSolution
;
import
com.dituhui.pea.dispatch.service.BatchService
;
import
com.dituhui.pea.dispatch.service.ExtractService
;
...
...
@@ -25,10 +29,6 @@ import lombok.extern.slf4j.Slf4j;
@Component
public
class
BatchScheduler
{
String
groupId
=
"gsuzhou"
;
@Value
(
"${dispatch.cron.next-day-limit}"
)
int
nextDaysLimit
=
2
;
...
...
@@ -41,6 +41,9 @@ public class BatchScheduler {
@Autowired
ExtractService
extractService
;
@Autowired
OrgTeamDao
orgTeamDao
;
private
DefaultSolverFactory
<
DispatchSolution
>
solverFactory
;
private
Solver
<
DispatchSolution
>
solver
;
...
...
@@ -51,9 +54,54 @@ public class BatchScheduler {
/*
* 异步执行任务开始
*
*/
*/
@Scheduled
(
cron
=
"${dispatch.cron.expr}"
)
public
void
dispatchRun2
()
{
String
groupId
=
"gsuzhou"
;
log
.
info
(
"dispatchRun group:{}"
,
groupId
);
// TODO 分布式任务,循环大区/分部/分站/小队
// 循环分站/网点下面的小队
List
<
OrgTeamEntity
>
teams
=
orgTeamDao
.
findByGroupId
(
groupId
);
for
(
OrgTeamEntity
team
:
teams
)
{
String
teamId
=
team
.
getTeamId
();
for
(
int
i
=
1
;
i
<=
nextDaysLimit
;
i
++)
{
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
);
UUID
problemId
=
solveService
.
generateProblemId
(
teamId
,
batchNo
);
log
.
info
(
"dispatchRun teamId:{}, day:{}, batch:{}, problemId:{}"
,
teamId
,
currDay
,
batchNo
,
problemId
);
DispatchSolution
problem
=
solveService
.
prepareSolution2
(
teamId
,
batchNo
);
if
(
problem
.
getCustomerList
().
size
()
<=
0
)
{
log
.
info
(
"dispatchRun 当前批次没有待指派工单 , teamId:{}, day:{}, batch:{}, problemId:{}, order-size:{}"
,
teamId
,
currDay
,
batchNo
,
problemId
,
problem
.
getCustomerList
().
size
());
continue
;
}
log
.
info
(
"dispatchRun prepare done, teamId:{}, day:{}, batch:{}, problemId:{}"
,
teamId
,
currDay
,
batchNo
,
problemId
);
DispatchSolution
solution
=
solver
.
solve
(
problem
);
DispatchSolutionUtils
.
removeHardConstraintCustomer
(
solution
,
solverFactory
);
log
.
info
(
"dispatchRun solve done, teamId:{}, day:{}, batch:{}, problemId:{}, score:{}"
,
teamId
,
currDay
,
batchNo
,
problemId
,
solution
.
getScore
().
toShortString
());
this
.
solveService
.
saveSolutionWrp
(
solution
);
// FIXME 替换工作队
this
.
extractService
.
extractDispatchToOrder
(
groupId
,
batchNo
,
false
);
log
.
info
(
"dispatchRun done ------ teamId:{}, day:{}"
,
teamId
,
currDay
);
JacksonSolutionFileIO
<
DispatchSolution
>
exporter
=
new
JacksonSolutionFileIO
<
DispatchSolution
>(
DispatchSolution
.
class
);
exporter
.
write
(
solution
,
new
File
(
String
.
format
(
"dispatchSolution_%s_%s.json"
,
groupId
,
currDay
)));
}
}
log
.
info
(
"dispatchRun group:{} done"
,
groupId
);
}
/*
* 异步执行任务开始
* */
//@Scheduled(cron = "${dispatch.cron.expr}")
public
void
dispatchRun
()
{
String
groupId
=
"gsuzhou"
;
log
.
info
(
"dispatchRun group:{}"
,
groupId
);
try
{
for
(
int
i
=
0
;
i
<=
nextDaysLimit
;
i
++)
{
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/BatchService.java
View file @
3f1796c
...
...
@@ -15,8 +15,6 @@ import java.sql.SQLException;
public
interface
BatchService
{
// 检查指定日期的小组是否有在运行的批次任务,有则返回,没有则创建后返回批次码
String
buildBatchData
(
String
groupId
,
String
day
);
DispatchBatch
queryBatchInfoByDay
(
String
groupId
,
String
day
);
...
...
@@ -25,4 +23,11 @@ public interface BatchService {
void
saveDispatchBatch
(
DispatchBatch
batchInfo
);
// 小队id
public
String
buildBatchData2
(
String
teamId
,
String
day
);
public
DispatchBatch
queryBatchInfoByDay2
(
String
teamId
,
String
day
);
public
String
queryBatchNoByDay2
(
String
teamId
,
String
day
);
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/ExtractService.java
View file @
3f1796c
...
...
@@ -23,5 +23,10 @@ public interface ExtractService {
* */
void
extractDispatchToOrder
(
String
groupId
,
String
batchNo
,
boolean
isConfirm
)
;
/*
* 按小队将dispath_order 中的计算结果,回写到 order_info
* */
void
extractDispatchToOrder2
(
String
TeamId
,
String
batchNo
,
boolean
isConfirm
)
;
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/SolveService.java
View file @
3f1796c
...
...
@@ -25,6 +25,9 @@ public interface SolveService {
DispatchSolution
prepareSolution
(
String
groupId
,
String
batchNo
)
;
DispatchSolution
prepareSolution2
(
String
teamId
,
String
batchNo
)
;
/*
* 将计算结果回写到dispatch2个表
* 是下面两个方法的包装
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/BatchServiceImpl.java
View file @
3f1796c
...
...
@@ -180,6 +180,85 @@ public class BatchServiceImpl implements BatchService {
return
batchNo
;
}
// 检查给定小队、日期是否有在运行的批次任务,没则返回,没有则创建
@Transactional
(
isolation
=
Isolation
.
READ_COMMITTED
)
@Override
public
String
buildBatchData2
(
String
teamId
,
String
day
)
{
entityManager
.
clear
();
log
.
info
(
"准备批次数据, teamId:{}, day:{}"
,
teamId
,
day
);
String
batchNo
=
""
;
String
batchDay
=
""
;
Optional
<
DispatchBatch
>
optional
=
batchRepository
.
findByTeamIdAndBatchDate
(
teamId
,
day
);
if
(!
optional
.
isPresent
())
{
// 创建batch
batchNo
=
calcBatchNo
(
day
);
batchDay
=
day
;
// 执行数据库操作
String
sqlInsert
=
"INSERT INTO `dispatch_batch` ( `team_id`, `batch_no`, `batch_date`, `engineer_num`, `order_num`, `start_time`, `end_time`, `status`) "
+
" VALUES(?, ?, ?, ?, ?, ?, ?, ?)"
;
jdbcTemplate
.
update
(
sqlInsert
,
teamId
,
batchNo
,
batchDay
,
0
,
0
,
LocalDateTime
.
now
(),
null
,
"RUNNING"
);
log
.
info
(
"生成新批次, teamId:{}, day:{}"
,
teamId
,
batchDay
);
}
else
{
batchNo
=
optional
.
get
().
getBatchNo
();
batchDay
=
optional
.
get
().
getBatchDate
();
}
log
.
info
(
"清理原批次数据, teamId:{}, day:{}, batchNo:{}"
,
teamId
,
batchDay
,
batchNo
);
jdbcTemplate
.
update
(
"delete from dispatch_engineer where team_id=? and batch_no=?"
,
teamId
,
batchNo
);
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"
+
" 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"
;
int
engCount
=
jdbcTemplate
.
update
(
sqlEngineer
,
batchNo
,
teamId
);
// 未派过的工单(已派过PRE状态还可以再次派)
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"
+
" SELECT a.org_group_id, ?, a.org_team_id , a.order_id, ?, a.x, a.y , \r\n"
+
" a.expect_time_begin, a.expect_time_end, a.tags, a.priority , \r\n"
+
" CONCAT(a.brand, '-', a.type, '-', a.skill) skills , a.take_time , a.appointment_status\r\n"
+
" FROM order_info a \r\n"
+
" WHERE a.org_team_id=? AND a.dt = ? AND bean_status='OPEN'\r\n"
+
" AND appointment_method LIKE 'AUTO%' AND a.appointment_status IN ('INIT', 'PRE')\r\n"
+
" AND order_status ='NORMAL' AND service_status='INIT'\r\n"
+
" ORDER BY a.expect_time_begin ASC \r\n"
;
int
orderCount
=
jdbcTemplate
.
update
(
sqlOrder
,
batchNo
,
batchDay
,
teamId
,
batchDay
);
// confirm的要做预占用,所以也加入进来
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"
+
" select a.org_group_id, ?, a.org_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"
+
" concat(a.brand, '-', a.type, '-', a.skill) skills , a.take_time, a.appointment_status, \n"
+
" a.engineer_code, a.plan_start_time, a.plan_end_time \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 ('CONFIRM')\n"
+
" and order_status ='NORMAL' and service_status='INIT'\n"
+
" order by a.expect_time_begin asc "
;
int
orderConfirmCount
=
jdbcTemplate
.
update
(
sqlOrderConfirm
,
batchNo
,
teamId
,
batchDay
);
log
.
info
(
"准备批次数据 engCount:{}, orderCount:{}, orderConfirmCount:{}"
,
engCount
,
orderCount
,
orderConfirmCount
);
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
);
}
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
);
}
log
.
info
(
"准备批次数据完成, teamId:{}, day:{}, batchNo:{}"
,
teamId
,
batchDay
,
batchNo
);
return
batchNo
;
}
@Override
public
String
queryBatchNoByDay
(
String
groupId
,
String
day
)
{
...
...
@@ -193,6 +272,17 @@ public class BatchServiceImpl implements BatchService {
}
@Override
public
String
queryBatchNoByDay2
(
String
teamId
,
String
day
)
{
entityManager
.
clear
();
Optional
<
DispatchBatch
>
optional
=
batchRepository
.
findByTeamIdAndBatchDate
(
teamId
,
day
);
if
(
optional
.
isPresent
())
{
return
optional
.
get
().
getBatchNo
();
}
else
{
return
""
;
}
}
@Override
public
DispatchBatch
queryBatchInfoByDay
(
String
groupId
,
String
day
)
{
entityManager
.
clear
();
Optional
<
DispatchBatch
>
optional
=
batchRepository
.
findByGroupIdAndBatchDate
(
groupId
,
day
);
...
...
@@ -200,6 +290,13 @@ public class BatchServiceImpl implements BatchService {
}
@Override
public
DispatchBatch
queryBatchInfoByDay2
(
String
teamId
,
String
day
)
{
entityManager
.
clear
();
Optional
<
DispatchBatch
>
optional
=
batchRepository
.
findByTeamIdAndBatchDate
(
teamId
,
day
);
return
optional
.
orElseGet
(
DispatchBatch:
:
new
);
}
@Override
public
void
saveDispatchBatch
(
DispatchBatch
batchInfo
)
{
batchRepository
.
save
(
batchInfo
);
}
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/ExtractServiceImpl.java
View file @
3f1796c
...
...
@@ -2,9 +2,13 @@ package com.dituhui.pea.dispatch.service.impl;
import
cn.hutool.core.date.DateTime
;
import
cn.hutool.core.date.DateUtil
;
import
com.alibaba.nacos.common.utils.CollectionUtils
;
import
com.dituhui.pea.dispatch.dao.*
;
import
com.dituhui.pea.dispatch.entity.*
;
import
com.dituhui.pea.dispatch.service.ExtractService
;
import
com.google.common.collect.Maps
;
import
cn.hutool.core.util.StrUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
org.aspectj.weaver.ast.Or
;
...
...
@@ -47,6 +51,8 @@ public class ExtractServiceImpl implements ExtractService {
@Autowired
OrderInfoRepository
orderInfoRepo
;
@Autowired
OrgTeamEngineerDao
orgTeamEngineerDao
;
@Autowired
OrderLogRepository
orderLogRepo
;
...
...
@@ -175,5 +181,132 @@ public class ExtractServiceImpl implements ExtractService {
log
.
info
(
"算法结果更新到工单完成, groupId:{}, batchNo:{}"
,
groupId
,
batchNo
);
}
/**
* 将dispath_order 中的计算结果,回写到 order_info
* order_info(主要更新状态)
*/
@Transactional
(
isolation
=
READ_COMMITTED
,
propagation
=
Propagation
.
REQUIRED
)
@Override
public
void
extractDispatchToOrder2
(
String
teamId
,
String
batchNo
,
boolean
isConfirm
)
{
log
.
info
(
"算法结果更新到工单, teamId:{}, batchNo:{}"
,
teamId
,
batchNo
);
entityManager
.
clear
();
// 工程师数据准备
// Map<String, EngineerInfo> engineerInfoMap =
// engineerInfoRepo.findByGroupId(groupId).stream().collect(Collectors.toMap(EngineerInfo::getEngineerCode,
// y -> y));
final
Map
<
String
,
EngineerInfo
>
engineerInfoMap
=
Maps
.
newHashMap
();
List
<
OrgTeamEngineerEntity
>
engineers
=
orgTeamEngineerDao
.
findAllByTeamId
(
teamId
);
if
(
CollectionUtils
.
isNotEmpty
(
engineers
))
{
List
<
String
>
codes
=
engineers
.
stream
().
map
(
o
->
o
.
getEngineerCode
()).
collect
(
Collectors
.
toList
());
List
<
EngineerInfo
>
engineers2
=
engineerInfoRepo
.
findByEngineerCodeIn
(
codes
);
if
(
CollectionUtils
.
isNotEmpty
(
engineers2
))
{
engineerInfoMap
.
putAll
(
engineers2
.
stream
().
collect
(
Collectors
.
toMap
(
EngineerInfo:
:
getEngineerCode
,
y
->
y
)));
}
}
List
<
DispatchOrder
>
dispatchOrderList
=
dispatchOrderRepo
.
findAllWithoutConfirm2
(
teamId
,
batchNo
);
log
.
info
(
"算法结果更新到工单, step1-开始处理, teamId:{}, batchNo:{}, order-size:{}"
,
teamId
,
batchNo
,
dispatchOrderList
.
size
());
AtomicInteger
atomicInteger
=
new
AtomicInteger
();
dispatchOrderList
.
forEach
(
dispatchOrder
->
{
int
idx
=
atomicInteger
.
getAndIncrement
();
String
orderId
=
dispatchOrder
.
getOrderId
();
String
dt
=
dispatchOrder
.
getDt
();
String
engCode
=
dispatchOrder
.
getEngineerCode
();
log
.
info
(
"算法结果更新到工单, step1.1-loop, {}/{}, teamId:{}, batchNo:{}, orderId:{}, dt:{}, engCode:{}"
,
idx
,
dispatchOrderList
.
size
(),
teamId
,
batchNo
,
orderId
,
dt
,
engCode
);
LocalDate
localDt
=
LocalDate
.
parse
(
dt
,
DateTimeFormatter
.
ofPattern
(
"yyyy-MM-dd"
));
Optional
<
OrderInfo
>
orderOpt
=
orderInfoRepo
.
findOrderInfoByOrderIdAndDt
(
orderId
,
localDt
);
if
(
orderOpt
.
isEmpty
())
{
log
.
warn
(
"算法结果更新到工单, step1.1-loop, 工单不存在, teamId:{}, batchNo:{}, orderId:{}"
,
teamId
,
batchNo
,
orderId
);
return
;
}
OrderInfo
orderInfo
=
orderOpt
.
get
();
if
(!(
"OPEN"
.
equals
(
orderInfo
.
getBeanStatus
())
&&
Set
.
of
(
"AUTO_NOW"
,
"AUTO_BATCH"
).
contains
(
orderInfo
.
getAppointmentMethod
())
&&
Set
.
of
(
"INIT"
,
"PRE"
).
contains
(
orderInfo
.
getAppointmentStatus
())
&&
"NORMAL"
.
equals
(
orderInfo
.
getOrderStatus
())
&&
"INIT"
.
equals
(
orderInfo
.
getServiceStatus
())))
{
log
.
warn
(
"算法结果更新到工单, step1.1-loop, 工单状态异常, teamId:{}, batchNo:{}, orderId:{}, bean-status:{}, appointment-status:{}, order-status:{}, service-status:{}"
,
teamId
,
batchNo
,
orderId
,
orderInfo
.
getBeanStatus
(),
orderInfo
.
getAppointmentStatus
(),
orderInfo
.
getOrderStatus
(),
orderInfo
.
getServiceStatus
());
return
;
}
// 未分配技术员时,清理原分配的信息
if
(!
StrUtil
.
isEmpty
(
engCode
))
{
EngineerInfo
engineerInfo
=
engineerInfoMap
.
get
(
engCode
);
if
(
engineerInfo
==
null
)
{
log
.
warn
(
"算法结果更新到工单, step1.1-loop, 未找到技术员, teamId:{}, batchNo:{}, engCode:{}"
,
teamId
,
batchNo
,
engCode
);
return
;
}
String
engName
=
engineerInfo
.
getName
();
String
phone
=
engineerInfo
.
getPhone
();
/*int age = 0;
if (!StringUtils.isNullOrEmpty(engineerInfo.getBirth())) {
DateTime birthDate = DateUtil.parse(engineerInfo.getBirth(), "yyyy-MM-dd");
age = DateUtil.age(birthDate.toJdkDate(), DateUtil.date());
}*/
orderInfo
.
setEngineerCode
(
engCode
);
orderInfo
.
setEngineerName
(
engName
);
orderInfo
.
setEngineerPhone
(
phone
);
orderInfo
.
setPlanStartTime
(
dispatchOrder
.
getTimeBegin
());
orderInfo
.
setPlanEndTime
(
dispatchOrder
.
getTimeEnd
());
orderInfo
.
setArriveElapsed
(
dispatchOrder
.
getPathTime
());
orderInfo
.
setArriveDistance
(
dispatchOrder
.
getPathDistance
());
orderInfo
.
setAppointmentStatus
(
isConfirm
?
"CONFIRM"
:
"PRE"
);
orderInfo
.
setDispatcher
(
"AUTO_BATCH"
);
orderInfo
.
setUpdateTime
(
LocalDateTime
.
now
());
orderInfoRepo
.
save
(
orderInfo
);
if
(
isConfirm
)
{
OrderEvent
orderEvent
=
new
OrderEvent
().
setOrderId
(
orderId
).
setSuborderId
(
orderInfo
.
getSubId
()).
setHappen
(
LocalDateTime
.
now
())
.
setEvent
(
"批量自动指派"
).
setOperator
(
"DISPATCH"
).
setOperatorName
(
"算法批量指派"
).
setSource
(
"PEA-DISPATCH"
)
.
setDescription
(
String
.
format
(
"批量自动指派:<%s,%s>"
,
engCode
,
engName
)).
setMemo
(
""
)
.
setCreateTime
(
LocalDateTime
.
now
()).
setUpdateTime
(
LocalDateTime
.
now
());
orderEventRepo
.
save
(
orderEvent
);
}
OrderLog
orderLog
=
new
OrderLog
().
setOrderId
(
orderId
).
setSuborderId
(
orderInfo
.
getSubId
()).
setSource
(
"PEA-DISPATCH"
).
setOperator
(
"DISPATCH"
)
.
setContent
(
String
.
format
(
"批量自动指派:<%s,%s>"
,
engCode
,
engName
)).
setContentOld
(
""
)
.
setMemo
(
"批量自动指派"
).
setCreateTime
(
LocalDateTime
.
now
()).
setUpdateTime
(
LocalDateTime
.
now
());
orderLogRepo
.
save
(
orderLog
);
}
else
{
log
.
warn
(
"算法结果更新到工单, step1.2-loop, 未能分配到技术员, teamId:{}, batchNo:{}, orderId:{}, dt:{}"
,
teamId
,
batchNo
,
orderId
,
dt
);
orderInfo
.
setEngineerCode
(
""
);
orderInfo
.
setEngineerName
(
""
);
orderInfo
.
setEngineerPhone
(
""
);
orderInfo
.
setPlanStartTime
(
null
);
orderInfo
.
setPlanEndTime
(
null
);
orderInfo
.
setArriveElapsed
(
0
);
orderInfo
.
setArriveDistance
(
0
);
orderInfo
.
setAppointmentStatus
(
"INIT"
);
orderInfo
.
setDispatcher
(
"AUTO_BATCH"
);
orderInfo
.
setUpdateTime
(
LocalDateTime
.
now
());
orderInfoRepo
.
save
(
orderInfo
);
OrderLog
orderLog
=
new
OrderLog
().
setOrderId
(
orderId
).
setSuborderId
(
orderInfo
.
getSubId
()).
setSource
(
"PEA-DISPATCH"
).
setOperator
(
"DISPATCH"
)
.
setContent
(
String
.
format
(
"批量自动指派:<%s,%s>"
,
""
,
"抹掉技术员"
)).
setContentOld
(
""
)
.
setMemo
(
"批量自动指派"
).
setCreateTime
(
LocalDateTime
.
now
()).
setUpdateTime
(
LocalDateTime
.
now
());
orderLogRepo
.
save
(
orderLog
);
}
});
log
.
info
(
"算法结果更新到工单完成, teamId:{}, batchNo:{}"
,
teamId
,
batchNo
);
}
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/SolveServiceImpl.java
View file @
3f1796c
...
...
@@ -6,8 +6,10 @@ import com.dituhui.pea.dispatch.constraint.DispatchConstraintProvider;
import
com.dituhui.pea.dispatch.dao.DispatchEngineerRepository
;
import
com.dituhui.pea.dispatch.dao.DispatchOrderRepository
;
import
com.dituhui.pea.dispatch.dao.OrgGroupRepository
;
import
com.dituhui.pea.dispatch.dao.OrgTeamDao
;
import
com.dituhui.pea.dispatch.entity.DispatchOrder
;
import
com.dituhui.pea.dispatch.entity.OrgGroup
;
import
com.dituhui.pea.dispatch.entity.OrgTeamEntity
;
import
com.dituhui.pea.dispatch.pojo.*
;
import
com.dituhui.pea.dispatch.service.ExtractService
;
import
com.dituhui.pea.dispatch.service.SolveService
;
...
...
@@ -69,6 +71,8 @@ public class SolveServiceImpl implements SolveService {
@Autowired
private
JdbcTemplate
jdbcTemplate
;
@Autowired
OrgTeamDao
orgTeamDao
;
// 查询技术员所有技能集
private
List
<
String
>
queryEngineerSkills
(
String
engineerCode
)
{
...
...
@@ -185,6 +189,117 @@ public class SolveServiceImpl implements SolveService {
}
// 按小队,批号组装问题对象
@Override
public
DispatchSolution
prepareSolution2
(
String
teamId
,
String
batchNo
)
{
log
.
info
(
"组织问题对象, teamId:{}, batchNo:{}"
,
teamId
,
batchNo
);
entityManager
.
clear
();
OrgTeamEntity
team
=
orgTeamDao
.
findByTeamId
(
teamId
);
// 统一出发地
Depot
oneDepot
;
Optional
<
OrgGroup
>
optional
=
groupRepository
.
findByGroupId
(
team
.
getGroupId
());
if
(
optional
.
isEmpty
())
{
log
.
error
(
"组织问题对象, 未查询到组织信息 ,groupId:{}, batchNo:{}"
,
team
.
getGroupId
(),
batchNo
);
throw
new
RuntimeException
(
String
.
format
(
"组织问题对象, 未查询到组织信息 ,groupId:%s, batchNo:%s"
,
team
.
getGroupId
(),
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
.
findAll2
(
teamId
,
batchNo
);
// List<DispatchOrder> dispatchOrderList = dispatchOrderRepo.findNotAssigned(groupId, batchNo);
log
.
info
(
"组织问题对象, dispatchorder-list, teamId:{}, batchNo:{}, dispatchorder-size:{}"
,
teamId
,
batchNo
,
dispatchOrderList
.
size
());
if
(
dispatchOrderList
.
isEmpty
())
{
log
.
error
(
"组织问题对象, 未查询到工单信息 ,teamId:{}, batchNo:{}"
,
teamId
,
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, teamId:{}, batchNo:{}, customer-list:{}"
,
teamId
,
batchNo
,
customerList
.
size
());
// technicianList
ArrayList
<
Technician
>
technicianList
=
new
ArrayList
<>();
dispatchEngineerRepo
.
findByTeamIdAndBatchNo
(
teamId
,
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
);
});
// 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
);
technicianList
.
add
(
vehicle
);
});
log
.
info
(
"组织问题对象, depotList-list, teamId:{}, batchNo:{}"
,
teamId
,
batchNo
);
log
.
info
(
"组织问题对象, technician-list, teamId:{}, batchNo:{}, technician-list:{}"
,
teamId
,
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
(
team
.
getGroupId
(),
teamId
,
batchNo
,
locationList
,
oneDepot
,
technicianList
,
customerList
);
// path 路网数据初始化,FIXME 需要专门路网数据缓存库
long
time1
=
System
.
currentTimeMillis
();
distanceCalculator
.
initDistanceMaps
(
locationList
);
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
);
return
solution
;
}
/*
* 按小组、批次号组装问题对象
* 调用optaplaner计算输出结果
...
...
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