9 Commits

Author SHA1 Message Date
Lemon
681691c183 修改办公室服务器ip地址为0.118 2026-06-30 14:16:33 +08:00
jsowell
e4be50b417 update 羽信预约充电 2026-06-26 16:44:16 +08:00
jsowell
e2c0d7fd34 update 打印日志 2026-06-26 15:45:10 +08:00
jsowell
ddcf6abb3e update 预约充电 2026-06-26 14:55:07 +08:00
jsowell
84fc754c39 update 预约充电逻辑 2026-06-26 14:28:59 +08:00
jsowell
944f4100ad update 设置挡板 2026-06-26 09:20:53 +08:00
jsowell
db544375bd update 打印日志 2026-06-25 17:03:05 +08:00
jsowell
b77ad0d686 update羽信主板预约充电 2026-06-25 16:14:08 +08:00
jsowell
838e37ed03 update 定时任务PRE挡板 2026-06-25 16:13:28 +08:00
9 changed files with 254 additions and 418 deletions

View File

@@ -522,8 +522,8 @@ public class PersonPileController extends BaseController {
try { try {
String memberId = getMemberIdByAuthorization(request); String memberId = getMemberIdByAuthorization(request);
dto.setMemberId(memberId); dto.setMemberId(memberId);
int reservedId = yuxinReservationChargingService.createReservation(dto); yuxinReservationChargingService.createReservation(dto);
response = new RestApiResponse<>(ImmutableMap.of("reservedId", reservedId)); response = new RestApiResponse<>();
} catch (BusinessException e) { } catch (BusinessException e) {
logger.error("羽信添加预约充电error, params:{}", dto, e); logger.error("羽信添加预约充电error, params:{}", dto, e);
response = new RestApiResponse<>(e.getCode(), e.getMessage()); response = new RestApiResponse<>(e.getCode(), e.getMessage());
@@ -535,102 +535,6 @@ public class PersonPileController extends BaseController {
return response; return response;
} }
/**
* 羽信主板修改预约充电
* http://localhost:8080/uniapp/personalPile/yuxin/updateReservation
*/
@PostMapping("/yuxin/updateReservation")
public RestApiResponse<?> updateYuxinReservation(HttpServletRequest request, @RequestBody YuxinReservationChargingDTO dto) {
RestApiResponse<?> response = null;
try {
String memberId = getMemberIdByAuthorization(request);
dto.setMemberId(memberId);
int i = yuxinReservationChargingService.updateReservation(dto);
if (i > 0) {
response = new RestApiResponse<>();
} else {
response = new RestApiResponse<>(ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_ERROR.getValue(), ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_ERROR.getLabel() + ": 充电桩返回修改失败");
}
} catch (BusinessException e) {
logger.error("羽信修改预约充电error, params:{}", dto, e);
response = new RestApiResponse<>(e.getCode(), e.getMessage());
} catch (Exception e) {
logger.error("羽信修改预约充电error, params:{}", dto, e);
response = new RestApiResponse<>(ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_ERROR);
}
logger.info("羽信修改预约充电params:{}, result:{}", dto, response);
return response;
}
/**
* 羽信主板取消预约充电
* http://localhost:8080/uniapp/personalPile/yuxin/cancelReservation
*/
@PostMapping("/yuxin/cancelReservation")
public RestApiResponse<?> cancelYuxinReservation(HttpServletRequest request, @RequestBody YuxinReservationChargingDTO dto) {
RestApiResponse<?> response = null;
try {
String memberId = getMemberIdByAuthorization(request);
dto.setMemberId(memberId);
yuxinReservationChargingService.cancelReservation(dto);
response = new RestApiResponse<>();
} catch (BusinessException e) {
logger.error("羽信取消预约充电error, params:{}", dto, e);
response = new RestApiResponse<>(e.getCode(), e.getMessage());
} catch (Exception e) {
logger.error("羽信取消预约充电error, params:{}", dto, e);
response = new RestApiResponse<>(ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_ERROR);
}
logger.info("羽信取消预约充电params:{}, result:{}", dto, response);
return response;
}
/**
* 羽信主板删除预约
* http://localhost:8080/uniapp/personalPile/yuxin/deleteReservation
*/
@PostMapping("/yuxin/deleteReservation")
public RestApiResponse<?> deleteYuxinReservation(HttpServletRequest request, @RequestBody YuxinReservationChargingDTO dto) {
RestApiResponse<?> response = null;
try {
String memberId = getMemberIdByAuthorization(request);
dto.setMemberId(memberId);
yuxinReservationChargingService.deleteReservation(dto);
response = new RestApiResponse<>();
} catch (BusinessException e) {
logger.error("羽信删除预约error, params:{}", dto, e);
response = new RestApiResponse<>(e.getCode(), e.getMessage());
} catch (Exception e) {
logger.error("羽信删除预约error, params:{}", dto, e);
response = new RestApiResponse<>(ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_ERROR);
}
logger.info("羽信删除预约params:{}, result:{}", dto, response);
return response;
}
/**
* 羽信主板查询预约信息
* http://localhost:8080/uniapp/personalPile/yuxin/queryReservationInfo
*/
@PostMapping("/yuxin/queryReservationInfo")
public RestApiResponse<?> queryYuxinReservationInfo(HttpServletRequest request, @RequestBody YuxinReservationChargingDTO dto) {
RestApiResponse<?> response = null;
try {
String memberId = getMemberIdByAuthorization(request);
dto.setMemberId(memberId);
PileReservationInfoVO vo = yuxinReservationChargingService.queryReservationInfo(dto);
response = new RestApiResponse<>(vo);
} catch (BusinessException e) {
logger.error("羽信查询预约状态error, params:{}", dto, e);
response = new RestApiResponse<>(e.getCode(), e.getMessage());
} catch (Exception e) {
logger.error("羽信查询预约状态error, params:{}", dto, e);
response = new RestApiResponse<>(ReturnCodeEnum.CODE_QUERY_RESERVATION_STATUS_ERROR);
}
logger.info("羽信查询预约状态params:{}, result:{}", dto, JSON.toJSONString(response));
return response;
}
/** /**
* 保存蓝牙充电记录 * 保存蓝牙充电记录
* http://localhost:8080/uniapp/personalPile/saveBluetoothChargingRecord * http://localhost:8080/uniapp/personalPile/saveBluetoothChargingRecord

View File

@@ -9,7 +9,7 @@ spring:
# redis 配置 # redis 配置
redis: redis:
# 地址 # 地址
host: 192.168.0.8 host: 192.168.0.118
# 端口默认为6379 # 端口默认为6379
port: 6379 port: 6379
# 数据库索引 # 数据库索引
@@ -36,9 +36,9 @@ spring:
druid: druid:
# 主库数据源 # 主库数据源
master: master:
# url: jdbc:mysql://192.168.0.8:3306/jsowell_pre?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 # url: jdbc:mysql://192.168.0.118:3306/jsowell_pre?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: jsowell_pre # username: jsowell_pre
url: jdbc:mysql://192.168.0.8:3306/jsowell_prd?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 url: jdbc:mysql://192.168.0.118:3306/jsowell_prd?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: jsowell_prd username: jsowell_prd
password: dev@js160829 password: dev@js160829
# 从库数据源 # 从库数据源
@@ -90,7 +90,7 @@ spring:
# rabbitmq配置 dev # rabbitmq配置 dev
rabbitmq: rabbitmq:
host: 192.168.0.8 host: 192.168.0.118
port: 5672 port: 5672
username: admin username: admin
password: admin password: admin
@@ -121,7 +121,7 @@ logging:
# 基础URL前缀 # 基础URL前缀
baseurl: baseurl:
prefix: http://192.168.0.8:8080 prefix: http://192.168.0.118:8080
# Minio配置 # Minio配置
minio: minio:
@@ -271,7 +271,7 @@ dubbo:
name: wcc-server name: wcc-server
qosEnable: false qosEnable: false
registry: registry:
address: nacos://192.168.0.8:8848 address: nacos://192.168.0.118:8848
parameters: parameters:
namespace: e328faaf-8516-42d0-817a-7406232b3581 namespace: e328faaf-8516-42d0-817a-7406232b3581
username: nacos username: nacos

View File

@@ -45,6 +45,15 @@ public class ReservationChargingResponseHandler extends AbstractYkcHandler {
// log.info("[====远程更新应答====] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); // log.info("[====远程更新应答====] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString());
// 消息体 // 消息体
byte[] msgBody = ykcDataProtocol.getMsgBody(); byte[] msgBody = ykcDataProtocol.getMsgBody();
String responseFrameType = YKCUtils.frameType2Str(ykcDataProtocol.getFrameType());
boolean yuxinResponse = StringUtils.equals(responseFrameType, yuxinType);
String rawMessage = BytesUtil.bin2HexStr(ykcDataProtocol.getBytes());
int minMsgBodyLength = yuxinResponse ? 27 : 26;
if (msgBody == null || msgBody.length < minMsgBodyLength) {
log.warn("预约充电响应长度异常, 帧类型:{}, 报文体长度:{}, 原始报文:{}",
responseFrameType, msgBody == null ? null : msgBody.length, rawMessage);
return null;
}
int startIndex = 0; int startIndex = 0;
int length = 16; int length = 16;
@@ -66,8 +75,6 @@ public class ReservationChargingResponseHandler extends AbstractYkcHandler {
startIndex += length; startIndex += length;
length = 1; length = 1;
byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String responseFrameType = YKCUtils.frameType2Str(ykcDataProtocol.getFrameType());
boolean yuxinResponse = StringUtils.equals(responseFrameType, yuxinType);
String connectorCode = yuxinResponse ? parseYuxinConnectorCode(connectorCodeByteArr) : BytesUtil.bcd2Str(connectorCodeByteArr); String connectorCode = yuxinResponse ? parseYuxinConnectorCode(connectorCodeByteArr) : BytesUtil.bcd2Str(connectorCodeByteArr);
String reservationType = null; String reservationType = null;
@@ -93,27 +100,41 @@ public class ReservationChargingResponseHandler extends AbstractYkcHandler {
String failedReasonMsg = yuxinResponse ? getYuxinFailedReasonMsg(failedReason) : failedReason; String failedReasonMsg = yuxinResponse ? getYuxinFailedReasonMsg(failedReason) : failedReason;
if (yuxinResponse) { if (yuxinResponse) {
log.info("{}预约充电响应, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 预约方式:{}, 结果:{}, 失败原因:{}", log.info("{}预约充电响应, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 预约方式:{}, 结果:{}({}), 失败原因:{}({}), 原始报文:{}",
responseFrameType, transactionCode, pileSn, connectorCode, reservationType, resultCode, failedReasonMsg); responseFrameType, transactionCode, pileSn, connectorCode, reservationType, resultCode,
getYuxinSetupResultMsg(resultCode), failedReason, failedReasonMsg, rawMessage);
if (!StringUtils.equals(resultCode, "01")) {
log.warn("羽信预约充电设置失败, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 预约方式:{}, 失败原因:{}({}), 原始报文:{}",
transactionCode, pileSn, connectorCode, reservationType, failedReason, failedReasonMsg, rawMessage);
}
} else { } else {
log.info("{}预约充电响应, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 结果:{}, 失败原因:{}", log.info("{}预约充电响应, 交易流水号:{}, 桩SN:{}, 枪口号:{}, 结果:{}, 失败原因:{}, 原始报文:{}",
responseFrameType, transactionCode, pileSn, connectorCode, resultCode, failedReason); responseFrameType, transactionCode, pileSn, connectorCode, resultCode, failedReason, rawMessage);
} }
// 根据请求id在集合中找到与外部线程通信的SyncPromise对象 // 根据请求id在集合中找到与外部线程通信的SyncPromise对象
String requestFrameType = YKCFrameTypeCode.PileAnswersRelation.getRequestFrameType(responseFrameType); String requestFrameType = YKCFrameTypeCode.PileAnswersRelation.getRequestFrameType(responseFrameType);
if (StringUtils.isBlank(requestFrameType)) { if (StringUtils.isBlank(requestFrameType)) {
requestFrameType = YKCUtils.frameType2Str(YKCFrameTypeCode.RESERVATION_CHARGING_SETUP_CODE.getBytes()); requestFrameType = yuxinResponse
? YKCUtils.frameType2Str(YKCFrameTypeCode.YUXIN_RESERVATION_CHARGING_SETUP_CODE.getBytes())
: YKCUtils.frameType2Str(YKCFrameTypeCode.RESERVATION_CHARGING_SETUP_CODE.getBytes());
} }
String msgId = ctx.channel().id().toString() + "_" + requestFrameType; String msgId = ctx.channel().id().toString() + "_" + requestFrameType;
log.info("同步获取响应数据-收到消息, msgId:{}", msgId); log.info("同步获取响应数据-收到消息, msgId:{}", msgId);
SyncPromise syncPromise = RpcUtil.getSyncPromiseMap().get(msgId); SyncPromise syncPromise = RpcUtil.getSyncPromiseMap().get(msgId);
if(syncPromise != null) { if (syncPromise != null) {
// 设置响应结果 // 设置响应结果
syncPromise.setRpcResult(ykcDataProtocol.getBytes()); syncPromise.setRpcResult(ykcDataProtocol.getBytes());
// 唤醒外部线程 // 唤醒外部线程
log.info("同步获取响应数据-唤醒外部线程, SyncPromise:{}", JSON.toJSONString(syncPromise)); log.info("同步获取响应数据-唤醒外部线程, SyncPromise:{}", JSON.toJSONString(syncPromise));
syncPromise.wake(); syncPromise.wake();
} else {
log.warn("同步获取响应数据-未找到等待线程, msgId:{}, responseFrameType:{}, requestFrameType:{}, 原始报文:{}",
msgId, responseFrameType, requestFrameType, rawMessage);
}
if (yuxinResponse) {
return null;
} }
// 如果收到成功, 从redis取值, 保存到数据库 // 如果收到成功, 从redis取值, 保存到数据库
@@ -147,4 +168,13 @@ public class ReservationChargingResponseHandler extends AbstractYkcHandler {
} }
return failedReason; return failedReason;
} }
private String getYuxinSetupResultMsg(String resultCode) {
if (StringUtils.equals(resultCode, "00")) {
return "失败";
} else if (StringUtils.equals(resultCode, "01")) {
return "成功";
}
return resultCode;
}
} }

View File

@@ -23,6 +23,11 @@ public class YuxinReservationChargingDTO {
*/ */
private String reservedId; private String reservedId;
/**
* 状态 0-停用1-启用)
*/
private String status;
/** /**
* 充电桩编号 * 充电桩编号
*/ */

View File

@@ -22,7 +22,6 @@ import com.jsowell.pile.domain.ykcCommond.*;
import com.jsowell.pile.dto.PublishBillingTemplateDTO; import com.jsowell.pile.dto.PublishBillingTemplateDTO;
import com.jsowell.pile.dto.RemoteAccountBalanceUpdateDTO; import com.jsowell.pile.dto.RemoteAccountBalanceUpdateDTO;
import com.jsowell.pile.dto.UpdateFirmwareDTO; import com.jsowell.pile.dto.UpdateFirmwareDTO;
import com.jsowell.pile.vo.base.ConnectorInfoVO;
import com.jsowell.pile.vo.web.BillingTemplateVO; import com.jsowell.pile.vo.web.BillingTemplateVO;
import com.jsowell.pile.vo.web.PileDetailVO; import com.jsowell.pile.vo.web.PileDetailVO;
import com.jsowell.wxpay.service.WxAppletRemoteService; import com.jsowell.wxpay.service.WxAppletRemoteService;
@@ -520,11 +519,86 @@ public class PileRemoteService {
/** /**
* 羽信预约充电指令 * 羽信预约充电指令
*
* @return result: 1-成功; 0-失败 * @return result: 1-成功; 0-失败
*/ */
public String yuxinReservationCharging(YuxinReservationChargingCommand command) { public String yuxinReservationCharging(YuxinReservationChargingCommand command) {
byte[] bytes = ykcPushCommandService.pushYuxinReservationChargingCommand(command); byte[] bytes = ykcPushCommandService.pushYuxinReservationChargingCommand(command);
return parseReservationChargingResponse(bytes); return parseYuxinReservationChargingResponse(bytes);
}
private String parseYuxinReservationChargingResponse(byte[] bytes) {
String result = "0";
if (Objects.isNull(bytes)) {
log.warn("羽信预约启动充电回复为空, 原始报文:null");
return result;
}
String rawMessage = BytesUtil.bin2HexStr(bytes);
try {
YKCDataProtocol ykcDataProtocol = new YKCDataProtocol(bytes);
String responseFrameType = YKCUtils.frameType2Str(ykcDataProtocol.getFrameType());
byte[] msgBody = ykcDataProtocol.getMsgBody();
if (!StringUtils.equals(responseFrameType,
YKCUtils.frameType2Str(YKCFrameTypeCode.YUXIN_RESERVATION_CHARGING_SETUP_ANSWER_CODE.getBytes()))) {
log.warn("羽信预约启动充电回复帧类型异常, 帧类型:{}, 原始报文:{}", responseFrameType, rawMessage);
return result;
}
if (Objects.isNull(msgBody) || msgBody.length < 27) {
log.warn("羽信预约启动充电回复长度异常, 帧类型:{}, 报文体长度:{}, 原始报文:{}",
responseFrameType, Objects.isNull(msgBody) ? null : msgBody.length, rawMessage);
return result;
}
int startIndex = 0;
int length = 16;
byte[] transactionCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String transactionCode = BytesUtil.bcd2Str(transactionCodeByteArr);
startIndex += length;
length = 7;
byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String pileSn = BytesUtil.bcd2Str(pileSnByteArr);
startIndex += length;
length = 1;
byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String connectorCode = parseYuxinConnectorCode(connectorCodeByteArr);
startIndex += length;
length = 1;
byte[] reservationTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String reservationType = BytesUtil.bin2HexStr(reservationTypeByteArr);
startIndex += length;
length = 1;
byte[] resultCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String resultCode = BytesUtil.bin2HexStr(resultCodeByteArr);
startIndex += length;
length = 1;
byte[] failedReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
String failedReason = BytesUtil.bin2HexStr(failedReasonByteArr);
String failedReasonMsg = getYuxinFailedReasonMsg(failedReason);
if (StringUtils.equals(resultCode, "01")) {
result = "1";
}
log.info("{}羽信预约启动充电回复sync, 交易流水号:{}, 桩SN:{}, 枪口号:{}({}), 预约方式:{}({}), 设置结果:{}({}), 失败原因:{}({}), 原始报文:{}",
responseFrameType, transactionCode, pileSn, connectorCode, getYuxinConnectorCodeMsg(connectorCode),
reservationType, getYuxinReservationTypeMsg(reservationType),
resultCode, getYuxinSetupResultMsg(resultCode), failedReason, failedReasonMsg, rawMessage);
if (!StringUtils.equals(resultCode, "01")) {
log.warn("羽信预约启动充电设置失败, 交易流水号:{}, 桩SN:{}, 枪口号:{}({}), 失败原因:{}({}), 原始报文:{}",
transactionCode, pileSn, connectorCode, getYuxinConnectorCodeMsg(connectorCode),
failedReason, failedReasonMsg, rawMessage);
}
} catch (Exception e) {
log.warn("羽信预约启动充电回复解析异常, 原始报文:{}", rawMessage, e);
}
return result;
} }
private String parseReservationChargingResponse(byte[] bytes) { private String parseReservationChargingResponse(byte[] bytes) {
@@ -601,6 +675,31 @@ public class PileRemoteService {
return String.format("%02d", connectorCodeByteArr[0] & 0xFF); return String.format("%02d", connectorCodeByteArr[0] & 0xFF);
} }
private String getYuxinConnectorCodeMsg(String connectorCode) {
if (StringUtils.equals(connectorCode, "00")) {
return "所有枪";
}
return Integer.parseInt(connectorCode) + "号枪";
}
private String getYuxinReservationTypeMsg(String reservationType) {
if (StringUtils.equals(reservationType, "00")) {
return "立即预约";
} else if (StringUtils.equals(reservationType, "01")) {
return "取消预约";
}
return reservationType;
}
private String getYuxinSetupResultMsg(String resultCode) {
if (StringUtils.equals(resultCode, "00")) {
return "失败";
} else if (StringUtils.equals(resultCode, "01")) {
return "成功";
}
return resultCode;
}
private String getYuxinFailedReasonMsg(String failedReason) { private String getYuxinFailedReasonMsg(String failedReason) {
if (StringUtils.equals(failedReason, "00")) { if (StringUtils.equals(failedReason, "00")) {
return ""; return "";

View File

@@ -1,17 +1,8 @@
package com.jsowell.pile.service; package com.jsowell.pile.service;
import com.jsowell.pile.dto.YuxinReservationChargingDTO; import com.jsowell.pile.dto.YuxinReservationChargingDTO;
import com.jsowell.pile.vo.PileReservationInfoVO;
public interface YuxinReservationChargingService { public interface YuxinReservationChargingService {
int createReservation(YuxinReservationChargingDTO dto); void createReservation(YuxinReservationChargingDTO dto);
int updateReservation(YuxinReservationChargingDTO dto);
void cancelReservation(YuxinReservationChargingDTO dto);
void deleteReservation(YuxinReservationChargingDTO dto);
PileReservationInfoVO queryReservationInfo(YuxinReservationChargingDTO dto);
} }

View File

@@ -47,6 +47,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService {
private static final BigDecimal DEFAULT_YUXIN_CHARGING_PARAM = BigDecimal.ZERO; private static final BigDecimal DEFAULT_YUXIN_CHARGING_PARAM = BigDecimal.ZERO;
private static final int DEFAULT_YUXIN_CHARGING_STRATEGY = 0; private static final int DEFAULT_YUXIN_CHARGING_STRATEGY = 0;
private static final int DEFAULT_YUXIN_RESERVATION_TIMEOUT = 0; private static final int DEFAULT_YUXIN_RESERVATION_TIMEOUT = 0;
private static final int YUXIN_RESERVATION_RESPONSE_TIMEOUT_SECONDS = 5;
@Autowired @Autowired
private PileBillingTemplateService pileBillingTemplateService; private PileBillingTemplateService pileBillingTemplateService;
@@ -786,13 +787,17 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService {
public byte[] pushYuxinReservationChargingCommand(YuxinReservationChargingCommand command) { public byte[] pushYuxinReservationChargingCommand(YuxinReservationChargingCommand command) {
String pileSn = command.getPileSn(); String pileSn = command.getPileSn();
byte[] msg = buildYuxinReservationChargingMsg(command); byte[] msg = buildYuxinReservationChargingMsg(command);
log.info("羽信预约充电下发原始报文, pileSn:{}, rawMessage:{}", pileSn, BytesUtil.bin2HexStr(msg));
byte[] response; byte[] response;
try { try {
response = this.supplySend(msg, pileSn, YKCFrameTypeCode.YUXIN_RESERVATION_CHARGING_SETUP_CODE); response = this.supplySend(msg, pileSn, YKCFrameTypeCode.YUXIN_RESERVATION_CHARGING_SETUP_CODE,
YUXIN_RESERVATION_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
} catch (Exception e) { } catch (Exception e) {
log.error("发送羽信预约充电消息异常", e); log.error("发送羽信预约充电消息异常", e);
response = null; response = null;
} }
log.info("羽信预约充电回复原始报文, pileSn:{}, rawMessage:{}",
pileSn, response == null ? "null" : BytesUtil.bin2HexStr(response));
log.info("【=====平台下发指令=====】: 羽信预约充电指令, 帧类型:{}, 交易流水号:{}, 桩编号:{}, 枪口号:{}, 账户余额:{}, 预约类型(00-立即预约;01-取消预约):{}, 充电策略:{}, 充电参数:{}, 系统时间:{}, 预约启动时间:{}, 预约超时时间:{}", log.info("【=====平台下发指令=====】: 羽信预约充电指令, 帧类型:{}, 交易流水号:{}, 桩编号:{}, 枪口号:{}, 账户余额:{}, 预约类型(00-立即预约;01-取消预约):{}, 充电策略:{}, 充电参数:{}, 系统时间:{}, 预约启动时间:{}, 预约超时时间:{}",
YKCUtils.frameType2Str(YKCFrameTypeCode.YUXIN_RESERVATION_CHARGING_SETUP_CODE.getBytes()), YKCUtils.frameType2Str(YKCFrameTypeCode.YUXIN_RESERVATION_CHARGING_SETUP_CODE.getBytes()),

View File

@@ -1,7 +1,6 @@
package com.jsowell.pile.service.impl; package com.jsowell.pile.service.impl;
import com.jsowell.common.constant.Constants; import com.jsowell.common.constant.Constants;
import com.jsowell.common.enums.DelFlagEnum;
import com.jsowell.common.enums.ykc.PileMainboardManufacturerEnum; import com.jsowell.common.enums.ykc.PileMainboardManufacturerEnum;
import com.jsowell.common.enums.ykc.ReturnCodeEnum; import com.jsowell.common.enums.ykc.ReturnCodeEnum;
import com.jsowell.common.exception.BusinessException; import com.jsowell.common.exception.BusinessException;
@@ -10,41 +9,31 @@ import com.jsowell.common.util.PileProgramVersionUtils;
import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.StringUtils;
import com.jsowell.common.util.YKCUtils; import com.jsowell.common.util.YKCUtils;
import com.jsowell.pile.domain.PileBasicInfo; import com.jsowell.pile.domain.PileBasicInfo;
import com.jsowell.pile.domain.PileReservationInfo;
import com.jsowell.pile.domain.ykcCommond.YuxinReservationChargingCommand; import com.jsowell.pile.domain.ykcCommond.YuxinReservationChargingCommand;
import com.jsowell.pile.dto.YuxinReservationChargingDTO; import com.jsowell.pile.dto.YuxinReservationChargingDTO;
import com.jsowell.pile.mapper.PileReservationInfoMapper;
import com.jsowell.pile.service.PileBasicInfoService; import com.jsowell.pile.service.PileBasicInfoService;
import com.jsowell.pile.service.PileRemoteService; import com.jsowell.pile.service.PileRemoteService;
import com.jsowell.pile.service.YuxinReservationChargingService; import com.jsowell.pile.service.YuxinReservationChargingService;
import com.jsowell.pile.vo.PileReservationInfoVO;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Time; import java.sql.Time;
import java.time.Duration; import java.time.Duration;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.LocalTime; import java.time.LocalTime;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
@Service @Service
public class YuxinReservationChargingServiceImpl implements YuxinReservationChargingService { public class YuxinReservationChargingServiceImpl implements YuxinReservationChargingService {
private static final String YUXIN_RESERVATION_TYPE_CREATE = "00"; private static final String YUXIN_RESERVATION_TYPE_CREATE = "00";
private static final String YUXIN_RESERVATION_TYPE_CANCEL = "01";
private static final BigDecimal YUXIN_ACCOUNT_BALANCE = new BigDecimal("999.99"); private static final BigDecimal YUXIN_ACCOUNT_BALANCE = new BigDecimal("999.99");
private static final BigDecimal DEFAULT_CHARGING_PARAM = BigDecimal.ZERO; private static final int TIME_CONTROL_CHARGING_STRATEGY = 1;
private static final int DEFAULT_CHARGING_STRATEGY = 0; private static final int DEFAULT_RESERVATION_TIMEOUT_MINUTES = 0xFF;
@Resource
private PileReservationInfoMapper pileReservationInfoMapper;
@Autowired @Autowired
private PileRemoteService pileRemoteService; private PileRemoteService pileRemoteService;
@@ -53,198 +42,47 @@ public class YuxinReservationChargingServiceImpl implements YuxinReservationChar
private PileBasicInfoService pileBasicInfoService; private PileBasicInfoService pileBasicInfoService;
@Override @Override
public int createReservation(YuxinReservationChargingDTO dto) { public void createReservation(YuxinReservationChargingDTO dto) {
validateCreateOrUpdateParam(dto); validateCreateOrUpdateParam(dto);
normalizePileInfo(dto); normalizePileInfo(dto);
assertYuxinMainboard(dto.getPileSn()); assertYuxinMainboard(dto.getPileSn());
PileReservationInfo currentReservation = pileReservationInfoMapper.selectByPileConnectorCode(dto.getPileConnectorCode()); sendYuxinReservationCommandAndAssertSuccess(dto, YUXIN_RESERVATION_TYPE_CREATE);
PileReservationInfo oldReservation = currentReservation == null ? null : copyReservationInfo(currentReservation);
boolean oldActive = oldReservation != null && StringUtils.equals(oldReservation.getStatus(), Constants.ONE);
PileReservationInfo reservationInfo = currentReservation == null ? new PileReservationInfo() : currentReservation;
fillReservationInfo(reservationInfo, dto);
if (currentReservation == null) {
reservationInfo.setCreateBy(dto.getMemberId());
} else {
reservationInfo.setUpdateBy(dto.getMemberId());
}
if (!isTimeSlotAvailable(dto.getMemberId(), dto.getPileSn(), reservationInfo.getStartTime(),
reservationInfo.getEndTime(), reservationInfo.getId())) {
throw new BusinessException(ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_REFUSED);
}
if (oldActive) {
cancelOldReservationBeforeCreate(dto, oldReservation);
}
sendYuxinReservationCommandAndAssertSuccess(dto, reservationInfo, YUXIN_RESERVATION_TYPE_CREATE);
pileReservationInfoMapper.insertOrUpdateSelective(reservationInfo);
return reservationInfo.getId();
}
@Override
public int updateReservation(YuxinReservationChargingDTO dto) {
if (StringUtils.isBlank(dto.getReservedId())) {
throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR);
}
PileReservationInfo reservationInfo = pileReservationInfoMapper.selectByPrimaryKey(Integer.valueOf(dto.getReservedId()));
if (reservationInfo == null) {
return 0;
}
dto.setPileSn(StringUtils.defaultIfBlank(dto.getPileSn(), reservationInfo.getPileSn()));
dto.setPileConnectorCode(StringUtils.defaultIfBlank(dto.getPileConnectorCode(), reservationInfo.getPileConnectorCode()));
dto.setStartTime(StringUtils.defaultIfBlank(dto.getStartTime(), reservationInfo.getStartTime().toString()));
dto.setEndTime(StringUtils.defaultIfBlank(dto.getEndTime(), reservationInfo.getEndTime().toString()));
assertYuxinMainboard(dto.getPileSn());
PileReservationInfo oldReservation = copyReservationInfo(reservationInfo);
fillReservationInfo(reservationInfo, dto);
reservationInfo.setUpdateBy(dto.getMemberId());
if (!isTimeSlotAvailable(dto.getMemberId(), dto.getPileSn(), reservationInfo.getStartTime(),
reservationInfo.getEndTime(), reservationInfo.getId())) {
throw new BusinessException(ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_REFUSED);
}
if (StringUtils.equals(oldReservation.getStatus(), Constants.ONE)) {
cancelOldReservationBeforeCreate(dto, oldReservation);
}
sendYuxinReservationCommandAndAssertSuccess(dto, reservationInfo, YUXIN_RESERVATION_TYPE_CREATE);
return pileReservationInfoMapper.insertOrUpdateSelective(reservationInfo);
}
@Override
public void cancelReservation(YuxinReservationChargingDTO dto) {
if (StringUtils.isBlank(dto.getReservedId())) {
throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR);
}
PileReservationInfo reservationInfo = pileReservationInfoMapper.selectByPrimaryKey(Integer.valueOf(dto.getReservedId()));
if (reservationInfo == null) {
return;
}
assertYuxinMainboard(reservationInfo.getPileSn());
boolean cancelSuccess = true;
if (StringUtils.equals(reservationInfo.getStatus(), Constants.ONE)) {
cancelSuccess = sendYuxinReservationCommand(dto, reservationInfo, YUXIN_RESERVATION_TYPE_CANCEL);
}
if (!cancelSuccess && !isReservationTimeEnded(reservationInfo)) {
throwReservationCommandFailed();
}
if (!cancelSuccess) {
log.warn("羽信取消预约失败, 但预约时间窗已过期, 本地停用预约, memberId:{}, reservation:{}",
dto.getMemberId(), reservationLogText(reservationInfo));
}
reservationInfo.setStatus(Constants.ZERO);
reservationInfo.setUpdateBy(dto.getMemberId());
pileReservationInfoMapper.updateByPrimaryKeySelective(reservationInfo);
}
@Override
public void deleteReservation(YuxinReservationChargingDTO dto) {
if (StringUtils.isBlank(dto.getReservedId())) {
throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR);
}
PileReservationInfo reservationInfo = pileReservationInfoMapper.selectByPrimaryKey(Integer.valueOf(dto.getReservedId()));
if (Objects.isNull(reservationInfo)) {
return;
}
assertYuxinMainboard(reservationInfo.getPileSn());
boolean cancelSuccess = true;
if (StringUtils.equals(reservationInfo.getStatus(), Constants.ONE)) {
cancelSuccess = sendYuxinReservationCommand(dto, reservationInfo, YUXIN_RESERVATION_TYPE_CANCEL);
}
if (!cancelSuccess && !isReservationTimeEnded(reservationInfo)) {
throwReservationCommandFailed();
}
reservationInfo.setStatus(Constants.ZERO);
reservationInfo.setDelFlag(DelFlagEnum.DELETE.getValue());
reservationInfo.setUpdateBy(dto.getMemberId());
pileReservationInfoMapper.updateByPrimaryKey(reservationInfo);
}
@Override
public PileReservationInfoVO queryReservationInfo(YuxinReservationChargingDTO dto) {
if (StringUtils.isBlank(dto.getPileConnectorCode())) {
throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR);
}
PileReservationInfo reservationInfo = pileReservationInfoMapper.selectByPileConnectorCode(dto.getPileConnectorCode());
if (reservationInfo == null) {
return null;
}
return PileReservationInfoVO.builder()
.reservedId(reservationInfo.getId() + "")
.pileSn(reservationInfo.getPileSn())
.pileConnectorCode(reservationInfo.getPileConnectorCode())
.startTime(reservationInfo.getStartTime().toString())
.endTime(reservationInfo.getEndTime().toString())
.verifyIdentity(reservationInfo.getVerifyIdentity())
.status(reservationInfo.getStatus())
.build();
}
private void fillReservationInfo(PileReservationInfo reservationInfo, YuxinReservationChargingDTO dto) {
reservationInfo.setMemberId(dto.getMemberId());
reservationInfo.setPileSn(dto.getPileSn());
reservationInfo.setPileConnectorCode(dto.getPileConnectorCode());
reservationInfo.setStatus(Constants.ONE);
reservationInfo.setDelFlag(DelFlagEnum.NORMAL.getValue());
reservationInfo.setReservationType("recurring");
reservationInfo.setFreq("daily");
reservationInfo.setVerifyIdentity(Constants.ZERO);
reservationInfo.setStartTime(parseSqlTime(dto.getStartTime()));
reservationInfo.setEndTime(parseSqlTime(dto.getEndTime()));
if (reservationInfo.getId() == null) {
reservationInfo.setCreateTime(DateUtils.getNowDate());
} else {
reservationInfo.setUpdateTime(DateUtils.getNowDate());
}
}
private void cancelOldReservationBeforeCreate(YuxinReservationChargingDTO dto, PileReservationInfo oldReservation) {
boolean cancelSuccess = sendYuxinReservationCommand(dto, oldReservation, YUXIN_RESERVATION_TYPE_CANCEL);
if (!cancelSuccess && !isReservationTimeEnded(oldReservation)) {
throwReservationCommandFailed();
}
if (!cancelSuccess) {
log.warn("羽信预约新时间前取消旧预约失败, 但旧预约时间窗已过期, 继续预约新时间, memberId:{}, oldReservation:{}",
dto.getMemberId(), reservationLogText(oldReservation));
}
} }
private void sendYuxinReservationCommandAndAssertSuccess(YuxinReservationChargingDTO dto, private void sendYuxinReservationCommandAndAssertSuccess(YuxinReservationChargingDTO dto,
PileReservationInfo reservationInfo,
String yuxinReservationType) { String yuxinReservationType) {
if (!sendYuxinReservationCommand(dto, reservationInfo, yuxinReservationType)) { if (!sendYuxinReservationCommand(dto, yuxinReservationType)) {
throwReservationCommandFailed(); throwReservationCommandFailed();
} }
} }
private boolean sendYuxinReservationCommand(YuxinReservationChargingDTO dto, private boolean sendYuxinReservationCommand(YuxinReservationChargingDTO dto,
PileReservationInfo reservationInfo,
String yuxinReservationType) { String yuxinReservationType) {
YuxinReservationChargingCommand command = buildYuxinReservationChargingCommand(dto, reservationInfo, yuxinReservationType); YuxinReservationChargingCommand command = buildYuxinReservationChargingCommand(dto, yuxinReservationType);
log.info("羽信预约充电指令下发, memberId:{}, reservedId:{}, reservationType:{}, reservation:{}", log.info("羽信预约充电指令下发, memberId:{}, reservationType:{}, command:{}",
dto.getMemberId(), reservationInfo.getId(), yuxinReservationType, reservationLogText(reservationInfo)); dto.getMemberId(), yuxinReservationType, reservationLogText(dto, command));
String result = pileRemoteService.yuxinReservationCharging(command); String result = pileRemoteService.yuxinReservationCharging(command);
boolean success = StringUtils.equals(result, Constants.ONE); boolean success = StringUtils.equals(result, Constants.ONE);
log.info("羽信预约充电指令返回, memberId:{}, reservedId:{}, reservationType:{}, result:{}, success:{}", log.info("羽信预约充电指令返回, memberId:{}, reservationType:{}, result:{}, success:{}",
dto.getMemberId(), reservationInfo.getId(), yuxinReservationType, result, success); dto.getMemberId(), yuxinReservationType, result, success);
return success; return success;
} }
private YuxinReservationChargingCommand buildYuxinReservationChargingCommand(YuxinReservationChargingDTO dto, private YuxinReservationChargingCommand buildYuxinReservationChargingCommand(YuxinReservationChargingDTO dto,
PileReservationInfo reservationInfo,
String yuxinReservationType) { String yuxinReservationType) {
LocalTime startTime = parseSqlTime(dto.getStartTime()).toLocalTime();
return YuxinReservationChargingCommand.builder() return YuxinReservationChargingCommand.builder()
.transactionCode(Constants.ILLEGAL_TRANSACTION_CODE) .transactionCode(Constants.ILLEGAL_TRANSACTION_CODE)
.pileSn(reservationInfo.getPileSn()) .pileSn(dto.getPileSn())
.connectorCode(getConnectorCode(reservationInfo)) .connectorCode(getConnectorCode(dto))
.accountBalance(YUXIN_ACCOUNT_BALANCE) .accountBalance(YUXIN_ACCOUNT_BALANCE)
.reservationType(yuxinReservationType) .reservationType(yuxinReservationType)
.chargingStrategy(dto.getChargingStrategy() == null ? DEFAULT_CHARGING_STRATEGY : dto.getChargingStrategy()) .chargingStrategy(TIME_CONTROL_CHARGING_STRATEGY)
.chargingParam(dto.getChargingParam() == null ? DEFAULT_CHARGING_PARAM : dto.getChargingParam()) .chargingParam(getChargingHours(dto))
.systemTime(new Date()) .systemTime(new Date())
.reservedStartTime(getReservedStartDate(reservationInfo.getStartTime().toLocalTime(), yuxinReservationType)) .reservedStartTime(getReservedStartDate(startTime, yuxinReservationType))
.reservationTimeout(getReservationTimeout(dto, reservationInfo, yuxinReservationType)) .reservationTimeout(getReservationTimeout(dto))
.build(); .build();
} }
@@ -258,26 +96,26 @@ public class YuxinReservationChargingServiceImpl implements YuxinReservationChar
return DateUtils.localDateTime2Date(reservedStartDateTime); return DateUtils.localDateTime2Date(reservedStartDateTime);
} }
private int getReservationTimeout(YuxinReservationChargingDTO dto, private int getReservationTimeout(YuxinReservationChargingDTO dto) {
PileReservationInfo reservationInfo,
String yuxinReservationType) {
if (StringUtils.equals(yuxinReservationType, YUXIN_RESERVATION_TYPE_CANCEL)) {
return 0;
}
if (dto.getReservationTimeout() != null) { if (dto.getReservationTimeout() != null) {
return Math.min(Math.max(dto.getReservationTimeout(), 0), 0xFF); return Math.min(Math.max(dto.getReservationTimeout(), 0), 0xFF);
} }
LocalTime startTime = reservationInfo.getStartTime().toLocalTime(); return DEFAULT_RESERVATION_TIMEOUT_MINUTES;
LocalTime endTime = reservationInfo.getEndTime().toLocalTime();
long timeout = Duration.between(startTime, endTime).toMinutes();
if (timeout <= 0) {
timeout += TimeUnit.DAYS.toMinutes(1);
}
return (int) Math.min(timeout, 0xFF);
} }
private String getConnectorCode(PileReservationInfo reservationInfo) { private BigDecimal getChargingHours(YuxinReservationChargingDTO dto) {
return reservationInfo.getPileConnectorCode().replace(reservationInfo.getPileSn(), ""); LocalTime startTime = parseSqlTime(dto.getStartTime()).toLocalTime();
LocalTime endTime = parseSqlTime(dto.getEndTime()).toLocalTime();
long timeout = Duration.between(startTime, endTime).toMinutes();
if (timeout <= 0) {
timeout += Duration.ofDays(1).toMinutes();
}
return BigDecimal.valueOf(timeout)
.divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP);
}
private String getConnectorCode(YuxinReservationChargingDTO dto) {
return dto.getPileConnectorCode().replace(dto.getPileSn(), "");
} }
private void normalizePileInfo(YuxinReservationChargingDTO dto) { private void normalizePileInfo(YuxinReservationChargingDTO dto) {
@@ -305,39 +143,6 @@ public class YuxinReservationChargingServiceImpl implements YuxinReservationChar
return Time.valueOf(time); return Time.valueOf(time);
} }
private boolean isTimeSlotAvailable(String memberId, String pileSn, Time startTime, Time endTime, Integer reservationId) {
List<PileReservationInfo> reservations = pileReservationInfoMapper.findByMemberIdAndPileSnAndStatus(memberId, pileSn, Constants.ONE);
LocalTime newStartTime = startTime.toLocalTime();
LocalTime newEndTime = endTime.toLocalTime();
for (PileReservationInfo res : reservations) {
if (reservationId != null && res.getId().equals(reservationId)) {
continue;
}
LocalTime existingStartTime = res.getStartTime().toLocalTime();
LocalTime existingEndTime = res.getEndTime().toLocalTime();
if (newStartTime.isBefore(existingEndTime) && newEndTime.isAfter(existingStartTime)) {
return false;
}
}
return true;
}
private boolean isReservationTimeEnded(PileReservationInfo reservationInfo) {
if (reservationInfo == null || reservationInfo.getStartTime() == null || reservationInfo.getEndTime() == null) {
return false;
}
LocalTime now = LocalTime.now();
LocalTime startTime = reservationInfo.getStartTime().toLocalTime();
LocalTime endTime = reservationInfo.getEndTime().toLocalTime();
boolean crossDay = endTime.isBefore(startTime);
boolean ended = crossDay
? !now.isBefore(endTime) && now.isBefore(startTime)
: !endTime.isAfter(now);
log.info("羽信预约过期判断, reservedId:{}, pileConnectorCode:{}, now:{}, startTime:{}, endTime:{}, crossDay:{}, ended:{}",
reservationInfo.getId(), reservationInfo.getPileConnectorCode(), now, startTime, endTime, crossDay, ended);
return ended;
}
private void assertYuxinMainboard(String pileSn) { private void assertYuxinMainboard(String pileSn) {
PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn);
String programVersion = pileBasicInfo == null ? null : pileBasicInfo.getProgramVersion(); String programVersion = pileBasicInfo == null ? null : pileBasicInfo.getProgramVersion();
@@ -352,33 +157,10 @@ public class YuxinReservationChargingServiceImpl implements YuxinReservationChar
ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_ERROR.getLabel() + ": 充电桩返回修改失败"); ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_ERROR.getLabel() + ": 充电桩返回修改失败");
} }
private String reservationLogText(PileReservationInfo reservationInfo) { private String reservationLogText(YuxinReservationChargingDTO dto, YuxinReservationChargingCommand command) {
if (reservationInfo == null) { return String.format("pileSn=%s,pileConnectorCode=%s,startTime=%s,endTime=%s,chargingStrategy=%s,chargingParam=%s,reservationTimeout=%s",
return "null"; dto.getPileSn(), dto.getPileConnectorCode(), dto.getStartTime(), dto.getEndTime(),
} command.getChargingStrategy(), command.getChargingParam(), command.getReservationTimeout());
return String.format("reservedId=%s,pileSn=%s,pileConnectorCode=%s,status=%s,reservationType=%s,verifyIdentity=%s,startTime=%s,endTime=%s",
reservationInfo.getId(), reservationInfo.getPileSn(), reservationInfo.getPileConnectorCode(),
reservationInfo.getStatus(), reservationInfo.getReservationType(), reservationInfo.getVerifyIdentity(),
reservationInfo.getStartTime(), reservationInfo.getEndTime());
} }
private PileReservationInfo copyReservationInfo(PileReservationInfo source) {
PileReservationInfo target = new PileReservationInfo();
target.setId(source.getId());
target.setMemberId(source.getMemberId());
target.setPileSn(source.getPileSn());
target.setPileConnectorCode(source.getPileConnectorCode());
target.setStatus(source.getStatus());
target.setReservationType(source.getReservationType());
target.setVerifyIdentity(source.getVerifyIdentity());
target.setStartTime(source.getStartTime());
target.setEndTime(source.getEndTime());
target.setFreq(source.getFreq());
target.setCreateBy(source.getCreateBy());
target.setCreateTime(source.getCreateTime());
target.setUpdateBy(source.getUpdateBy());
target.setUpdateTime(source.getUpdateTime());
target.setDelFlag(source.getDelFlag());
return target;
}
} }

View File

@@ -83,17 +83,32 @@ public class JsowellTask {
@Autowired @Autowired
private AdapayUnsplitRecordHandleService adapayUnsplitRecordHandleService; private AdapayUnsplitRecordHandleService adapayUnsplitRecordHandleService;
private static final String PRE_PROFILE = "pre";
private static final long YKC_DAILY_TIMECHECK_INTERVAL_MILLIS = 200L; private static final long YKC_DAILY_TIMECHECK_INTERVAL_MILLIS = 200L;
/** /**
* 设置挡板, PRE环境不执行 * 设置挡板, PRE环境不执行
*/ */
public void setBarrier() { public void setBarrier() {
String env = SpringUtils.getActiveProfile(); skipInPre("设置挡板");
if (StringUtils.equalsIgnoreCase(env, "pre")) { }
log.debug("PRE环境不执行");
// return; private boolean skipInPre(String taskName) {
if (!isPreProfile()) {
return false;
} }
log.info("PRE环境不执行{}", taskName);
return true;
}
private boolean isPreProfile() {
String[] activeProfiles = SpringUtils.getActiveProfiles();
if (activeProfiles == null) {
return false;
}
return Arrays.stream(activeProfiles)
.anyMatch(profile -> StringUtils.equalsIgnoreCase(profile, PRE_PROFILE));
} }
/** /**
@@ -101,9 +116,7 @@ public class JsowellTask {
* close15MinutesOfUnpaidOrders * close15MinutesOfUnpaidOrders
*/ */
public void close15MinutesOfUnpaidOrders() { public void close15MinutesOfUnpaidOrders() {
String env = SpringUtils.getActiveProfile(); if (skipInPre("关闭15分钟未支付的订单")) {
if (StringUtils.equalsIgnoreCase(env, "pre")) {
log.debug("PRE环境不执行");
return; return;
} }
// log.info("关闭15分钟未支付的订单"); // log.info("关闭15分钟未支付的订单");
@@ -115,10 +128,8 @@ public class JsowellTask {
* 订单支付成功在15分钟内未启动 * 订单支付成功在15分钟内未启动
*/ */
public void closeStartFailedOrder() { public void closeStartFailedOrder() {
String env = SpringUtils.getActiveProfile(); if (skipInPre("关闭启动失败的订单")) {
if (StringUtils.equalsIgnoreCase(env, "pre")) { return;
log.debug("PRE环境不执行");
// return;
} }
// 查询出最近2天支付成功并且订单状态为未启动的订单 // 查询出最近2天支付成功并且订单状态为未启动的订单
String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.addDays(new Date(), -2)); String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.addDays(new Date(), -2));
@@ -130,9 +141,7 @@ public class JsowellTask {
* 查询预约充电的订单并启动 * 查询预约充电的订单并启动
*/ */
public void appointmentOrderStart() { public void appointmentOrderStart() {
String env = SpringUtils.getActiveProfile(); if (skipInPre("查询预约充电的订单并启动")) {
if (StringUtils.equalsIgnoreCase(env, "pre")) {
log.debug("PRE环境不执行");
return; return;
} }
// 查询出 已支付 设置预约充电 未启动 的订单 // 查询出 已支付 设置预约充电 未启动 的订单
@@ -187,9 +196,7 @@ public class JsowellTask {
* jsowellTask.dailyProofreadTimeForYkcV160(200) * jsowellTask.dailyProofreadTimeForYkcV160(200)
*/ */
public void dailyProofreadTimeForYkcV160(Long intervalMillis) { public void dailyProofreadTimeForYkcV160(Long intervalMillis) {
String env = SpringUtils.getActiveProfile(); if (skipInPre("云快充1.6每日自动对时")) {
if (StringUtils.equalsIgnoreCase(env, "pre")) {
log.debug("PRE环境不执行");
return; return;
} }
@@ -250,9 +257,7 @@ public class JsowellTask {
* jsowellTask.calculateTheSiteOrdersReport() * jsowellTask.calculateTheSiteOrdersReport()
*/ */
public void calculateTheSiteOrdersReport() { public void calculateTheSiteOrdersReport() {
String env = SpringUtils.getActiveProfile(); if (skipInPre("计算站点订单报表")) {
if (StringUtils.equalsIgnoreCase(env, "pre")) {
log.debug("PRE环境不执行");
return; return;
} }
// 查询出所有站点 // 查询出所有站点
@@ -279,9 +284,7 @@ public class JsowellTask {
* jsowellTask.pushToAMap() * jsowellTask.pushToAMap()
*/ */
public void pushToAMap() { public void pushToAMap() {
String env = SpringUtils.getActiveProfile(); if (skipInPre("站点的枪口数据推送到高德")) {
if (StringUtils.equalsIgnoreCase(env, "pre")) {
log.debug("PRE环境不执行");
return; return;
} }
Set<String> stationIds = redisCache.getCacheSet(CacheConstants.PUSH_STATION_CONNECTOR); Set<String> stationIds = redisCache.getCacheSet(CacheConstants.PUSH_STATION_CONNECTOR);
@@ -304,9 +307,7 @@ public class JsowellTask {
* 贵州省平台推送充电站实时功率 15分钟执行一次 * 贵州省平台推送充电站实时功率 15分钟执行一次
*/ */
public void pushStationRealTimePowerInfo() { public void pushStationRealTimePowerInfo() {
String env = SpringUtils.getActiveProfile(); if (skipInPre("贵州省平台推送充电站实时功率")) {
if (StringUtils.equalsIgnoreCase(env, "pre")) {
log.debug("PRE环境不执行");
return; return;
} }
@@ -344,9 +345,7 @@ public class JsowellTask {
* 推送统计信息 24小时执行一次 * 推送统计信息 24小时执行一次
*/ */
public void pushStatisticsInfo() { public void pushStatisticsInfo() {
String env = SpringUtils.getActiveProfile(); if (skipInPre("推送统计信息 24小时执行一次")) {
if (StringUtils.equalsIgnoreCase(env, "pre")) {
log.debug("PRE环境不执行");
return; return;
} }
@@ -385,9 +384,7 @@ public class JsowellTask {
* jsowellTask.processOrderSplitting() * jsowellTask.processOrderSplitting()
*/ */
public void processOrderSplitting() { public void processOrderSplitting() {
String env = SpringUtils.getActiveProfile(); if (skipInPre("定时任务, 订单分账")) {
if (StringUtils.equalsIgnoreCase(env, "pre")) {
log.debug("PRE环境不执行");
return; return;
} }
// 查询运营商列表 // 查询运营商列表
@@ -424,9 +421,7 @@ public class JsowellTask {
* *
*/ */
public void generateMerchantBill() { public void generateMerchantBill() {
String env = SpringUtils.getActiveProfile(); if (skipInPre("生成运营商日报表")) {
if (StringUtils.equalsIgnoreCase(env, "pre")) {
log.debug("PRE环境不执行");
return; return;
} }
// 查询运营商列表 // 查询运营商列表
@@ -453,9 +448,7 @@ public class JsowellTask {
* jsowellTask.automaticPayouts() * jsowellTask.automaticPayouts()
*/ */
public void automaticPayouts() { public void automaticPayouts() {
String env = SpringUtils.getActiveProfile(); if (skipInPre("定时任务,自动提现")) {
if (StringUtils.equalsIgnoreCase(env, "pre")) {
log.debug("PRE环境不执行");
return; return;
} }
// 查询开启自动提现运营商列表 // 查询开启自动提现运营商列表
@@ -484,6 +477,9 @@ public class JsowellTask {
* jsowellTask.processUnSettledOrder() * jsowellTask.processUnSettledOrder()
*/ */
public void processUnSettledOrder() { public void processUnSettledOrder() {
if (skipInPre("处理未分帐订单")) {
return;
}
adapayUnsplitRecordHandleService.processUnSettledOrder(); adapayUnsplitRecordHandleService.processUnSettledOrder();
} }
@@ -493,6 +489,9 @@ public class JsowellTask {
* jsowellTask.processUnsplitRecordToDefaultMember() * jsowellTask.processUnsplitRecordToDefaultMember()
*/ */
public void processUnsplitRecordToDefaultMember() { public void processUnsplitRecordToDefaultMember() {
if (skipInPre("处理adapay_unsplit_record待分账数据")) {
return;
}
adapayUnsplitRecordHandleService.processUnsplitRecordToDefaultMember(); adapayUnsplitRecordHandleService.processUnsplitRecordToDefaultMember();
} }
@@ -501,6 +500,9 @@ public class JsowellTask {
* jsowellTask.processUnsplitRecordToDefaultMember(wechatAppId, pageSize) * jsowellTask.processUnsplitRecordToDefaultMember(wechatAppId, pageSize)
*/ */
public void processUnsplitRecordToDefaultMember(String wechatAppId, Integer pageSize) { public void processUnsplitRecordToDefaultMember(String wechatAppId, Integer pageSize) {
if (skipInPre("处理adapay_unsplit_record待分账数据")) {
return;
}
adapayUnsplitRecordHandleService.processUnsplitRecordToDefaultMember(wechatAppId, pageSize); adapayUnsplitRecordHandleService.processUnsplitRecordToDefaultMember(wechatAppId, pageSize);
} }
@@ -515,6 +517,9 @@ public class JsowellTask {
* jsowellTask.importAdapayUnsplitRecordAndCompleteFields() * jsowellTask.importAdapayUnsplitRecordAndCompleteFields()
*/ */
public void importAdapayUnsplitRecordAndCompleteFields() { public void importAdapayUnsplitRecordAndCompleteFields() {
if (skipInPre("从Excel导入adapay_unsplit_record并补齐缺失字段")) {
return;
}
adapayUnsplitRecordHandleService.importAdapayUnsplitRecordAndCompleteFields(); adapayUnsplitRecordHandleService.importAdapayUnsplitRecordAndCompleteFields();
} }
@@ -525,6 +530,9 @@ public class JsowellTask {
* 示例jsowellTask.completeAdapayUnsplitRecordFields('2024-01-01 00:00:00', '2025-12-31 23:59:59') * 示例jsowellTask.completeAdapayUnsplitRecordFields('2024-01-01 00:00:00', '2025-12-31 23:59:59')
*/ */
public void completeAdapayUnsplitRecordFields(String startTime, String endTime) { public void completeAdapayUnsplitRecordFields(String startTime, String endTime) {
if (skipInPre("补齐adapay_unsplit_record表中缺失字段")) {
return;
}
adapayUnsplitRecordHandleService.completeAdapayUnsplitRecordFields(startTime, endTime); adapayUnsplitRecordHandleService.completeAdapayUnsplitRecordFields(startTime, endTime);
} }
@@ -533,6 +541,9 @@ public class JsowellTask {
* jsowellTask.syncAndRefreshFlagsFromAdapay(paymentId, wechatAppId) * jsowellTask.syncAndRefreshFlagsFromAdapay(paymentId, wechatAppId)
*/ */
public void syncAndRefreshFlagsFromAdapay(String paymentId, String wechatAppId) { public void syncAndRefreshFlagsFromAdapay(String paymentId, String wechatAppId) {
if (skipInPre("按paymentId从汇付同步并刷新adapay_unsplit_record标识")) {
return;
}
adapayUnsplitRecordHandleService.syncAndRefreshFlagsFromAdapay(paymentId, wechatAppId); adapayUnsplitRecordHandleService.syncAndRefreshFlagsFromAdapay(paymentId, wechatAppId);
} }
@@ -542,6 +553,9 @@ public class JsowellTask {
* 示例jsowellTask.syncAndRefreshFlagsFromAdapay('2024-01-01 00:00:00', '2025-12-31 23:59:59', 'app_id', 500) * 示例jsowellTask.syncAndRefreshFlagsFromAdapay('2024-01-01 00:00:00', '2025-12-31 23:59:59', 'app_id', 500)
*/ */
public void syncAndRefreshFlagsFromAdapay(String startTime, String endTime, String wechatAppId, Integer pageSize) { public void syncAndRefreshFlagsFromAdapay(String startTime, String endTime, String wechatAppId, Integer pageSize) {
if (skipInPre("批量从汇付同步并刷新adapay_unsplit_record标识")) {
return;
}
adapayUnsplitRecordHandleService.syncAndRefreshFlagsFromAdapay(startTime, endTime, wechatAppId, pageSize); adapayUnsplitRecordHandleService.syncAndRefreshFlagsFromAdapay(startTime, endTime, wechatAppId, pageSize);
} }
@@ -555,10 +569,16 @@ public class JsowellTask {
* jsowellTask.importAdapayUnsplitRecordAndCompleteFields(文件路径) * jsowellTask.importAdapayUnsplitRecordAndCompleteFields(文件路径)
*/ */
public void importAdapayUnsplitRecordAndCompleteFields(String filePath) { public void importAdapayUnsplitRecordAndCompleteFields(String filePath) {
if (skipInPre("从Excel导入adapay_unsplit_record并补齐缺失字段")) {
return;
}
adapayUnsplitRecordHandleService.importAdapayUnsplitRecordAndCompleteFields(filePath); adapayUnsplitRecordHandleService.importAdapayUnsplitRecordAndCompleteFields(filePath);
} }
public void updateOrderReview() { public void updateOrderReview() {
if (skipInPre("更新订单评价标识")) {
return;
}
LocalDate yesterday = DateUtils.getYesterday(); LocalDate yesterday = DateUtils.getYesterday();
LocalDateTime start = yesterday.atStartOfDay(); LocalDateTime start = yesterday.atStartOfDay();
LocalDateTime end = yesterday.atTime(23, 59, 59); LocalDateTime end = yesterday.atTime(23, 59, 59);