Commit 5639abe7 by chamberone

Merge branch 'develop' of https://zhangguoping@gitlab.dituhui.com/bsh/project/pr…

…oject.git into develop
2 parents 706543dd 33cb9c35
Showing with 1255 additions and 706 deletions
......@@ -33,6 +33,19 @@ public class DispatchController {
return res;
}
@GetMapping("/dispatch/order/group")
public Result<?> getDispatchOrderGroup(@Valid DispatchOrderListReq reqDTO) {
// 获取派工台待派订单列表
Result<?> res = null;
try {
res = dispatchService.getDispatchOrderGroup(reqDTO);
}catch (BusinessException e) {
return Result.failed(e.getMessage());
}
return res;
}
@GetMapping("/dispatch/engineer/order/list")
public Result<?> getDispatchEngineerOrderList(@Valid DispatchEngineerOrderListReq reqDTO) {
// 获取派工台工程师已派订单列表
......
......@@ -40,8 +40,10 @@ public class MsgController {
MsgQuery request) {
CommonUtil.setNullValue(request);
request.setUserId(userId);
if (!"is_read".equalsIgnoreCase(request.getSort())) {
if (!"isRead".equalsIgnoreCase(request.getSort())) {
request.setSort("create_time");
} else {
request.setSort("is_read");
}
if (!"asc".equalsIgnoreCase(request.getSortType())) {
request.setSortType("desc");
......@@ -63,7 +65,7 @@ public class MsgController {
* @date 2023/10/24
*/
@PostMapping("/msg/delete")
public Result<Boolean> delete(@RequestHeader(name = "userId", required = true) String userId, @RequestBody @Valid IdDTO dto) {
public Result<Boolean> delete(@RequestHeader(name = "userId", required = true) String userId, @RequestBody @Valid MsgDTO.IdDTO dto) {
AssertUtil.isNotEmpty(userId, "用户ID不能为空");
AssertUtil.isNotNull(dto.getId(), "消息ID不能为空");
msgService.delete(dto.getId(), userId);
......
......@@ -21,7 +21,9 @@ public interface MsgDao extends JpaRepository<MsgEntity, Integer> {
" where IF(:#{#req.startDate} is not null, tt.create_time>=:#{#req.startDate}, 1=1)" +
" and IF(:#{#req.endDate} is not null, tt.create_time<:#{#req.endDate}, 1=1)" +
" and IF(:#{#req.keyWord} is not null, tt.content like concat('%',:#{#req.keyWord},'%'), 1=1)" +
" and IF(:#{#req.orgTreeValue} is not null, (tt.cluster_id=:#{#req.orgTreeValue} or tt.branch_id=:#{#req.orgTreeValue} or tt.group_id=:#{#req.orgTreeValue}), 1=1)" +
" and IF(:#{#req.clusterId} is not null, tt.cluster_id=:#{#req.clusterId}, 1=1)" +
" and IF(:#{#req.branchId} is not null, tt.branch_id=:#{#req.branchId}, 1=1)" +
" and IF(:#{#req.groupId} is not null, tt.group_id=:#{#req.groupId}, 1=1)" +
"group by tt.cluster_id,tt.branch_id,tt.group_id" +
") t",
countQuery = "select count(t.cluster_id)" +
......@@ -31,7 +33,9 @@ public interface MsgDao extends JpaRepository<MsgEntity, Integer> {
" where IF(:#{#req.startDate} is not null, tt.create_time>=:#{#req.startDate}, 1=1)" +
" and IF(:#{#req.endDate} is not null, tt.create_time<:#{#req.endDate}, 1=1)" +
" and IF(:#{#req.keyWord} is not null, tt.content like concat('%',:#{#req.keyWord},'%'), 1=1)" +
" and IF(:#{#req.orgTreeValue} is not null, (tt.cluster_id=:#{#req.orgTreeValue} or tt.branch_id=:#{#req.orgTreeValue} or tt.group_id=:#{#req.orgTreeValue}), 1=1)" +
" and IF(:#{#req.clusterId} is not null, tt.cluster_id=:#{#req.clusterId}, 1=1)" +
" and IF(:#{#req.branchId} is not null, tt.branch_id=:#{#req.branchId}, 1=1)" +
" and IF(:#{#req.groupId} is not null, tt.group_id=:#{#req.groupId}, 1=1)" +
"group by tt.cluster_id,tt.branch_id,tt.group_id" +
") t"
, nativeQuery = true // 开启原生sql
......@@ -69,8 +73,8 @@ public interface MsgDao extends JpaRepository<MsgEntity, Integer> {
" join sys_user_org uo on u.id=uo.user_id" +
" join sys_user_role ur on ur.user_id=u.id" +
" join sys_role r on r.id=ur.role_id and r.name='分站派工'" +
" and IF(:groupId is not null, uo.org_id=:groupId and uo.org_level=2, 1=1)" +
" and IF(:groupId is null and :branchId is not null, uo.org_id=:branchId and uo.org_level=1, 1=1)" +
" and IF(:groupId is not null, ((uo.org_id=:groupId and uo.org_level=2) or (uo.org_id=:branchId and uo.org_level=1) or (uo.org_id=:clusterId and uo.org_level=0)), 1=1)" +
" and IF(:groupId is null and :branchId is not null, ((uo.org_id=:branchId and uo.org_level=1) or (uo.org_id=:clusterId and uo.org_level=0)), 1=1)" +
" and IF(:groupId is null and :branchId is null and :clusterId is not null, uo.org_id=:clusterId and uo.org_level=0, 1=1)"
, nativeQuery = true // 开启原生sql
)
......
......@@ -10,18 +10,31 @@ import java.util.List;
public interface OrderInfoDao extends JpaRepository<OrderInfoEntity, Long>, JpaSpecificationExecutor<OrderInfoEntity> {
OrderInfoEntity getByOrderId(String orderId);
OrderInfoEntity getByOrderIdAndDt(String orderId, LocalDate dt);
List<OrderInfoEntity> findByOrderId(String orderId);
List<OrderInfoEntity> findByDtAndEngineerCodeIn(LocalDate date, List<String> engineerCodes);
List<OrderInfoEntity> findByDtAndEngineerCode(LocalDate date, String engineerCode);
@Query("SELECT o.orderId, s.skillCategory as skillCaption FROM OrderInfoEntity o JOIN SkillInfoEntity s on o.brand=s.brand and o.type=s.type and o.skill=s.skill WHERE o.orderId = :orderId and o.dt = :dt")
OrderSkillProjection getOrderSkillCaptionByOrderIdAndDt(String orderId, LocalDate dt);
List<OrderInfoEntity> findAllByOrderIdIn(List<String> orderIds);
List<OrderInfoEntity> findAllByDtAndOrderIdIn(LocalDate dt, List<String> orderIds);
List<OrderInfoEntity> findByEngineerCodeAndDtAndAppointmentStatusIn(String engineerCode, LocalDate dt, List<String> appointmentStatus);
List<OrderInfoEntity> findByDtAndOrgTeamIdAndAppointmentStatusIn(LocalDate dt, String orgTeamId, List<String> appointmentStatus);
OrderInfoEntity findTopBySkillAndAppointmentStatus(String skill, String status);
List<OrderInfoEntity> findByServiceStatusAndEngineerCode(String serviceStatus, String engineerCode);
List<OrderInfoEntity> findByDtAndAddressId(String dt, String addressId);
List<OrderInfoEntity> findByMultipleOrders(String multipleOrders);
}
......@@ -3,53 +3,95 @@ package com.dituhui.pea.order.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import javax.persistence.Column;
import java.util.List;
@Data
public class DispatchEngineerOrderListResp {
private List<EngineerInfo> engineers;
@Data
public static class EngineerInfo{
private String engineerCode;
private String engineerName;
private String capacity;
private String capacityStatus;
private String grade;
private List<OrderInfo> orders;
}
@JsonInclude(JsonInclude.Include.ALWAYS)
@Data
public static class OrderInfo{
private boolean weight;
private String orderId;
private String description;
private String brand;
private String type;
private String skill;
private String typeCategory;
private String skillCategory;
private String faultDescribe;
private String applyNote;
private Integer duration;
private String province;
private String city;
private String county;
private String address;
private String name;
private String phone;
private String expectTimeDesc;
private String source;
private String dispatcher;
private String appointmentType;
private String appointmentStatus;
private String serviceStatus;
private String orderStatus;
private String orderStatusDesc;
private String createTime;
private String groupTag;
private Integer groupWeight;
}
private List<EngineerInfo> engineers;
@Data
public static class EngineerInfo {
private String engineerCode;
private String engineerName;
private String capacity;
private String capacityStatus;
private String grade;
private List<OrderInfo> orders;
}
@JsonInclude(JsonInclude.Include.ALWAYS)
@Data
public static class OrderInfo {
private boolean weight;
private String orderId;
private String description;
private String brand;
private String type;
private String skill;
private String typeCategory;
private String skillCategory;
private String faultDescribe;
private String applyNote;
private Integer duration;
private String province;
private String city;
private String county;
private String address;
private String name;
private String phone;
private String expectTimeDesc;
private String source;
private String dispatcher;
private String appointmentType;
private String appointmentStatus;
private String serviceStatus;
private String orderStatus;
private String orderStatusDesc;
private String createTime;
private String groupTag;
private Integer groupWeight;
/**
* 一家多单id,有则多条订单关联,没有则不是一家多单
*/
private String multipleOrders;
/**
* 一家多单订单集合
*/
private List<OrderInfo> multipleOrderList;
/**
* 是否重物搬运(双人上门) 0:否 1:是 默认0
*/
private Integer isMultiple = 0;
/**
* 是否指定某个工程师/是否排除某个工程师 0:否 1:指定 2:排除 默认0
*/
private Integer isAppointEngineer = 0;
/**
* 指定某个工程师/排除某个工程师 codes 多个,分割
*/
private String appointEngineerCodes;
/**
* 是否超派,0否 1是,默认0
*/
private Integer transcend;
/**
* 工单优先级
*/
private String beanPriority;
/**
* 是否是特殊时间段,0否 1是 默认0
*/
private Integer isSpecialTime;
}
}
......@@ -13,6 +13,10 @@ public class DispatchOrderListReq {
private String levelValue;
@NotNull
private String Date;
/**
* 0:工单优先级,1:耗时,2:意向时间,3:分站/网点,4:技能,5:一家多单
*/
@NotNull
private String groupTagId;
private List<String> branchIds;
......
......@@ -3,41 +3,93 @@ package com.dituhui.pea.order.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import javax.persistence.Column;
import java.util.List;
@Data
public class DispatchOrderListResp {
private List<Order> orders;
@JsonInclude(JsonInclude.Include.ALWAYS)
@Data
public static class Order{
private boolean weight;
private String orderId;
private String description;
private String brand;
private String type;
private String skill;
private String typeCategory;
private String skillCategory;
private String faultDescribe;
private String applyNote;
private Integer duration;
private String province;
private String city;
private String county;
private String address;
private String name;
private String phone;
private String expectTimeDesc;
private String source;
private String appointmentType;
private String dispatcher;
private String appointmentStatus;
private String orderStatus;
private String serviceStatus;
private String createTime;
private String groupTag;
private Integer groupWeight;
}
private List<Order> orders;
@JsonInclude(JsonInclude.Include.ALWAYS)
@Data
public static class Order {
private boolean weight;
private String orderId;
private String description;
private String brand;
private String type;
private String skill;
private String typeCategory;
private String skillCategory;
private String faultDescribe;
private String applyNote;
private Integer duration;
private String province;
private String city;
private String county;
private String address;
private String name;
private String phone;
private String expectTimeDesc;
private String source;
private String appointmentType;
private String dispatcher;
private String appointmentStatus;
private String orderStatus;
private String serviceStatus;
private String createTime;
private String groupTag;
private Integer groupWeight;
/**
* 一家多单id,有则多条订单关联,没有则不是一家多单
*/
private String multipleOrders;
/**
* 分站/网点id
*/
private String orgGroupId;
/**
* 分站/网点name
*/
private String orgGroupName;
/**
* 一家多单订单集合
*/
private List<DispatchOrderListResp.Order> multipleOrderList;
/**
* 是否重物搬运(双人上门) 0:否 1:是 默认0
*/
private Integer isMultiple;
/**
* 是否指定某个工程师/是否排除某个工程师 0:否 1:指定 2:排除 默认0
*/
private Integer isAppointEngineer;
/**
* 指定某个工程师/排除某个工程师 codes 多个,分割
*/
private String appointEngineerCodes;
/**
* 是否超派,0否 1是,默认0
*/
private Integer transcend;
/**
* 工单优先级
*/
private String beanPriority;
/**
* 是否是特殊时间段,0否 1是 默认0
*/
private Integer isSpecialTime;
}
}
package com.dituhui.pea.order.dto;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 公共 id类
*
* @author RenPing
* @date 2023/10/26
*/
@Data
public class IdDTO {
@NotNull(message = "ID不能为空")
private Integer id;
}
......@@ -49,4 +49,12 @@ public class MsgDTO {
@Min(value = 0, message = "标签类型格式不对")
@Max(value = 1, message = "标签类型格式不对")
private Integer tag;
@Data
public static class IdDTO {
@NotNull(message = "ID不能为空")
private Integer id;
}
}
\ No newline at end of file
......@@ -56,7 +56,17 @@ public class MsgQuery {
private String keyWord;
/**
* 大区ID、部门ID、小组ID
* 大区ID(大区Id、分部Id、分组Id只需传一个)
*/
private String orgTreeValue;
private String clusterId;
/**
* 分部ID
*/
private String branchId;
/**
* 小组ID
*/
private String groupId;
}
\ No newline at end of file
......@@ -2,6 +2,8 @@ package com.dituhui.pea.order.dto;
import lombok.Data;
import java.util.List;
@Data
public class OrderServiceList {
private String orderId;
......@@ -54,4 +56,24 @@ public class OrderServiceList {
private String appointEngineerCodes;
/**
* 一家多单订单集合
*/
private List<OrderServiceList> multipleOrderList;
/**
* 一家多单id,有则多条订单关联,没有则不是一家多单
*/
private String multipleOrders;
/**
* 是否超派,0否 1是,默认0
*/
private Integer transcend;
/**
* 是否是特殊时间段,0否 1是 默认0
*/
private Integer isSpecialTime;
}
......@@ -75,4 +75,27 @@ public class OrderInfo {
* 指定某个工程师/排除某个工程师 codes 多个,分割
*/
private String appointEngineerCodes;
/**
* 一家多单id,有则多条订单关联,没有则不是一家多单
*/
private String multipleOrders;
/**
* bean同步地址id
*/
private String addressId;
/**
* 是否超派,0否 1是,默认0
*/
private Integer transcend;
/**
* 是否是特殊时间段,0否 1是 默认0
*/
private Integer isSpecialTime;
}
\ No newline at end of file
......@@ -197,4 +197,32 @@ public class OrderInfoEntity {
*/
@Column(name = "appoint_engineer_codes")
private String appointEngineerCodes;
/**
* 一家多单id,有则多条订单关联,没有则不是一家多单
*/
@Column(name = "multiple_orders")
private String multipleOrders;
/**
* bean同步地址id
*/
@Column(name = "address_id")
private String addressId;
/**
* 是否超派,0否 1是,默认0
*/
@Column(name = "transcend")
private Integer transcend;
/**
* 是否是特殊时间段,0否 1是 默认0
*/
@Column(name = "is_special_time")
private Integer isSpecialTime = 0;
}
package com.dituhui.pea.order.enums;
public enum OrderGroupEnum {
zero("0"),
one("1"),
two("2"),
three("3"),
four("4"),
five("5");
private String code;
OrderGroupEnum(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
......@@ -8,9 +8,17 @@ import java.util.List;
public interface DispatchService {
Result<?> getDispatchOrderList(DispatchOrderListReq reqDTO);
Result<?> getDispatchOrderList(DispatchOrderListReq reqDTO);
Result<?> getDispatchEngineerOrderList(DispatchEngineerOrderListReq reqDTO);
Result<?> getDispatchEngineerOrderList(DispatchEngineerOrderListReq reqDTO);
Result<?> dispatchOrderConfirm(String engineerCode, String date, List<String> orderIds);
Result<?> dispatchOrderConfirm(String engineerCode, String date, List<String> orderIds);
/**
* 待派工工单池分组
*
* @param reqDTO
* @return
*/
Result<?> getDispatchOrderGroup(DispatchOrderListReq reqDTO);
}
package com.dituhui.pea.order.service;
import com.dituhui.pea.common.Result;
/**
* 订单相关
*/
public interface OrderInfoService {
/**
* 新增订单处理一家多单逻辑
*
* @param dt 订单日期 列:2023-07-21
* @param addressId 地址id
* @return 有则返回多条订单关联id,没有则不是一家多单
*/
Result<String> addMultipleOrders(String dt, String addressId);
/**
* 取消指定订单一家多台
*
* @param multipleOrders 订单关联id
* @param orderId 订单id
* @return 有则返回多条订单关联id,没有则不是一家多单
*/
Result deleteMultipleOrders(String multipleOrders, String orderId);
}
package com.dituhui.pea.order.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.common.ListUtils;
......@@ -11,9 +10,11 @@ import com.dituhui.pea.order.dto.DispatchEngineerOrderListResp;
import com.dituhui.pea.order.dto.DispatchOrderListReq;
import com.dituhui.pea.order.dto.DispatchOrderListResp;
import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.enums.OrderGroupEnum;
import com.dituhui.pea.order.enums.OrderStatus;
import com.dituhui.pea.order.service.DispatchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
......@@ -28,9 +29,9 @@ import java.util.*;
import java.util.stream.Collectors;
interface GroupTag {
// 订单分类tag
// 订单分类tag
String getGroupTag(OrderInfoEntity order);
String getGroupTag(OrderInfoEntity order);
}
......@@ -38,625 +39,767 @@ interface GroupTag {
@Service
public class DispatchServiceImpl implements DispatchService {
@Autowired
private OrderInfoDao orderInfoDao;
@Autowired
private OrgTeamDao orgTeamDao;
@Autowired
private EngineerInfoDao engineerInfoDao;
@Autowired
private SkillInfoDao skillInfoDao;
@Autowired
private CapacityEngineerStatDao capacityEngineerStatDao;
@Autowired
private EntityManager entityManager;
@Transactional
@Override
public Result<?> getDispatchOrderList(DispatchOrderListReq reqDTO) {
// 获取派工台订单列表
// 获取技能信息
HashMap<String, SkillInfoEntity> skillInfo = this.querySkillInfo();
// 获取工单列表
List<OrderInfoEntity> orders = this.queryOrders(reqDTO);
// 获取分组标签
GroupTag gt = new GroupTagFactory().getGroupTag(reqDTO.getGroupTagId());
List<DispatchOrderListResp.Order> items = new ArrayList<>();
for (OrderInfoEntity o : orders) {
DispatchOrderListResp.Order item = new DispatchOrderListResp.Order();
item.setOrderId(o.getOrderId());
item.setDescription(String.format("%s:%s-%s-%s\n%s:%s-%s-%s", o.getOrderId(), o.getBrand(), o.getType(),
o.getSkill(), o.getName(), o.getCity(), o.getCounty(), o.getAddress()));
item.setBrand(o.getBrand());
item.setType(o.getType());
item.setSkill(o.getSkill());
item.setFaultDescribe(o.getFaultDescribe());
item.setApplyNote(o.getApplyNote());
String key = String.format("%s%s%s", o.getBrand(), o.getType(), o.getSkill());
SkillInfoEntity skill = skillInfo.get(key);
if (skill != null) {
item.setDuration(skill.getTakeTime());
item.setSkillCategory(skill.getSkillCategory());
item.setTypeCategory(skill.getTypeCategory());
}
item.setName(o.getName());
item.setPhone(o.getPhone());
item.setCity(o.getCity());
item.setAddress(o.getAddress());
item.setProvince(o.getProvince());
item.setCity(o.getCity());
item.setCounty(o.getCounty());
item.setAddress(o.getAddress());
item.setName(o.getName());
item.setPhone(o.getPhone());
item.setExpectTimeDesc(o.getExpectTimeDesc());
item.setSource(o.getSource());
item.setDispatcher(o.getDispatcher());
item.setAppointmentType(o.getAppointmentMethod());
item.setAppointmentStatus(o.getAppointmentStatus());
item.setOrderStatus(o.getOrderStatus());
item.setServiceStatus(o.getServiceStatus());
item.setCreateTime(TimeUtils.IsoLocalDateTime2String(o.getCreateTime()));
String[] tags = gt.getGroupTag(o).split("#");
item.setGroupTag(tags[0]); // 设置tag名称
item.setGroupWeight(Integer.parseInt(tags[1])); // 设置tag权重
items.add(item);
}
DispatchOrderListResp res = new DispatchOrderListResp();
res.setOrders(items);
return Result.success(res);
}
@Transactional
@Override
public Result<?> getDispatchEngineerOrderList(DispatchEngineerOrderListReq reqDTO) throws BusinessException {
// 派工台技术员预约单列表
LocalDate date = TimeUtils.IsoDate2LocalDate(reqDTO.getDate());
// 获取技能信息
HashMap<String, SkillInfoEntity> skillInfo = this.querySkillInfo();
// 获取teamIds
List<String> teamIds = this.queryOrgTeamIds(reqDTO.getLevelType(), reqDTO.getLevelValue(), reqDTO.getBranchIds(),
reqDTO.getGroupIds(), reqDTO.getTeamIds());
if (teamIds.isEmpty()) {
throw new BusinessException("大区/分部/小组组织结构配置可能错误或缺失,请联系管理员/研发");
}
// 获取engineer列表
List<EngineerInfoEntity> engineers = this.queryEngineers(teamIds, reqDTO.getEngineerCodes(), reqDTO.getKey());
if (engineers.isEmpty()) {
// 该group下没有技术员,返回空
log.warn("没有找到技术员");
DispatchEngineerOrderListResp res = new DispatchEngineerOrderListResp();
List<DispatchEngineerOrderListResp.EngineerInfo> egs = new ArrayList<>();
res.setEngineers(egs);
return Result.success(res);
}
// 获取engineerCodes
List<String> engineerCodes = engineers.stream().map(EngineerInfoEntity::getEngineerCode).collect(Collectors.toList());
// 获取技术员已指派单列表
Map<String, List<OrderInfoEntity>> engineerOrders = this.queryEngineerOrders(engineerCodes, date);
// 获取技术员的容量
HashMap<String, CapacityEngineerStatEntity> engineerCap = this.queryCapacityEngineerStat(engineerCodes, reqDTO.getDate());
// 获取技术员已指派单列表
List<DispatchEngineerOrderListResp.EngineerInfo> egs = new ArrayList<>();
for (EngineerInfoEntity e : engineers) {
List<DispatchEngineerOrderListResp.OrderInfo> items = new ArrayList<>();
// 技术员已指派的订单列表
List<OrderInfoEntity> records = engineerOrders.getOrDefault(e.getEngineerCode(), new ArrayList<>());
for (OrderInfoEntity o : records) {
DispatchEngineerOrderListResp.OrderInfo item = new DispatchEngineerOrderListResp.OrderInfo();
item.setOrderId(o.getOrderId());
item.setDescription(String.format("%s:%s-%s-%s\n%s:%s-%s-%s", o.getOrderId(), o.getBrand(), o.getType(),
o.getSkill(), o.getName(), o.getCity(), o.getCounty(), o.getAddress()));
item.setBrand(o.getBrand());
item.setType(o.getType());
item.setSkill(o.getSkill());
item.setFaultDescribe(o.getFaultDescribe());
item.setApplyNote(o.getApplyNote());
String key = String.format("%s%s%s", o.getBrand(), o.getType(), o.getSkill());
SkillInfoEntity skill = skillInfo.get(key);
if (skill != null) {
item.setDuration(skill.getTakeTime());
item.setSkillCategory(skill.getSkillCategory());
item.setTypeCategory(skill.getTypeCategory());
}
item.setName(o.getName());
item.setPhone(o.getPhone());
item.setCity(o.getCity());
item.setAddress(o.getAddress());
item.setProvince(o.getProvince());
item.setCity(o.getCity());
item.setCounty(o.getCounty());
item.setAddress(o.getAddress());
item.setName(o.getName());
item.setPhone(o.getPhone());
String time = TimeUtils.localDateTime2String(o.getPlanStartTime(), "HH:mm");
String timeSlot = this.parseTimeSlot(o.getPlanStartTime());
item.setExpectTimeDesc(String.format("%s/%s", time, timeSlot));
item.setSource(o.getSource());
item.setDispatcher(o.getDispatcher());
item.setAppointmentType(o.getAppointmentMethod());
item.setAppointmentStatus(o.getAppointmentStatus());
item.setOrderStatus(o.getOrderStatus()); // 订单状态
item.setServiceStatus(o.getServiceStatus());
item.setOrderStatusDesc(OrderStatus.valueOf(o.getOrderStatus()).getDescription());
item.setCreateTime(TimeUtils.IsoLocalDateTime2String(o.getCreateTime()));
items.add(item);
}
// 获取容量
int capUsed = 0;
int capTotal = 0;
String capacityStatus = "less";
CapacityEngineerStatEntity cap = engineerCap.get(e.getEngineerCode());
if (cap != null) {
capUsed = cap.getCapUsed();
capTotal = cap.getCapTotal();
if (capTotal > 0 && (float) capUsed / capTotal < 0.8) {
capacityStatus = "normal";
}
}
DispatchEngineerOrderListResp.EngineerInfo eg = new DispatchEngineerOrderListResp.EngineerInfo();
eg.setOrders(items);
eg.setEngineerCode(e.getEngineerCode());
eg.setEngineerName(e.getName());
eg.setGrade(e.getGrade());
eg.setCapacity(String.format("%d/%d", capUsed, capTotal));
eg.setCapacityStatus(capacityStatus);
egs.add(eg);
}
DispatchEngineerOrderListResp res = new DispatchEngineerOrderListResp();
res.setEngineers(egs);
return Result.success(res);
}
@Transactional
@Override
public Result<?> dispatchOrderConfirm(String engineerCode, String date, List<String> orderIds) throws BusinessException {
// 派工台确认派单
LocalDate localDate = TimeUtils.IsoDate2LocalDate(date);
EngineerInfoEntity engineer = engineerInfoDao.getByEngineerCode(engineerCode);
if (engineer == null) {
throw new BusinessException("技术员不存在");
}
List<OrderInfoEntity> orders = orderInfoDao.findAllByDtAndOrderIdIn(localDate, orderIds);
if (ListUtils.isEmpty(orders)) {
throw new BusinessException("订单不存在");
}
// 已经指派的订单
List<OrderInfoEntity> engineerOrders = orderInfoDao.findByDtAndEngineerCode(localDate, engineerCode);
engineerOrders.sort(Comparator.comparing(OrderInfoEntity::getPlanStartTime)); // 按照planStartTime排序
List<OrderInfoEntity> orderAppointments = engineerOrders.stream()
.filter(o -> o.getOrderStatus().equals("NORMAL"))
.collect(Collectors.toList()); // 过滤,只有NORMAL订单才需要处理,取消订单不需要处理
// TODO,临时处理方案,后续调用派单引擎处理
OrderRequestScheduler scheduler = new OrderRequestScheduler();
List<LineSegment> results = scheduler.scheduler(orders, orderAppointments);
for (LineSegment r : results) {
String orderId = r.id;
LocalDateTime planStartTime = scheduler.linePoint2DateTime(r.start, date);
LocalDateTime planEndTime = scheduler.linePoint2DateTime(r.end, date);
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaUpdate<OrderInfoEntity> update = criteriaBuilder.createCriteriaUpdate(OrderInfoEntity.class);
Root<OrderInfoEntity> root = update.from(OrderInfoEntity.class);
update.set(root.get("planStartTime"), planStartTime);
update.set(root.get("planEndTime"), planEndTime);
update.set(root.get("appointmentStatus"), "CONFIRM");
update.set(root.get("appointmentMethod"), "MANUAL");
update.set(root.get("engineerCode"), engineerCode);
update.where(
criteriaBuilder.equal(root.get("orderId"), orderId),
criteriaBuilder.equal(root.get("dt"), localDate)
);
entityManager.createQuery(update).executeUpdate();
}
return Result.success(null);
}
private List<OrderInfoEntity> queryOrders(DispatchOrderListReq reqDTO) {
// 获取服务单列表
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<OrderInfoEntity> criteriaQuery = criteriaBuilder.createQuery(OrderInfoEntity.class);
Root<OrderInfoEntity> root = criteriaQuery.from(OrderInfoEntity.class);
List<Predicate> predicates = new ArrayList<>();
predicates.add(criteriaBuilder.equal(root.get("dt"), TimeUtils.IsoDate2LocalDate(reqDTO.getDate())));
predicates.add(criteriaBuilder.equal(root.get("appointmentStatus"), "INIT"));
String levelType = reqDTO.getLevelType();
String levelValue = reqDTO.getLevelValue();
if ("cluster".equals(levelType)) {
predicates.add(criteriaBuilder.equal(root.get("orgClusterId"), levelValue));
} else if ("branch".equals(levelType)) {
predicates.add(criteriaBuilder.equal(root.get("orgBranchId"), levelValue));
} else if ("group".equals(levelType)) {
predicates.add(criteriaBuilder.equal(root.get("orgGroupId"), levelValue));
}
// 筛选项
if (StringUtils.isNotEmpty(reqDTO.getPhone())) {
predicates.add(criteriaBuilder.equal(root.get("phone"), reqDTO.getPhone()));
}
if (StringUtils.isNotEmpty(reqDTO.getOrderId())) {
predicates.add(criteriaBuilder.equal(root.get("orderId"), reqDTO.getOrderId()));
}
if (ListUtils.isNotEmpty(reqDTO.getBranchIds())) {
predicates.add(root.get("orgBranchId").in(reqDTO.getBranchIds()));
}
if (ListUtils.isNotEmpty(reqDTO.getGroupIds())) {
predicates.add(root.get("orgGroupId").in(reqDTO.getGroupIds()));
}
if (ListUtils.isNotEmpty(reqDTO.getTeamIds())) {
predicates.add(root.get("orgTeamId").in(reqDTO.getTeamIds()));
}
if (ListUtils.isNotEmpty(reqDTO.getAppointmentType())) {
predicates.add(root.get("appointmentMethod").in(reqDTO.getAppointmentType()));
}
if (ListUtils.isNotEmpty(reqDTO.getPriorities())) {
List<Integer> p = reqDTO.getPriorities();
if (p.contains(0) && p.contains(1)) {
predicates.add(criteriaBuilder.ge(root.get("priority"), 1));
} else if (p.contains(0) && !p.contains(1)) {
predicates.add(criteriaBuilder.le(root.get("priority"), 1));
} else if (p.contains(1) && !p.contains(0)) {
predicates.add(criteriaBuilder.ge(root.get("priority"), 5));
}
}
if (ListUtils.isNotEmpty(reqDTO.getEngineerCodes())) {
Predicate engineerCodePredicate = root.get("engineerCode").in(reqDTO.getEngineerCodes());
Predicate engineerCodeSubPredicate = root.get("engineerCodeSub").in(reqDTO.getEngineerCodes());
predicates.add(criteriaBuilder.or(engineerCodePredicate, engineerCodeSubPredicate));
}
if (ListUtils.isNotEmpty(reqDTO.getTypeCategory())) {
Subquery<OrderInfoEntity> typeCategorySubquery = criteriaQuery.subquery(OrderInfoEntity.class);
Root<SkillInfoEntity> skillInfoRoot = typeCategorySubquery.from(SkillInfoEntity.class);
typeCategorySubquery.select(root)
.where(
criteriaBuilder.equal(skillInfoRoot.get("brand"), root.get("brand")),
criteriaBuilder.equal(skillInfoRoot.get("type"), root.get("type")),
criteriaBuilder.equal(skillInfoRoot.get("skill"), root.get("skill")),
skillInfoRoot.get("typeCategory").in(reqDTO.getTypeCategory())
);
predicates.add(criteriaBuilder.exists(typeCategorySubquery));
}
if (ListUtils.isNotEmpty(reqDTO.getSkillCategory())) {
Subquery<OrderInfoEntity> skillCategorySubquery = criteriaQuery.subquery(OrderInfoEntity.class);
Root<SkillInfoEntity> skillInfoRoot = skillCategorySubquery.from(SkillInfoEntity.class);
skillCategorySubquery.select(root) // 注意这里的 select 使用主查询的 root
.where(
criteriaBuilder.equal(skillInfoRoot.get("brand"), root.get("brand")),
criteriaBuilder.equal(skillInfoRoot.get("type"), root.get("type")),
criteriaBuilder.equal(skillInfoRoot.get("skill"), root.get("skill")),
skillInfoRoot.get("skillCategory").in(reqDTO.getSkillCategory())
);
predicates.add(criteriaBuilder.exists(skillCategorySubquery));
}
if (ListUtils.isNotEmpty(reqDTO.getGroupCategory())) {
Subquery<OrderInfoEntity> skillGroupCategorySubquery = criteriaQuery.subquery(OrderInfoEntity.class);
Root<SkillInfoEntity> skillInfoRoot = skillGroupCategorySubquery.from(SkillInfoEntity.class);
skillGroupCategorySubquery.select(root) // 注意这里的 select 使用主查询的 root
.where(
criteriaBuilder.equal(skillInfoRoot.get("brand"), root.get("brand")),
criteriaBuilder.equal(skillInfoRoot.get("type"), root.get("type")),
criteriaBuilder.equal(skillInfoRoot.get("skill"), root.get("skill")),
skillInfoRoot.get("groupCategory").in(reqDTO.getGroupCategory())
);
predicates.add(criteriaBuilder.exists(skillGroupCategorySubquery));
}
criteriaQuery.where(predicates.toArray(new Predicate[0]));
return entityManager.createQuery(criteriaQuery).getResultList();
}
private Map<String, List<OrderInfoEntity>> queryEngineerOrders(List<String> engineerCodes, LocalDate date) {
// 获取工程师服务单列表
List<OrderInfoEntity> records = orderInfoDao.findByDtAndEngineerCodeIn(date, engineerCodes);
// 排序
records.sort(Comparator.comparing(OrderInfoEntity::getEngineerCode));
records.sort(Comparator.comparing(OrderInfoEntity::getPlanStartTime));
//过滤
List<OrderInfoEntity> orders = records.stream()
.filter(r -> r.getOrderStatus().equals("NORMAL"))
.collect(Collectors.toList());
return orders.stream().collect(Collectors.groupingBy(OrderInfoEntity::getEngineerCode));
}
public List<EngineerInfoEntity> queryEngineers(List<String> teamIds, List<String> engineerCodes, String key) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<EngineerInfoEntity> criteriaQuery = criteriaBuilder.createQuery(EngineerInfoEntity.class);
Root<EngineerInfoEntity> root = criteriaQuery.from(EngineerInfoEntity.class);
List<Predicate> predicates = new ArrayList<>();
predicates.add(criteriaBuilder.equal(root.get("beanStatus"), 1));
if (ListUtils.isNotEmpty(engineerCodes)) {
predicates.add(root.get("engineerCode").in(engineerCodes));
}
Subquery<Integer> teamSubquery = criteriaQuery.subquery(Integer.class);
Root<OrgTeamEngineerEntity> teamRoot = teamSubquery.from(OrgTeamEngineerEntity.class);
teamSubquery.select(criteriaBuilder.literal(1))
.where(
criteriaBuilder.equal(teamRoot.get("engineerCode"), root.get("engineerCode")),
teamRoot.get("teamId").in(teamIds)
);
predicates.add(criteriaBuilder.exists(teamSubquery));
if (StringUtils.isNotEmpty(key)) {
predicates.add(criteriaBuilder.or(
criteriaBuilder.like(root.get("phone"), "%" + key + "%"),
criteriaBuilder.like(root.get("name"), "%" + key + "%"),
criteriaBuilder.like(root.get("engineerCode"), "%" + key + "%")
));
}
criteriaQuery.where(predicates.toArray(new Predicate[0]));
criteriaQuery.orderBy(criteriaBuilder.asc(root.get("name")));
return entityManager.createQuery(criteriaQuery).getResultList();
}
private List<String> queryOrgTeamIds(String levelType, String levelIds, List<String> branchIds, List<String> groupIds, List<String> teamIds) {
Specification<OrgTeamEntity> specification = (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
if ("cluster".equals(levelType)) {
predicates.add(criteriaBuilder.in(root.get("clusterId")).value(levelIds));
} else if ("branch".equals(levelType)) {
predicates.add(criteriaBuilder.in(root.get("branchId")).value(levelIds));
} else if ("group".equals(levelType)) {
predicates.add(criteriaBuilder.in(root.get("groupId")).value(levelIds));
}
if (ListUtils.isNotEmpty(branchIds)) {
predicates.add(root.get("branchId").in(branchIds));
}
if (ListUtils.isNotEmpty(groupIds)) {
predicates.add(root.get("groupId").in(groupIds));
}
if (ListUtils.isNotEmpty(teamIds)) {
predicates.add(root.get("teamId").in(teamIds));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
};
List<OrgTeamEntity> teams = orgTeamDao.findAll(specification);
return teams.stream().map(OrgTeamEntity::getTeamId).collect(Collectors.toList());
}
private HashMap<String, Integer> querySkillTakeTime() {
HashMap<String, Integer> map = new HashMap<>();
List<SkillInfoEntity> records = skillInfoDao.findAll();
for (SkillInfoEntity r : records) {
String key = String.format("%s%s%s", r.getBrand(), r.getType(), r.getSkill());
map.put(key, r.getTakeTime());
}
return map;
}
private HashMap<String, SkillInfoEntity> querySkillInfo() {
HashMap<String, SkillInfoEntity> map = new HashMap<>();
List<SkillInfoEntity> records = skillInfoDao.findAll();
for (SkillInfoEntity r : records) {
String key = String.format("%s%s%s", r.getBrand(), r.getType(), r.getSkill());
map.put(key, r);
}
return map;
}
private HashMap<String, CapacityEngineerStatEntity> queryCapacityEngineerStat(List<String> engineerCodes, String date) {
List<CapacityEngineerStatEntity> records = capacityEngineerStatDao.getByWorkdayAndEngineerCodeIn(date, engineerCodes);
HashMap<String, CapacityEngineerStatEntity> map = new HashMap<>();
for (CapacityEngineerStatEntity r : records) {
map.put(r.getEngineerCode(), r);
}
return map;
}
private String parseTimeSlot(LocalDateTime t) {
String h = TimeUtils.localDateTime2String(t, "HH");
Integer hour = Integer.parseInt(h);
if (hour <= 12) {
return "上午";
} else if (hour <= 18) {
return "下午";
} else {
return "晚上";
}
}
@Autowired
private OrderInfoDao orderInfoDao;
@Autowired
private OrgTeamDao orgTeamDao;
@Autowired
private EngineerInfoDao engineerInfoDao;
@Autowired
private SkillInfoDao skillInfoDao;
@Autowired
private CapacityEngineerStatDao capacityEngineerStatDao;
@Autowired
private EntityManager entityManager;
@Autowired
private OrgGroupDao orgGroupDao;
@Transactional
@Override
public Result<?> getDispatchOrderList(DispatchOrderListReq reqDTO) {
// 获取派工台订单列表
// 获取技能信息
HashMap<String, SkillInfoEntity> skillInfo = this.querySkillInfo();
// 获取工单列表
List<OrderInfoEntity> orders = this.queryOrders(reqDTO);
// 获取分组标签
GroupTag gt = new GroupTagFactory().getGroupTag(reqDTO.getGroupTagId());
List<DispatchOrderListResp.Order> items = new ArrayList<>();
for (OrderInfoEntity o : orders) {
DispatchOrderListResp.Order item = new DispatchOrderListResp.Order();
item.setOrderId(o.getOrderId());
item.setDescription(String.format("%s:%s-%s-%s\n%s:%s-%s-%s", o.getOrderId(), o.getBrand(), o.getType(),
o.getSkill(), o.getName(), o.getCity(), o.getCounty(), o.getAddress()));
item.setBrand(o.getBrand());
item.setType(o.getType());
item.setSkill(o.getSkill());
item.setFaultDescribe(o.getFaultDescribe());
item.setApplyNote(o.getApplyNote());
String key = String.format("%s%s%s", o.getBrand(), o.getType(), o.getSkill());
SkillInfoEntity skill = skillInfo.get(key);
if (skill != null) {
item.setDuration(skill.getTakeTime());
item.setSkillCategory(skill.getSkillCategory());
item.setTypeCategory(skill.getTypeCategory());
}
item.setName(o.getName());
item.setPhone(o.getPhone());
item.setCity(o.getCity());
item.setAddress(o.getAddress());
item.setProvince(o.getProvince());
item.setCity(o.getCity());
item.setCounty(o.getCounty());
item.setAddress(o.getAddress());
item.setName(o.getName());
item.setPhone(o.getPhone());
item.setExpectTimeDesc(o.getExpectTimeDesc());
item.setSource(o.getSource());
item.setDispatcher(o.getDispatcher());
item.setAppointmentType(o.getAppointmentMethod());
item.setAppointmentStatus(o.getAppointmentStatus());
item.setOrderStatus(o.getOrderStatus());
item.setServiceStatus(o.getServiceStatus());
item.setCreateTime(TimeUtils.IsoLocalDateTime2String(o.getCreateTime()));
String[] tags = gt.getGroupTag(o).split("#");
item.setGroupTag(tags[0]); // 设置tag名称
item.setGroupWeight(Integer.parseInt(tags[1])); // 设置tag权重
items.add(item);
}
DispatchOrderListResp res = new DispatchOrderListResp();
res.setOrders(items);
return Result.success(res);
}
@Transactional
@Override
public Result<?> getDispatchEngineerOrderList(DispatchEngineerOrderListReq reqDTO) throws BusinessException {
// 派工台技术员预约单列表
LocalDate date = TimeUtils.IsoDate2LocalDate(reqDTO.getDate());
// 获取技能信息
HashMap<String, SkillInfoEntity> skillInfo = this.querySkillInfo();
// 获取teamIds
List<String> teamIds = this.queryOrgTeamIds(reqDTO.getLevelType(), reqDTO.getLevelValue(), reqDTO.getBranchIds(),
reqDTO.getGroupIds(), reqDTO.getTeamIds());
if (teamIds.isEmpty()) {
throw new BusinessException("大区/分部/小组组织结构配置可能错误或缺失,请联系管理员/研发");
}
// 获取engineer列表
List<EngineerInfoEntity> engineers = this.queryEngineers(teamIds, reqDTO.getEngineerCodes(), reqDTO.getKey());
if (engineers.isEmpty()) {
// 该group下没有技术员,返回空
log.warn("没有找到技术员");
DispatchEngineerOrderListResp res = new DispatchEngineerOrderListResp();
List<DispatchEngineerOrderListResp.EngineerInfo> egs = new ArrayList<>();
res.setEngineers(egs);
return Result.success(res);
}
// 获取engineerCodes
List<String> engineerCodes = engineers.stream().map(EngineerInfoEntity::getEngineerCode).collect(Collectors.toList());
// 获取技术员已指派单列表
Map<String, List<OrderInfoEntity>> engineerOrders = this.queryEngineerOrders(engineerCodes, date);
// 获取技术员的容量
HashMap<String, CapacityEngineerStatEntity> engineerCap = this.queryCapacityEngineerStat(engineerCodes, reqDTO.getDate());
// 获取技术员已指派单列表
List<DispatchEngineerOrderListResp.EngineerInfo> egs = new ArrayList<>();
for (EngineerInfoEntity e : engineers) {
List<DispatchEngineerOrderListResp.OrderInfo> items = new ArrayList<>();
// 技术员已指派的订单列表
List<OrderInfoEntity> records = engineerOrders.getOrDefault(e.getEngineerCode(), new ArrayList<>());
for (OrderInfoEntity o : records) {
addOrderToItems(o, items, skillInfo, true);
}
// 获取容量
int capUsed = 0;
int capTotal = 0;
String capacityStatus = "less";
CapacityEngineerStatEntity cap = engineerCap.get(e.getEngineerCode());
if (cap != null) {
capUsed = cap.getCapUsed();
capTotal = cap.getCapTotal();
if (capTotal > 0 && (float) capUsed / capTotal < 0.8) {
capacityStatus = "normal";
}
}
DispatchEngineerOrderListResp.EngineerInfo eg = new DispatchEngineerOrderListResp.EngineerInfo();
eg.setOrders(items);
eg.setEngineerCode(e.getEngineerCode());
eg.setEngineerName(e.getName());
eg.setGrade(e.getGrade());
eg.setCapacity(String.format("%d/%d", capUsed, capTotal));
eg.setCapacityStatus(capacityStatus);
egs.add(eg);
}
DispatchEngineerOrderListResp res = new DispatchEngineerOrderListResp();
res.setEngineers(egs);
return Result.success(res);
}
private void addOrderToItems(OrderInfoEntity o, List<DispatchEngineerOrderListResp.OrderInfo> items, HashMap<String, SkillInfoEntity> skillInfo, boolean isContinue) {
DispatchEngineerOrderListResp.OrderInfo item = new DispatchEngineerOrderListResp.OrderInfo();
item.setOrderId(o.getOrderId());
item.setDescription(String.format("%s:%s-%s-%s\n%s:%s-%s-%s", o.getOrderId(), o.getBrand(), o.getType(),
o.getSkill(), o.getName(), o.getCity(), o.getCounty(), o.getAddress()));
item.setBrand(o.getBrand());
item.setType(o.getType());
item.setSkill(o.getSkill());
item.setFaultDescribe(o.getFaultDescribe());
item.setApplyNote(o.getApplyNote());
String key = String.format("%s%s%s", o.getBrand(), o.getType(), o.getSkill());
SkillInfoEntity skill = skillInfo.get(key);
if (skill != null) {
item.setDuration(skill.getTakeTime());
item.setSkillCategory(skill.getSkillCategory());
item.setTypeCategory(skill.getTypeCategory());
}
item.setName(o.getName());
item.setPhone(o.getPhone());
item.setCity(o.getCity());
item.setAddress(o.getAddress());
item.setProvince(o.getProvince());
item.setCity(o.getCity());
item.setCounty(o.getCounty());
item.setAddress(o.getAddress());
item.setName(o.getName());
item.setPhone(o.getPhone());
String time = TimeUtils.localDateTime2String(o.getPlanStartTime(), "HH:mm");
String timeSlot = this.parseTimeSlot(o.getPlanStartTime());
item.setExpectTimeDesc(String.format("%s/%s", time, timeSlot));
item.setSource(o.getSource());
item.setDispatcher(o.getDispatcher());
item.setAppointmentType(o.getAppointmentMethod());
item.setAppointmentStatus(o.getAppointmentStatus());
item.setOrderStatus(o.getOrderStatus()); // 订单状态
item.setServiceStatus(o.getServiceStatus());
item.setOrderStatusDesc(OrderStatus.valueOf(o.getOrderStatus()).getDescription());
item.setCreateTime(TimeUtils.IsoLocalDateTime2String(o.getCreateTime()));
item.setMultipleOrders(o.getMultipleOrders());
item.setIsMultiple(o.getIsMultiple());
item.setIsAppointEngineer(o.getIsAppointEngineer());
item.setAppointEngineerCodes(o.getAppointEngineerCodes());
item.setTranscend(o.getTranscend());
item.setBeanPriority(o.getBeanPriority());
item.setIsSpecialTime(o.getIsSpecialTime());
if (isContinue && StringUtils.isNotEmpty(o.getMultipleOrders())) {
List<OrderInfoEntity> byMultipleOrders = orderInfoDao.findByMultipleOrders(o.getMultipleOrders());
List<DispatchEngineerOrderListResp.OrderInfo> multipleItems = new ArrayList<>();
for (OrderInfoEntity info : byMultipleOrders) {
addOrderToItems(info, multipleItems, skillInfo, false);
}
item.setMultipleOrderList(multipleItems);
}
items.add(item);
}
@Transactional
@Override
public Result<?> dispatchOrderConfirm(String engineerCode, String date, List<String> orderIds) throws BusinessException {
// 派工台确认派单
LocalDate localDate = TimeUtils.IsoDate2LocalDate(date);
EngineerInfoEntity engineer = engineerInfoDao.getByEngineerCode(engineerCode);
if (engineer == null) {
throw new BusinessException("技术员不存在");
}
List<OrderInfoEntity> orders = orderInfoDao.findAllByDtAndOrderIdIn(localDate, orderIds);
if (ListUtils.isEmpty(orders)) {
throw new BusinessException("订单不存在");
}
// 已经指派的订单
List<OrderInfoEntity> engineerOrders = orderInfoDao.findByDtAndEngineerCode(localDate, engineerCode);
engineerOrders.sort(Comparator.comparing(OrderInfoEntity::getPlanStartTime)); // 按照planStartTime排序
List<OrderInfoEntity> orderAppointments = engineerOrders.stream()
.filter(o -> o.getOrderStatus().equals("NORMAL"))
.collect(Collectors.toList()); // 过滤,只有NORMAL订单才需要处理,取消订单不需要处理
// TODO,临时处理方案,后续调用派单引擎处理
OrderRequestScheduler scheduler = new OrderRequestScheduler();
List<LineSegment> results = scheduler.scheduler(orders, orderAppointments);
for (LineSegment r : results) {
String orderId = r.id;
LocalDateTime planStartTime = scheduler.linePoint2DateTime(r.start, date);
LocalDateTime planEndTime = scheduler.linePoint2DateTime(r.end, date);
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaUpdate<OrderInfoEntity> update = criteriaBuilder.createCriteriaUpdate(OrderInfoEntity.class);
Root<OrderInfoEntity> root = update.from(OrderInfoEntity.class);
update.set(root.get("planStartTime"), planStartTime);
update.set(root.get("planEndTime"), planEndTime);
update.set(root.get("appointmentStatus"), "CONFIRM");
update.set(root.get("appointmentMethod"), "MANUAL");
update.set(root.get("engineerCode"), engineerCode);
update.where(
criteriaBuilder.equal(root.get("orderId"), orderId),
criteriaBuilder.equal(root.get("dt"), localDate)
);
entityManager.createQuery(update).executeUpdate();
}
return Result.success(null);
}
@Override
public Result<?> getDispatchOrderGroup(DispatchOrderListReq reqDTO) {
// 获取技能信息
HashMap<String, SkillInfoEntity> skillInfo = this.querySkillInfo();
// 获取工单列表
List<OrderInfoEntity> orders = this.queryOrders(reqDTO);
if (CollectionUtils.isEmpty(orders)) {
return Result.success();
}
List<String> groupIds = orders.stream().map(OrderInfoEntity::getOrgGroupId).distinct().collect(Collectors.toList());
List<OrgGroupEntity> byGroupIdIn = orgGroupDao.findByGroupIdIn(groupIds);
Map<String, String> groupMap = byGroupIdIn.stream().collect(Collectors.toMap(OrgGroupEntity::getGroupId, OrgGroupEntity::getGroupName));
List<DispatchOrderListResp.Order> items = new ArrayList<>();
Map<Object, List<DispatchOrderListResp.Order>> groupByMap = new HashMap<>();
for (OrderInfoEntity o : orders) {
items.add(orderItemByOrderInfo(o, skillInfo, true, groupMap, groupByMap, reqDTO.getGroupTagId()));
}
return Result.success(groupByMap);
}
/**
* 组装订单数据,并封装进map
*
* @param o
* @param skillInfo
* @param isContinue
* @param groupMap
* @param groupByMap
* @param groupTagId
* @return
*/
private DispatchOrderListResp.Order orderItemByOrderInfo(OrderInfoEntity o, HashMap<String, SkillInfoEntity> skillInfo,
boolean isContinue, Map<String, String> groupMap, Map<Object, List<DispatchOrderListResp.Order>> groupByMap, String groupTagId) {
DispatchOrderListResp.Order item = new DispatchOrderListResp.Order();
item.setOrderId(o.getOrderId());
item.setDescription(String.format("%s:%s-%s-%s\n%s:%s-%s-%s", o.getOrderId(), o.getBrand(), o.getType(),
o.getSkill(), o.getName(), o.getCity(), o.getCounty(), o.getAddress()));
item.setBrand(o.getBrand());
item.setType(o.getType());
item.setSkill(o.getSkill());
item.setFaultDescribe(o.getFaultDescribe());
item.setApplyNote(o.getApplyNote());
String key = String.format("%s%s%s", o.getBrand(), o.getType(), o.getSkill());
SkillInfoEntity skill = skillInfo.get(key);
if (skill != null) {
item.setDuration(skill.getTakeTime());
item.setSkillCategory(skill.getSkillCategory());
item.setTypeCategory(skill.getTypeCategory());
}
item.setName(o.getName());
item.setPhone(o.getPhone());
item.setCity(o.getCity());
item.setAddress(o.getAddress());
item.setProvince(o.getProvince());
item.setCity(o.getCity());
item.setCounty(o.getCounty());
item.setAddress(o.getAddress());
item.setName(o.getName());
item.setPhone(o.getPhone());
item.setExpectTimeDesc(o.getExpectTimeDesc());
item.setSource(o.getSource());
item.setDispatcher(o.getDispatcher());
item.setAppointmentType(o.getAppointmentMethod());
item.setAppointmentStatus(o.getAppointmentStatus());
item.setOrderStatus(o.getOrderStatus());
item.setServiceStatus(o.getServiceStatus());
item.setCreateTime(TimeUtils.IsoLocalDateTime2String(o.getCreateTime()));
item.setMultipleOrders(o.getMultipleOrders());
item.setIsMultiple(o.getIsMultiple());
item.setIsAppointEngineer(o.getIsAppointEngineer());
item.setAppointEngineerCodes(o.getAppointEngineerCodes());
item.setTranscend(o.getTranscend());
item.setBeanPriority(o.getBeanPriority());
item.setOrgGroupId(o.getOrgGroupId());
item.setIsSpecialTime(o.getIsSpecialTime());
item.setOrgGroupName(groupMap.get(o.getOrgGroupId()));
if (isContinue && StringUtils.isNotEmpty(o.getMultipleOrders())) {
List<OrderInfoEntity> byMultipleOrders = orderInfoDao.findByMultipleOrders(o.getMultipleOrders());
List<DispatchOrderListResp.Order> multipleItems = new ArrayList<>();
for (OrderInfoEntity info : byMultipleOrders) {
multipleItems.add(orderItemByOrderInfo(info, skillInfo, false, groupMap, groupByMap, groupTagId));
}
item.setMultipleOrderList(multipleItems);
}
if (groupTagId.equals(OrderGroupEnum.zero.getCode()) && StringUtils.isNotEmpty(item.getBeanPriority())) {
makeOrderMap(groupByMap, item, item.getBeanPriority());
} else if (groupTagId.equals(OrderGroupEnum.one.getCode()) && null != item.getDuration()) {
makeOrderMap(groupByMap, item, item.getDuration());
} else if (groupTagId.equals(OrderGroupEnum.two.getCode()) && StringUtils.isNotEmpty(item.getExpectTimeDesc())) {
makeOrderMap(groupByMap, item, item.getExpectTimeDesc());
} else if (groupTagId.equals(OrderGroupEnum.three.getCode()) && StringUtils.isNotEmpty(item.getOrgGroupName())) {
makeOrderMap(groupByMap, item, item.getOrgGroupName());
} else if (groupTagId.equals(OrderGroupEnum.four.getCode()) && StringUtils.isNotEmpty(item.getSkill())) {
makeOrderMap(groupByMap, item, item.getSkill());
} else if (groupTagId.equals(OrderGroupEnum.five.getCode()) && StringUtils.isNotEmpty(item.getMultipleOrders())) {
makeOrderMap(groupByMap, item, item.getMultipleOrders());
} else {
makeOrderMap(groupByMap, item, "默认分类");
}
return item;
}
/**
* 组装data数据到map
*
* @param groupByMap
* @param item
* @param groupkey
*/
private void makeOrderMap(Map<Object, List<DispatchOrderListResp.Order>> groupByMap, DispatchOrderListResp.Order item, Object groupkey) {
List<DispatchOrderListResp.Order> groupByList;
if (groupByMap.containsKey(groupkey)) {
groupByList = groupByMap.get(groupkey);
} else {
groupByList = new ArrayList<>();
}
groupByList.add(item);
groupByMap.put(groupkey, groupByList);
}
private List<OrderInfoEntity> queryOrders(DispatchOrderListReq reqDTO) {
// 获取服务单列表
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<OrderInfoEntity> criteriaQuery = criteriaBuilder.createQuery(OrderInfoEntity.class);
Root<OrderInfoEntity> root = criteriaQuery.from(OrderInfoEntity.class);
List<Predicate> predicates = new ArrayList<>();
predicates.add(criteriaBuilder.equal(root.get("dt"), TimeUtils.IsoDate2LocalDate(reqDTO.getDate())));
predicates.add(criteriaBuilder.equal(root.get("appointmentStatus"), "INIT"));
String levelType = reqDTO.getLevelType();
String levelValue = reqDTO.getLevelValue();
if ("cluster".equals(levelType)) {
predicates.add(criteriaBuilder.equal(root.get("orgClusterId"), levelValue));
} else if ("branch".equals(levelType)) {
predicates.add(criteriaBuilder.equal(root.get("orgBranchId"), levelValue));
} else if ("group".equals(levelType)) {
predicates.add(criteriaBuilder.equal(root.get("orgGroupId"), levelValue));
}
// 筛选项
if (StringUtils.isNotEmpty(reqDTO.getPhone())) {
predicates.add(criteriaBuilder.equal(root.get("phone"), reqDTO.getPhone()));
}
if (StringUtils.isNotEmpty(reqDTO.getOrderId())) {
predicates.add(criteriaBuilder.equal(root.get("orderId"), reqDTO.getOrderId()));
}
if (ListUtils.isNotEmpty(reqDTO.getBranchIds())) {
predicates.add(root.get("orgBranchId").in(reqDTO.getBranchIds()));
}
if (ListUtils.isNotEmpty(reqDTO.getGroupIds())) {
predicates.add(root.get("orgGroupId").in(reqDTO.getGroupIds()));
}
if (ListUtils.isNotEmpty(reqDTO.getTeamIds())) {
predicates.add(root.get("orgTeamId").in(reqDTO.getTeamIds()));
}
if (ListUtils.isNotEmpty(reqDTO.getAppointmentType())) {
predicates.add(root.get("appointmentMethod").in(reqDTO.getAppointmentType()));
}
if (ListUtils.isNotEmpty(reqDTO.getPriorities())) {
List<Integer> p = reqDTO.getPriorities();
if (p.contains(0) && p.contains(1)) {
predicates.add(criteriaBuilder.ge(root.get("priority"), 1));
} else if (p.contains(0) && !p.contains(1)) {
predicates.add(criteriaBuilder.le(root.get("priority"), 1));
} else if (p.contains(1) && !p.contains(0)) {
predicates.add(criteriaBuilder.ge(root.get("priority"), 5));
}
}
if (ListUtils.isNotEmpty(reqDTO.getEngineerCodes())) {
Predicate engineerCodePredicate = root.get("engineerCode").in(reqDTO.getEngineerCodes());
Predicate engineerCodeSubPredicate = root.get("engineerCodeSub").in(reqDTO.getEngineerCodes());
predicates.add(criteriaBuilder.or(engineerCodePredicate, engineerCodeSubPredicate));
}
if (ListUtils.isNotEmpty(reqDTO.getTypeCategory())) {
Subquery<OrderInfoEntity> typeCategorySubquery = criteriaQuery.subquery(OrderInfoEntity.class);
Root<SkillInfoEntity> skillInfoRoot = typeCategorySubquery.from(SkillInfoEntity.class);
typeCategorySubquery.select(root)
.where(
criteriaBuilder.equal(skillInfoRoot.get("brand"), root.get("brand")),
criteriaBuilder.equal(skillInfoRoot.get("type"), root.get("type")),
criteriaBuilder.equal(skillInfoRoot.get("skill"), root.get("skill")),
skillInfoRoot.get("typeCategory").in(reqDTO.getTypeCategory())
);
predicates.add(criteriaBuilder.exists(typeCategorySubquery));
}
if (ListUtils.isNotEmpty(reqDTO.getSkillCategory())) {
Subquery<OrderInfoEntity> skillCategorySubquery = criteriaQuery.subquery(OrderInfoEntity.class);
Root<SkillInfoEntity> skillInfoRoot = skillCategorySubquery.from(SkillInfoEntity.class);
skillCategorySubquery.select(root) // 注意这里的 select 使用主查询的 root
.where(
criteriaBuilder.equal(skillInfoRoot.get("brand"), root.get("brand")),
criteriaBuilder.equal(skillInfoRoot.get("type"), root.get("type")),
criteriaBuilder.equal(skillInfoRoot.get("skill"), root.get("skill")),
skillInfoRoot.get("skillCategory").in(reqDTO.getSkillCategory())
);
predicates.add(criteriaBuilder.exists(skillCategorySubquery));
}
if (ListUtils.isNotEmpty(reqDTO.getGroupCategory())) {
Subquery<OrderInfoEntity> skillGroupCategorySubquery = criteriaQuery.subquery(OrderInfoEntity.class);
Root<SkillInfoEntity> skillInfoRoot = skillGroupCategorySubquery.from(SkillInfoEntity.class);
skillGroupCategorySubquery.select(root) // 注意这里的 select 使用主查询的 root
.where(
criteriaBuilder.equal(skillInfoRoot.get("brand"), root.get("brand")),
criteriaBuilder.equal(skillInfoRoot.get("type"), root.get("type")),
criteriaBuilder.equal(skillInfoRoot.get("skill"), root.get("skill")),
skillInfoRoot.get("groupCategory").in(reqDTO.getGroupCategory())
);
predicates.add(criteriaBuilder.exists(skillGroupCategorySubquery));
}
criteriaQuery.where(predicates.toArray(new Predicate[0]));
return entityManager.createQuery(criteriaQuery).getResultList();
}
private Map<String, List<OrderInfoEntity>> queryEngineerOrders(List<String> engineerCodes, LocalDate date) {
// 获取工程师服务单列表
List<OrderInfoEntity> records = orderInfoDao.findByDtAndEngineerCodeIn(date, engineerCodes);
// 排序
records.sort(Comparator.comparing(OrderInfoEntity::getEngineerCode));
records.sort(Comparator.comparing(OrderInfoEntity::getPlanStartTime));
//过滤
List<OrderInfoEntity> orders = records.stream()
.filter(r -> r.getOrderStatus().equals("NORMAL"))
.collect(Collectors.toList());
return orders.stream().collect(Collectors.groupingBy(OrderInfoEntity::getEngineerCode));
}
public List<EngineerInfoEntity> queryEngineers(List<String> teamIds, List<String> engineerCodes, String key) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<EngineerInfoEntity> criteriaQuery = criteriaBuilder.createQuery(EngineerInfoEntity.class);
Root<EngineerInfoEntity> root = criteriaQuery.from(EngineerInfoEntity.class);
List<Predicate> predicates = new ArrayList<>();
predicates.add(criteriaBuilder.equal(root.get("beanStatus"), 1));
if (ListUtils.isNotEmpty(engineerCodes)) {
predicates.add(root.get("engineerCode").in(engineerCodes));
}
Subquery<Integer> teamSubquery = criteriaQuery.subquery(Integer.class);
Root<OrgTeamEngineerEntity> teamRoot = teamSubquery.from(OrgTeamEngineerEntity.class);
teamSubquery.select(criteriaBuilder.literal(1))
.where(
criteriaBuilder.equal(teamRoot.get("engineerCode"), root.get("engineerCode")),
teamRoot.get("teamId").in(teamIds)
);
predicates.add(criteriaBuilder.exists(teamSubquery));
if (StringUtils.isNotEmpty(key)) {
predicates.add(criteriaBuilder.or(
criteriaBuilder.like(root.get("phone"), "%" + key + "%"),
criteriaBuilder.like(root.get("name"), "%" + key + "%"),
criteriaBuilder.like(root.get("engineerCode"), "%" + key + "%")
));
}
criteriaQuery.where(predicates.toArray(new Predicate[0]));
criteriaQuery.orderBy(criteriaBuilder.asc(root.get("name")));
return entityManager.createQuery(criteriaQuery).getResultList();
}
private List<String> queryOrgTeamIds(String levelType, String levelIds, List<String> branchIds, List<String> groupIds, List<String> teamIds) {
Specification<OrgTeamEntity> specification = (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
if ("cluster".equals(levelType)) {
predicates.add(criteriaBuilder.in(root.get("clusterId")).value(levelIds));
} else if ("branch".equals(levelType)) {
predicates.add(criteriaBuilder.in(root.get("branchId")).value(levelIds));
} else if ("group".equals(levelType)) {
predicates.add(criteriaBuilder.in(root.get("groupId")).value(levelIds));
}
if (ListUtils.isNotEmpty(branchIds)) {
predicates.add(root.get("branchId").in(branchIds));
}
if (ListUtils.isNotEmpty(groupIds)) {
predicates.add(root.get("groupId").in(groupIds));
}
if (ListUtils.isNotEmpty(teamIds)) {
predicates.add(root.get("teamId").in(teamIds));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
};
List<OrgTeamEntity> teams = orgTeamDao.findAll(specification);
return teams.stream().map(OrgTeamEntity::getTeamId).collect(Collectors.toList());
}
private HashMap<String, Integer> querySkillTakeTime() {
HashMap<String, Integer> map = new HashMap<>();
List<SkillInfoEntity> records = skillInfoDao.findAll();
for (SkillInfoEntity r : records) {
String key = String.format("%s%s%s", r.getBrand(), r.getType(), r.getSkill());
map.put(key, r.getTakeTime());
}
return map;
}
private HashMap<String, SkillInfoEntity> querySkillInfo() {
HashMap<String, SkillInfoEntity> map = new HashMap<>();
List<SkillInfoEntity> records = skillInfoDao.findAll();
for (SkillInfoEntity r : records) {
String key = String.format("%s%s%s", r.getBrand(), r.getType(), r.getSkill());
map.put(key, r);
}
return map;
}
private HashMap<String, CapacityEngineerStatEntity> queryCapacityEngineerStat(List<String> engineerCodes, String date) {
List<CapacityEngineerStatEntity> records = capacityEngineerStatDao.getByWorkdayAndEngineerCodeIn(date, engineerCodes);
HashMap<String, CapacityEngineerStatEntity> map = new HashMap<>();
for (CapacityEngineerStatEntity r : records) {
map.put(r.getEngineerCode(), r);
}
return map;
}
private String parseTimeSlot(LocalDateTime t) {
String h = TimeUtils.localDateTime2String(t, "HH");
Integer hour = Integer.parseInt(h);
if (hour <= 12) {
return "上午";
} else if (hour <= 18) {
return "下午";
} else {
return "晚上";
}
}
}
class GroupTagFactory {
public GroupTag getGroupTag(String groupTagId) {
if (groupTagId.equals("0")) {
return new GroupTagUrgency();
} else {
return new GroupTagOmit();
}
}
public GroupTag getGroupTag(String groupTagId) {
if (groupTagId.equals("0")) {
return new GroupTagUrgency();
} else {
return new GroupTagOmit();
}
}
}
class GroupTagUrgency implements GroupTag {
// 根据紧急程度来分组
public String getGroupTag(OrderInfoEntity order) {
String s = order.getTags();
if (s == null) {
return "正常#1";
}
if (s.contains("VIP") || s.contains("财产损失")) {
return "超急#10";
} else if (s.contains("自保点") || s.contains("紧急")) {
return "紧急#8";
} else if (s.contains("3天前单") || s.contains("同地址多单") || s.contains("超重需多人")) {
return "一般#5";
} else {
return "正常#1";
}
}
// 根据紧急程度来分组
public String getGroupTag(OrderInfoEntity order) {
String s = order.getTags();
if (s == null) {
return "正常#1";
}
if (s.contains("VIP") || s.contains("财产损失")) {
return "超急#10";
} else if (s.contains("自保点") || s.contains("紧急")) {
return "紧急#8";
} else if (s.contains("3天前单") || s.contains("同地址多单") || s.contains("超重需多人")) {
return "一般#5";
} else {
return "正常#1";
}
}
}
class GroupTagOmit implements GroupTag {
public String getGroupTag(OrderInfoEntity order) {
return "默认分类#5";
}
public String getGroupTag(OrderInfoEntity order) {
return "默认分类#5";
}
}
class LineSegment {
public String id;
public int start;
public int end;
public String id;
public int start;
public int end;
public LineSegment(String id, int start, int end) {
this.id = id;
this.start = start;
this.end = end;
}
public LineSegment(String id, int start, int end) {
this.id = id;
this.start = start;
this.end = end;
}
}
class Line {
public String id;
public int length;
public String id;
public int length;
public Line(String id, int length) {
this.id = id;
this.length = length;
}
public Line(String id, int length) {
this.id = id;
this.length = length;
}
}
class LineSegmentScheduler {
public List<LineSegment> scheduleLineSegments(List<LineSegment> used, List<Line> newTasks) {
used.sort(Comparator.comparingInt(a -> a.start));
List<LineSegment> result = new ArrayList<>();
for (Line task : newTasks) {
String taskId = task.id;
int taskLength = task.length;
boolean scheduled = false;
int startRange = 480;
int endRange = 1440;
if (!scheduled) {
for (int i = 0; i <= used.size(); i++) {
int start;
if (i == 0) {
start = startRange;
} else {
start = used.get(i - 1).end;
}
int end;
if (i == used.size() || used.get(i).start > endRange) {
end = endRange;
} else {
end = used.get(i).start;
}
if (end - start >= taskLength) {
int taskStart = start;
int taskEnd = start + taskLength;
LineSegment s = new LineSegment(taskId, taskStart, taskEnd);
result.add(s);
used.add(i, s);
break;
}
}
}
}
return result;
}
public List<LineSegment> scheduleLineSegments(List<LineSegment> used, List<Line> newTasks) {
used.sort(Comparator.comparingInt(a -> a.start));
List<LineSegment> result = new ArrayList<>();
for (Line task : newTasks) {
String taskId = task.id;
int taskLength = task.length;
boolean scheduled = false;
int startRange = 480;
int endRange = 1440;
if (!scheduled) {
for (int i = 0; i <= used.size(); i++) {
int start;
if (i == 0) {
start = startRange;
} else {
start = used.get(i - 1).end;
}
int end;
if (i == used.size() || used.get(i).start > endRange) {
end = endRange;
} else {
end = used.get(i).start;
}
if (end - start >= taskLength) {
int taskStart = start;
int taskEnd = start + taskLength;
LineSegment s = new LineSegment(taskId, taskStart, taskEnd);
result.add(s);
used.add(i, s);
break;
}
}
}
}
return result;
}
}
class OrderRequestScheduler {
public List<LineSegment> scheduler(List<OrderInfoEntity> orderRequests, List<OrderInfoEntity> orderAppointments) {
List<LineSegment> used = new ArrayList<>();
for (OrderInfoEntity o : orderAppointments) {
LineSegment s = new LineSegment(o.getOrderId(),
this.localTime2LinePoint(o.getPlanStartTime()),
this.localTime2LinePoint(o.getPlanEndTime()));
used.add(s);
}
List<Line> newTasks = new ArrayList<>();
for (OrderInfoEntity o : orderRequests) {
if (!o.getAppointmentStatus().equals("INIT")) {
continue;
}
Line t = new Line(o.getOrderId(), 30);
newTasks.add(t);
}
if (newTasks.isEmpty()) {
List<LineSegment> empty = new ArrayList<>();
return empty;
}
LineSegmentScheduler scheduler = new LineSegmentScheduler();
return scheduler.scheduleLineSegments(used, newTasks);
}
public int localTime2LinePoint(LocalDateTime datetime) {
return datetime.getHour() * 60 + datetime.getMinute();
}
public LocalDateTime linePoint2DateTime(int x, String date) {
int base = 60;
int hour = x / base;
int minute = x % base;
String datetime = String.format("%s %02d:%02d:00", date, hour, minute);
return TimeUtils.IsoDateTime2LocalDateTime(datetime);
}
public List<LineSegment> scheduler(List<OrderInfoEntity> orderRequests, List<OrderInfoEntity> orderAppointments) {
List<LineSegment> used = new ArrayList<>();
for (OrderInfoEntity o : orderAppointments) {
LineSegment s = new LineSegment(o.getOrderId(),
this.localTime2LinePoint(o.getPlanStartTime()),
this.localTime2LinePoint(o.getPlanEndTime()));
used.add(s);
}
List<Line> newTasks = new ArrayList<>();
for (OrderInfoEntity o : orderRequests) {
if (!o.getAppointmentStatus().equals("INIT")) {
continue;
}
Line t = new Line(o.getOrderId(), 30);
newTasks.add(t);
}
if (newTasks.isEmpty()) {
List<LineSegment> empty = new ArrayList<>();
return empty;
}
LineSegmentScheduler scheduler = new LineSegmentScheduler();
return scheduler.scheduleLineSegments(used, newTasks);
}
public int localTime2LinePoint(LocalDateTime datetime) {
return datetime.getHour() * 60 + datetime.getMinute();
}
public LocalDateTime linePoint2DateTime(int x, String date) {
int base = 60;
int hour = x / base;
int minute = x % base;
String datetime = String.format("%s %02d:%02d:00", date, hour, minute);
return TimeUtils.IsoDateTime2LocalDateTime(datetime);
}
}
package com.dituhui.pea.order.service.impl;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.dao.OrderInfoDao;
import com.dituhui.pea.order.entity.OrderInfoEntity;
import com.dituhui.pea.order.service.OrderInfoService;
import com.dituhui.pea.util.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Slf4j
public class OrderInfoServiceImpl implements OrderInfoService {
@Autowired
private OrderInfoDao orderInfoDao;
/**
* 新增订单处理一家多单逻辑
*
* @param dt 订单日期 列:2023-07-21
* @param addressId 地址id
* @return 有则返回多条订单关联id,没有则不是一家多单
*/
@Override
@Transactional
public Result<String> addMultipleOrders(String dt, String addressId) {
List<OrderInfoEntity> infoList = orderInfoDao.findByDtAndAddressId(dt, addressId);
if (CollectionUtils.isEmpty(infoList)) {
return Result.success(null);
}
List<String> multipleOrdersList = infoList.stream().filter(e -> StringUtils.isNotEmpty(e.getMultipleOrders())).map(OrderInfoEntity::getMultipleOrders).distinct().collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(multipleOrdersList)) {
return Result.success(multipleOrdersList.get(0));
}
String uuid = UUIDUtil.getUuid();
for (OrderInfoEntity orderInfoEntity : infoList) {
orderInfoEntity.setMultipleOrders(uuid);
orderInfoDao.save(orderInfoEntity);
}
return Result.success(uuid);
}
/**
* 取消指定订单一家多台
*
* @param multipleOrders 订单关联id
* @param orderId 订单id
* @return 有则返回多条订单关联id,没有则不是一家多单
*/
@Override
@Transactional
public Result deleteMultipleOrders(String multipleOrders, String orderId) {
List<OrderInfoEntity> infoList = orderInfoDao.findByMultipleOrders(multipleOrders);
for (OrderInfoEntity infoEntity : infoList) {
if (infoEntity.getOrderId().equals(orderId)) {
infoEntity.setMultipleOrders(null);
orderInfoDao.save(infoEntity);
}
if (infoList.size() == 2) {
infoEntity.setMultipleOrders(null);
orderInfoDao.save(infoEntity);
}
}
return Result.success();
}
}
......@@ -33,6 +33,9 @@ public class OrderServiceListServiceImpl implements OrderServiceListService {
@Autowired
private OrgBranchDao orgBranchDao;
@Autowired
private OrderInfoDao orderInfoDao;
@Transactional
@Override
public Result<OrderServiceListResp> getOrderServiceList(OrderServiceListReq reqDTO) throws BusinessException {
......@@ -124,12 +127,12 @@ public class OrderServiceListServiceImpl implements OrderServiceListService {
record.setDescription(o.getDescription());
record.setPriority(o.getPriority());
record.setOrgBranchName(branchNames.getOrDefault(o.getOrgBranchId(), ""));
// 获取工程师信息,为派工为空
if(StringUtils.isNotBlank(o.getEngineerCode())) {
List<String> names = this.getOrderEngineerNames(o.getEngineerCode(), o.getEngineerCodeSub(), engineerNames);
record.setEngineerNum(names.size()); //工程师数量
record.setEngineerNames(String.join("、", names)); //工程师姓名列表
if (StringUtils.isNotBlank(o.getEngineerCode())) {
List<String> names = this.getOrderEngineerNames(o.getEngineerCode(), o.getEngineerCodeSub(), engineerNames);
record.setEngineerNum(names.size()); //工程师数量
record.setEngineerNames(String.join("、", names)); //工程师姓名列表
}
record.setExpectTimeBegin(TimeUtils.IsoTimestamp2DateTime(o.getExpectTimeBegin()));
......@@ -146,7 +149,17 @@ public class OrderServiceListServiceImpl implements OrderServiceListService {
record.setIsMultiple(o.getIsMultiple());
record.setIsAppointEngineer(o.getIsAppointEngineer());
record.setAppointEngineerCodes(o.getAppointEngineerCodes());
record.setMultipleOrders(o.getMultipleOrders());
record.setTranscend(o.getTranscend());
record.setIsSpecialTime(o.getIsSpecialTime());
if (StringUtils.isNotEmpty(o.getMultipleOrders())) {
List<OrderInfoEntity> byMultipleOrders = orderInfoDao.findByMultipleOrders(o.getMultipleOrders());
List<OrderServiceList> multipleItems = new ArrayList<>();
for (OrderInfoEntity info : byMultipleOrders) {
multipleItems.add(toMultipleOrders(info, branchNames, engineerNames));
}
record.setMultipleOrderList(multipleItems);
}
content.add(record);
}
......@@ -161,6 +174,50 @@ public class OrderServiceListServiceImpl implements OrderServiceListService {
return Result.success(res);
}
private OrderServiceList toMultipleOrders(OrderInfoEntity o, Map<String, String> branchNames, Map<String, String> engineerNames) {
OrderServiceList record = new OrderServiceList();
record.setOrderId(o.getOrderId());
record.setType(o.getType());
record.setBrand(o.getBrand());
record.setSkill(o.getSkill());
record.setTakeTime(o.getTakeTime());
record.setFaultDescribe(o.getFaultDescribe());
record.setName(o.getName());
record.setPhone(o.getPhone());
record.setAddress(String.format("%s-%s-%s", o.getCity(), o.getCounty(), o.getAddress()));
record.setX(o.getX());
record.setY(o.getY());
record.setSource(o.getSource());
record.setDescription(o.getDescription());
record.setPriority(o.getPriority());
record.setOrgBranchName(branchNames.getOrDefault(o.getOrgBranchId(), ""));
// 获取工程师信息,为派工为空
if (StringUtils.isNotBlank(o.getEngineerCode())) {
List<String> names = this.getOrderEngineerNames(o.getEngineerCode(), o.getEngineerCodeSub(), engineerNames);
record.setEngineerNum(names.size()); //工程师数量
record.setEngineerNames(String.join("、", names)); //工程师姓名列表
}
record.setExpectTimeBegin(TimeUtils.IsoLocalDateTime2String(o.getExpectTimeBegin()));
record.setExpectTimeEnd(TimeUtils.IsoLocalDateTime2String(o.getExpectTimeEnd()));
record.setExpectTimeDesc(o.getExpectTimeDesc());
record.setAppointmentType(o.getAppointmentMethod());
record.setAppointmentStatus(o.getAppointmentStatus());
record.setOrderStatus(o.getOrderStatus());
record.setServiceStatus(o.getServiceStatus());
record.setDispatcher(o.getDispatcher());
record.setCreateTime(TimeUtils.IsoLocalDateTime2String(o.getCreateTime()));
record.setBeanPriority(o.getBeanPriority());
record.setIsMultiple(o.getIsMultiple());
record.setIsAppointEngineer(o.getIsAppointEngineer());
record.setAppointEngineerCodes(o.getAppointEngineerCodes());
record.setMultipleOrders(o.getMultipleOrders());
record.setTranscend(o.getTranscend());
return record;
}
private Map<String, String> getEngineerNames(List<OrderInfo> orders) {
// 获取技术员姓名
Set<String> engineerCodes = new HashSet<>();
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!