Commit 185fa736 by 刘鑫

Merge branch 'develop' of https://gitlab.dituhui.com/bsh/project/project into develop-16542

2 parents e5ccf54d 36263ee8
Showing with 534 additions and 75 deletions
......@@ -20,7 +20,6 @@ import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
......
......@@ -134,7 +134,7 @@ public enum StatusCodeEnum {
FENDAN_IS_TRANSCEND("024", "分单超派", false),
RESOURCE_USER_EXISTS_ROLE("025", "用绑定用户的角色不允许删除,需要解绑后才可以删除角色", false),
RESOURCE_USER_EXISTS_ROLE("025", "角色已绑定用户,请解绑用户后再删除角色!", false),
ORDER_EXISTS("026", "订单已存在", false);
......
......@@ -556,6 +556,22 @@ public class DateUtil {
return false;
}
/***
* @param localDateTime
* @return: boolean
* @Description: 根据LocalDateTime来判断是否是今天
*/
public boolean judgeTimeIsisTomorrow(LocalDateTime localDateTime) {
LocalDateTime startTime = LocalDate.now().plusDays(1).atTime(0, 0, 0);
LocalDateTime endTime = LocalDate.now().plusDays(1).atTime(23, 59, 59);
//如果大于今天的开始日期,小于今天的结束日期
if (localDateTime.isAfter(startTime) && localDateTime.isBefore(endTime)) {
return true;
}
return false;
}
/**
* 根据日期转换到指定时间
* 2023-10-30+2023-10-22 21:21:12 -> 2023-10-30 21:21:12
......
......@@ -45,7 +45,7 @@ public interface MsgDao extends JpaRepository<MsgEntity, Integer> {
@Query(value = "select t.* from (select tt.*,r.is_read," +
" (select group_concat(u.nickname) from zzz_msg_receiver rr join sys_user u on u.id=rr.user_id where rr.msg_id=tt.id) receivers"+
" from zzz_msg tt join zzz_msg_receiver r on r.msg_id=tt.id and r.user_id=:#{#req.userId}" +
" from zzz_msg tt join zzz_msg_receiver r on r.deleted=0 and r.msg_id=tt.id and r.user_id=:#{#req.userId}" +
" where IF(:#{#msgGroupResp.clusterId} is not null, tt.cluster_id=:#{#msgGroupResp.clusterId}, tt.cluster_id is null)" +
" and IF(:#{#msgGroupResp.branchId} is not null, tt.branch_id=:#{#msgGroupResp.branchId}, tt.branch_id is null)" +
" and IF(:#{#msgGroupResp.groupId} is not null, tt.group_id=:#{#msgGroupResp.groupId}, tt.group_id is null)" +
......
......@@ -86,10 +86,19 @@ public class DispatchOrderListResp {
*/
private String beanPriority;
/**
* 是否是特殊时间段,0否 1是 默认0
*/
private Integer isSpecialTime;
/**
* 是否是cutoff,0否 1是 默认0
*/
private Integer isCutoff;
/**
* bean标签
*/
private String beanTags;
}
}
......@@ -83,5 +83,10 @@ public class EngineersGanttDTO {
private String text;
private List<LabelValueDTO> tooltip;
private String url;
/**
* 服务状态:INIT-初始化/PENDING待服务/CONTACTED已排期/STARTED-已开始/FINISHED已完成/UNFINISHED-已上门未完成
*/
private String serviceStatus;
}
}
......@@ -22,12 +22,30 @@ public class ScheduleEngineerOverviewResp {
private String skill;
private String orderStatus;
private String orderStatusName;
/**
* 在途公里数
*/
private Integer distance;
/**
* 上门时间
*/
private String arriveTime;
private String timeType;
/**
* 在途时间段
*/
private String expectArriveDuration;
/**
* 实际到达时间
*/
private String arriveDuration;
/**
* 计划工时
*/
private String expectWorkDuration;
/**
* 工实际工时
*/
private String workDuration;
}
......
......@@ -124,13 +124,13 @@ public class OrderDTO {
/**
* 服务单标签列表
*/
@NotNull
// @NotNull
private List<String> orderTags;
/**
* 备注(周末安装/到小区打电话)
*/
@NotBlank
// @NotBlank
private String description;
/**
......
......@@ -42,6 +42,12 @@ public class MsgReceiverEntity {
@Column(name = "is_read")
private Integer isRead;
/**
* 是否删除,0:正常,1:删除
*/
@Column(name = "deleted")
private Integer deleted = 0;
@Column(name = "create_time", nullable = false, columnDefinition = "datetime default current_timestamp")
private Date createTime;
......
package com.dituhui.pea.order.entity;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.enums.ServiceStatusEnum;
import lombok.Data;
import javax.persistence.*;
......@@ -132,7 +132,7 @@ public class OrderInfoEntity {
private String orderStatus = "NORMAL";
@Column(name = "service_status", nullable = true, length = 20, columnDefinition = "varchar(20) default 'INIT'")
private String serviceStatus = OrderFlowEnum.INIT.name();
private String serviceStatus = ServiceStatusEnum.INIT.getCode();
@Column(name = "engineer_code", nullable = true, length = 32, columnDefinition = "varchar(32) default ''")
private String engineerCode = "";
......@@ -234,4 +234,10 @@ public class OrderInfoEntity {
*/
@Column(name = "reason_for_failure")
private String reasonForFailure;
/**
* 是否是cutoff,0否 1是 默认0
*/
@Column(name = "is_cutoff")
private Integer isCutoff = 0;
}
package com.dituhui.pea.order.enums;
public enum AppointmentMethodEnum {
// 指派方式(MANUAL人工/AUTO_NOW 自动立即/AUTO_BATCH/PROTECTION 自保点)
MANUAL, AUTO_NOW, AUTO_BATCH, PROTECTION
}
package com.dituhui.pea.order.enums;
public enum AppointmentStatus {
// 指派状态: INIT-待指派/PRE-预指派/CONFIRM-确认指派(通知BEAN)
INIT("待指派"),
PRE("预指派"),
CONFIRM("确认指派");
private final String description;
AppointmentStatus(String description){
this.description = description;
}
public String getDescription() {
return description;
}
public static String getEnumName(AppointmentStatus appointmentStatus){
return appointmentStatus.toString();
}
}
package com.dituhui.pea.order.enums;
import cn.hutool.core.util.ObjectUtil;
import java.util.Objects;
/**
* 交通工具:1汽车;2电动车;3自行车;4步行 默认是汽车
*
* @author RenPing
* @date 2023/10/24
*/
public enum VehicleEnum {
CAR(1, "汽车"),
ELECTRIC_CAR(2, "电动车"),
BICYCLE(3, "自行车"),
WALK(4, "步行");
private Integer code;
private String name;
private VehicleEnum(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
public static String getNameByValue(Integer value) {
if (Objects.isNull(value)) {
return null;
}
for (VehicleEnum enums : VehicleEnum.values()) {
if (ObjectUtil.equal(enums.getCode(), value)) {
return enums.getName();
}
}
return null;
}
}
......@@ -10,6 +10,7 @@ import com.dituhui.pea.order.dto.BusinessServerBlocksRespDTO;
import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.feign.ISaaSRemoteService;
import com.dituhui.pea.order.service.BusinessBlockService;
import com.dituhui.pea.order.utils.EncryptionUtil;
import com.dituhui.pea.order.utils.TypeUtils;
import com.google.gson.internal.LinkedTreeMap;
......@@ -57,6 +58,8 @@ public class BusinessBlockServiceImpl implements BusinessBlockService {
private MapLayerCustomizeDao mapLayerCustomizeDao;
@Autowired
private EntityManager entityManager;
@Autowired
private EncryptionUtil encryptionUtil;
@Override
public Result<?> businessServerBlocks(String levelType, String levelValue, int page, int size, String layerId, String teamId) {
......@@ -143,6 +146,8 @@ public class BusinessBlockServiceImpl implements BusinessBlockService {
+ "&jump=basedata&navHidden=true&layerId=" + StringUtils.trimToEmpty(b.getSaasLayerId())
+ "&layercode=" + StringUtils.trimToEmpty(b.getSaasLayercode()) + "&area_ids="
+ StringUtils.trimToEmpty(b.getAreaIds());
// 传输加密
saasUrl = encryptionUtil.AESEncrypt(saasUrl);
block.setSaasUrl(saasUrl);
if(null != b.getUpdateTime()) {
block.setUpdateTime(TimeUtils.IsoLocalDateTime2String(b.getUpdateTime()));
......
......@@ -388,6 +388,8 @@ public class DispatchServiceImpl implements DispatchService {
item.setBeanPriority(o.getBeanPriority());
item.setOrgGroupId(o.getOrgGroupId());
item.setIsSpecialTime(o.getIsSpecialTime());
item.setBeanTags(o.getBeanTags());
item.setIsCutoff(o.getIsCutoff());
item.setOrgGroupName(groupMap.get(o.getOrgGroupId()));
if (isContinue && StringUtils.isNotEmpty(o.getMultipleOrders())) {
List<OrderInfoEntity> byMultipleOrders = orderInfoDao.findByMultipleOrdersAndOrderIdNot(o.getMultipleOrders(), o.getOrderId());
......@@ -425,7 +427,7 @@ public class DispatchServiceImpl implements DispatchService {
} 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());
makeOrderMap(groupByMap, item, "一家多台ID:" + item.getMultipleOrders());
} else {
makeOrderMap(groupByMap, item, "其他");
}
......@@ -457,7 +459,7 @@ public class DispatchServiceImpl implements DispatchService {
CriteriaQuery<OrderInfoEntity> criteriaQuery = criteriaBuilder.createQuery(OrderInfoEntity.class);
Root<OrderInfoEntity> root = criteriaQuery.from(OrderInfoEntity.class);
List<Predicate> predicates = new ArrayList<>();
criteriaQuery.orderBy(criteriaBuilder.desc(root.get("createTime")));
predicates.add(criteriaBuilder.equal(root.get("dt"), TimeUtils.IsoDate2LocalDate(reqDTO.getDate())));
predicates.add(criteriaBuilder.equal(root.get("appointmentStatus"), OrderFlowEnum.INIT.name()));
......
......@@ -62,6 +62,7 @@ public class EngineerGanttServiceImpl implements EngineerGanttService {
EngineersGanttDTO.Slot slot = new EngineersGanttDTO.Slot();
// todo 需要根据订单时间和状态,采用expectXXXX或者actualXXXX
slot.setOrderId(order.getOrderId());
slot.setServiceStatus(order.getServiceStatus());
if (checkOrderIsFinish(order.getServiceStatus())) {
slot.setBtime(getHourMinute(order.getActualStartTime()));
slot.setEtime(getHourMinute(order.getActualEndTime()));
......
......@@ -87,9 +87,14 @@ public class MsgServiceImpl implements MsgService {
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(Integer msgId, String userId) {
List<MsgReceiverEntity> list = msgReceiverDao.findAll(Example.of(new MsgReceiverEntity().setMsgId(msgId).setUserId(userId)));
List<MsgReceiverEntity> list = msgReceiverDao.findAll(Example.
of(new MsgReceiverEntity()
.setMsgId(msgId).
setUserId(userId)
.setDeleted(0)));
list.forEach(msgReceiverEntity -> {
msgReceiverDao.deleteById(msgReceiverEntity.getId());
msgReceiverEntity.setDeleted(1);
msgReceiverDao.save(msgReceiverEntity);
});
}
......
......@@ -17,6 +17,7 @@
package com.dituhui.pea.order.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.common.ResultEnum;
import com.dituhui.pea.enums.StatusCodeEnum;
......@@ -27,7 +28,7 @@ import com.dituhui.pea.order.dto.param.Location;
import com.dituhui.pea.order.dto.param.OrderDTO;
import com.dituhui.pea.order.dto.param.OrgTeamInfo;
import com.dituhui.pea.order.entity.*;
import com.dituhui.pea.order.enums.AppointmentStatus;
import com.dituhui.pea.order.enums.AppointmentMethodEnum;
import com.dituhui.pea.order.enums.OrderFlowEnum;
import com.dituhui.pea.order.enums.OrderStatusEnum;
import com.dituhui.pea.order.service.*;
......@@ -128,7 +129,7 @@ public class OrderCreateServiceImpl implements OrderCreateService {
@Override
@Transactional
public Result<?> createOrder(OrderDTO.OrderCreateRequest req) {
log.info("[createOrder] current XID: {}", RootContext.getXID());
log.info("[createOrder] req: {}", JSONObject.toJSONString(req));
OrderInfoEntity entity = new OrderInfoEntity();
String orderId = req.getOrderId();
if (StringUtils.isEmpty(orderId)) {
......@@ -140,14 +141,13 @@ public class OrderCreateServiceImpl implements OrderCreateService {
return Result.failed(StatusCodeEnum.ORDER_EXISTS);
}
// 分单处理
String peaBrand = fixBrand(req.getBrand());
// location
Location location = req.getLocation();
//先处理时间,后面用
//预处理字段
entity.setExpectTimeBegin(DateUtil.fromDate(req.getExpectBegin()));
entity.setExpectTimeEnd(DateUtil.fromDate(req.getExpectEnd()));
entity.setAppointmentStatus(AppointmentStatus.INIT.getDescription());
entity.setAppointmentStatus(OrderFlowEnum.INIT.name());
entity.setAppointmentMethod(AppointmentMethodEnum.AUTO_NOW.name());
//获取省市区
AdministrativeDistrictReq administrativeDistrictReq = new AdministrativeDistrictReq();
administrativeDistrictReq.setPoints(location.getLongitude() + "," + location.getLatitude());
......@@ -157,21 +157,19 @@ public class OrderCreateServiceImpl implements OrderCreateService {
entity.setCity(adminDistrict.getResult().getSubNames().getCity());
entity.setCounty(adminDistrict.getResult().getSubNames().getCounty());
}
// 分单处理
Result<OrgTeamInfo> fendanResult = fendanService.fendanToGroupCapacity(req, 2, entity.getExpectTimeBegin().toLocalDate(), entity.getExpectTimeBegin().toLocalTime(), entity.getExpectTimeEnd().toLocalTime());
if (!fendanResult.getCode().equals(ResultEnum.SUCCESS.getCode()) || ObjectUtil.isNull(fendanResult.getResult())) {
if (fendanResult.getCode().equals(StatusCodeEnum.FENDAN_IS_TRANSCEND.getCode())) {
// 处理超派
entity.setTranscend(1);
}
OrgBranchEntity branchEntity = orgBranchDao.findByCitycodeListLike("%" + adminDistrict.getResult().getSubNames().getCounty() + "%");
OrgBranchEntity branchEntity = orgBranchDao.findByCitycodeListLike("%" + adminDistrict.getResult().getSubNames().getCity() + "%");
entity.setOrgClusterId(branchEntity.getClusterId());
entity.setOrgBranchId(branchEntity.getBranchId());
entity.setAppointmentMethod(AppointmentMethodEnum.MANUAL.name());
//发送通知分部消息
MsgDTO msgDTO = new MsgDTO();
msgDTO.setBranchId(branchEntity.getBranchId());
msgDTO.setType(0);
msgDTO.setOrderIds(orderId);
msgDTO.setContent("有1条预约日期在" + entity.getExpectTimeBegin().toLocalDate() + "的工单需人工外理");
msgService.add(msgDTO);
sendMsg(branchEntity.getBranchId(), orderId, entity.getExpectTimeBegin().toLocalDate());
} else {
// 根据分单工作队,填写clusterId/branchId/groupId/teamId等
OrgTeamInfo teamInfo = fendanResult.getResult();
......@@ -179,11 +177,25 @@ public class OrderCreateServiceImpl implements OrderCreateService {
entity.setOrgBranchId(teamInfo.getBranchId());
entity.setOrgGroupId(teamInfo.getGroupId());
entity.setOrgTeamId(teamInfo.getTeamId());
entity.setAppointmentStatus(AppointmentStatus.PRE.getDescription());
//处理超派,特殊时间段
entity.setIsSpecialTime(CommonUtil.isSpecial(entity.getExpectTimeBegin().toLocalTime(),
entity.getExpectTimeEnd().toLocalTime(), teamInfo.getWorkOn(), teamInfo.getWorkOff()));
entity.setAppointmentStatus(OrderFlowEnum.PRE.name());
//特殊时间段
Integer special = CommonUtil.isSpecial(entity.getExpectTimeBegin().toLocalTime(),
entity.getExpectTimeEnd().toLocalTime(), teamInfo.getWorkOn(), teamInfo.getWorkOff());
Integer cutoff = CommonUtil.isCutoff(LocalDateTime.now(), teamInfo.getWorkOff());
// 处理cutoff 动态排班结束后创建的当日单和次日单
boolean isToday = DateUtil.judgeTimeIsToday(entity.getExpectTimeBegin());
boolean isTomorrow = DateUtil.judgeTimeIsisTomorrow(entity.getExpectTimeBegin());
// 特殊时间段,当天单,cutoff需要人工处理
if (isToday || (isTomorrow && cutoff == 1) || special == 1) {
//判断是否在今天cutoff之后
entity.setIsCutoff(cutoff);
entity.setIsSpecialTime(special);
entity.setAppointmentMethod(AppointmentMethodEnum.MANUAL.name());
//发送通知分部消息
sendMsg(teamInfo.getBranchId(), orderId, entity.getExpectTimeBegin().toLocalDate());
}
}
// 字段转换
entity.setSource(req.getSource());
entity.setOrderId(orderId);
entity.setName(req.getName());
......@@ -197,7 +209,8 @@ public class OrderCreateServiceImpl implements OrderCreateService {
// 使用期望时间来初始化计划时间,后面在指派环节更新为真正的有效的计划时间
entity.setPlanStartTime(entity.getExpectTimeBegin());
entity.setPlanEndTime(entity.getExpectTimeEnd());
entity.setApplyNote(req.getDescription()); // order_request的description字段,仅仅用于内部备注,不对外
// order_request的description字段,仅仅用于内部备注,不对外
entity.setApplyNote(req.getDescription());
entity.setDt(entity.getExpectTimeBegin().toLocalDate());
entity.setSubId(newSubId(entity.getOrderId(), entity.getDt()));
entity.setX(req.getLocation().getLongitude().toString());
......@@ -205,38 +218,44 @@ public class OrderCreateServiceImpl implements OrderCreateService {
entity.setAddress(location.getAddress());
entity.setAddressId(location.getAddressId());
// 默认值
entity.setAppointmentStatus(OrderFlowEnum.INIT.name());
// entity.setAppointmentStatus(OrderFlowEnum.INIT.name());
entity.setBeanStatus("OPEN");
entity.setBeanSubStatus("");
entity.setAppointmentMethod("AUTO_NOW");
entity.setWorkshop(false);
// 处理工程师
entity.setIsAppointEngineer(req.getIsAppointEngineer());
String appointEngineerCodes = CollectionUtils.isEmpty(req.getAppointEngineerCodes()) ? "" : String.join(",", req.getAppointEngineerCodes());
entity.setAppointEngineerCodes(appointEngineerCodes);
// 处理技能和标签
SkillInfoEntity skillInfoEntity = skillInfoDao.getByBrandAndTypeAndSkill(peaBrand, req.getProductType(), req.getServiceType());
assert skillInfoEntity != null;
entity.setTakeTime(skillInfoEntity.getTakeTime());
// 基础保存
String joinTags = CollectionUtils.isEmpty(req.getOrderTags()) ? "" : String.join(",", req.getOrderTags());
entity.setBeanTags(joinTags);
entity.setBeanPriority(req.getPriority());
entity.setIsMultiple(joinTags.contains("重物搬运") ? 1 : 0);
//一家多单
Result<String> addMultipleOrders = orderInfoService.addMultipleOrders(entity.getDt(), location.getAddressId(), orderId);
entity.setMultipleOrders(addMultipleOrders.getResult());
// todo 服务单状态、预约状态等
// 记录订单和节点
orderInfoDao.save(entity);
// 登记
commonService.addOrderEvent(orderId, "", req.getSource(), "API", OrderStatusEnum.CREATE.getDescription(), OrderStatusEnum.CREATE.getDescription(), "");
// 指派检查,简单处理,遇到第一个可以指派的就停止检查
// tryVirtualAppointment(entity, req.getSource(), teamId);
return Result.success(null);
}
private void sendMsg(String branchId, String orderId, LocalDate toLocalDate) {
MsgDTO msgDTO = new MsgDTO();
msgDTO.setBranchId(branchId);
msgDTO.setType(0);
msgDTO.setOrderIds(orderId);
msgDTO.setContent("有1条预约日期在" + toLocalDate + "的工单需人工外理");
msgService.add(msgDTO);
}
private void tryVirtualAppointment(OrderInfoEntity thisOrderEntity, String source, String teamId) {
try {
List<String> engineerCodes = engineerUtils.getEngineersByLevel("team", teamId).stream()
......
......@@ -364,7 +364,7 @@ public class OrderInfoServiceImpl implements OrderInfoService {
if (fendanResult.getCode().equals(StatusCodeEnum.FENDAN_IS_TRANSCEND.getCode())) {
order.setTranscend(1);
}
OrgBranchEntity branchEntity = orgBranchDao.findByCitycodeListLike("%" + adminDistrict.getResult().getSubNames().getCounty() + "%");
OrgBranchEntity branchEntity = orgBranchDao.findByCitycodeListLike("%" + adminDistrict.getResult().getSubNames().getCity() + "%");
clusterId = branchEntity.getClusterId();
branchId = branchEntity.getBranchId();
sendMsg(branchEntity.getBranchId(), order.getOrderId(), req.getExpectBegin());
......
package com.dituhui.pea.order.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dituhui.pea.common.BusinessException;
import com.dituhui.pea.common.Result;
import com.dituhui.pea.order.common.DateUtils;
import com.dituhui.pea.order.common.ListUtils;
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.OrderFlowEnum;
import com.dituhui.pea.order.enums.VehicleEnum;
import com.dituhui.pea.order.service.ScheduleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
......@@ -20,7 +23,10 @@ import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
......@@ -48,6 +54,9 @@ public class ScheduleServiceImpl implements ScheduleService {
private EngineerInfoDao engineerInfoDao;
@Autowired
private EngineerBusinessDao engineerBusinessDao;
@Autowired
private SkillInfoDao skillInfoDao;
@Override
......@@ -116,6 +125,7 @@ public class ScheduleServiceImpl implements ScheduleService {
Collectors.groupingBy(EngineerInfoEntity::getEngineerCode));
List<ScheduleOverviewResp.Item> children = new ArrayList<>();
Integer teamDistance = 0;
for (Map.Entry<String, List<EngineerInfoEntity>> entry : engineers.entrySet()) {
ScheduleOverviewResp.Item child = new ScheduleOverviewResp.Item();
......@@ -131,7 +141,9 @@ public class ScheduleServiceImpl implements ScheduleService {
child.setLevel("engineer");
child.setOrder(this.getTeamOrderSum(orders2, skillMapping));
child.setOrderDesc(Integer.toString(orders2.size()));
child.setDistanceDesc("");
Integer distanceSum = orders2.stream().map(order -> Objects.nonNull(order.getArriveDistance()) ? order.getArriveDistance() : 0).reduce(Integer::sum).orElse(0);
teamDistance += distanceSum;
child.setDistanceDesc(distanceSum + "");
children.add(child);
}
......@@ -139,7 +151,7 @@ public class ScheduleServiceImpl implements ScheduleService {
team.setChildren(children);
team.setOrderDesc(String.format("人均:%d", teamEngineers.size() > 0 ? (orders.size() / teamEngineers.size()) : 0));
team.setDistanceDesc("");
team.setDistanceDesc(teamDistance + "");
teams.add(team);
}
......@@ -160,11 +172,14 @@ public class ScheduleServiceImpl implements ScheduleService {
if (engineer == null) {
throw new BusinessException("分销员不存在");
}
EngineerBusinessEntity engineerBusinessEntity = engineerBusinessDao.getByEngineerCode(engineerCode);
List<LabelValueDTO> emptyTips = new ArrayList<>();
List<OrderInfoEntity> orderAppointments = orderInfoDao.findByEngineerCodeAndDtAndAppointmentStatusIn(
engineerCode, date, List.of(OrderFlowEnum.PRE.name(), OrderFlowEnum.CONFIRM.name()));
List<TimeLineDTO> timelines = new ArrayList<>();
int sumDistance = 0;
int sumElapsed = 0;
for (OrderInfoEntity o : orderAppointments) {
TimeLineDTO item = new TimeLineDTO();
item.setOrderId(o.getOrderId());
......@@ -173,6 +188,8 @@ public class ScheduleServiceImpl implements ScheduleService {
item.setEndTime(TimeUtils.IsoLocalDateTime2String(o.getPlanEndTime()));
item.setTips(emptyTips);
timelines.add(item);
sumDistance += Objects.isNull(o.getArriveDistance()) ? 0 : o.getArriveDistance();
sumElapsed += Objects.isNull(o.getArriveElapsed()) ? 0 : o.getArriveElapsed();
}
Map<String, List<OrderInfoEntity>> statusGroup = orderAppointments.stream().collect(Collectors.groupingBy(OrderInfoEntity::getServiceStatus));
......@@ -188,10 +205,17 @@ public class ScheduleServiceImpl implements ScheduleService {
dynamics.add(new LabelValueDTO("已完成", Integer.toString(statusGroup.getOrDefault("FINISHED", empty).size())));
dynamics.add(new LabelValueDTO("已取消", Integer.toString(statusGroup.getOrDefault("CANCELED", empty).size())));
dynamics.add(new LabelValueDTO("已改约", Integer.toString(statusGroup.getOrDefault("RESCHEDULED", empty).size())));
dynamics.add(new LabelValueDTO("预计总耗时", "6小时"));
dynamics.add(new LabelValueDTO("公里数", "42公里"));
dynamics.add(new LabelValueDTO("预计总耗时", new BigDecimal(sumElapsed)
.divide(new BigDecimal(60), 2, RoundingMode.HALF_UP)
.stripTrailingZeros()
+ "小时"));
dynamics.add(new LabelValueDTO("公里数", sumDistance + ""));
if (Objects.nonNull(engineerBusinessEntity)) {
dynamics.add(new LabelValueDTO("工作时间", engineerBusinessEntity.getWorkOn() + "-" + engineerBusinessEntity.getWorkOff()));
} else {
dynamics.add(new LabelValueDTO("工作时间", "08:00-18:00"));
dynamics.add(new LabelValueDTO("交通工具", "电动车"));
}
dynamics.add(new LabelValueDTO("交通工具", VehicleEnum.getNameByValue(engineer.getVehicle())));
List<String> orderIds = orderAppointments.stream().map(OrderInfoEntity::getOrderId).collect(Collectors.toList());
List<OrderInfoEntity> orderRequests = new ArrayList<>();
......@@ -209,8 +233,22 @@ public class ScheduleServiceImpl implements ScheduleService {
item.setOrderStatusName("");
item.setDistance(o.getArriveDistance());
item.setTimeType("auto");
item.setExpectArriveDuration(o.getArriveElapsed() + "分钟");
item.setArriveTime(null);
if (Objects.nonNull(o.getArriveElapsed())) {
String btime = null;
String etime = null;
if (checkOrderIsFinish(o.getServiceStatus())) {
btime = getHourMinute(o.getActualStartTime(), -o.getArriveElapsed());
etime = getHourMinute(o.getActualStartTime());
} else {
btime = getHourMinute(o.getPlanStartTime(), -o.getArriveElapsed());
etime = getHourMinute(o.getPlanStartTime());
}
//在途时间段
item.setExpectArriveDuration(String.format("%s-%s", btime, etime));
}
item.setArriveTime(DateUtil.format(o.getActualStartTime(), "HH:mm"));
item.setArriveDuration(null);
if (ObjectUtil.isAllNotEmpty(o.getPlanStartTime(), o.getPlanEndTime())) {
item.setExpectWorkDuration(LocalDateTimeUtil.between(o.getPlanStartTime(), o.getPlanEndTime(), ChronoUnit.MINUTES) + "分钟");
}
......@@ -239,6 +277,19 @@ public class ScheduleServiceImpl implements ScheduleService {
return Result.success(res);
}
private boolean checkOrderIsFinish(String serviceStatus) {
String[] array = {"FINISHED", "UNFINISHED"};
return Arrays.asList(array).contains(serviceStatus);
}
private String getHourMinute(LocalDateTime time) {
return this.getHourMinute(time, 0);
}
private String getHourMinute(LocalDateTime time, int deltaMinute) {
return DateUtils.formatDateTime(time.plusMinutes(deltaMinute), "HH:mm");
}
public Page<OrgTeamEntity> queryOrgTeams(long page, long size, String levelType, List<String> levelIds) {
Pageable pageable = PageRequest.of((int) page, (int) size);
......
......@@ -4,6 +4,8 @@ import cn.hutool.core.util.StrUtil;
import com.dituhui.pea.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
......@@ -74,7 +76,20 @@ public class CommonUtil {
public static Integer isSpecial(LocalTime expectBegin, LocalTime expectEnd, String strOn, String strOff) {
LocalTime workOn = LocalTime.parse(strOn + ":00", DateUtil.TIME_FORMATTER);
LocalTime workOff = LocalTime.parse(strOff + ":00", DateUtil.TIME_FORMATTER);
if (expectBegin.isBefore(workOn) || expectEnd.isAfter(workOff)) {
if (expectBegin.isBefore(workOn) || expectBegin.isAfter(workOff) || expectEnd.isAfter(workOff) || expectEnd.isBefore(workOn)) {
return 1;
}
return 0;
}
/**
* 判断是否cutoff
*
* @return
*/
public static Integer isCutoff(LocalDateTime localTime, String strOff) {
LocalDateTime workOff = LocalDate.now().atTime(Integer.parseInt(strOff.split(":")[0]), Integer.parseInt(strOff.split(":")[1]), 0);
if (localTime.isAfter(workOff)) {
return 1;
}
return 0;
......
package com.dituhui.pea.order.utils;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
/**
* 加密工具
*/
@Component
@Slf4j
public class EncryptionUtil {
public static Encoder encoder = Base64.getEncoder();
public static Decoder decoder = Base64.getDecoder();
@Value("${SaaS.encryptionPassWord}")
String passWord;
@Value("${SaaS.encryptionPassWord}")
String IV;
/*
* AES加密算法
*
* @author 加密用的Key 可以用26个字母和数字组成,最好不要用保留字符,虽然不会错,至于怎么裁决,个人看情况而定
* 此处使用AES-128-CBC加密模式,key需要为16位。
* */
public String AESEncrypt(String sSrc) {
System.out.println("passWord:"+passWord);
System.out.println("IV:"+IV);
try {
if (passWord == null) {
log.error("password 未加载");
return null;
}
// 判断Key是否为16位
if (passWord.length() != 16) {
log.error("password 长度异常: [" + passWord + "],length=" + passWord.length());
return null;
}
byte[] raw = passWord.getBytes("utf-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");// "算法/模式/补码方式"
IvParameterSpec iv = new IvParameterSpec(IV.getBytes("utf-8"));// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
return encoder.encodeToString(encrypted);// 此处使用BAES64做转码功能,同时能起到2次
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage(), e);
return null;
}
}
/**
* AES解密
*
* @param sSrc
* @return
* @see
*/
public String AESDecrypt(String sSrc) {
try {
// 判断Key是否正确
if (passWord == null) {
log.error("password 未加载");
return null;
}
// 判断Key是否为16位
if (passWord.length() != 16) {
log.error("password 长度异常: [" + passWord + "],length=" + passWord.length());
return null;
}
SecretKeySpec secretKeySpec = new SecretKeySpec(passWord.getBytes("utf-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5padding");
AlgorithmParameterSpec iv = new IvParameterSpec(IV.getBytes("utf-8"));
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, iv);
// 先用bAES64解密
byte[] encrypted1 = decoder.decode(sSrc);
try {
byte[] original = cipher.doFinal(encrypted1);
return new String(original);
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage(), e);
return null;
}
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage(), e);
return null;
}
}
/**
* 加密
*
* @param encData 原始待加密串
* @param key 16位key
* @param ivs 16位向量
* @return
* @throws Exception
* @see
*/
public static String AESEncode(String key, String ivs, String encData) throws Exception {
if (key == null) {
return null;
}
if (key.length() != 16) {
return null;
}
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();
byte[] dataBytes = encData.getBytes();
int plaintextLength = dataBytes.length;
if (plaintextLength % blockSize != 0) {
plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
}
byte[] plaintext = new byte[plaintextLength];
System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(ivs.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(plaintext);
return encoder.encodeToString(encrypted);
}
/**
* 解密
*
* @param sSrc
* @param key 16位key
* @param ivs 16位向量
* @return
* @see
*/
public static String AESDncode(String key, String ivs, String sSrc) {
try {
byte[] raw = key.getBytes(StandardCharsets.US_ASCII);
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
IvParameterSpec iv = new IvParameterSpec(ivs.getBytes());
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] encrypted1 = decoder.decode(sSrc);// 先用base64解密
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original, StandardCharsets.UTF_8);
return originalString.trim();
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
/*
* 加密
* 1.构造密钥生成器
* 2.根据ecnodeRules规则初始化密钥生成器
* 3.产生密钥
* 4.创建和初始化密码器
* 5.内容加密
* 6.返回字符串
*/
public static String AESEncode_ECB(String encodeRules, String content) {
try {
//1.构造密钥生成器,指定为AES算法,不区分大小写
KeyGenerator keygen = KeyGenerator.getInstance("AES");
//2.根据ecnodeRules规则初始化密钥生成器
//生成一个128位的随机源,根据传入的字节数组
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(encodeRules.getBytes());
keygen.init(128, random);
//3.产生原始对称密钥
SecretKey original_key = keygen.generateKey();
//4.获得原始对称密钥的字节数组
byte[] raw = original_key.getEncoded();
System.out.println(raw.length);
//5.根据字节数组生成AES密钥
SecretKey key = new SecretKeySpec(raw, "AES");
//6.根据指定算法AES自成密码器
Cipher cipher = Cipher.getInstance("AES");
//7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
cipher.init(Cipher.ENCRYPT_MODE, key);
//8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
byte[] byte_encode = content.getBytes(StandardCharsets.UTF_8);
//9.根据密码器的初始化方式--加密:将数据加密
byte[] byte_AES = cipher.doFinal(byte_encode);
//10.将加密后的数据转换为字符串
//这里用Base64Encoder中会找不到包
//解决办法:
//在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
String AES_encode = new String(encoder.encode(byte_AES));
//11.将字符串返回
return AES_encode;
} catch (Exception e) {
e.printStackTrace();
}
//如果有错就返加nulll
return null;
}
/*
* 解密
* 解密过程:
* 1.同加密1-4步
* 2.将加密后的字符串反纺成byte[]数组
* 3.将加密内容解密
*/
public static String AESDncode_ECB(String encodeRules, String content) {
try {
//1.构造密钥生成器,指定为AES算法,不区分大小写
KeyGenerator keygen = KeyGenerator.getInstance("AES");
//2.根据ecnodeRules规则初始化密钥生成器
//生成一个128位的随机源,根据传入的字节数组
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(encodeRules.getBytes());
keygen.init(128, random);
//3.产生原始对称密钥
SecretKey original_key = keygen.generateKey();
//4.获得原始对称密钥的字节数组
byte[] raw = original_key.getEncoded();
//5.根据字节数组生成AES密钥
SecretKey key = new SecretKeySpec(raw, "AES");
//6.根据指定算法AES自成密码器
Cipher cipher = Cipher.getInstance("AES");
//7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
cipher.init(Cipher.DECRYPT_MODE, key);
//8.将加密并编码后的内容解码成字节数组
byte[] byte_content = decoder.decode(content);
/*
* 解密
*/
byte[] byte_decode = cipher.doFinal(byte_content);
String AES_decode = new String(byte_decode, StandardCharsets.UTF_8);
return AES_decode;
} catch (Exception e) {
e.printStackTrace();
}
//如果有错就返加nulll
return null;
}
public static void main(String[] args) throws Exception {
// String aR = "1234567890";
// System.out.println(AESEncrypt(aR));
// System.out.println(AESDecrypt(AESEncrypt(aR)));
}
}
......@@ -65,6 +65,7 @@ SaaS:
ak: 64e1cde3f9144bfb850b7d37c51af559
userAccount: sMvf3yZWA69lKcvlgKcOHQ==
userPassword: qjOHxpQPXLnJP+Jq1CZGBQ==
encryptionPassWord: 64e1cde3f9144bfb
bean:
server: https://bean-test.bshg.com.cn
app-key: eDZEhTCxAcM9paRfwPjAM7RGkfmbf15S_PEA
......
......@@ -58,8 +58,7 @@ public class RoleController implements IRole {
if (StringUtils.isBlank(roleInfo.getId())) {
return Result.failed(StatusCodeEnum.COMMON_PARAM_EMPTY, false);
}
roleService.deleteRole(roleInfo.getId());
return Result.success(true);
return roleService.deleteRole(roleInfo.getId());
}
@Override
......
......@@ -125,15 +125,15 @@ public class RoleService {
}
@Transactional(rollbackFor = Exception.class)
public void deleteRole(String roleId) {
public Result deleteRole(String roleId) {
// 查询角色是否存在
RoleEntity roleEntity = roleDao.findById(roleId).orElse(null);
if (ObjectUtil.isNull(roleEntity)) {
throw new BusinessException(StatusCodeEnum.ROLE_DOES_NOT_EXIST);
return Result.failed(StatusCodeEnum.ROLE_DOES_NOT_EXIST);
}
List<UserRoleEntity> roleEntities = userRoleDao.findByRoleId(roleId);
if (CollectionUtils.isNotEmpty(roleEntities)) {
throw new BusinessException(StatusCodeEnum.RESOURCE_USER_EXISTS_ROLE);
return Result.failed(StatusCodeEnum.RESOURCE_USER_EXISTS_ROLE);
}
// 删除角色
roleDao.deleteById(roleId);
......@@ -141,6 +141,7 @@ public class RoleService {
userRoleDao.deleteByRoleId(roleId);
// 删除权限和角色的关系
roleResourceDao.deleteByRoleId(roleId);
return Result.success();
}
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!