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 28d0f9a4
authored
Nov 15, 2023
by
chamberone
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' of
https://zhangguoping@gitlab.dituhui.com/bsh/project/pr…
…oject.git into develop
2 parents
e509492e
1b1cb771
Hide whitespace changes
Inline
Side-by-side
Showing
39 changed files
with
908 additions
and
199 deletions
project-dispatch/src/main/java/com/dituhui/pea/dispatch/controller/PathController.java
project-interface/src/main/java/com/dituhui/pea/dispatch/IPath.java
project-interface/src/main/java/com/dituhui/pea/enums/StatusCodeEnum.java
project-interface/src/main/java/com/dituhui/pea/pojo/DistanceParam.java
project-interface/src/main/java/com/dituhui/pea/pojo/Location.java
project-interface/src/main/java/com/dituhui/pea/user/IUser.java
project-order/src/main/java/com/dituhui/pea/order/controller/OrderAssignController.java
project-order/src/main/java/com/dituhui/pea/order/controller/PeaApiController.java
project-order/src/main/java/com/dituhui/pea/order/dao/EngineerSkillGroupDao.java
project-order/src/main/java/com/dituhui/pea/order/dao/OrderInfoDao.java
project-order/src/main/java/com/dituhui/pea/order/dao/OrgTeamDao.java
project-order/src/main/java/com/dituhui/pea/order/dao/OrgTeamEngineerDao.java
project-order/src/main/java/com/dituhui/pea/order/dto/OrderAssignRecommendResp.java
project-order/src/main/java/com/dituhui/pea/order/dto/OrderServiceDetailResp.java
project-order/src/main/java/com/dituhui/pea/order/dto/OrderServiceList.java
project-order/src/main/java/com/dituhui/pea/order/dto/OrderServiceListReq.java
project-order/src/main/java/com/dituhui/pea/order/dto/param/RecommendEngineersReq.java
project-order/src/main/java/com/dituhui/pea/order/entity/EngineerSkillGroupEntity.java
project-order/src/main/java/com/dituhui/pea/order/entity/OrgTeamEngineerEntity.java
project-order/src/main/java/com/dituhui/pea/order/enums/ServiceStatusEnum.java
project-order/src/main/java/com/dituhui/pea/order/enums/TestimonialsEngineerTag.java
project-order/src/main/java/com/dituhui/pea/order/scheduler/CalcEngineerCapacityScheduler.java
project-order/src/main/java/com/dituhui/pea/order/scheduler/CalcOrgCapacityScheduler.java
project-order/src/main/java/com/dituhui/pea/order/service/EngineerCalendarService.java
project-order/src/main/java/com/dituhui/pea/order/service/OrderAssign.java
project-order/src/main/java/com/dituhui/pea/order/service/impl/DispatchServiceImpl.java
project-order/src/main/java/com/dituhui/pea/order/service/impl/EngineerCalendarServiceImpl.java
project-order/src/main/java/com/dituhui/pea/order/service/impl/EngineerGanttServiceImpl.java
project-order/src/main/java/com/dituhui/pea/order/service/impl/OrderAssignImpl.java
project-order/src/main/java/com/dituhui/pea/order/service/impl/OrderCreateServiceImpl.java
project-order/src/main/java/com/dituhui/pea/order/service/impl/OrderInfoServiceImpl.java
project-order/src/main/java/com/dituhui/pea/order/service/impl/OrderServiceDetailImpl.java
project-order/src/main/java/com/dituhui/pea/order/service/impl/OrderServiceListServiceImpl.java
project-order/src/main/java/com/dituhui/pea/order/service/impl/PeaOuterAPIServiceImpl.java
project-order/src/main/java/com/dituhui/pea/order/service/impl/WorkbenchServiceImpl.java
project-order/src/main/java/com/dituhui/pea/order/utils/OrderUtil.java
project-order/src/test/java/com/dituhui/pea/order/scheduler/CalcEngineerCapacitySchedulerTest.java
project-user/src/main/java/com/dituhui/pea/user/controller/UserController.java
project-user/src/main/java/com/dituhui/pea/user/service/UserService.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/controller/PathController.java
View file @
28d0f9a
package
com
.
dituhui
.
pea
.
dispatch
.
controller
;
import
java.util.List
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.RestController
;
import
com.alibaba.druid.util.StringUtils
;
import
com.dituhui.pea.common.BusinessException
;
import
com.dituhui.pea.common.Result
;
...
...
@@ -16,6 +10,12 @@ import com.dituhui.pea.dispatch.pojo.Location;
import
com.dituhui.pea.dispatch.utils.RoadDistanceUtils
;
import
com.dituhui.pea.dispatch.utils.RoadDistanceUtils.Distance
;
import
com.dituhui.pea.pojo.DistanceDTO
;
import
com.dituhui.pea.pojo.DistanceParam
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.List
;
/**
* 道路控制层
...
...
@@ -69,4 +69,19 @@ public class PathController implements IPath {
}
}
@Override
public
DistanceDTO
getLocationDistance
(
DistanceParam
distanceParam
)
{
com
.
dituhui
.
pea
.
pojo
.
Location
origin
=
distanceParam
.
getOrigin
();
com
.
dituhui
.
pea
.
pojo
.
Location
destination
=
distanceParam
.
getDestination
();
Distance
distance
=
roadDistanceUtils
.
getDistance2
(
new
Location
(
0L
,
null
,
null
,
origin
.
getLongitude
(),
origin
.
getLatitude
()),
new
Location
(
0L
,
null
,
null
,
destination
.
getLongitude
(),
destination
.
getLatitude
()),
distanceParam
.
getVehicle
());
DistanceDTO
dto
=
new
DistanceDTO
();
dto
.
setDis
(
distance
.
getDis
());
dto
.
setTime
(
distance
.
getTime
());
return
dto
;
}
}
project-interface/src/main/java/com/dituhui/pea/dispatch/IPath.java
View file @
28d0f9a
package
com
.
dituhui
.
pea
.
dispatch
;
import
com.dituhui.pea.common.Result
;
import
com.dituhui.pea.pojo.DistanceDTO
;
import
com.dituhui.pea.pojo.DistanceParam
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
com.dituhui.pea.common.Result
;
import
com.dituhui.pea.pojo.DistanceDTO
;
/**
* 道路相关接口
*
...
...
@@ -16,17 +18,27 @@ import com.dituhui.pea.pojo.DistanceDTO;
@FeignClient
(
value
=
"project-dispatch"
,
contextId
=
"dispatch"
)
public
interface
IPath
{
/**
* 获取2个订单之间的道路距离
*
* @param fromOrderId 出发订单id
* @param toOrderId 到达订单id
* @param vehicleType 交通工具:1汽车;2电动车;3自行车;4步行 默认是汽车
* @return
*/
@RequestMapping
(
value
=
"/pea-dispatch/getRoadDistance"
,
method
=
RequestMethod
.
POST
)
public
Result
<
DistanceDTO
>
getRoadDistance
(
@RequestParam
(
"fromOrderId"
)
String
fromOrderId
,
@RequestParam
(
"toOrderId"
)
String
toOrderId
,
@RequestParam
(
name
=
"vehicleType"
,
required
=
false
)
Integer
vehicleType
);
/**
* 获取2个订单之间的道路距离
*
* @param fromOrderId 出发订单id
* @param toOrderId 到达订单id
* @param vehicleType 交通工具:1汽车;2电动车;3自行车;4步行 默认是汽车
* @return
*/
@RequestMapping
(
value
=
"/pea-dispatch/getRoadDistance"
,
method
=
RequestMethod
.
POST
)
public
Result
<
DistanceDTO
>
getRoadDistance
(
@RequestParam
(
"fromOrderId"
)
String
fromOrderId
,
@RequestParam
(
"toOrderId"
)
String
toOrderId
,
@RequestParam
(
name
=
"vehicleType"
,
required
=
false
)
Integer
vehicleType
);
/**
* 根据交通方式计算两点间距离
*
* @param distanceParam 参数, 包含起始点, 交通方式
* @return 返回两点距离以及所需时间
*/
@PostMapping
(
"/pea-dispatch/locationDistance"
)
DistanceDTO
getLocationDistance
(
@RequestBody
DistanceParam
distanceParam
);
}
project-interface/src/main/java/com/dituhui/pea/enums/StatusCodeEnum.java
View file @
28d0f9a
...
...
@@ -143,6 +143,8 @@ public enum StatusCodeEnum {
ORDER_RESCHEDULE_BEFORE_TIME
(
"028"
,
"订单不能改约到当前时间以前!"
,
false
),
TEAM_UNMATCHED
(
"029"
,
"工程师没有匹配到工作队"
,
false
),
ORDER_FINISHED
(
"030"
,
"订单已结束,请勿操作"
,
false
),
;
/**
...
...
project-interface/src/main/java/com/dituhui/pea/pojo/DistanceParam.java
0 → 100644
View file @
28d0f9a
package
com
.
dituhui
.
pea
.
pojo
;
import
lombok.Getter
;
import
lombok.Setter
;
@Setter
@Getter
public
class
DistanceParam
{
/**
* 出发点经纬度
*/
private
Location
origin
;
/**
* 出发点经纬度
*/
private
Location
destination
;
/**
* 交通工具:1汽车;2电动车;3自行车;默认是汽车
*/
private
Integer
vehicle
;
}
project-interface/src/main/java/com/dituhui/pea/pojo/Location.java
0 → 100644
View file @
28d0f9a
package
com
.
dituhui
.
pea
.
pojo
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
lombok.Setter
;
import
javax.validation.constraints.NotNull
;
@Setter
@Getter
@AllArgsConstructor
public
class
Location
{
/**
* 地址纬度
*/
@NotNull
(
message
=
"地址纬度必填"
)
private
Double
latitude
;
/**
* 地址经度
*/
@NotNull
(
message
=
"地址经度必填"
)
private
Double
longitude
;
}
project-interface/src/main/java/com/dituhui/pea/user/IUser.java
View file @
28d0f9a
...
...
@@ -173,6 +173,15 @@ public interface IUser {
* @return
*/
@RequestMapping
(
value
=
"/pea-user/orgs"
,
method
=
RequestMethod
.
GET
)
Result
<
List
<
OrgInfo
>>
orgs
(
String
userId
);
Result
<
List
<
OrgInfo
>>
orgs
(
@RequestParam
(
"userId"
)
String
userId
);
/**
* 获取用户组织
*
* @param userId 查询条件
* @return
*/
@RequestMapping
(
value
=
"/pea-user/orgsNoName"
,
method
=
RequestMethod
.
GET
)
Result
<
List
<
OrgInfo
>>
orgsNoName
(
@RequestParam
(
"userId"
)
String
userId
);
}
project-order/src/main/java/com/dituhui/pea/order/controller/OrderAssignController.java
View file @
28d0f9a
...
...
@@ -2,17 +2,19 @@ package com.dituhui.pea.order.controller;
import
com.dituhui.pea.common.BusinessException
;
import
com.dituhui.pea.common.Result
;
import
com.dituhui.pea.order.common.TimeUtils
;
import
com.dituhui.pea.order.dto.OrderAssignReq
;
import
com.dituhui.pea.order.dto.OrderReschedule
;
import
com.dituhui.pea.order.dto.OrderRevokeAssign
;
import
com.dituhui.pea.order.dto.param.RecommendEngineersReq
;
import
com.dituhui.pea.order.service.OrderAssign
;
import
com.dituhui.pea.order.service.OrderInfoService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
...
...
@@ -27,14 +29,12 @@ public class OrderAssignController {
private
OrderInfoService
orderInfoService
;
@GetMapping
(
"/order/assign/recommend/engineers"
)
public
Result
<?>
getOrderAssignRecommendEngineers
(
@RequestParam
String
orderId
,
@RequestParam
(
required
=
false
)
String
key
,
@RequestParam
(
required
=
false
)
String
distance
,
@RequestParam
(
required
=
false
)
String
recommend
)
{
public
Result
<?>
getOrderAssignRecommendEngineers
(
RecommendEngineersReq
req
)
{
//服务单指派-推荐技术员列表
Result
<?>
res
=
null
;
try
{
res
=
orderAssign
.
getOrderAssignRecommendEngineers
(
orderId
,
key
,
distance
,
recommend
);
res
=
orderAssign
.
getOrderAssignRecommendEngineers
(
req
);
}
catch
(
BusinessException
e
)
{
return
Result
.
failed
(
e
.
getMessage
());
}
...
...
project-order/src/main/java/com/dituhui/pea/order/controller/PeaApiController.java
View file @
28d0f9a
...
...
@@ -2,12 +2,13 @@ package com.dituhui.pea.order.controller;
import
com.dituhui.pea.common.BusinessException
;
import
com.dituhui.pea.common.Result
;
import
com.dituhui.pea.dispatch.IPath
;
import
com.dituhui.pea.enums.StatusCodeEnum
;
import
com.dituhui.pea.order.common.jackson.DateUtil
;
import
com.dituhui.pea.order.common.jackson.JsonUtil
;
import
com.dituhui.pea.order.dao.TableCodeCheckDao
;
import
com.dituhui.pea.order.dto.param.BaseDistance
;
import
com.dituhui.pea.order.dto.param.BaseDistanceParam
;
import
com.dituhui.pea.order.dto.param.BaseLocation
;
import
com.dituhui.pea.order.dto.param.CapacityQueryDTO
;
import
com.dituhui.pea.order.dto.param.EngineerCalendarResultDTO
;
import
com.dituhui.pea.order.dto.param.EngineerOrderParam
;
...
...
@@ -22,6 +23,9 @@ import com.dituhui.pea.order.service.EngineerCalendarService;
import
com.dituhui.pea.order.service.OrderCreateService
;
import
com.dituhui.pea.order.service.OrderInfoService
;
import
com.dituhui.pea.order.service.PeaOuterAPIService
;
import
com.dituhui.pea.pojo.DistanceDTO
;
import
com.dituhui.pea.pojo.DistanceParam
;
import
com.dituhui.pea.pojo.Location
;
import
com.fasterxml.jackson.annotation.JsonFormat
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
...
...
@@ -64,6 +68,7 @@ public class PeaApiController {
private
OrderInfoService
orderInfoService
;
private
final
CapacityQueryService
capacityQueryService
;
private
final
TableCodeCheckDao
tableCodeCheckDao
;
private
final
IPath
path
;
private
static
final
String
stage
=
"{\"orderId\": \"X10001\", \"engineerCode\": \"E12005\", \"engineerName\": \"祝枝山\", \"engineerCodeAssist\": \"E12446\", \"engineerNameAssist\": \"李晓阳\", \"planVisitTime\": \"2023-07-27 12:00:00\", \"realtimeInfo\": {\"engineerLocation\": {\"latitude\": 31.349701, \"longitude\": 120.675945, \"address\": \"江苏省苏州市苏州工业园区和顺路\", \"name\": \"和顺大酒店\"}, \"estimate\": {\"distance\": 2300, \"arriveTime\": \"2023-07-27 12:12:00\"}}}"
;
...
...
@@ -332,9 +337,21 @@ public class PeaApiController {
public
Result
<
BaseDistance
>
baseDistance
(
@RequestBody
BaseDistanceParam
param
)
{
BaseDistance
result
=
new
BaseDistance
();
result
.
setOrigin
(
param
.
getOrigin
());
result
.
setDestination
(
param
.
getDestination
());
BaseLocation
origin
=
param
.
getOrigin
();
result
.
setOrigin
(
origin
);
BaseLocation
destination
=
param
.
getDestination
();
result
.
setDestination
(
destination
);
result
.
setVehicle
(
param
.
getVehicle
());
DistanceParam
distanceParam
=
new
DistanceParam
();
distanceParam
.
setOrigin
(
new
Location
(
origin
.
getLongitude
(),
origin
.
getLatitude
()));
distanceParam
.
setOrigin
(
new
Location
(
destination
.
getLongitude
(),
destination
.
getLatitude
()));
distanceParam
.
setVehicle
(
param
.
getVehicle
());
DistanceDTO
locationDistance
=
path
.
getLocationDistance
(
distanceParam
);
result
.
setDistance
((
int
)
locationDistance
.
getDis
());
result
.
setDuration
((
long
)
locationDistance
.
getTime
());
return
Result
.
success
(
result
);
}
...
...
project-order/src/main/java/com/dituhui/pea/order/dao/EngineerSkillGroupDao.java
View file @
28d0f9a
package
com
.
dituhui
.
pea
.
order
.
dao
;
import
com.dituhui.pea.order.entity.EngineerSkillGroupEntity
;
import
com.dituhui.pea.order.entity.SkillGroupEntity
;
import
org.springframework.data.jpa.repository.JpaRepository
;
import
org.springframework.data.jpa.repository.Query
;
import
org.springframework.stereotype.Repository
;
import
java.util.List
;
...
...
project-order/src/main/java/com/dituhui/pea/order/dao/OrderInfoDao.java
View file @
28d0f9a
...
...
@@ -77,4 +77,29 @@ public interface OrderInfoDao extends JpaRepository<OrderInfoEntity, Long>, JpaS
" WHERE si.skill_group_code = :skillGroupCode AND oi.expect_time_begin >= :dateTime AND oi.is_multiple = 0 "
+
" AND (appointment_status = 'INIT' AND order_status != 'CANCELED') AND oi.reason_for_failure IS NULL "
,
nativeQuery
=
true
)
List
<
OrderInfoEntity
>
getSkillGroupOrder
(
String
skillGroupCode
,
LocalDateTime
dateTime
);
@Query
(
value
=
"SELECT count(*) from order_info WHERE dt =:dt and (service_status ='INIT' or service_status ='CONTACTED') "
+
"and DATE_ADD(NOW(), INTERVAL 10 MINUTE) > expect_time_begin and org_cluster_id = :orgCusterId"
,
nativeQuery
=
true
)
long
countDelayByDtAndOrgClusterId
(
LocalDate
dt
,
String
orgCusterId
);
@Query
(
value
=
"SELECT count(*) from order_info WHERE dt =:dt and (service_status ='INIT' or service_status ='CONTACTED') "
+
"and DATE_ADD(NOW(), INTERVAL 10 MINUTE) > expect_time_begin and org_group_id = :orgGroupId"
,
nativeQuery
=
true
)
long
countDelayByDtAndOrgGroupId
(
LocalDate
dt
,
String
orgGroupId
);
@Query
(
value
=
"SELECT count(*) from order_info WHERE dt =:dt and (service_status ='INIT' or service_status ='CONTACTED') "
+
"and DATE_ADD(NOW(), INTERVAL 10 MINUTE) > expect_time_begin and org_branch_id = :orgBranchId"
,
nativeQuery
=
true
)
long
countDelayByDtAndOrgBranchId
(
LocalDate
dt
,
String
orgBranchId
);
@Query
(
value
=
"SELECT count(*) from order_info WHERE dt =:dt and service_status ='STARTED' and actual_end_time is null "
+
"and DATE_ADD(NOW(), INTERVAL 10 MINUTE) > plan_end_time and org_cluster_id = :orgCusterId"
,
nativeQuery
=
true
)
long
countOvertimeByDtAndOrgClusterId
(
LocalDate
dt
,
String
orgCusterId
);
@Query
(
value
=
"SELECT count(*) from order_info WHERE dt =:dt and service_status ='STARTED' and actual_end_time is null "
+
"and DATE_ADD(NOW(), INTERVAL 10 MINUTE) > plan_end_time and org_group_id = :orgGroupId"
,
nativeQuery
=
true
)
long
countOvertimeByDtAndOrgGroupId
(
LocalDate
dt
,
String
orgGroupId
);
@Query
(
value
=
"SELECT count(*) from order_info WHERE dt =:dt and service_status ='STARTED' and actual_end_time is null "
+
"and DATE_ADD(NOW(), INTERVAL 10 MINUTE) > plan_end_time and org_branch_id = :orgBranchId"
,
nativeQuery
=
true
)
long
countOvertimeByDtAndOrgBranchId
(
LocalDate
dt
,
String
orgBranchId
);
}
project-order/src/main/java/com/dituhui/pea/order/dao/OrgTeamDao.java
View file @
28d0f9a
...
...
@@ -45,6 +45,12 @@ public interface OrgTeamDao extends JpaRepository<OrgTeamEntity, Integer>, JpaSp
public
List
<
OrgTeamEntity
>
findByTeamIdIn
(
List
<
String
>
ids
);
public
List
<
OrgTeamEntity
>
findByClusterIdIn
(
List
<
String
>
ids
);
public
List
<
OrgTeamEntity
>
findByBranchIdIn
(
List
<
String
>
ids
);
public
List
<
OrgTeamEntity
>
findByGroupIdIn
(
List
<
String
>
ids
);
/**
* 获取工程师所在的工作队
*
...
...
project-order/src/main/java/com/dituhui/pea/order/dao/OrgTeamEngineerDao.java
View file @
28d0f9a
...
...
@@ -11,7 +11,6 @@ import java.util.List;
@Repository
@Where
(
clause
=
"status = 1"
)
public
interface
OrgTeamEngineerDao
extends
JpaRepository
<
OrgTeamEngineerEntity
,
Integer
>
{
@Query
(
"select t from OrgTeamEngineerEntity t where t.teamId = :teamId and t.status=1"
)
...
...
@@ -34,6 +33,7 @@ public interface OrgTeamEngineerDao extends JpaRepository<OrgTeamEngineerEntity,
@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
);
@Query
(
"select t from OrgTeamEngineerEntity t where t.engineerCode in :engineerCode and t.status=1"
)
List
<
OrgTeamEngineerEntity
>
findByEngineerCode
(
String
engineerCode
);
/**
...
...
project-order/src/main/java/com/dituhui/pea/order/dto/OrderAssignRecommendResp.java
View file @
28d0f9a
package
com
.
dituhui
.
pea
.
order
.
dto
;
import
com.dituhui.pea.order.enums.TestimonialsEngineerTag
;
import
lombok.Data
;
import
java.util.List
;
...
...
@@ -7,32 +8,35 @@ import java.util.List;
@Data
public
class
OrderAssignRecommendResp
{
List
<
Engineer
>
engineers
;
List
<
Engineer
>
engineers
;
@Data
public
static
class
Engineer
{
private
String
engineerCode
;
private
String
engineerName
;
private
String
location
;
private
String
distanceDesc
;
private
String
timeDesc
;
private
String
desc
;
private
String
startTime
;
private
String
endTime
;
private
InsertInfo
insertInfo
;
private
List
<
TimeLineDTO
>
orders
;
}
@Data
public
static
class
Engineer
{
private
String
engineerCode
;
private
String
engineerName
;
private
String
location
;
/**
* 工程师标签
*/
private
TestimonialsEngineerTag
distanceDesc
;
private
String
timeDesc
;
private
String
desc
;
private
String
startTime
;
private
String
endTime
;
private
InsertInfo
insertInfo
;
private
List
<
TimeLineDTO
>
orders
;
}
@Data
public
static
class
InsertInfo
{
private
String
number
;
private
String
distanceDesc
;
private
String
TimeDesc
;
}
@Data
public
static
class
InsertInfo
{
private
String
number
;
private
String
distanceDesc
;
private
String
TimeDesc
;
}
@Data
public
static
class
Tag
{
private
String
title
;
private
String
color
;
}
@Data
public
static
class
Tag
{
private
String
title
;
private
String
color
;
}
}
project-order/src/main/java/com/dituhui/pea/order/dto/OrderServiceDetailResp.java
View file @
28d0f9a
...
...
@@ -64,6 +64,8 @@ public class OrderServiceDetailResp {
private
String
expectTimeBegin
;
private
String
expectTimeEnd
;
private
String
expectTimeDesc
;
private
String
source
;
...
...
project-order/src/main/java/com/dituhui/pea/order/dto/OrderServiceList.java
View file @
28d0f9a
...
...
@@ -34,6 +34,9 @@ public class OrderServiceList {
private
String
serviceStatus
;
private
String
createTime
;
private
String
engineerCode
;
private
String
engineerName
;
private
String
engineerPhone
;
/**
* bean优先级,例如:紧急、正常
*/
...
...
project-order/src/main/java/com/dituhui/pea/order/dto/OrderServiceListReq.java
View file @
28d0f9a
...
...
@@ -13,10 +13,12 @@ public class OrderServiceListReq {
private
String
levelType
;
@NotNull
private
String
levelValue
;
// @NotNull
// private String startDate;
// @NotNull
// private String endDate;
@NotNull
private
String
startDate
;
@NotNull
private
String
endDate
;
private
String
date
;
@NotNull
private
long
page
;
@NotNull
...
...
project-order/src/main/java/com/dituhui/pea/order/dto/param/RecommendEngineersReq.java
0 → 100644
View file @
28d0f9a
package
com
.
dituhui
.
pea
.
order
.
dto
.
param
;
import
lombok.Data
;
@Data
public
class
RecommendEngineersReq
{
/**
* 工单ID
*/
private
String
orderId
;
/**
* 待补充doc
*/
private
String
key
;
/**
* 距离范围(单位:KM), 不传改值为:不限
*/
private
Double
distance
;
/**
* 待补充doc
*/
private
String
recommend
;
/**
* 待补充doc
*/
private
String
userId
;
}
project-order/src/main/java/com/dituhui/pea/order/entity/EngineerSkillGroupEntity.java
View file @
28d0f9a
package
com
.
dituhui
.
pea
.
order
.
entity
;
import
lombok.Data
;
import
org.hibernate.annotations.Where
;
import
javax.persistence.*
;
import
java.time.LocalDateTime
;
...
...
@@ -8,6 +9,7 @@ import java.time.LocalDateTime;
@Data
@Entity
@Table
(
name
=
"engineer_skill_group"
)
@Where
(
clause
=
" status = 1"
)
public
class
EngineerSkillGroupEntity
{
@Id
...
...
project-order/src/main/java/com/dituhui/pea/order/entity/OrgTeamEngineerEntity.java
View file @
28d0f9a
...
...
@@ -2,6 +2,7 @@ package com.dituhui.pea.order.entity;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
org.hibernate.annotations.Where
;
import
javax.persistence.*
;
import
java.time.LocalDateTime
;
...
...
@@ -10,6 +11,7 @@ import java.util.Date;
@Entity
@Data
@Accessors
(
chain
=
true
)
@Where
(
clause
=
"status = 1"
)
@Table
(
name
=
"org_team_engineer"
)
public
class
OrgTeamEngineerEntity
{
...
...
project-order/src/main/java/com/dituhui/pea/order/enums/ServiceStatusEnum.java
View file @
28d0f9a
...
...
@@ -6,6 +6,7 @@ public enum ServiceStatusEnum {
PENDING
(
"PENDING"
,
"待服务"
),
CONTACTED
(
"CONTACTED"
,
"已排期"
),
STARTED
(
"STARTED"
,
"已开始"
),
CANCELED
(
"CANCELED"
,
"已取消"
),
FINISHED
(
"FINISHED"
,
"已完成"
),
UNFINISHED
(
"UNFINISHED"
,
"已上门未完成"
);
...
...
project-order/src/main/java/com/dituhui/pea/order/enums/TestimonialsEngineerTag.java
0 → 100644
View file @
28d0f9a
package
com
.
dituhui
.
pea
.
order
.
enums
;
import
lombok.Getter
;
/**
* 推荐工程师标签
*/
@Getter
public
enum
TestimonialsEngineerTag
{
/**
* 队内 ,和工单现有人员同属一个小队
*/
TEAM
,
/**
* 周边, 不同队 但在10KM内
*/
PERIPHERAL
,
/**
* 搜索, 通过搜索出来的人
*/
SEARCH
;
}
project-order/src/main/java/com/dituhui/pea/order/scheduler/CalcEngineerCapacityScheduler.java
View file @
28d0f9a
...
...
@@ -11,6 +11,7 @@ import com.dituhui.pea.order.dao.EngineerBusinessDao;
import
com.dituhui.pea.order.dao.EngineerInfoDao
;
import
com.dituhui.pea.order.dao.EngineerSliceUsedCapacityDao
;
import
com.dituhui.pea.order.dao.OrderInfoDao
;
import
com.dituhui.pea.order.dao.TimeSliceDao
;
import
com.dituhui.pea.order.entity.CapacityEngineerSliceUsedEntity
;
import
com.dituhui.pea.order.entity.CapacityEngineerStatEntity
;
import
com.dituhui.pea.order.entity.EngineerBusinessEntity
;
...
...
@@ -19,6 +20,7 @@ import com.dituhui.pea.order.entity.OrderInfoEntity;
import
com.dituhui.pea.order.entity.TimeSliceEntity
;
import
com.dituhui.pea.order.service.EngineerCalendarService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.scheduling.annotation.Scheduled
;
...
...
@@ -30,10 +32,12 @@ import java.time.LocalDateTime;
import
java.time.LocalTime
;
import
java.time.ZoneId
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.Optional
;
import
java.util.Set
;
import
java.util.concurrent.TimeUnit
;
import
java.util.stream.Collectors
;
@Slf4j
...
...
@@ -57,6 +61,8 @@ public class CalcEngineerCapacityScheduler {
private
EngineerSliceUsedCapacityDao
engineerSliceUsedCapacityDao
;
@Autowired
private
EngineerCalendarService
engineerCalendarService
;
@Autowired
private
TimeSliceDao
timeSliceDao
;
@Scheduled
(
cron
=
"${scheduler.calc-engineer-capacity.cron-expr}"
)
public
void
run
()
{
...
...
@@ -108,8 +114,9 @@ public class CalcEngineerCapacityScheduler {
})
.
collect
(
Collectors
.
toList
());
initOneEngineerTimeSlot
(
date
,
engineerCode
,
configs
,
orders
);
List
<
TimeSliceEntity
>
commonTimeSliceList
=
timeSliceDao
.
findByType
(
"HOURS"
);
initOneEngineerTimeSlot
(
date
,
engineerCode
,
configs
,
orders
,
commonTimeSliceList
);
caculateEngineerOneDay
(
date
,
businessEntity
,
orders
,
configs
,
statEntity
);
capacityEngineerStatDao
.
save
(
statEntity
);
}
...
...
@@ -125,20 +132,51 @@ public class CalcEngineerCapacityScheduler {
List
<
OccupyInfoDetail
>
durationTime
=
CapacityUtils
.
getMaxRemainBlock
(
startTime
,
endTime
,
occupyInfo
);
long
maxRemainBlock
=
durationTime
.
stream
().
mapToLong
(
OccupyInfoDetail:
:
getDuration
).
max
().
orElse
(
0L
);
//总时长
long
total
=
Duration
.
between
(
startTime
,
endTime
).
abs
().
toMinutes
();
statEntity
.
setCapTotal
((
int
)
total
);
statEntity
.
setOrderCount
(
orders
.
size
());
statEntity
.
setCapUsed
((
int
)
totalUseTime
);
statEntity
.
setCapLeft
(
statEntity
.
getCapTotal
()
-
(
int
)
totalUseTime
);
statEntity
.
setCapLeft
(
(
int
)
total
-
(
int
)
totalUseTime
);
statEntity
.
setMaxDuration
((
int
)
maxRemainBlock
);
statEntity
.
setUpdateTime
(
LocalDateTime
.
now
());
}
//添加工程师日历参数
private
void
initOneEngineerTimeSlot
(
String
date
,
String
engineerCode
,
List
<
OccupyInfoDetail
>
configs
,
List
<
OrderInfoEntity
>
orders
)
{
List
<
OrderInfoEntity
>
orders
,
List
<
TimeSliceEntity
>
commonTimeSliceList
)
{
final
LocalDate
localDate
=
LocalDate
.
parse
(
date
,
DateTimeUtil
.
DATE_FORMAT
);
//查询时间片容量
List
<
CapacityEngineerSliceUsedEntity
>
engineerTimeSlice
=
engineerSliceUsedCapacityDao
.
findByWorkdayAndEngineerCode
(
date
,
engineerCode
);
//查询哪些时间片需要新增, 哪些时间片需要删除
List
<
TimeSliceEntity
>
timeCorridor
=
engineerTimeSlice
(
engineerCode
,
date
,
commonTimeSliceList
);
//需要删除的时间片记录
List
<
CapacityEngineerSliceUsedEntity
>
needDeleteTimeSlice
=
engineerTimeSlice
.
stream
()
.
filter
(
t
->
timeCorridor
.
stream
().
noneMatch
(
ti
->
Objects
.
equals
(
ti
,
t
.
getTimmeSlice
())))
.
collect
(
Collectors
.
toList
());
if
(
CollectionUtils
.
isNotEmpty
(
needDeleteTimeSlice
))
{
engineerTimeSlice
.
removeAll
(
needDeleteTimeSlice
);
engineerSliceUsedCapacityDao
.
deleteAll
(
needDeleteTimeSlice
);
engineerSliceUsedCapacityDao
.
flush
();
}
//需要增加的时间切片
List
<
CapacityEngineerSliceUsedEntity
>
needAdd
=
timeCorridor
.
stream
()
.
filter
(
slice
->
engineerTimeSlice
.
stream
()
.
map
(
CapacityEngineerSliceUsedEntity:
:
getTimmeSlice
).
noneMatch
(
ti
->
Objects
.
equals
(
ti
,
slice
))
).
map
(
timeSlice
->
{
CapacityEngineerSliceUsedEntity
r
=
new
CapacityEngineerSliceUsedEntity
();
r
.
setTimmeSlice
(
timeSlice
);
r
.
setEngineerCode
(
engineerCode
);
r
.
setWorkday
(
date
);
LocalTime
sliceStartLocalTime
=
LocalTime
.
parse
(
timeSlice
.
getStart
(),
DateUtil
.
TIME_FORMATTER
);
LocalTime
sliceEndLocalTime
=
LocalTime
.
parse
(
timeSlice
.
getEnd
(),
DateUtil
.
TIME_FORMATTER
);
r
.
setCapTotal
(
DateTimeUtil
.
betweenTwoTime
(
sliceStartLocalTime
,
sliceEndLocalTime
,
TimeUnit
.
MINUTES
));
r
.
setCreateTime
(
LocalDateTime
.
now
());
return
r
;
}).
collect
(
Collectors
.
toList
());
engineerTimeSlice
.
addAll
(
needAdd
);
for
(
CapacityEngineerSliceUsedEntity
sliceCap
:
engineerTimeSlice
)
{
final
TimeSliceEntity
timeSlice
=
sliceCap
.
getTimmeSlice
();
LocalTime
sliceStartLocalTime
=
LocalTime
.
parse
(
timeSlice
.
getStart
(),
DateUtil
.
TIME_FORMATTER
);
...
...
@@ -164,4 +202,35 @@ public class CalcEngineerCapacityScheduler {
engineerSliceUsedCapacityDao
.
saveAll
(
engineerTimeSlice
);
}
private
List
<
TimeSliceEntity
>
engineerTimeSlice
(
String
engineerCode
,
String
date
,
List
<
TimeSliceEntity
>
commonTimeSliceList
)
{
EngineerBusinessEntity
businessEntity
=
engineerBusinessDao
.
getByEngineerCode
(
engineerCode
);
LocalDateTime
workStartTime
=
DateUtils
.
localDateTimeFromStr
(
String
.
format
(
"%s %s:00"
,
date
,
businessEntity
.
getWorkOn
()));
LocalDateTime
workEndTime
=
DateUtils
.
localDateTimeFromStr
(
String
.
format
(
"%s %s:00"
,
date
,
businessEntity
.
getWorkOff
()));
return
getTimeSliceEntities
(
workStartTime
,
workEndTime
,
commonTimeSliceList
);
}
private
List
<
TimeSliceEntity
>
getTimeSliceEntities
(
LocalDateTime
workStartTime
,
LocalDateTime
workEndTime
,
List
<
TimeSliceEntity
>
commonTimeSliceList
)
{
//切片开始时间
LocalTime
sliceStartHour
=
LocalTime
.
of
(
workStartTime
.
getHour
(),
0
);
//切片结束时间
LocalTime
sliceEndHour
;
int
minuteOfHour
=
workEndTime
.
getMinute
();
if
(
minuteOfHour
>
0
)
{
sliceEndHour
=
LocalTime
.
of
(
workEndTime
.
getHour
(),
0
).
plusHours
(
1
);
}
else
{
sliceEndHour
=
LocalTime
.
of
(
workEndTime
.
getHour
(),
0
);
}
List
<
TimeSliceEntity
>
timeCorridor
=
commonTimeSliceList
.
stream
()
.
filter
(
slice
->
{
LocalTime
startLocalTime
=
LocalTime
.
parse
(
slice
.
getStart
(),
DateUtil
.
TIME_FORMATTER
);
LocalTime
endLocalTime
=
LocalTime
.
parse
(
slice
.
getEnd
(),
DateUtil
.
TIME_FORMATTER
);
return
(
startLocalTime
.
isAfter
(
sliceStartHour
)
&&
endLocalTime
.
isBefore
(
sliceEndHour
))
||
(
startLocalTime
.
equals
(
sliceStartHour
)
||
endLocalTime
.
equals
(
sliceEndHour
));
}).
sorted
(
Comparator
.
comparing
(
TimeSliceEntity:
:
getId
)).
collect
(
Collectors
.
toList
());
return
timeCorridor
;
}
}
project-order/src/main/java/com/dituhui/pea/order/scheduler/CalcOrgCapacityScheduler.java
View file @
28d0f9a
...
...
@@ -10,6 +10,8 @@ import org.springframework.beans.factory.annotation.Value;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Component
;
import
java.math.BigDecimal
;
import
java.math.BigInteger
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.util.ArrayList
;
...
...
@@ -100,10 +102,10 @@ public class CalcOrgCapacityScheduler {
dto
.
setOrgId
(
groupId
);
dto
.
setLayerId
((
String
)
result
[
1
]);
dto
.
setLayer
((
String
)
result
[
2
]);
dto
.
setEngineerCount
((
Integer
)
result
[
3
]
);
dto
.
setCapTotal
((
Integer
)
result
[
4
]
);
dto
.
setCapUsed
((
Integer
)
result
[
5
]
);
dto
.
setCapLeft
((
Integer
)
result
[
6
]
);
dto
.
setEngineerCount
((
(
BigInteger
)
result
[
3
]).
intValue
()
);
dto
.
setCapTotal
((
(
BigDecimal
)
result
[
4
]).
intValue
()
);
dto
.
setCapUsed
((
(
BigDecimal
)
result
[
5
]).
intValue
()
);
dto
.
setCapLeft
((
(
BigDecimal
)
result
[
6
]).
intValue
()
);
stats
.
add
(
dto
);
}
// 逐条保存
...
...
@@ -178,7 +180,7 @@ public class CalcOrgCapacityScheduler {
}
}
p
rivate
void
calcAllGroupByDays
(
String
bdate
,
String
edate
)
{
p
ublic
void
calcAllGroupByDays
(
String
bdate
,
String
edate
)
{
LocalDate
currentDate
=
DateUtils
.
localDateFromStr
(
bdate
);
LocalDate
endDate
=
DateUtils
.
localDateFromStr
(
edate
);
List
<
String
>
allGroupIds
=
orgGroupDao
.
findAll
().
stream
().
map
(
OrgGroupEntity:
:
getGroupId
).
collect
(
Collectors
.
toList
());
...
...
project-order/src/main/java/com/dituhui/pea/order/service/EngineerCalendarService.java
View file @
28d0f9a
...
...
@@ -65,10 +65,20 @@ public interface EngineerCalendarService {
* 获取工程师的工作时间窗
*
* @param engineerCode 工程师编号
* @param teamId 工程师所属工作队 (解决一个工程师属多个多工作对情况)
* @param teamId
工程师所属工作队 (解决一个工程师属多个多工作对情况)
* @param targetDate 目标日期
* @return 时间窗格式
* @apiNote 时间窗格式:[[起始时间段1, 结束时间段1],[起始时间段2, 结束时间段2]] <br/> 时间格式: 从0点开始的分钟数, 如8:00AM 为480
*/
int
[][]
timeWindows
(
String
engineerCode
,
String
teamId
,
LocalDate
targetDate
);
/**
* 获取工程师的工作时间窗
*
* @param engineerCode 工程师编号
* @param teamId 工程师所属工作队 (解决一个工程师属多个多工作对情况)
* @param targetDate 目标日期
* @return 时间窗格式
*/
List
<
OccupyInfoDetail
>
timeWindowsSlice
(
String
engineerCode
,
String
teamId
,
LocalDate
targetDate
);
}
project-order/src/main/java/com/dituhui/pea/order/service/OrderAssign.java
View file @
28d0f9a
...
...
@@ -3,6 +3,7 @@ package com.dituhui.pea.order.service;
import
com.dituhui.pea.common.Result
;
import
com.dituhui.pea.order.dto.OrderAssignReq
;
import
com.dituhui.pea.order.dto.OrderReschedule
;
import
com.dituhui.pea.order.dto.param.RecommendEngineersReq
;
import
org.bouncycastle.asn1.cms.TimeStampAndCRL
;
import
java.sql.Timestamp
;
...
...
@@ -12,7 +13,7 @@ import java.time.LocalDateTime;
public
interface
OrderAssign
{
// 服务单指派-推荐技术员列表
Result
<?>
getOrderAssignRecommendEngineers
(
String
orderId
,
String
key
,
String
distance
,
String
recommend
);
Result
<?>
getOrderAssignRecommendEngineers
(
RecommendEngineersReq
req
);
// 服务单指派-指派提交
Result
<?>
orderAssign
(
OrderAssignReq
req
);
...
...
project-order/src/main/java/com/dituhui/pea/order/service/impl/DispatchServiceImpl.java
View file @
28d0f9a
...
...
@@ -326,6 +326,7 @@ public class DispatchServiceImpl implements DispatchService {
if
(!
entityResult
.
getCode
().
equals
(
ResultEnum
.
SUCCESS
.
getCode
()))
{
// return Result.failed("当前工程师无法预约合适时间");
errorList
.
add
(
entity
.
getOrderId
());
continue
;
}
entity
=
entityResult
.
getResult
();
entity
.
setTakeTime
(
skill
.
getTakeTime
());
...
...
project-order/src/main/java/com/dituhui/pea/order/service/impl/EngineerCalendarServiceImpl.java
View file @
28d0f9a
...
...
@@ -613,27 +613,47 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
@Override
public
int
[][]
timeWindows
(
String
engineerCode
,
String
teamId
,
LocalDate
targetDate
)
{
final
LocalDateTime
minDate
=
LocalDateTime
.
of
(
targetDate
,
LocalTime
.
MIN
);
//工作时间与时间时间并集求差集
List
<
OccupyInfoDetail
>
result
=
timeWindowsSlice
(
engineerCode
,
teamId
,
targetDate
);
if
(
CollectionUtils
.
isEmpty
(
result
))
{
return
new
int
[
0
][];
}
int
[][]
ints
=
new
int
[
result
.
size
()][
2
];
for
(
int
i
=
0
;
i
<
result
.
size
();
i
++)
{
OccupyInfoDetail
occupy
=
result
.
get
(
i
);
int
start
=
(
int
)
Duration
.
between
(
occupy
.
getBeginTime
(),
minDate
).
abs
().
toMinutes
();
int
end
=
(
int
)
Duration
.
between
(
occupy
.
getEndTime
(),
minDate
).
abs
().
toMinutes
();
ints
[
i
][
0
]
=
start
;
ints
[
i
][
1
]
=
end
;
}
return
ints
;
}
@Override
public
List
<
OccupyInfoDetail
>
timeWindowsSlice
(
String
engineerCode
,
String
teamId
,
LocalDate
targetDate
)
{
EngineerInfoEntity
engineerInfoEntity
=
engineerInfoDao
.
selectEngineerByEngineerCodeAndTeamId
(
engineerCode
,
teamId
);
if
(
Objects
.
isNull
(
engineerInfoEntity
))
{
return
new
int
[
0
][]
;
return
Collections
.
emptyList
()
;
}
OrgTeamEntity
e
=
orgTeamDao
.
getByTeamId
(
teamId
);
List
<
String
>
workDay
=
List
.
of
(
e
.
getWorkdays
().
split
(
","
));
final
int
dayOfWeek
=
targetDate
.
getDayOfWeek
().
getValue
();
if
(!
workDay
.
contains
(
String
.
valueOf
(
dayOfWeek
)))
{
return
new
int
[
0
][]
;
return
Collections
.
emptyList
()
;
}
//是工作日, 取当前天的日历事件
EngineerBusinessEntity
businessEntity
=
engineerBusinessDao
.
getByEngineerCode
(
engineerCode
);
LocalDateTime
workStartTime
=
DateUtils
.
localDateTimeFromStr
(
String
.
format
(
"%s %s:00"
,
targetDate
,
businessEntity
.
getWorkOn
()));
LocalDateTime
workEndTime
=
DateUtils
.
localDateTimeFromStr
(
String
.
format
(
"%s %s:00"
,
targetDate
,
businessEntity
.
getWorkOff
()));
final
LocalDateTime
minDate
=
LocalDateTime
.
of
(
targetDate
,
LocalTime
.
MIN
);
List
<
OccupyInfoDetail
>
configs
=
getEngineerWorkDayCalendar
(
engineerCode
,
targetDate
);
if
(
CollectionUtils
.
isEmpty
(
configs
))
{
return
new
int
[][]{{(
int
)
Duration
.
between
(
workStartTime
,
minDate
).
abs
().
toMinutes
(),
(
int
)
Duration
.
between
(
workEndTime
,
minDate
).
abs
().
toMinutes
()}};
OccupyInfoDetail
occupyInfoDetail
=
new
OccupyInfoDetail
(
workStartTime
,
workEndTime
);
return
List
.
of
(
occupyInfoDetail
);
}
// 多个休息时间不存在交集
...
...
@@ -645,23 +665,9 @@ public class EngineerCalendarServiceImpl implements EngineerCalendarService {
return
usedTime
;
}).
collect
(
Collectors
.
toList
());
//工作时间与时间时间并集求差集
List
<
OccupyInfoDetail
>
result
=
CapacityUtils
.
intervalTime
(
workStartTime
,
workEndTime
,
usedTimeInfo
);
if
(
CollectionUtils
.
isEmpty
(
result
))
{
return
new
int
[
0
][];
}
int
[][]
ints
=
new
int
[
result
.
size
()][
2
];
for
(
int
i
=
0
;
i
<
result
.
size
();
i
++)
{
OccupyInfoDetail
occupy
=
result
.
get
(
i
);
int
start
=
(
int
)
Duration
.
between
(
occupy
.
getBeginTime
(),
minDate
).
abs
().
toMinutes
();
int
end
=
(
int
)
Duration
.
between
(
occupy
.
getEndTime
(),
minDate
).
abs
().
toMinutes
();
ints
[
i
][
0
]
=
start
;
ints
[
i
][
1
]
=
end
;
}
return
ints
;
return
CapacityUtils
.
intervalTime
(
workStartTime
,
workEndTime
,
usedTimeInfo
);
}
private
EngineerCalendarDTO
.
Calendar
getEmptyCalendar
(
String
teamId
,
String
date
)
{
// 初始化一天的日历
EngineerCalendarDTO
.
Calendar
calendar
=
new
EngineerCalendarDTO
.
Calendar
();
...
...
project-order/src/main/java/com/dituhui/pea/order/service/impl/EngineerGanttServiceImpl.java
View file @
28d0f9a
...
...
@@ -180,19 +180,19 @@ public class EngineerGanttServiceImpl implements EngineerGanttService {
// 最后,还需要根据key进行过滤(需要结合数据库表)
engineerCodes
=
engineerUtils
.
filterEngineersByKey
(
engineerCodes
,
key
).
stream
().
map
(
EngineerInfoEntity:
:
getEngineerCode
).
collect
(
Collectors
.
toList
());
}
if
(
CollectionUtils
.
isNotEmpty
(
orderIds
))
{
List
<
OrderInfoEntity
>
infoEntities
=
orderInfoDao
.
findAllByOrderIdIn
(
orderIds
);
Set
<
String
>
skillGroupCodes
=
Sets
.
newConcurrentHashSet
();
for
(
OrderInfoEntity
orderInfo
:
infoEntities
)
{
//查询对应的技能信息
SkillInfoEntity
skill
=
skillInfoDao
.
getByBrandAndTypeAndSkill
(
orderInfo
.
getBrand
(),
orderInfo
.
getType
(),
orderInfo
.
getSkill
());
if
(
Objects
.
isNull
(
skill
))
{
throw
new
BusinessException
(
"查询不到对应的技能组信息:"
+
String
.
join
(
","
,
orderInfo
.
getType
(),
orderInfo
.
getSkill
()));
}
skillGroupCodes
.
add
(
skill
.
getSkillGroupCode
());
}
engineerCodes
=
engineerInfoDao
.
findByEngineerCodesBySkillCodes
(
engineerCodes
,
skillGroupCodes
);
}
//
if (CollectionUtils.isNotEmpty(orderIds)) {
//
List<OrderInfoEntity> infoEntities = orderInfoDao.findAllByOrderIdIn(orderIds);
//
Set<String> skillGroupCodes = Sets.newConcurrentHashSet();
//
for (OrderInfoEntity orderInfo : infoEntities) {
//
//查询对应的技能信息
//
SkillInfoEntity skill = skillInfoDao.getByBrandAndTypeAndSkill(orderInfo.getBrand(), orderInfo.getType(), orderInfo.getSkill());
//
if (Objects.isNull(skill)) {
//
throw new BusinessException("查询不到对应的技能组信息:" + String.join(",", orderInfo.getType(), orderInfo.getSkill()));
//
}
//
skillGroupCodes.add(skill.getSkillGroupCode());
//
}
//
engineerCodes = engineerInfoDao.findByEngineerCodesBySkillCodes(engineerCodes, skillGroupCodes);
//
}
return
engineerCodes
;
}
...
...
project-order/src/main/java/com/dituhui/pea/order/service/impl/OrderAssignImpl.java
View file @
28d0f9a
...
...
@@ -5,15 +5,53 @@ import com.dituhui.pea.common.BusinessException;
import
com.dituhui.pea.common.Result
;
import
com.dituhui.pea.common.ResultEnum
;
import
com.dituhui.pea.enums.StatusCodeEnum
;
import
com.dituhui.pea.order.common.DateUtils
;
import
com.dituhui.pea.order.common.OrderAssignCheck
;
import
com.dituhui.pea.order.common.Stapial4jUtil
;
import
com.dituhui.pea.order.common.TimeUtils
;
import
com.dituhui.pea.order.dao.*
;
import
com.dituhui.pea.order.dto.*
;
import
com.dituhui.pea.order.entity.*
;
import
com.dituhui.pea.order.enums.*
;
import
com.dituhui.pea.order.service.*
;
import
com.dituhui.pea.order.dao.EngineerBusinessDao
;
import
com.dituhui.pea.order.dao.EngineerInfoDao
;
import
com.dituhui.pea.order.dao.EngineerSkillGroupDao
;
import
com.dituhui.pea.order.dao.OrderInfoDao
;
import
com.dituhui.pea.order.dao.OrgBranchDao
;
import
com.dituhui.pea.order.dao.OrgGroupDao
;
import
com.dituhui.pea.order.dao.OrgTeamDao
;
import
com.dituhui.pea.order.dao.OrgTeamEngineerDao
;
import
com.dituhui.pea.order.dao.SkillInfoDao
;
import
com.dituhui.pea.order.dto.LabelValueDTO
;
import
com.dituhui.pea.order.dto.MsgDTO
;
import
com.dituhui.pea.order.dto.OrderAssignRecommendResp
;
import
com.dituhui.pea.order.dto.OrderAssignReq
;
import
com.dituhui.pea.order.dto.OrderReschedule
;
import
com.dituhui.pea.order.dto.TimeLineDTO
;
import
com.dituhui.pea.order.dto.param.Location
;
import
com.dituhui.pea.order.dto.param.RecommendEngineersReq
;
import
com.dituhui.pea.order.entity.EngineerBusinessEntity
;
import
com.dituhui.pea.order.entity.EngineerInfoEntity
;
import
com.dituhui.pea.order.entity.EngineerSkillGroupEntity
;
import
com.dituhui.pea.order.entity.OrderInfoEntity
;
import
com.dituhui.pea.order.entity.OrgTeamEngineerEntity
;
import
com.dituhui.pea.order.entity.OrgTeamEntity
;
import
com.dituhui.pea.order.entity.SkillInfoEntity
;
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.OrderStatusEnum
;
import
com.dituhui.pea.order.enums.ServiceStatusEnum
;
import
com.dituhui.pea.order.enums.TestimonialsEngineerTag
;
import
com.dituhui.pea.order.service.CapacityQueryService
;
import
com.dituhui.pea.order.service.CommonService
;
import
com.dituhui.pea.order.service.FendanService
;
import
com.dituhui.pea.order.service.MsgService
;
import
com.dituhui.pea.order.service.OrderAssign
;
import
com.dituhui.pea.order.service.OrderInfoService
;
import
com.dituhui.pea.order.utils.CommonUtil
;
import
com.dituhui.pea.order.utils.OrderUtil
;
import
com.dituhui.pea.pojo.user.OrgInfo
;
import
com.dituhui.pea.user.IUser
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
lombok.Setter
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.collections.CollectionUtils
;
import
org.apache.commons.lang3.StringUtils
;
...
...
@@ -26,8 +64,19 @@ import javax.persistence.criteria.CriteriaBuilder;
import
javax.persistence.criteria.CriteriaQuery
;
import
javax.persistence.criteria.Predicate
;
import
javax.persistence.criteria.Root
;
import
java.math.BigDecimal
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.util.*
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.Optional
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
@Service
...
...
@@ -79,24 +128,38 @@ public class OrderAssignImpl implements OrderAssign {
@Autowired
private
CapacityQueryService
capacityQueryService
;
@Autowired
private
IUser
userService
;
@Autowired
private
EngineerBusinessDao
engineerBusinessDao
;
@Transactional
@Override
public
Result
<?>
getOrderAssignRecommendEngineers
(
String
orderId
,
String
key
,
String
distance
,
String
recommend
)
{
public
Result
<?>
getOrderAssignRecommendEngineers
(
RecommendEngineersReq
req
)
{
// 服务单指派-推荐技术员列表
OrderInfoEntity
order
=
orderInfoDao
.
getByOrderId
(
orderId
);
OrderInfoEntity
order
=
orderInfoDao
.
getByOrderId
(
req
.
getOrderId
()
);
if
(
order
==
null
)
{
throw
new
BusinessException
(
"订单不存在"
);
}
String
date
=
TimeUtils
.
IsoLocalDate2String
(
order
.
getDt
());
// 获取符合筛选条件的技术员
List
<
String
>
engineerCodes
=
this
.
searchEngineerCodes
(
order
,
distance
,
key
,
recommend
);
// 改造本方法 让其支持标签返回
List
<
TempEngineer
>
engineerLocationList
=
this
.
searchEngineerCodes
(
order
,
req
.
getDistance
(),
req
.
getKey
(),
req
.
getRecommend
(),
req
.
getUserId
());
List
<
String
>
engineerCodes
=
engineerLocationList
.
stream
().
map
(
TempEngineer:
:
getEngineerCode
).
collect
(
Collectors
.
toList
());
Map
<
String
,
TempEngineer
>
engineerDistanceMap
=
engineerLocationList
.
stream
().
collect
(
Collectors
.
toMap
(
TempEngineer:
:
getEngineerCode
,
a
->
a
,
(
k1
,
k2
)
->
k1
));
List
<
EngineerInfoEntity
>
engineers
=
engineerInfoDao
.
findByEngineerCodeIn
(
engineerCodes
);
List
<
OrderAssignRecommendResp
.
Engineer
>
items
=
new
ArrayList
<>();
final
String
orgTeamId
=
order
.
getOrgTeamId
();
final
BigDecimal
judgeDistance
=
new
BigDecimal
(
"10"
);
for
(
EngineerInfoEntity
engineer
:
engineers
)
{
OrderAssignCheck
.
Result
result
=
orderAssignCheck
.
orderAssignCheck
(
orderId
,
order
.
getDt
(),
engineer
.
getEngineerCode
());
final
String
engineerCode
=
engineer
.
getEngineerCode
();
OrderAssignCheck
.
Result
result
=
orderAssignCheck
.
orderAssignCheck
(
req
.
getOrderId
(),
order
.
getDt
(),
engineerCode
);
log
.
info
(
"指派检查结果:{}"
,
result
);
if
(
result
.
getIndex
()
<
0
)
{
continue
;
...
...
@@ -104,7 +167,7 @@ public class OrderAssignImpl implements OrderAssign {
// 获取已技术员已指派订单列表
List
<
OrderInfoEntity
>
orderAppointments
=
orderInfoDao
.
findByEngineerCodeAndDtAndAppointmentStatusIn
(
engineer
.
getEngineerCode
()
,
order
.
getDt
(),
List
.
of
(
OrderFlowEnum
.
CONFIRM
.
name
()),
null
);
engineer
Code
,
order
.
getDt
(),
List
.
of
(
OrderFlowEnum
.
CONFIRM
.
name
()),
null
);
// 获取订单tips
HashMap
<
String
,
List
<
LabelValueDTO
>>
orderTips
=
new
HashMap
<>();
...
...
@@ -113,7 +176,6 @@ public class OrderAssignImpl implements OrderAssign {
List
<
OrderInfoEntity
>
orders
=
orderInfoDao
.
findAllByDtAndOrderIdIn
(
order
.
getDt
(),
orderIds
);
orderTips
=
this
.
packOrderTips
(
orders
);
}
OrderAssignRecommendResp
.
Engineer
item
=
new
OrderAssignRecommendResp
.
Engineer
();
OrderAssignRecommendResp
.
InsertInfo
insertInfo
=
new
OrderAssignRecommendResp
.
InsertInfo
();
...
...
@@ -121,11 +183,23 @@ public class OrderAssignImpl implements OrderAssign {
insertInfo
.
setTimeDesc
(
String
.
format
(
"+%d分钟"
,
result
.
getAdditionElapsed
()));
insertInfo
.
setDistanceDesc
(
String
.
format
(
"+%d公里"
,
result
.
getAdditionDistance
()
/
1000
));
item
.
setEngineerCode
(
engineer
.
getEngineerCode
());
TestimonialsEngineerTag
engineerTag
;
//标签判定
//判定当前工程师是否在队内, 否则判定是否在10KM内, 否则
TempEngineer
tempEngineer
=
engineerDistanceMap
.
get
(
engineerCode
);
if
(
Objects
.
nonNull
(
orgTeamEngineerDao
.
findByTeamIdAndEngineerCode
(
orgTeamId
,
engineerCode
)))
{
engineerTag
=
TestimonialsEngineerTag
.
TEAM
;
}
else
if
(
tempEngineer
.
getDistance
().
compareTo
(
judgeDistance
)
<=
0
)
{
engineerTag
=
TestimonialsEngineerTag
.
PERIPHERAL
;
}
else
{
engineerTag
=
TestimonialsEngineerTag
.
SEARCH
;
}
item
.
setEngineerCode
(
engineerCode
);
item
.
setEngineerName
(
engineer
.
getName
());
item
.
setLocation
(
String
.
format
(
"%s,%s"
,
order
.
getX
(),
order
.
getY
()));
item
.
setInsertInfo
(
insertInfo
);
item
.
setDistanceDesc
(
""
);
item
.
setDistanceDesc
(
engineerTag
);
item
.
setTimeDesc
(
""
);
int
index
=
result
.
getIndex
()
+
1
;
...
...
@@ -194,11 +268,23 @@ public class OrderAssignImpl implements OrderAssign {
if
(
order
==
null
)
{
return
Result
.
failed
(
"订单不存在"
);
}
// 更新order_request表为未指派
if
(
order
.
getOrderStatus
().
equals
(
OrderStatusEnum
.
CANCELED
.
getCode
())
||
order
.
getServiceStatus
().
equals
(
ServiceStatusEnum
.
FINISHED
.
getCode
()))
{
return
Result
.
failed
(
StatusCodeEnum
.
ORDER_FINISHED
);
}
OrgTeamEntity
orgTeam
=
orgTeamDao
.
getByTeamId
(
order
.
getOrgTeamId
());
// 判断cutoff
Integer
cutoff
=
CommonUtil
.
isCutoff
(
order
.
getExpectTimeBegin
(),
orgTeam
.
getWorkOff
());
order
.
setAppointmentStatus
(
OrderFlowEnum
.
INIT
.
name
());
order
.
setServiceStatus
(
OrderFlowEnum
.
INIT
.
name
());
order
=
OrderUtil
.
handleErrorOrder
(
order
);
if
(
cutoff
>
0
)
{
// cutoff更新order_request表为人工指派
order
.
setAppointmentMethod
(
AppointmentMethodEnum
.
MANUAL
.
name
());
order
=
OrderUtil
.
handleErrorOrder
(
order
);
order
.
setIsCutoff
(
cutoff
);
}
else
{
// 更新order_request表为未指派
order
=
OrderUtil
.
handleErrorOrder2
(
order
);
}
orderInfoDao
.
save
(
order
);
commonService
.
addOrderEvent
(
orderId
,
""
,
"PEA"
,
"PEA"
,
OrderEventEnum
.
backOrderPool
.
getEvent
(),
OrderEventEnum
.
backOrderPool
.
getMsg
(),
""
);
...
...
@@ -235,8 +321,8 @@ public class OrderAssignImpl implements OrderAssign {
return
order
;
}
private
List
<
String
>
searchEngineerCodes
(
OrderInfoEntity
order
,
String
distance
,
String
key
,
String
recommen
d
)
{
Set
<
String
>
engineerCodes1
=
this
.
searchEngineerByRecommend
(
order
,
recommend
);
private
List
<
TempEngineer
>
searchEngineerCodes
(
OrderInfoEntity
order
,
Double
distance
,
String
key
,
String
recommend
,
String
userI
d
)
{
Set
<
String
>
engineerCodes1
=
this
.
searchEngineerByRecommend
(
order
,
recommend
,
userId
);
if
(
engineerCodes1
.
isEmpty
())
{
log
.
info
(
"recommend:{}筛选条件未找到技术员"
,
recommend
);
return
new
ArrayList
<>();
...
...
@@ -258,13 +344,13 @@ public class OrderAssignImpl implements OrderAssign {
SkillInfoEntity
skill
=
skillInfoDao
.
getByBrandAndTypeAndSkill
(
order
.
getBrand
(),
order
.
getType
(),
order
.
getSkill
());
if
(
skill
==
null
)
{
log
.
info
(
"skill_info表没有匹配到技能配置:{}-{}-{}"
,
order
.
getBrand
(),
order
.
getY
(),
order
.
getSkill
());
return
new
ArrayList
<>
();
return
Collections
.
emptyList
();
}
Set
<
String
>
engineerCodes3
=
engineerSkillGroupDao
.
findBySkillGroupCode
(
skill
.
getSkillGroupCode
()).
stream
().
map
(
EngineerSkillGroupEntity:
:
getEngineerCode
).
collect
(
Collectors
.
toSet
());
if
(
engineerCodes3
.
isEmpty
())
{
log
.
info
(
"没有匹配到技能相匹配的技术员:{}-{}-{}"
,
order
.
getBrand
(),
order
.
getType
(),
order
.
getSkill
());
return
new
ArrayList
<>
();
return
Collections
.
emptyList
();
}
engineerCodes1
.
retainAll
(
engineerCodes3
);
if
(
engineerCodes1
.
isEmpty
())
{
...
...
@@ -272,37 +358,128 @@ public class OrderAssignImpl implements OrderAssign {
return
new
ArrayList
<>();
}
/*
if (StringUtils.isEmpty(distance)) {
return new ArrayList<>(engineerCodes1);
}
//进行距离匹配TODO
*/
// 获取工程师位置(准实时位置)并进行距离判定, distance如果为空值 默认10KM
double
orderLongitude
=
Double
.
parseDouble
(
order
.
getX
());
double
orderLatitude
=
Double
.
parseDouble
(
order
.
getY
());
//均计算距离
List
<
TempEngineer
>
result
=
engineerCodes1
.
stream
()
.
map
(
engineerCode
->
{
Location
location
=
engineerDateLocation
(
engineerCode
);
BigDecimal
orderAndEngineerDistance
=
BigDecimal
.
valueOf
(
Stapial4jUtil
.
getDistance
(
location
.
getLongitude
(),
location
.
getLatitude
(),
orderLongitude
,
orderLatitude
));
return
new
TempEngineer
(
engineerCode
,
orderAndEngineerDistance
);
}).
collect
(
Collectors
.
toList
());
// 距离过滤
if
(
Objects
.
nonNull
(
distance
))
{
final
BigDecimal
finalDistance
=
BigDecimal
.
valueOf
(
distance
);
// return ;
result
=
result
.
stream
().
filter
(
t
->
t
.
getDistance
().
compareTo
(
finalDistance
)
<=
0
).
collect
(
Collectors
.
toList
());
}
return
result
;
}
return
new
ArrayList
<>(
engineerCodes1
);
@Setter
@Getter
@AllArgsConstructor
class
TempEngineer
{
/**
* 工程师编号
*/
private
String
engineerCode
;
/**
* 距离 (KM)
*/
private
BigDecimal
distance
;
}
private
Set
<
String
>
searchEngineerByRecommend
(
OrderInfoEntity
order
,
String
recommend
)
{
private
Location
engineerDateLocation
(
String
engineerCode
)
{
final
LocalDate
currentDate
=
LocalDate
.
now
();
List
<
OrderInfoEntity
>
engineerDateOrderList
=
orderInfoDao
.
getEngineerDateOrder
(
engineerCode
,
DateUtils
.
formatDate
(
currentDate
));
Set
<
String
>
ss
=
Set
.
of
(
"CANCELED"
,
"RESCHEDULED"
);
engineerDateOrderList
=
engineerDateOrderList
.
stream
()
.
filter
(
e
->
!
ss
.
contains
(
e
.
getOrderStatus
()))
.
collect
(
Collectors
.
toList
());
Location
location
=
new
Location
();
//查询工程师已开始的工单
Optional
<
OrderInfoEntity
>
startedOrder
=
engineerDateOrderList
.
stream
()
.
filter
(
e
->
Objects
.
equals
(
"STARTED"
,
e
.
getServiceStatus
()))
.
max
(
Comparator
.
comparing
(
OrderInfoEntity:
:
getPlanStartTime
));
if
(
startedOrder
.
isPresent
())
{
OrderInfoEntity
startedOrderInfo
=
startedOrder
.
get
();
location
.
setAddress
(
startedOrderInfo
.
getAddress
());
location
.
setLongitude
(
Double
.
parseDouble
(
startedOrderInfo
.
getX
()));
location
.
setLatitude
(
Double
.
parseDouble
(
startedOrderInfo
.
getY
()));
return
location
;
}
//如果没有已开始的工单 查询 最后一个已完成工单
Optional
<
OrderInfoEntity
>
finishedOrder
=
engineerDateOrderList
.
stream
()
.
filter
(
e
->
Objects
.
equals
(
"FINISHED"
,
e
.
getServiceStatus
()))
.
max
(
Comparator
.
comparing
(
OrderInfoEntity:
:
getActualEndTime
));
if
(
finishedOrder
.
isPresent
())
{
OrderInfoEntity
finishedOrderInfo
=
finishedOrder
.
get
();
location
.
setAddress
(
finishedOrderInfo
.
getAddress
());
location
.
setLongitude
(
Double
.
parseDouble
(
finishedOrderInfo
.
getX
()));
location
.
setLatitude
(
Double
.
parseDouble
(
finishedOrderInfo
.
getY
()));
}
else
{
// 如果都没有, 则获取工程师出发地址
EngineerBusinessEntity
byEngineerCode
=
engineerBusinessDao
.
getByEngineerCode
(
engineerCode
);
location
.
setAddress
(
byEngineerCode
.
getAddress
());
location
.
setLongitude
(
StringUtils
.
isNotBlank
(
byEngineerCode
.
getX
())
?
Double
.
parseDouble
(
byEngineerCode
.
getX
())
:
0.0
);
location
.
setLatitude
(
StringUtils
.
isNotBlank
(
byEngineerCode
.
getY
())
?
Double
.
parseDouble
(
byEngineerCode
.
getY
())
:
0.0
);
}
return
location
;
}
private
Set
<
String
>
searchEngineerByRecommend
(
OrderInfoEntity
order
,
String
recommend
,
String
userId
)
{
if
(
StringUtils
.
isNotEmpty
(
recommend
)
&&
recommend
.
equals
(
"team"
))
{
return
orgTeamEngineerDao
.
findAllByTeamId
(
order
.
getOrgTeamId
()).
stream
().
map
(
OrgTeamEngineerEntity:
:
getEngineerCode
).
collect
(
Collectors
.
toSet
());
}
String
levelType
;
String
levelValue
;
String
levelType
=
null
;
String
levelValue
=
null
;
List
<
OrgTeamEntity
>
teams
=
new
ArrayList
<>();
if
(
StringUtils
.
isEmpty
(
recommend
)
||
recommend
.
equals
(
"branch"
))
{
levelType
=
"branch"
;
levelValue
=
order
.
getOrgBranchId
();
}
else
if
(
recommend
.
equals
(
"group"
))
{
levelType
=
"group"
;
levelValue
=
order
.
getOrgGroupId
();
}
else
if
(
recommend
.
equals
(
"all"
))
{
levelType
=
"cluster"
;
levelValue
=
order
.
getOrgClusterId
();
}
else
if
(
recommend
.
equals
(
"all"
)
&&
StringUtils
.
isNotBlank
(
userId
))
{
Result
<
List
<
OrgInfo
>>
listResult
=
userService
.
orgsNoName
(
userId
);
if
(
CollectionUtils
.
isEmpty
(
listResult
.
getResult
()))
{
return
new
HashSet
<>();
}
List
<
OrgInfo
>
orgInfos
=
listResult
.
getResult
();
Integer
orgLevel
=
orgInfos
.
get
(
0
).
getOrgLevel
();
List
<
String
>
collect
=
orgInfos
.
stream
().
map
(
OrgInfo:
:
getId
).
collect
(
Collectors
.
toList
());
switch
(
orgLevel
)
{
case
-
1
:
teams
=
orgTeamDao
.
findAll
();
break
;
case
0
:
teams
=
orgTeamDao
.
findByClusterIdIn
(
collect
);
break
;
case
1
:
teams
=
orgTeamDao
.
findByBranchIdIn
(
collect
);
break
;
case
2
:
teams
=
orgTeamDao
.
findByGroupIdIn
(
collect
);
break
;
}
List
<
String
>
groupIds
=
teams
.
stream
().
map
(
OrgTeamEntity:
:
getGroupId
).
collect
(
Collectors
.
toList
());
return
engineerInfoDao
.
findByGroupIdIn
(
groupIds
).
stream
().
map
(
EngineerInfoEntity:
:
getEngineerCode
).
collect
(
Collectors
.
toSet
());
}
else
{
return
new
HashSet
<>();
}
List
<
OrgTeamEntity
>
teams
=
new
ArrayList
<>();
if
(
levelType
.
equals
(
"cluster"
))
{
teams
=
orgTeamDao
.
findAllByClusterId
(
levelValue
);
}
else
if
(
levelType
.
equals
(
"branch"
))
{
...
...
project-order/src/main/java/com/dituhui/pea/order/service/impl/OrderCreateServiceImpl.java
View file @
28d0f9a
...
...
@@ -199,11 +199,21 @@ public class OrderCreateServiceImpl implements OrderCreateService {
OrderDTO
.
Estimate
estimate
=
new
OrderDTO
.
Estimate
();
// 计算两点间距离
double
distance
=
Stapial4jUtil
.
getDistance
(
location
.
getL
atitude
(),
location
.
getLong
itude
(),
double
distance
=
Stapial4jUtil
.
getDistance
(
location
.
getL
ongitude
(),
location
.
getLat
itude
(),
Double
.
parseDouble
(
orderInfo
.
getX
()),
Double
.
parseDouble
(
orderInfo
.
getY
()));
estimate
.
setDistance
(
distance
);
estimate
.
setArriveTime
(
palnDate
);
if
(
Math
.
abs
(
distance
)
<
1
e
-
15
)
{
estimate
.
setArriveTime
(
com
.
dituhui
.
pea
.
order
.
common
.
jackson
.
DateUtil
.
toDate
(
orderInfo
.
getActualStartTime
()));
}
else
{
//当前时间 加大概需要的时间
//计算大概时间, 电动车 19KM/H
double
speed
=
0.3167
;
LocalDateTime
localDateTime
=
LocalDateTime
.
now
().
plusMinutes
((
int
)
Math
.
ceil
(
distance
/
speed
));
estimate
.
setArriveTime
(
com
.
dituhui
.
pea
.
order
.
common
.
jackson
.
DateUtil
.
toDate
(
localDateTime
));
}
realtimeInfo
.
setEstimate
(
estimate
);
stageResult
.
setRealtimeInfo
(
realtimeInfo
);
...
...
@@ -295,8 +305,10 @@ public class OrderCreateServiceImpl implements OrderCreateService {
entity
.
setBeanTags
(
joinTags
);
entity
.
setIsMultiple
(
joinTags
.
contains
(
"重物搬运"
)
?
1
:
0
);
entity
.
setBeanPriority
(
req
.
getPriority
());
if
(
req
.
getPriority
().
equals
(
"1"
)
&&
!
DateUtil
.
judgeTimeIsToday
(
entity
.
getExpectTimeBegin
()))
{
entity
.
setAppointmentMethod
(
AppointmentMethodEnum
.
AUTO_NOW
.
name
());
if
(
req
.
getPriority
().
equals
(
"1"
))
{
if
(!
DateUtil
.
judgeTimeIsToday
(
entity
.
getExpectTimeBegin
()))
{
entity
.
setAppointmentMethod
(
AppointmentMethodEnum
.
AUTO_NOW
.
name
());
}
tags
.
add
(
OrderPeaTagsEnum
.
urgent
.
getTag
());
//发送通知分部消息
// sendMsg(entity.getOrgBranchId(), orderId, entity.getExpectTimeBegin().toLocalDate());
...
...
@@ -430,6 +442,9 @@ public class OrderCreateServiceImpl implements OrderCreateService {
if
(
special
==
1
)
{
tags
.
add
(
OrderPeaTagsEnum
.
special
.
getTag
());
}
if
(
CollectionUtils
.
isNotEmpty
(
tags
))
{
tags
=
tags
.
stream
().
filter
(
e
->
StringUtils
.
isNotBlank
(
e
)).
collect
(
Collectors
.
toList
());
}
MsgDTO
msgDTO
=
new
MsgDTO
();
msgDTO
.
setBranchId
(
branchId
);
msgDTO
.
setType
(
0
);
...
...
project-order/src/main/java/com/dituhui/pea/order/service/impl/OrderInfoServiceImpl.java
View file @
28d0f9a
...
...
@@ -7,6 +7,7 @@ import com.dituhui.pea.common.Result;
import
com.dituhui.pea.common.ResultEnum
;
import
com.dituhui.pea.dispatch.IPath
;
import
com.dituhui.pea.enums.StatusCodeEnum
;
import
com.dituhui.pea.order.common.OccupyInfoDetail
;
import
com.dituhui.pea.order.common.TimeUtils
;
import
com.dituhui.pea.order.common.jackson.JsonUtil
;
import
com.dituhui.pea.order.constant.OrderReschedulingReason
;
...
...
@@ -74,6 +75,9 @@ public class OrderInfoServiceImpl implements OrderInfoService {
@Autowired
private
IPath
pathService
;
@Autowired
private
EngineerCalendarService
engineerCalendarService
;
/**
* 新增订单处理一家多单逻辑
...
...
@@ -452,29 +456,27 @@ public class OrderInfoServiceImpl implements OrderInfoService {
@Transactional
@Override
public
Result
<
OrderInfoEntity
>
insterEngineerOrders
(
List
<
OrderInfoEntity
>
engineerOrders
,
OrderInfoEntity
insertOrder
,
SkillInfoEntity
skillInfo
,
OrgTeamEntity
orgTeam
,
EngineerInfoEntity
engineer
)
{
// 没有单直接返回
// 获取团队工作起止时间
String
[]
teamWorkStartTime
=
orgTeam
.
getWorkOn
().
split
(
":"
);
String
[]
teamWorkEndTime
=
orgTeam
.
getWorkOff
().
split
(
":"
);
LocalDateTime
startTeam
=
insertOrder
.
getDt
().
atTime
(
Integer
.
parseInt
(
teamWorkStartTime
[
0
]),
Integer
.
parseInt
(
teamWorkStartTime
[
1
]),
0
);
LocalDateTime
endTeam
=
insertOrder
.
getDt
().
atTime
(
Integer
.
parseInt
(
teamWorkEndTime
[
0
]),
Integer
.
parseInt
(
teamWorkEndTime
[
1
]),
0
);
// 获取客户期望时间段
LocalDateTime
start
=
insertOrder
.
getExpectTimeBegin
();
LocalDateTime
end
=
insertOrder
.
getExpectTimeEnd
();
LocalDateTime
workStartTime
=
insertOrder
.
getExpectTimeBegin
();
LocalDateTime
workEndTime
=
insertOrder
.
getExpectTimeEnd
();
//查询工程师当天出勤时间
// List<OccupyInfoDetail> engineerWorkTimeSlice = engineerCalendarService.timeWindowsSlice(engineer.getEngineerCode(), orgTeam.getTeamId(), insertOrder.getDt());
//查询工程师当天请假时间
List
<
OccupyInfoDetail
>
engineerLeaveTimeSlice
=
engineerCalendarService
.
getEngineerWorkDayCalendar
(
engineer
.
getEngineerCode
(),
insertOrder
.
getDt
());
log
.
info
(
"【engineerWorkTimeSlice】结果------------->{}"
,
JsonUtil
.
toJson
(
engineerLeaveTimeSlice
));
// 没有单直接返回
if
(
CollectionUtils
.
isEmpty
(
engineerOrders
))
{
// 特殊时间不插单
if
(
LocalDateTime
.
now
().
isBefore
(
startTeam
)
||
LocalDateTime
.
now
().
isAfter
(
endTeam
)
||
end
.
isAfter
(
endTeam
)
||
end
.
isBefore
(
startTeam
))
{
LocalDateTime
planStartTime
=
handleLeaveTime
(
engineerLeaveTimeSlice
,
insertOrder
.
getExpectTimeBegin
(),
insertOrder
.
getExpectTimeEnd
(),
skillInfo
.
getTakeTime
());
if
(
ObjectUtil
.
isNull
(
planStartTime
))
{
return
Result
.
failed
(
insertOrder
);
}
insertOrder
.
setTakeTime
(
skillInfo
.
getTakeTime
());
insertOrder
.
setPlanStartTime
(
insertOrder
.
getExpectTimeBegin
()
);
insertOrder
.
setPlanEndTime
(
insertOrder
.
getExpectTimeBegin
()
.
plusMinutes
(
skillInfo
.
getTakeTime
()));
insertOrder
.
setPlanStartTime
(
planStartTime
);
insertOrder
.
setPlanEndTime
(
planStartTime
.
plusMinutes
(
skillInfo
.
getTakeTime
()));
return
Result
.
success
(
insertOrder
);
}
int
takeTime
=
skillInfo
.
getTakeTime
();
// 计算最早派工和最晚派工时间
LocalDateTime
workStartTime
=
start
.
isAfter
(
startTeam
)
?
start
:
startTeam
;
LocalDateTime
workEndTime
=
end
.
isBefore
(
endTeam
)
?
end
:
endTeam
;
// 订单工作时间顺序排序
List
<
OrderSegment
>
orderSegments
=
new
ArrayList
<>();
for
(
OrderInfoEntity
orderInfo
:
engineerOrders
)
{
...
...
@@ -493,9 +495,13 @@ public class OrderInfoServiceImpl implements OrderInfoService {
}
// 没有单直接返回
if
(
CollectionUtils
.
isEmpty
(
orderSegments
))
{
LocalDateTime
planStartTime
=
handleLeaveTime
(
engineerLeaveTimeSlice
,
insertOrder
.
getExpectTimeBegin
(),
insertOrder
.
getExpectTimeEnd
(),
skillInfo
.
getTakeTime
());
if
(
ObjectUtil
.
isNull
(
planStartTime
))
{
return
Result
.
failed
(
insertOrder
);
}
insertOrder
.
setTakeTime
(
skillInfo
.
getTakeTime
());
insertOrder
.
setPlanStartTime
(
insertOrder
.
getExpectTimeBegin
()
);
insertOrder
.
setPlanEndTime
(
insertOrder
.
getExpectTimeBegin
()
.
plusMinutes
(
skillInfo
.
getTakeTime
()));
insertOrder
.
setPlanStartTime
(
planStartTime
);
insertOrder
.
setPlanEndTime
(
planStartTime
.
plusMinutes
(
skillInfo
.
getTakeTime
()));
return
Result
.
success
(
insertOrder
);
}
orderSegments
=
orderSegments
.
stream
().
sorted
(
Comparator
.
comparing
(
OrderSegment:
:
getStart
)).
collect
(
Collectors
.
toList
());
...
...
@@ -511,11 +517,13 @@ public class OrderInfoServiceImpl implements OrderInfoService {
int
roadTime
=
distanceDTO
.
getTime
()
/
1000
;
// 先判断第一单开始时间
if
(
i
==
0
&&
orderSegment
.
getStart
().
compareTo
(
workStartTime
.
plusMinutes
(
takeTime
+
roadTime
))
>=
0
)
{
LocalDateTime
planStartTime
=
handleLeaveTime
(
engineerLeaveTimeSlice
,
insertOrder
.
getExpectTimeBegin
(),
insertOrder
.
getExpectTimeEnd
(),
skillInfo
.
getTakeTime
());
if
(
ObjectUtil
.
isNull
(
planStartTime
))
{
return
Result
.
failed
(
insertOrder
);
}
insertOrder
.
setTakeTime
(
skillInfo
.
getTakeTime
());
// insertOrder.setArriveDistance(roadTime);
// insertOrder.setArriveDistance(Integer.valueOf(String.valueOf(distanceDTO.getDis() * 1000)));
insertOrder
.
setPlanStartTime
(
insertOrder
.
getExpectTimeBegin
());
insertOrder
.
setPlanEndTime
(
insertOrder
.
getExpectTimeBegin
().
plusMinutes
(
skillInfo
.
getTakeTime
()));
insertOrder
.
setPlanStartTime
(
planStartTime
);
insertOrder
.
setPlanEndTime
(
planStartTime
.
plusMinutes
(
skillInfo
.
getTakeTime
()));
OrderInfoEntity
nestOrder
=
orderInfoDao
.
getByOrderId
(
orderSegment
.
getOrderId
());
nestOrder
.
setArriveDistance
(
roadTime
);
...
...
@@ -529,11 +537,18 @@ public class OrderInfoServiceImpl implements OrderInfoService {
if
(
workEndTime
.
compareTo
(
orderSegment
.
getEnd
().
plusMinutes
(
takeTime
+
roadTime
))
<
0
)
{
return
Result
.
failed
(
insertOrder
);
}
insertOrder
.
setTakeTime
(
skillInfo
.
getTakeTime
());
insertOrder
.
setArriveDistance
(
roadTime
);
// 判断工单开始时间
LocalDateTime
planStartTime
=
insertOrder
.
getExpectTimeBegin
().
compareTo
(
orderSegment
.
getEnd
().
plusMinutes
(
roadTime
))
>=
0
?
insertOrder
.
getExpectTimeBegin
()
:
orderSegment
.
getEnd
().
plusMinutes
(
roadTime
);
planStartTime
=
handleLeaveTime
(
engineerLeaveTimeSlice
,
planStartTime
,
insertOrder
.
getExpectTimeEnd
(),
skillInfo
.
getTakeTime
());
if
(
ObjectUtil
.
isNull
(
planStartTime
))
{
return
Result
.
failed
(
insertOrder
);
}
insertOrder
.
setArriveElapsed
(
roadTime
);
insertOrder
.
setArriveDistance
(
BigDecimal
.
valueOf
(
distanceDTO
.
getDis
()
*
1000
).
intValue
());
insertOrder
.
setPlanStartTime
(
orderSegment
.
getEnd
().
plusMinutes
(
roadTime
));
insertOrder
.
setPlanEndTime
(
orderSegment
.
getEnd
().
plusMinutes
(
takeTime
+
roadTime
));
insertOrder
.
setTakeTime
(
skillInfo
.
getTakeTime
());
insertOrder
.
setPlanStartTime
(
planStartTime
);
insertOrder
.
setPlanEndTime
(
planStartTime
.
plusMinutes
(
skillInfo
.
getTakeTime
()));
return
Result
.
success
(
insertOrder
);
}
// 当前单在中间
...
...
@@ -545,15 +560,22 @@ public class OrderInfoServiceImpl implements OrderInfoService {
continue
;
}
if
(
nestOrderSegment
.
getStart
().
minusMinutes
(
roadResult2
.
getResult
().
getTime
()
/
1000
).
compareTo
(
orderSegment
.
getEnd
().
plusMinutes
(
takeTime
+
roadTime
))
>=
0
)
{
// 判断工单开始时间
LocalDateTime
planStartTime
=
insertOrder
.
getExpectTimeBegin
().
compareTo
(
orderSegment
.
getEnd
().
plusMinutes
(
roadTime
))
>=
0
?
insertOrder
.
getExpectTimeBegin
()
:
orderSegment
.
getEnd
().
plusMinutes
(
roadTime
);
planStartTime
=
handleLeaveTime
(
engineerLeaveTimeSlice
,
planStartTime
,
insertOrder
.
getExpectTimeEnd
(),
skillInfo
.
getTakeTime
());
if
(
ObjectUtil
.
isNull
(
planStartTime
))
{
return
Result
.
failed
(
insertOrder
);
}
insertOrder
.
setArriveElapsed
(
roadTime
);
insertOrder
.
setArriveDistance
(
BigDecimal
.
valueOf
(
distanceDTO
.
getDis
()
*
1000
).
intValue
());
insertOrder
.
setTakeTime
(
skillInfo
.
getTakeTime
());
insertOrder
.
setArriveDistance
(
roadTime
);
insertOrder
.
setArriveElapsed
(
BigDecimal
.
valueOf
(
distanceDTO
.
getDis
()
*
1000
).
intValue
());
insertOrder
.
setPlanStartTime
(
orderSegment
.
getEnd
().
plusMinutes
(
roadTime
));
insertOrder
.
setPlanEndTime
(
orderSegment
.
getEnd
().
plusMinutes
(
takeTime
+
roadTime
));
insertOrder
.
setPlanStartTime
(
planStartTime
);
insertOrder
.
setPlanEndTime
(
planStartTime
.
plusMinutes
(
skillInfo
.
getTakeTime
()));
OrderInfoEntity
nestOrder
=
orderInfoDao
.
getByOrderId
(
nestOrderSegment
.
getOrderId
());
nestOrder
.
setArrive
Distance
(
roadResult2
.
getResult
().
getTime
()
/
1000
);
nestOrder
.
setArrive
Elapsed
(
BigDecimal
.
valueOf
(
roadResult2
.
getResult
().
getDis
()
*
1000
).
intValue
());
nestOrder
.
setArrive
Elapsed
(
roadResult2
.
getResult
().
getTime
()
/
1000
);
nestOrder
.
setArrive
Distance
(
BigDecimal
.
valueOf
(
roadResult2
.
getResult
().
getDis
()
*
1000
).
intValue
());
orderInfoDao
.
save
(
nestOrder
);
return
Result
.
success
(
insertOrder
);
}
...
...
@@ -561,6 +583,56 @@ public class OrderInfoServiceImpl implements OrderInfoService {
return
Result
.
failed
(
insertOrder
);
}
/**
* 处理工程师请假时间和工单计划开始时间
*
* @param engineerLeaveTimeSlice
* @param expectTimeBegin
* @param expectTimeEnd
* @return 工单计划开始时间
*/
private
LocalDateTime
handleLeaveTime
(
List
<
OccupyInfoDetail
>
engineerLeaveTimeSlice
,
LocalDateTime
expectTimeBegin
,
LocalDateTime
expectTimeEnd
,
Integer
takeTime
)
{
if
(
CollectionUtils
.
isEmpty
(
engineerLeaveTimeSlice
))
{
return
expectTimeBegin
;
}
for
(
int
i
=
0
;
i
<
engineerLeaveTimeSlice
.
size
();
i
++)
{
OccupyInfoDetail
occupyInfoDetail
=
engineerLeaveTimeSlice
.
get
(
i
);
// 处理请假开始时间
if
(
expectTimeBegin
.
plusMinutes
(
takeTime
).
compareTo
(
occupyInfoDetail
.
getBeginTime
())
<=
0
)
{
return
expectTimeBegin
;
}
if
(
expectTimeEnd
.
compareTo
(
occupyInfoDetail
.
getEndTime
().
plusMinutes
(
takeTime
))
>=
0
)
{
return
expectTimeBegin
.
compareTo
(
occupyInfoDetail
.
getEndTime
())
>=
0
?
expectTimeBegin
:
occupyInfoDetail
.
getEndTime
();
}
return
null
;
}
return
null
;
}
/**
* 处理工程师出勤时间和工单计划开始时间
*
* @param engineerWorkTimeSlice
* @param expectTimeBegin
* @param expectTimeEnd
* @return 工单计划开始时间
*/
private
LocalDateTime
handleWorkTime
(
List
<
OccupyInfoDetail
>
engineerWorkTimeSlice
,
LocalDateTime
expectTimeBegin
,
LocalDateTime
expectTimeEnd
,
Integer
takeTime
)
{
if
(
CollectionUtils
.
isEmpty
(
engineerWorkTimeSlice
))
{
return
null
;
}
for
(
int
i
=
0
;
i
<
engineerWorkTimeSlice
.
size
();
i
++)
{
OccupyInfoDetail
occupyInfoDetail
=
engineerWorkTimeSlice
.
get
(
i
);
LocalDateTime
planStartTime
=
expectTimeBegin
.
compareTo
(
occupyInfoDetail
.
getBeginTime
())
>=
0
?
expectTimeBegin
:
occupyInfoDetail
.
getBeginTime
();
LocalDateTime
planEndTime
=
expectTimeEnd
.
compareTo
(
occupyInfoDetail
.
getEndTime
())
<=
0
?
expectTimeEnd
:
occupyInfoDetail
.
getEndTime
();
if
(
planStartTime
.
plusMinutes
(
takeTime
).
compareTo
(
planEndTime
)
>
0
)
{
continue
;
}
return
planStartTime
;
}
return
null
;
}
/**
* 订单重新分单
...
...
project-order/src/main/java/com/dituhui/pea/order/service/impl/OrderServiceDetailImpl.java
View file @
28d0f9a
...
...
@@ -79,6 +79,7 @@ public class OrderServiceDetailImpl implements OrderServiceDetail {
res
.
setSkill
(
order
.
getSkill
());
res
.
setFaultDescribe
(
order
.
getFaultDescribe
());
res
.
setExpectTimeBegin
(
TimeUtils
.
IsoLocalDateTime2String
(
order
.
getExpectTimeBegin
()));
res
.
setExpectTimeEnd
(
TimeUtils
.
IsoLocalDateTime2String
(
order
.
getExpectTimeEnd
()));
res
.
setExpectTimeDesc
(
order
.
getExpectTimeDesc
());
res
.
setSource
(
order
.
getSource
());
res
.
setTags
(
order
.
getTags
());
...
...
project-order/src/main/java/com/dituhui/pea/order/service/impl/OrderServiceListServiceImpl.java
View file @
28d0f9a
...
...
@@ -44,15 +44,11 @@ public class OrderServiceListServiceImpl implements OrderServiceListService {
//分页
Page
<
OrderInfo
>
pg
=
new
Page
(
reqDTO
.
getPage
(),
reqDTO
.
getSize
());
LocalDate
startDate
=
TimeUtils
.
IsoDate2LocalDate
(
reqDTO
.
getStartDate
());
LocalDate
endDate
=
TimeUtils
.
IsoDate2LocalDate
(
reqDTO
.
getEndDate
());
LambdaQueryWrapper
<
OrderInfo
>
lqw
=
new
LambdaQueryWrapper
<>();
lqw
.
eq
(
reqDTO
.
getLevelType
().
equals
(
"cluster"
),
OrderInfo:
:
getOrgClusterId
,
reqDTO
.
getLevelValue
());
lqw
.
eq
(
reqDTO
.
getLevelType
().
equals
(
"branch"
),
OrderInfo:
:
getOrgBranchId
,
reqDTO
.
getLevelValue
());
lqw
.
eq
(
reqDTO
.
getLevelType
().
equals
(
"group"
),
OrderInfo:
:
getOrgGroupId
,
reqDTO
.
getLevelValue
());
lqw
.
ge
(
OrderInfo:
:
getDt
,
startDate
);
//预约开始日期
lqw
.
le
(
OrderInfo:
:
getDt
,
endDate
);
//预约开始日期
lqw
.
eq
(
OrderInfo:
:
getDt
,
reqDTO
.
getDate
());
//预约开始日期
//筛选项
if
(
StringUtils
.
isNotBlank
(
reqDTO
.
getOrderId
()))
{
lqw
.
in
(
StringUtils
.
isNotEmpty
(
reqDTO
.
getOrderId
()),
OrderInfo:
:
getOrderId
,
reqDTO
.
getOrderId
().
split
(
","
));
...
...
@@ -160,6 +156,9 @@ public class OrderServiceListServiceImpl implements OrderServiceListService {
record
.
setAddressId
(
o
.
getAddressId
());
record
.
setIsCutoff
(
o
.
getIsCutoff
());
record
.
setReschedulingReason
(
o
.
getReschedulingReason
());
record
.
setEngineerName
(
o
.
getEngineerName
());
record
.
setEngineerCode
(
o
.
getEngineerCode
());
record
.
setEngineerPhone
(
o
.
getEngineerPhone
());
record
.
setActualStartTime
(
ObjectUtil
.
isNull
(
o
.
getActualStartTime
())
?
""
:
TimeUtils
.
IsoTimestamp2DateTime
(
o
.
getActualStartTime
()));
record
.
setActualEndTime
(
ObjectUtil
.
isNull
(
o
.
getActualEndTime
())
?
""
:
TimeUtils
.
IsoTimestamp2DateTime
(
o
.
getActualEndTime
()));
...
...
project-order/src/main/java/com/dituhui/pea/order/service/impl/PeaOuterAPIServiceImpl.java
View file @
28d0f9a
...
...
@@ -23,9 +23,11 @@ import com.dituhui.pea.order.entity.MapBlockInfoEntity;
import
com.dituhui.pea.order.entity.OrderInfoEntity
;
import
com.dituhui.pea.order.entity.OrgGroupEntity
;
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.OrderStatusEnum
;
import
com.dituhui.pea.order.enums.ServiceStatusEnum
;
import
com.dituhui.pea.order.service.CommonService
;
import
com.dituhui.pea.order.service.PeaOuterAPIService
;
import
com.dituhui.pea.pojo.fendan.FendanDTO
;
import
lombok.RequiredArgsConstructor
;
...
...
@@ -63,6 +65,7 @@ public class PeaOuterAPIServiceImpl implements PeaOuterAPIService {
private
final
SaasUtils
saasUtils
;
private
final
MapBlockInfoDao
mapBlockInfoDao
;
private
final
EngineerInfoDao
engineerInfoDao
;
private
final
CommonService
commonService
;
@Override
public
EstimateDTO
.
VisitResult
estimateVisitService
(
String
brand
,
String
productType
,
String
serviceType
,
Location
clientLocation
)
{
...
...
@@ -174,7 +177,7 @@ public class PeaOuterAPIServiceImpl implements PeaOuterAPIService {
orderInfo
.
setAppointmentStatus
(
String
.
valueOf
(
OrderFlowEnum
.
CONFIRM
));
orderInfo
.
setServiceStatus
(
ServiceStatusEnum
.
CONTACTED
.
getCode
());
orderInfo
.
setOrderStatus
(
OrderStatusEnum
.
RESCHEDULED
.
getCode
());
orderInfo
.
setAppointment
Status
(
String
.
valueOf
(
AppointmentMethodEnum
.
AUTO_NOW
));
orderInfo
.
setAppointment
Method
(
String
.
valueOf
(
AppointmentMethodEnum
.
AUTO_NOW
));
orderInfo
.
setEngineerCode
(
engineerInfo
.
getEngineerCode
());
orderInfo
.
setEngineerName
(
engineerInfo
.
getName
());
// 更新上门时间, 结束时间
...
...
@@ -187,7 +190,16 @@ public class PeaOuterAPIServiceImpl implements PeaOuterAPIService {
orderInfo
.
setReasonForFailure
(
request
.
getReasonForFailure
());
orderInfoDao
.
save
(
orderInfo
);
//TODO 回调BEAN 改约接口
String
memo
;
if
(
Objects
.
equals
(
request
.
getAppointmentResult
(),
"CONFIRMED"
))
{
//TODO 回调BEAN 改约接口
memo
=
"SUCCESS"
;
}
else
{
memo
=
"FAIL:"
+
request
.
getReasonForFailure
();
}
String
msg
=
String
.
format
(
OrderEventEnum
.
reassignment
.
getMsg
(),
engineerInfo
.
getName
());
commonService
.
addOrderEvent
(
orderInfo
.
getOrderId
(),
""
,
"BEAN"
,
"BEAN"
,
OrderEventEnum
.
reassignment
.
getEvent
(),
msg
,
memo
,
LocalDateTime
.
now
());
OrderConfirmResult
orderConfirmResult
=
new
OrderConfirmResult
();
orderConfirmResult
.
setOrderId
(
orderId
);
orderConfirmResult
.
setEngineerCode
(
engineerInfo
.
getEngineerCode
());
...
...
project-order/src/main/java/com/dituhui/pea/order/service/impl/WorkbenchServiceImpl.java
View file @
28d0f9a
package
com
.
dituhui
.
pea
.
order
.
service
.
impl
;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.dituhui.pea.common.Result
;
import
com.dituhui.pea.order.common.DateUtils
;
...
...
@@ -91,7 +92,16 @@ public class WorkbenchServiceImpl implements WorkbenchService {
HashMap
<
String
,
Long
>
statusSummary
=
this
.
transOrderStatus
(
this
.
queryCountByOrderStatus
(
levelType
,
levelValue
,
dt
));
WorkbenchSummaryResp
.
ItemDTO
statusItem
=
new
WorkbenchSummaryResp
.
ItemDTO
();
statusItem
.
setType
(
"order"
);
statusItem
.
setRows
(
this
.
packValueOrderStatus
(
statusSummary
));
List
<
WorkbenchSummaryResp
.
ValueDTO
>
valueDTOS
=
this
.
packValueOrderStatus
(
statusSummary
);
// - 已改约:预约单状态为“已改约”的工单.
HashMap
<
String
,
List
<
String
>>
p5
=
this
.
packParams
(
"appointmentStatus"
,
"RESCHEDULED"
);
valueDTOS
.
add
(
new
WorkbenchSummaryResp
.
ValueDTO
(
"已改约"
,
queryRescheduledNum
(
levelType
,
levelValue
,
dt
),
null
,
null
,
""
,
p5
));
// - 已延误:已到开始时间,TARO没有反馈开始的工单.
valueDTOS
.
add
(
new
WorkbenchSummaryResp
.
ValueDTO
(
"已延误"
,
queryDelayNum
(
levelType
,
levelValue
,
dt
),
null
,
"#FF3D44"
,
""
,
new
HashMap
<>()));
statusItem
.
setRows
(
valueDTOS
);
// - 已超时:已到开始时间,TARO没有反馈开始的工单.
valueDTOS
.
add
(
new
WorkbenchSummaryResp
.
ValueDTO
(
"已超时"
,
queryOvertimeNum
(
levelType
,
levelValue
,
dt
),
null
,
"#FF3D44"
,
""
,
new
HashMap
<>()));
statusItem
.
setRows
(
valueDTOS
);
items
.
add
(
statusItem
);
WorkbenchSummaryResp
res
=
new
WorkbenchSummaryResp
();
...
...
@@ -99,6 +109,83 @@ public class WorkbenchServiceImpl implements WorkbenchService {
return
Result
.
success
(
res
);
}
private
String
queryOvertimeNum
(
String
levelType
,
String
levelValue
,
LocalDate
dt
)
{
if
(
"cluster"
.
equals
(
levelType
))
{
long
clusterCount
=
orderInfoDao
.
countOvertimeByDtAndOrgClusterId
(
dt
,
levelValue
);
return
String
.
valueOf
(
clusterCount
);
}
else
if
(
"branch"
.
equals
(
levelType
))
{
long
branchCount
=
orderInfoDao
.
countOvertimeByDtAndOrgBranchId
(
dt
,
levelValue
);
return
String
.
valueOf
(
branchCount
);
}
else
if
(
"group"
.
equals
(
levelType
))
{
long
groupCount
=
orderInfoDao
.
countOvertimeByDtAndOrgGroupId
(
dt
,
levelValue
);
return
String
.
valueOf
(
groupCount
);
}
return
"0"
;
}
/**
* 查询延误工单数据
*
* @param levelType
* @param levelValue
* @param dt
* @return
*/
private
String
queryDelayNum
(
String
levelType
,
String
levelValue
,
LocalDate
dt
)
{
if
(
"cluster"
.
equals
(
levelType
))
{
long
clusterCount
=
orderInfoDao
.
countDelayByDtAndOrgClusterId
(
dt
,
levelValue
);
return
String
.
valueOf
(
clusterCount
);
}
else
if
(
"branch"
.
equals
(
levelType
))
{
long
branchCount
=
orderInfoDao
.
countDelayByDtAndOrgBranchId
(
dt
,
levelValue
);
return
String
.
valueOf
(
branchCount
);
}
else
if
(
"group"
.
equals
(
levelType
))
{
long
groupCount
=
orderInfoDao
.
countDelayByDtAndOrgGroupId
(
dt
,
levelValue
);
return
String
.
valueOf
(
groupCount
);
}
return
"0"
;
}
/**
* 查询改约工单数据
*
* @param levelType
* @param levelValue
* @param dt
* @return
*/
private
String
queryRescheduledNum
(
String
levelType
,
String
levelValue
,
LocalDate
dt
)
{
CriteriaBuilder
criteriaBuilder
=
entityManager
.
getCriteriaBuilder
();
CriteriaQuery
<
Object
[]>
criteriaQuery
=
criteriaBuilder
.
createQuery
(
Object
[].
class
);
Root
<
OrderInfoEntity
>
root
=
criteriaQuery
.
from
(
OrderInfoEntity
.
class
);
criteriaQuery
.
multiselect
(
criteriaBuilder
.
count
(
root
).
alias
(
"count"
)
);
Predicate
datePredicate
=
criteriaBuilder
.
equal
(
root
.
get
(
"dt"
),
dt
);
Predicate
orderStatusPredicate
=
criteriaBuilder
.
equal
(
root
.
get
(
"orderStatus"
),
"RESCHEDULED"
);
Predicate
levelPredicate
=
null
;
if
(
"cluster"
.
equals
(
levelType
))
{
levelPredicate
=
criteriaBuilder
.
equal
(
root
.
get
(
"orgClusterId"
),
levelValue
);
}
else
if
(
"branch"
.
equals
(
levelType
))
{
levelPredicate
=
criteriaBuilder
.
equal
(
root
.
get
(
"orgBranchId"
),
levelValue
);
}
else
if
(
"group"
.
equals
(
levelType
))
{
levelPredicate
=
criteriaBuilder
.
equal
(
root
.
get
(
"orgGroupId"
),
levelValue
);
}
if
(
levelPredicate
!=
null
)
{
criteriaQuery
.
where
(
orderStatusPredicate
,
datePredicate
,
levelPredicate
);
}
else
{
criteriaQuery
.
where
(
orderStatusPredicate
,
datePredicate
);
}
TypedQuery
<
Object
[]>
typedQuery
=
entityManager
.
createQuery
(
criteriaQuery
);
List
<
Object
[]>
results
=
typedQuery
.
getResultList
();
String
rescheduledNum
=
String
.
valueOf
(
ObjectUtil
.
isNull
(
results
.
get
(
0
))
?
"0"
:
results
.
get
(
0
));
return
rescheduledNum
;
}
private
List
<
Map
<
String
,
Object
>>
queryCountByAppointmentMethod
(
String
levelType
,
String
levelValue
,
LocalDate
dt
)
{
CriteriaBuilder
criteriaBuilder
=
entityManager
.
getCriteriaBuilder
();
CriteriaQuery
<
Object
[]>
criteriaQuery
=
criteriaBuilder
.
createQuery
(
Object
[].
class
);
...
...
@@ -262,31 +349,27 @@ public class WorkbenchServiceImpl implements WorkbenchService {
String
urlName
=
""
;
// 不返回,前端就不跳转了
Long
assigned
=
summary
.
getOrDefault
(
"INIT
"
,
0L
);
Long
contacted
=
summary
.
getOrDefault
(
"CONTACTED
"
,
0L
);
Long
pending
=
summary
.
getOrDefault
(
"PENDING"
,
0L
);
Long
dealing
=
assign
ed
+
pending
;
Long
dealing
=
contact
ed
+
pending
;
Long
started
=
summary
.
getOrDefault
(
"STARTED"
,
0L
);
Long
finished
=
summary
.
getOrDefault
(
"FINISHED"
,
0L
)
+
summary
.
getOrDefault
(
"UNFINISHED"
,
0L
);
Long
cancel
=
0L
;
HashMap
<
String
,
List
<
String
>>
p1
=
this
.
packParams
(
"appointmentStatus"
,
"ASSIGNED"
,
"CONTACTED"
,
"DEPARTED"
);
Long
cancel
=
summary
.
getOrDefault
(
"1"
,
0L
);
// 服务状态:INIT-初始化/PENDING待服务/CONTACTED已排期/STARTED-已开始/FINISHED已完成/UNFINISHED-已上门未完成
// - 待上门:服务状态为“待服务、已排期”的工单.
HashMap
<
String
,
List
<
String
>>
p1
=
this
.
packParams
(
"appointmentStatus"
,
"CONTACTED"
,
"PENDING"
);
items
.
add
(
new
WorkbenchSummaryResp
.
ValueDTO
(
"待上门"
,
dealing
.
toString
(),
null
,
"#469967"
,
urlName
,
p1
));
// - 服务中:服务状态为“已开始”的工单.
HashMap
<
String
,
List
<
String
>>
p2
=
this
.
packParams
(
"appointmentStatus"
,
"STARTED"
);
items
.
add
(
new
WorkbenchSummaryResp
.
ValueDTO
(
"服务中"
,
started
.
toString
(),
null
,
"#016FFF"
,
urlName
,
p2
));
// - 已完成:服务状态为“已完成”的工单.
HashMap
<
String
,
List
<
String
>>
p3
=
this
.
packParams
(
"appointmentStatus"
,
"FINISHED"
);
items
.
add
(
new
WorkbenchSummaryResp
.
ValueDTO
(
"已完成"
,
finished
.
toString
(),
null
,
null
,
urlName
,
p3
));
// - 已取消:预约单状态为“已取消”的工单.
HashMap
<
String
,
List
<
String
>>
p4
=
this
.
packParams
(
"appointmentStatus"
,
"CANCELED"
);
items
.
add
(
new
WorkbenchSummaryResp
.
ValueDTO
(
"已取消"
,
cancel
.
toString
(),
null
,
null
,
urlName
,
p4
));
HashMap
<
String
,
List
<
String
>>
p5
=
this
.
packParams
(
"appointmentStatus"
,
"RESCHEDULED"
);
items
.
add
(
new
WorkbenchSummaryResp
.
ValueDTO
(
"已改约"
,
"0"
,
null
,
null
,
urlName
,
p5
));
items
.
add
(
new
WorkbenchSummaryResp
.
ValueDTO
(
"已延误"
,
"0"
,
null
,
"#FF3D44"
,
urlName
,
new
HashMap
<>()));
return
items
;
}
...
...
project-order/src/main/java/com/dituhui/pea/order/utils/OrderUtil.java
View file @
28d0f9a
...
...
@@ -18,4 +18,17 @@ public class OrderUtil {
return
order
;
}
/**
* 分单,超派,特殊时间等处理工单指派工程师,网点等数据
*
* @param order
* @return
*/
public
static
OrderInfoEntity
handleErrorOrder2
(
OrderInfoEntity
order
)
{
order
.
setEngineerPhone
(
null
);
order
.
setEngineerName
(
null
);
order
.
setEngineerCode
(
null
);
return
order
;
}
}
project-order/src/test/java/com/dituhui/pea/order/scheduler/CalcEngineerCapacitySchedulerTest.java
View file @
28d0f9a
package
com
.
dituhui
.
pea
.
order
.
scheduler
;
import
com.dituhui.pea.order.OrderServiceApplication
;
import
com.dituhui.pea.order.service.EngineerCalendarService
;
import
org.junit.jupiter.api.Assertions
;
import
org.junit.jupiter.api.Test
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
java.time.LocalDate
;
@SpringBootTest
(
classes
=
OrderServiceApplication
.
class
)
class
CalcEngineerCapacitySchedulerTest
{
@Autowired
private
CalcEngineerCapacityScheduler
calcEngineerCapacityScheduler
;
@Autowired
private
CalcOrgCapacityScheduler
calcOrgCapacityScheduler
;
@Autowired
private
EngineerCalendarService
engineerCalendarService
;
@Test
void
calcOneEngineer
()
{
// calcEngineerCapacityScheduler.calcOneEngineer("2023-11-09", "6200044665");
// calcEngineerCapacityScheduler.calcOneEngineer("2023-11-15", "G20210H1301-jiangbei");
// calcOrgCapacityScheduler.calcAllGroupByDays("2023-11-14", "2023-11-17");
}
@Test
void
engineerTimeWindow
()
{
// int[][] ints = engineerCalendarService.timeWindows("6200043046", "1716782616477233152", LocalDate.now().plusDays(1));
// Assertions.assertEquals(480, ints[0][0]);
}
}
\ No newline at end of file
project-user/src/main/java/com/dituhui/pea/user/controller/UserController.java
View file @
28d0f9a
...
...
@@ -166,4 +166,11 @@ public class UserController implements IUser {
return
Result
.
success
(
orgInfos
);
}
@Override
public
Result
<
List
<
OrgInfo
>>
orgsNoName
(
String
userId
)
{
List
<
OrgInfo
>
orgInfos
=
userService
.
orgsNoName
(
userId
);
return
Result
.
success
(
orgInfos
);
}
}
project-user/src/main/java/com/dituhui/pea/user/service/UserService.java
View file @
28d0f9a
...
...
@@ -887,4 +887,32 @@ public class UserService {
});
return
orgInfos
;
}
public
List
<
OrgInfo
>
orgsNoName
(
String
userId
)
{
List
<
OrgInfo
>
orgInfos
=
new
ArrayList
<>();
// 获取角色
List
<
UserRoleEntity
>
userRoles
=
userRoleDao
.
findByUserId
(
userId
);
if
(
CollectionUtils
.
isEmpty
(
userRoles
))
{
return
null
;
}
List
<
String
>
ids
=
userRoles
.
stream
().
map
(
r
->
r
.
getRoleId
()).
collect
(
Collectors
.
toList
());
if
(
ids
.
contains
(
Globals
.
SUPER_ADMIN_ID
))
{
OrgInfo
orgInfo
=
new
OrgInfo
();
orgInfo
.
setId
(
"admin"
);
orgInfo
.
setOrgLevel
(-
1
);
orgInfos
.
add
(
orgInfo
);
return
orgInfos
;
}
List
<
UserOrgEntity
>
byUserId
=
userOrgDao
.
findByUserId
(
userId
);
if
(
CollectionUtils
.
isEmpty
(
byUserId
))
{
return
orgInfos
;
}
byUserId
.
forEach
(
e
->
{
OrgInfo
orgInfo
=
new
OrgInfo
();
orgInfo
.
setId
(
e
.
getOrgId
());
orgInfo
.
setOrgLevel
(
e
.
getOrgLevel
());
orgInfos
.
add
(
orgInfo
);
});
return
orgInfos
;
}
}
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