Merge branch 'dev' into dev-g

This commit is contained in:
Guoqs
2025-06-24 16:14:20 +08:00
20 changed files with 1766 additions and 69 deletions

View File

@@ -0,0 +1,202 @@
package com.jsowell.api.thirdparty;
import com.alibaba.fastjson2.JSON;
import com.jsowell.common.annotation.Anonymous;
import com.jsowell.common.enums.thirdparty.ThirdPartyReturnCodeEnum;
import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum;
import com.jsowell.pile.dto.*;
import com.jsowell.pile.thirdparty.CommonParamsDTO;
import com.jsowell.thirdparty.lianlian.common.CommonResult;
import com.jsowell.thirdparty.platform.service.ThirdPartyPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* 四川对接接口
*/
@RestController
@Anonymous
@RequestMapping("/sichuan")
public class SiChuanController extends ThirdPartyBaseController {
private final String platformName = "";
private final String platformType = ThirdPlatformTypeEnum.SI_CHUAN_PLATFORM.getTypeCode();
@Autowired
@Qualifier("siChuanPlatformServiceImpl")
private ThirdPartyPlatformService platformLogic;
/**
* getToken
*/
@PostMapping("/v1/query_token")
public CommonResult<?> queryToken(@RequestBody CommonParamsDTO dto) {
logger.info("{}-请求令牌 params:{}" , platformName , JSON.toJSONString(dto));
try {
// Map<String, String> map = zdlService.generateToken(dto);
Map<String, String> map = platformLogic.queryToken(dto);
logger.info("{}-请求令牌 result:{}" , platformName , map);
return CommonResult.success(0 , "请求令牌成功!" , map.get("Data") , map.get("Sig"));
} catch (Exception e) {
logger.info("{}-请求令牌 error:" , platformName , e);
return CommonResult.failed("获取token发生异常");
}
}
/**
* 查询运营商信息
* supervise_query_operator_info
*/
@PostMapping("/v1/supervise_query_operator_info")
public CommonResult<?> supervise_query_operator_info(HttpServletRequest request , @RequestBody CommonParamsDTO dto) {
logger.info("{}-查询运营商信息 params:{}" , platformName , JSON.toJSONString(dto));
try {
// 校验令牌
if (!verifyToken(request.getHeader("Authorization"))) {
// 校验失败
return CommonResult.failed(ThirdPartyReturnCodeEnum.TOKEN_ERROR);
}
// 校验签名
if (!verifySignature(dto)) {
// 签名错误
return CommonResult.failed(ThirdPartyReturnCodeEnum.SIGN_ERROR);
}
// 解析入参
QueryOperatorInfoDTO queryOperatorInfoDTO = parseParamsDTO(dto , QueryOperatorInfoDTO.class);
// 执行逻辑
Map<String, String> map = platformLogic.queryOperatorInfo(queryOperatorInfoDTO);
logger.info("{}-查询运营商信息 result:{}" , platformName , map);
return CommonResult.success(0 , "查询运营商信息成功!" , map.get("Data") , map.get("Sig"));
} catch (Exception e) {
logger.info("{}-查询运营商信息 error:" , platformName , e);
}
return CommonResult.failed("查询运营商信息发生异常");
}
/**
* 查询充电站信息
* supervise_query_stations_info
*/
@PostMapping("/v1/supervise_query_stations_info")
public CommonResult<?> supervise_query_stations_info(HttpServletRequest request , @RequestBody CommonParamsDTO dto) {
logger.info("{}-查询充电站信息 params:{}" , platformName , JSON.toJSONString(dto));
try {
logger.info("{}-携带的token:{}",platformName, request.getHeader("Authorization"));
// 校验令牌
if (!verifyToken(request.getHeader("Authorization"))) {
// 校验失败
return CommonResult.failed(ThirdPartyReturnCodeEnum.TOKEN_ERROR);
}
// 校验签名
if (!verifySignature(dto)) {
// 签名错误
return CommonResult.failed(ThirdPartyReturnCodeEnum.SIGN_ERROR);
}
// 解析入参
QueryStationInfoDTO queryStationInfoDTO = parseParamsDTO(dto , QueryStationInfoDTO.class);
// 执行逻辑
Map<String, String> map = platformLogic.queryStationsInfo(queryStationInfoDTO);
logger.info("{}-查询充电站信息 result:{}" , platformName , JSON.toJSONString(map));
return CommonResult.success(0 , "查询充电站信息成功!" , map.get("Data") , map.get("Sig"));
} catch (Exception e) {
logger.info("{}-查询充电站信息 error:" , platformName , e);
}
return CommonResult.failed("查询充电站信息发生异常");
}
/**
* 设备接口状态查询 query_station_status
*
* @param request
* @param dto
* @return
*/
@PostMapping("/v1/supervise_query_station_status")
public CommonResult<?> query_stations_status(HttpServletRequest request , @RequestBody CommonParamsDTO dto) {
logger.info("{}-设备接口状态查询 params:{}" , platformName , JSON.toJSONString(dto));
try {
// 校验令牌
if (!verifyToken(request.getHeader("Authorization"))) {
// 校验失败
return CommonResult.failed(ThirdPartyReturnCodeEnum.TOKEN_ERROR);
}
// 校验签名
if (!verifySignature(dto)) {
// 签名错误
return CommonResult.failed(ThirdPartyReturnCodeEnum.SIGN_ERROR);
}
// 解析入参
QueryStationInfoDTO queryStationInfoDTO = parseParamsDTO(dto , QueryStationInfoDTO.class);
// 执行逻辑
Map<String, String> map = platformLogic.queryStationStatus(queryStationInfoDTO);
logger.info("{}-设备接口状态查询 result:{}" , platformName , map);
return CommonResult.success(0 , "设备接口状态查询成功!" , map.get("Data") , map.get("Sig"));
} catch (Exception e) {
logger.info("{}-设备接口状态查询 error:" , platformName , e);
}
return CommonResult.failed("设备接口状态查询发生异常");
}
/**
* 查询补贴发放信息
* supervise_query_subsidy_grant_info
* @param request
* @param dto
* @return
*/
/* @PostMapping("/v1/supervise_query_subsidy_grant_info")
public CommonResult<?> supervise_query_subsidy_grant_info(HttpServletRequest request , @RequestBody CommonParamsDTO dto) {
logger.info("{}-查询补贴发放信息 params:{}" , platformName , JSON.toJSONString(dto));
try {
// 校验令牌
if (!verifyToken(request.getHeader("Authorization"))) {
// 校验失败
return CommonResult.failed(ThirdPartyReturnCodeEnum.TOKEN_ERROR);
}
// 校验签名
if (!verifySignature(dto)) {
// 签名错误
return CommonResult.failed(ThirdPartyReturnCodeEnum.SIGN_ERROR);
}
// 解析入参
QueryStationInfoDTO querySubsidyGrantInfoDTO = parseParamsDTO(dto , QueryStationInfoDTO.class);
// 执行逻辑
Map<String, String> map = platformLogic.querySubsidyGrantInfo(querySubsidyGrantInfoDTO);
logger.info("{}-查询补贴发放信息 result:{}" , platformName , map);
return CommonResult.success(0 , "查询补贴发放信息成功!" , map.get("Data") , map.get("Sig"));
} catch (Exception e) {
logger.info("{}-查询补贴发放信息 error:" , platformName , e);
}
return CommonResult.failed("查询补贴发放信息发生异常");
}*/
}

View File

@@ -8,17 +8,17 @@ spring:
# redis 配置
redis:
# 地址
# host: r-uf6k0uet7mihr5z78f.redis.rds.aliyuncs.com
host: 106.14.94.149
host: r-uf6k0uet7mihr5z78f.redis.rds.aliyuncs.com
# host: 106.14.94.149
# 端口默认为6379
port: 6379
# 数据库索引
database: 0
# 账号
# username: jsowell
# # 密码
# password: js@160829
password: js160829
username: jsowell
# 密码
password: js@160829
# password: js160829
# 连接超时时间
timeout: 10s
lettuce:
@@ -38,12 +38,12 @@ spring:
druid:
# 主库数据源
master:
# url: jdbc:mysql://rm-uf6ra51u33dc3798l.mysql.rds.aliyuncs.com:3306/jsowell_prd?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: jsowell
# password: js@160829
url: jdbc:mysql://106.14.94.149:3306/jsowell_pre?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: jsowell_pre
password: Js@160829
url: jdbc:mysql://rm-uf6ra51u33dc3798l.mysql.rds.aliyuncs.com:3306/jsowell_prd?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: jsowell
password: js@160829
# url: jdbc:mysql://106.14.94.149:3306/jsowell_pre?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: jsowell_pre
# password: Js@160829
# 从库数据源
slave:
# 从数据源开关/默认关闭

View File

@@ -103,6 +103,8 @@ public class Constants {
// public static final String OPERATORID_GUI_ZHOU = "MAC9K4RRX";
public static final String MANUFACTURER_NAME = "举视(江苏)新能源设备制造有限公司";
//设备所属公司
public static final String Equipment_Owner_Name = "举视(上海)新能源科技有限公司";
public static final String OPERATORID_XI_XIAO = "MAC13L2Q9";

View File

@@ -50,4 +50,16 @@ public enum MemberWalletEnum {
this.value = value;
this.label = label;
}
/**
* 根据value获取label
*/
public static String getLabelByValue(String value) {
for (MemberWalletEnum item : MemberWalletEnum.values()) {
if (item.getValue().equals(value)) {
return item.getLabel();
}
}
return "未知类型";
}
}

View File

@@ -18,6 +18,7 @@ public enum ThirdPartyOperatorIdEnum {
HAI_NAN_1("7", "578725200"),
HAI_NAN_2("8", "MAA9A0PP1"),
HUA_WEI("9", "MA5GTQ528"),
CHANG_ZHOU("25", "0585PCW57")
;
private String type;

View File

@@ -36,6 +36,7 @@ public enum ThirdPlatformTypeEnum {
WEI_WANG_XIN_DIAN("23", "微网新电", "MA005DBW1"),
HU_ZHOU_PLATFORM("24", "湖州市监管平台", "MA27U00HZ"),
CHANG_ZHOU_PLATFORM("25", "新运常畅充", "0585PCW57"),
SI_CHUAN_PLATFORM("26", "四川省平台", ""),
;
private String typeCode;

View File

@@ -1,5 +1,6 @@
package com.jsowell.common.enums.ykc;
import java.util.Objects;
/**
* order_basic_info表 order_status字段
* 订单状态(0-未启动1-充电中2-待结算3-待补缴4-异常5-可疑6-订单完成7-超时关闭)
@@ -48,4 +49,21 @@ public enum OrderStatusEnum {
}
return "";
}
// 中电联订单状态转化
public static Integer convertToNewStatus(String orderStatus) {
if (Objects.equals(orderStatus , IN_THE_CHARGING.value)) {
return 2; // 充电中
} else if (Objects.equals(orderStatus , ORDER_COMPLETE.value)) {
return 4; // 充电完成
} else if (Objects.equals(orderStatus , NOT_START.value)) {
return 1; // 启动中
} else if (Objects.equals(orderStatus , STAY_SETTLEMENT.value) || Objects.equals(orderStatus , STAY_RETROACTIVE_AMOUNT.value)) {
return 3; // 停止中
} else {
return 5; // 未知
}
}
}

View File

@@ -22,6 +22,7 @@ import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
@Slf4j
public class YKCUtils {
@@ -474,4 +475,17 @@ public class YKCUtils {
return stationIdList;
}
/**
* 两个BigDecimal, 取出大于0的最小值
* @param settleAmount 结算金额
* @param actualReceivedAmount 实收金额
*/
public static BigDecimal getMinBigDecimal(BigDecimal settleAmount, BigDecimal actualReceivedAmount) {
BigDecimal minValue = Stream.of(settleAmount, actualReceivedAmount)
.filter(v -> v.compareTo(BigDecimal.ZERO) > 0) // 过滤出大于 0 的值
.min(BigDecimal::compareTo) // 取最小值
.orElse(settleAmount); // 如果没有大于 0 的值,则返回结算金额
return minValue;
}
}

View File

@@ -2046,35 +2046,11 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService {
// 根据站点id查询分账配置(如果未配置则初始化)
List<StationSplitConfig> stationSplitConfigList = stationSplitConfigService.queryByStationIdWithInit(stationId);
// 查字典是否开启收取平台支持服务费
// 查字典是否开启收取平台支持服务费 1-开启; 0-关闭
String dictValue = DictUtils.getDictValue("platform_service_flag", "status");
if (StringUtils.equals(dictValue, Constants.ONE)) { // 开启收取平台支持服务费
// 根据站点id查询平台支持服务费率
PileStationInfo pileStationInfo = pileStationInfoService.selectPileStationInfoById(Long.parseLong(stationId));
// 如果是否对接高德为1, 并且支持服务费率大于0, 则收取平台支持服务费
if (pileStationInfo != null
&& StringUtils.equals(pileStationInfo.getAMapFlag(), Constants.ONE)
&& pileStationInfo.getServiceRate().compareTo(BigDecimal.ZERO) > 0) {
// 获取平台支持服务费率
BigDecimal serviceRate = pileStationInfo.getServiceRate();
// 取出stationSplitConfigList中手续费承担方, 并把电费分成比例和服务费分成比例减去serviceRate
for (StationSplitConfig stationSplitConfig : stationSplitConfigList) {
if (Constants.ONE.equals(stationSplitConfig.getFeeFlag())) {
stationSplitConfig.setElectricitySplitRatio(stationSplitConfig.getElectricitySplitRatio().subtract(serviceRate));
stationSplitConfig.setServiceSplitRatio(stationSplitConfig.getServiceSplitRatio().subtract(serviceRate));
}
}
// 添加一个账户, adapayMemberId为0, 电费分成比例为serviceRate, 服务费分成比例为serviceRate
stationSplitConfigList.add(StationSplitConfig.builder()
.adapayMemberId(Constants.ZERO)
.electricitySplitRatio(serviceRate)
.serviceSplitRatio(serviceRate)
.feeFlag(Constants.ZERO)
.build()
);
logger.info("realTimeOrderSplit-订单:{}, 收取平台支持服务费, 平台分成比例为:{}, stationSplitConfigList:{}",
orderCode, serviceRate, JSON.toJSONString(stationSplitConfigList));
}
if (StringUtils.equals(dictValue, Constants.ONE)) {
// 开启收取平台支持服务费, 更新参与分账的账户列表
updateSplitConfigList(stationId, stationSplitConfigList, orderCode);
}
// 计算每个参与分账的用户, 应分多少钱
@@ -2100,12 +2076,72 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService {
.wechatAppId(appId)
.build();
PaymentConfirmResponse paymentConfirmRequest = adapayService.createPaymentConfirmRequest(param);
// 保存订单分账记录
OrderInfoDetailVO orderInfoDetailVO = getOrderInfoDetailVO(orderCode);
orderSplitRecordService.saveOrderSplitRecord(param, paymentConfirmRequest, splitDataList, orderInfoDetailVO);
// 更新订单实收金额
updateOrderReceivedAmount(orderCode, splitDataList);
return paymentConfirmRequest;
}
/**
* 开启了收取平台支持服务费, 更新订单分账账户列表
* @param stationId
* @param stationSplitConfigList
* @param orderCode
*/
private void updateSplitConfigList(String stationId, List<StationSplitConfig> stationSplitConfigList, String orderCode) {
// 根据站点id查询平台支持服务费率
PileStationInfo pileStationInfo = pileStationInfoService.selectPileStationInfoById(Long.parseLong(stationId));
// 如果是否对接高德为1, 并且支持服务费率大于0, 则收取平台支持服务费
if (pileStationInfo != null
&& StringUtils.equals(pileStationInfo.getAMapFlag(), Constants.ONE)
&& pileStationInfo.getServiceRate().compareTo(BigDecimal.ZERO) > 0) {
// 获取平台支持服务费率
BigDecimal serviceRate = pileStationInfo.getServiceRate();
// 取出stationSplitConfigList中手续费承担方, 并把电费分成比例和服务费分成比例减去serviceRate
for (StationSplitConfig stationSplitConfig : stationSplitConfigList) {
if (Constants.ONE.equals(stationSplitConfig.getFeeFlag())) {
stationSplitConfig.setElectricitySplitRatio(stationSplitConfig.getElectricitySplitRatio().subtract(serviceRate));
stationSplitConfig.setServiceSplitRatio(stationSplitConfig.getServiceSplitRatio().subtract(serviceRate));
}
}
// 添加一个账户, adapayMemberId为0, 电费分成比例为serviceRate, 服务费分成比例为serviceRate
stationSplitConfigList.add(StationSplitConfig.builder()
.adapayMemberId(Constants.ZERO)
.electricitySplitRatio(serviceRate)
.serviceSplitRatio(serviceRate)
.feeFlag(Constants.ZERO)
.build()
);
logger.info("realTimeOrderSplit-订单:{}, 收取平台支持服务费, 平台分成比例为:{}, stationSplitConfigList:{}",
orderCode, serviceRate, JSON.toJSONString(stationSplitConfigList));
}
}
/**
* 更新订单实收金额
*/
private void updateOrderReceivedAmount(String orderCode, List<SplitData> splitDataList) {
BigDecimal actualReceivedAmount = BigDecimal.ZERO;
for (SplitData splitData : splitDataList) {
// 如果是手续费承担方, 计算实收金额
if (StringUtils.equals(splitData.getFeeFlag(), Constants.Y)) {
actualReceivedAmount = splitData.getElecAmount().add(splitData.getServiceAmount());
}
}
// 先查再更新
OrderBasicInfo orderInfo = getOrderInfoByOrderCode(orderCode);
if (orderInfo != null && actualReceivedAmount.compareTo(BigDecimal.ZERO) > 0) {
orderInfo.setActualReceivedAmount(actualReceivedAmount);
orderInfo.setUpdateBy(Constants.SYSTEM);
orderInfo.setUpdateTime(DateUtils.getNowDate());
this.updateOrderBasicInfo(orderInfo);
}
}
/**
* 计算每个账户需要分账的金额
* @param stationSplitConfigList 参与分账的账户信息

View File

@@ -17,6 +17,7 @@ import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.DateUtils;
import com.jsowell.common.util.PageUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.common.util.YKCUtils;
import com.jsowell.common.util.id.IdUtils;
import com.jsowell.pile.domain.PileStationInfo;
import com.jsowell.pile.domain.SettleOrderReport;
@@ -399,6 +400,12 @@ public class SettleOrderReportServiceImpl implements SettleOrderReportService {
return vo;
}
/**
* 查询运营商订单报告
* 财务中心-财务详情-运营汇总
* @param dto
* @return
*/
private OrderReportDetail queryMerchantOrderReport(MerchantOrderReportDTO dto) {
// 进行数据汇总
OrderReportDetail report = new OrderReportDetail();
@@ -420,6 +427,10 @@ public class SettleOrderReportServiceImpl implements SettleOrderReportService {
BigDecimal amount = settleOrderReportVO.getSettleAmount() != null
? settleOrderReportVO.getSettleAmount()
: settleOrderReportVO.getTotalAmount();
// 2025年6月19日15点11分 修改逻辑, 使用实收金额进行计算
totalAmount = totalAmount.add(amount);
virtualAmount = virtualAmount.add(settleOrderReportVO.getVirtualAmount());
}
@@ -437,10 +448,6 @@ public class SettleOrderReportServiceImpl implements SettleOrderReportService {
report.setTotalAmount(totalAmount);
// 虚拟金额
report.setVirtualAmount(virtualAmount);
// 交易金额
// report.setTradeAmount(list.stream().map(SettleOrderReportVO::getTradeAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
// 交易手续费
// report.setTradeFee(list.stream().map(SettleOrderReportVO::getTradeFee).reduce(BigDecimal.ZERO, BigDecimal::add));
// 从清分账单中计算交易金额,交易手续费
GetClearingBillDTO clearingBillDTO = GetClearingBillDTO.builder()
@@ -676,10 +683,9 @@ public class SettleOrderReportServiceImpl implements SettleOrderReportService {
BigDecimal settleAmount = StringUtils.isBlank(vo.getSettleAmount())
? BigDecimal.ZERO
: new BigDecimal(vo.getSettleAmount());
// if (settleAmount.compareTo(BigDecimal.ZERO) <= 0) {
// // 只统计用电量大于0的
// continue;
// }
// 实收金额
BigDecimal actualReceivedAmount = vo.getActualReceivedAmount();
// 用电度数
BigDecimal chargingDegree = StringUtils.isBlank(vo.getChargingDegree())
@@ -698,6 +704,9 @@ public class SettleOrderReportServiceImpl implements SettleOrderReportService {
continue;
}
// 结算金额与实收金额取大于0的最小值
settleAmount = YKCUtils.getMinBigDecimal(settleAmount, actualReceivedAmount);
String orderAmount = vo.getOrderAmount(); // 订单消费金额
useElectricity = useElectricity.add(chargingDegree); // 充电度数累计

View File

@@ -495,11 +495,13 @@ public abstract class AbstractProgramLogic implements InitializingBean {
// 该时段电费单价
BigDecimal electricityPrice = orderDetail.getSharpElectricityPrice();
// 计算该时段电费 = 电费单价 x 用电量
BigDecimal electricityAmount = electricityPrice.multiply(sharpUsedElectricity).setScale(2, RoundingMode.DOWN);
// BigDecimal electricityAmount = electricityPrice.multiply(sharpUsedElectricity).setScale(2, RoundingMode.DOWN);
BigDecimal electricityAmount = electricityPrice.multiply(sharpUsedElectricity);
// 该时段服务费单价
BigDecimal servicePrice = orderDetail.getSharpServicePrice();
// 计算该时段服务费 = 服务费单价 x 用电量
BigDecimal serviceAmount = servicePrice.multiply(sharpUsedElectricity).setScale(2, RoundingMode.DOWN);
// BigDecimal serviceAmount = servicePrice.multiply(sharpUsedElectricity).setScale(2, RoundingMode.DOWN);
BigDecimal serviceAmount = servicePrice.multiply(sharpUsedElectricity);
// 汇总
totalElectricityAmount = totalElectricityAmount.add(electricityAmount);
totalServiceAmount = totalServiceAmount.add(serviceAmount);
@@ -519,11 +521,13 @@ public abstract class AbstractProgramLogic implements InitializingBean {
// 该时段电费单价
BigDecimal electricityPrice = orderDetail.getPeakElectricityPrice();
// 计算该时段电费 = 电费单价 x 用电量
BigDecimal electricityAmount = electricityPrice.multiply(peakUsedElectricity).setScale(2, RoundingMode.DOWN);
// BigDecimal electricityAmount = electricityPrice.multiply(peakUsedElectricity).setScale(2, RoundingMode.DOWN);
BigDecimal electricityAmount = electricityPrice.multiply(peakUsedElectricity);
// 该时段服务费单价
BigDecimal servicePrice = orderDetail.getPeakServicePrice();
// 计算该时段服务费 = 服务费单价 x 用电量
BigDecimal serviceAmount = servicePrice.multiply(peakUsedElectricity).setScale(2, RoundingMode.DOWN);
// BigDecimal serviceAmount = servicePrice.multiply(peakUsedElectricity).setScale(2, RoundingMode.DOWN);
BigDecimal serviceAmount = servicePrice.multiply(peakUsedElectricity);
// 汇总
totalElectricityAmount = totalElectricityAmount.add(electricityAmount);
totalServiceAmount = totalServiceAmount.add(serviceAmount);
@@ -543,11 +547,13 @@ public abstract class AbstractProgramLogic implements InitializingBean {
// 该时段电费单价
BigDecimal electricityPrice = orderDetail.getFlatElectricityPrice();
// 计算该时段电费 = 电费单价 x 用电量
BigDecimal electricityAmount = electricityPrice.multiply(flatUsedElectricity).setScale(2, RoundingMode.DOWN);
// BigDecimal electricityAmount = electricityPrice.multiply(flatUsedElectricity).setScale(2, RoundingMode.DOWN);
BigDecimal electricityAmount = electricityPrice.multiply(flatUsedElectricity);
// 该时段服务费单价
BigDecimal servicePrice = orderDetail.getFlatServicePrice();
// 计算该时段服务费 = 服务费单价 x 用电量
BigDecimal serviceAmount = servicePrice.multiply(flatUsedElectricity).setScale(2, RoundingMode.DOWN);
// BigDecimal serviceAmount = servicePrice.multiply(flatUsedElectricity).setScale(2, RoundingMode.DOWN);
BigDecimal serviceAmount = servicePrice.multiply(flatUsedElectricity);
// 汇总
totalElectricityAmount = totalElectricityAmount.add(electricityAmount);
totalServiceAmount = totalServiceAmount.add(serviceAmount);
@@ -567,11 +573,13 @@ public abstract class AbstractProgramLogic implements InitializingBean {
// 该时段电费单价
BigDecimal electricityPrice = orderDetail.getValleyElectricityPrice();
// 计算该时段电费 = 电费单价 x 用电量
BigDecimal electricityAmount = electricityPrice.multiply(valleyUsedElectricity).setScale(2, RoundingMode.DOWN);
// BigDecimal electricityAmount = electricityPrice.multiply(valleyUsedElectricity).setScale(2, RoundingMode.DOWN);
BigDecimal electricityAmount = electricityPrice.multiply(valleyUsedElectricity);
// 该时段服务费单价
BigDecimal servicePrice = orderDetail.getValleyServicePrice();
// 计算该时段服务费 = 服务费单价 x 用电量
BigDecimal serviceAmount = servicePrice.multiply(valleyUsedElectricity).setScale(2, RoundingMode.DOWN);
// BigDecimal serviceAmount = servicePrice.multiply(valleyUsedElectricity).setScale(2, RoundingMode.DOWN);
BigDecimal serviceAmount = servicePrice.multiply(valleyUsedElectricity);
// 汇总
totalElectricityAmount = totalElectricityAmount.add(electricityAmount);
totalServiceAmount = totalServiceAmount.add(serviceAmount);
@@ -588,8 +596,8 @@ public abstract class AbstractProgramLogic implements InitializingBean {
// 尖峰平谷用电量汇总
BigDecimal sumUsedElectricity = sharpUsedElectricity.add(peakUsedElectricity).add(flatUsedElectricity).add(valleyUsedElectricity);
// 平台计算的总消费金额 平台计算总电费金额 + 平台计算总服务费金额
BigDecimal computeTotalAmount = totalElectricityAmount.add(totalServiceAmount);
// 平台计算的总消费金额 平台计算总电费金额 + 平台计算总服务费金额, 保留2位小数
BigDecimal computeTotalAmount = totalElectricityAmount.add(totalServiceAmount).setScale(2, RoundingMode.DOWN);
/*
如果算出来的 电费金额 + 服务费金额 != 总消费金额并且尖峰平谷总用电量大于0, 则使用平台计算金额
@@ -623,6 +631,8 @@ public abstract class AbstractProgramLogic implements InitializingBean {
// 如果totalElectricityAmount + totalServiceAmount != dataOrderAmount则totalElectricityAmount = dataOrderAmount - totalServiceAmount
if (totalElectricityAmount.add(totalServiceAmount).compareTo(dataOrderAmount) != 0) {
logger.info("updateOrderBasicInfoAndOrderDetail结算订单:【{}】, 电费金额({}) + 服务费金额({}) != 订单金额({}), 电费金额设置为订单金额- 服务费金额", orderCode, totalElectricityAmount, totalServiceAmount, dataOrderAmount);
// 订单总服务费金额保留2位小数
totalServiceAmount = totalServiceAmount.setScale(2, RoundingMode.DOWN);
totalElectricityAmount = dataOrderAmount.subtract(totalServiceAmount);
}

View File

@@ -1,6 +1,7 @@
package com.jsowell.pile.vo.uniapp.customer;
import com.jsowell.common.annotation.Excel;
import com.jsowell.common.enums.MemberWalletEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -30,9 +31,14 @@ public class MemberWalletLogVO {
/**
* 子类型 10-充值, 11-赠送, 12-订单结算退款20-后管扣款, 21-订单付款, 22-用户退款
*/
@Excel(name = "操作类型(10-充值, 11-赠送, 12-订单结算退款20-后管扣款, 21-订单付款, 22-用户退款)")
private String subType;
/**
* 子类型名称
*/
@Excel(name = "操作类型")
private String subTypeName;
/**
* 出账/入账金额
*/
@@ -52,6 +58,7 @@ public class MemberWalletLogVO {
/**
* 关联订单
*/
@Excel(name = "关联订单号")
private String relatedOrderCode;
/**
@@ -75,15 +82,21 @@ public class MemberWalletLogVO {
/**
* 变动前金额
*/
@Excel(name = "变动前金额")
private BigDecimal beforeAmount;
/**
* 变动后金额
*/
@Excel(name = "变动后金额")
private BigDecimal afterAmount;
/**
* 操作人员
*/
private String createBy;
public String getSubTypeName() {
return MemberWalletEnum.getLabelByValue(this.subType);
}
}

View File

@@ -248,6 +248,11 @@ public class OrderListVO {
@Excel(name = "结算金额")
private String settleAmount;
/**
* 实收金额
*/
private BigDecimal actualReceivedAmount;
/**
* 交易服务费/通道手续费
*/

View File

@@ -1765,6 +1765,7 @@
t1.virtual_amount as virtualAmount,
t1.discount_amount as discountAmount,
t1.settle_amount as settleAmount,
ifnull(t1.actual_received_amount, '0') as actualReceivedAmount,
t1.settlement_time as settlementTime,
t1.start_soc as startSoc,
t1.end_soc as endSoc,
@@ -3181,4 +3182,4 @@
LIMIT 1;
</select>
</mapper>
</mapper>

View File

@@ -957,5 +957,6 @@
<if test="dto.endTime != null and dto.endTime != ''">
and trade_date <![CDATA[ <= ]]> #{dto.endTime,jdbcType=VARCHAR}
</if>
order by trade_date DESC
</select>
</mapper>

View File

@@ -173,6 +173,9 @@ public class NotificationService {
platformService.notificationChargeOrderInfo(orderCode);
//停止充电结果推送
platformService.notificationStopChargeResult(orderCode);
//推送充换电站用能统计信息
platformService.notificationOperationStatsInfo(stationId);
} catch (Exception e) {
logger.error("充电订单信息推送error", e);
}

View File

@@ -131,5 +131,42 @@ public class SupStationInfo extends StationInfo {
@JSONField(name = "SupportingFacilities")
private String supportingFacilities;
/**
* 设备所属方名称
*/
@JSONField(name = "EquipmentOwnerName")
private String equipmentOwnerName;
/**
* 供电类型
* 1直供电 2转供电
*/
@JSONField(name = "SupplyType")
private Integer supplyType;
/**
* 供电局用户编号
*/
@JSONField(name = "ResidentNo")
private String residentNo;
/**
* 表号
*/
@JSONField(name = "WattHourMeterNo")
private String wattHourMeterNo;
/**
* 外电功率
*/
@JSONField(name = "ForwardPower")
private String forwardPower;
/**
* 充电站全省 唯一备案号
*/
@JSONField(name = "RecordUniqueNo")
private String recordUniqueNo;
private List<PolicyInfo> PolicyInfos;
}

View File

@@ -260,6 +260,16 @@ public interface ThirdPartyPlatformService extends InitializingBean {
throw new UnsupportedOperationException("This method is not yet implemented");
}
/**
* 查询补贴发放信息
* supervise_query_subsidy_grant_info
* @param querySubsidyGrantInfoDTO
* @return
*/
default Map<String, String> querySubsidyGrantInfo(QueryStationInfoDTO querySubsidyGrantInfoDTO){
throw new UnsupportedOperationException("This method is not yet implemented");
}
// =================================================================================== //
// ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ 由对方平台实现此接口,我方平台调用的通知接口 ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ //

View File

@@ -8,6 +8,7 @@ import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.domain.ykc.RealTimeMonitorData;
import com.jsowell.common.enums.thirdparty.BusinessInformationExchangeEnum;
import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum;
import com.jsowell.common.enums.ykc.BillingTimeTypeEnum;
import com.jsowell.common.enums.ykc.OrderStatusEnum;
import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum;
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
@@ -31,6 +32,8 @@ import com.jsowell.thirdparty.lianlian.domain.ConnectorChargeStatusInfo;
import com.jsowell.thirdparty.lianlian.domain.ConnectorStatusInfo;
import com.jsowell.thirdparty.lianlian.domain.StationStatusInfo;
import com.jsowell.thirdparty.lianlian.vo.*;
import com.jsowell.thirdparty.platform.common.ChargeDetail;
import com.jsowell.thirdparty.platform.domain.SupChargeDetails;
import com.jsowell.thirdparty.platform.domain.SupStationInfo;
import com.jsowell.thirdparty.platform.factory.ThirdPartyPlatformFactory;
import com.jsowell.thirdparty.platform.service.ThirdPartyPlatformService;
@@ -48,6 +51,10 @@ import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidKeySpecException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
@Service
@@ -241,6 +248,10 @@ public class ChangZhouPlatformServiceImpl implements ThirdPartyPlatformService {
String dataSecretIv = thirdPartySecretInfoVO.getTheirDataSecretIv();
String urlAddress = thirdPartySecretInfoVO.getTheirUrlPrefix();
if(Objects.equals(status , PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue())){
status =PileConnectorDataBaseStatusEnum.FAULT.getValue() ; // 离网改成255故障
}
String url = urlAddress + BusinessInformationExchangeEnum.NOTIFICATION_STATION_STATUS.getValue();
ConnectorStatusInfo info = ConnectorStatusInfo.builder()
.connectorID(pileConnectorCode)
@@ -281,7 +292,11 @@ public class ChangZhouPlatformServiceImpl implements ThirdPartyPlatformService {
// 其他
ConnectorStatusInfo connectorStatusInfo = new ConnectorStatusInfo();
connectorStatusInfo.setConnectorID(connectorInfoVO.getPileConnectorCode());
connectorStatusInfo.setStatus(Integer.parseInt(connectorInfoVO.getConnectorStatus()));
String connectorStatus = connectorInfoVO.getConnectorStatus();
if (connectorStatus.equals(PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue())){
connectorStatus = PileConnectorDataBaseStatusEnum.FAULT.getValue(); //离网改成255故障
}
connectorStatusInfo.setStatus(Integer.parseInt(connectorStatus));
connectorStatusInfos.add(connectorStatusInfo);
}
stationStatusInfo.setConnectorStatusInfos(connectorStatusInfos);
@@ -410,8 +425,11 @@ public class ChangZhouPlatformServiceImpl implements ThirdPartyPlatformService {
return null;
}
ThirdPartySecretInfoVO thirdPartySecretInfoVO = getChangZhouSecretInfo();
// 设置最大充电金额
dto.setAccountBalance(Constants.LIAN_LIAN_MAX_AMOUNT);
// 生成订单
Map<String, Object> map = orderBasicInfoService.generateOrderForThirdParty(dto);
String orderCode = (String) map.get("orderCode");
String transactionCode = (String) map.get("transactionCode");
OrderBasicInfo orderBasicInfo = (OrderBasicInfo) map.get("orderBasicInfo");
@@ -525,6 +543,10 @@ public class ChangZhouPlatformServiceImpl implements ThirdPartyPlatformService {
}else {
connectorStatus = Integer.parseInt(status);
}
if(connectorStatus == Integer.parseInt(PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue())){
connectorStatus = Integer.parseInt(PileConnectorDataBaseStatusEnum.FAULT.getValue());
}
String soc = data.getSOC() == null ? Constants.ZERO : data.getSOC();
BigDecimal totalElectricityAmount = orderDetail.getTotalElectricityAmount() == null ? BigDecimal.ZERO : orderDetail.getTotalElectricityAmount();
BigDecimal totalServiceAmount = orderDetail.getTotalServiceAmount() == null ? BigDecimal.ZERO : orderDetail.getTotalServiceAmount();
// 拼装联联平台数据
@@ -535,7 +557,7 @@ public class ChangZhouPlatformServiceImpl implements ThirdPartyPlatformService {
.connectorStatus(connectorStatus) // 枪口状态
.currentA(new BigDecimal(data.getOutputCurrent())) // 电流
.voltageA(new BigDecimal(data.getOutputVoltage())) // 电压
.soc(new BigDecimal(data.getSOC()))
.soc(new BigDecimal(soc))
.startTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderInfo.getChargeStartTime())) // 开始时间
.endTime(DateUtils.getDateTime()) // 本次采样时间
.totalPower(new BigDecimal(data.getChargingDegree()).setScale(2, BigDecimal.ROUND_HALF_UP)) // 累计充电量
@@ -579,14 +601,20 @@ public class ChangZhouPlatformServiceImpl implements ThirdPartyPlatformService {
BigDecimal totalElectricityAmount = orderDetail.getTotalElectricityAmount() == null ? BigDecimal.ZERO : orderDetail.getTotalElectricityAmount();
BigDecimal totalServiceAmount = orderDetail.getTotalServiceAmount() == null ? BigDecimal.ZERO : orderDetail.getTotalServiceAmount();
Integer orderStatus = OrderStatusEnum.convertToNewStatus(orderInfo.getOrderStatus());
Integer connectorStatus = info.getStatus();
if(connectorStatus == Integer.parseInt(PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue())){
connectorStatus = Integer.parseInt(PileConnectorDataBaseStatusEnum.FAULT.getValue());
}
QueryChargingStatusVO vo = QueryChargingStatusVO.builder()
.startChargeSeq(orderInfo.getOrderCode()) // 订单号
.startChargeSeqStat(Integer.parseInt(orderInfo.getOrderStatus())) // 订单状态
.startChargeSeqStat(orderStatus) // 订单状态
.connectorID(orderInfo.getPileConnectorCode()) // 枪口编码
.connectorStatus(info.getStatus()) // 枪口状态
.currentA(info.getCurrent()) // 电流
.voltageA(info.getVoltage()) // 电压
.soc(new BigDecimal(info.getSOC()))
.connectorStatus(connectorStatus) // 枪口状态
.currentA(current) // 电流
.voltageA(voltage) // 电压
.soc(new BigDecimal(soc))
.startTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderInfo.getChargeStartTime())) // 开始时间
.endTime(DateUtils.getDateTime()) // 本次采样时间
.totalPower(info.getChargingDegree()) // 累计充电量
@@ -617,7 +645,7 @@ public class ChangZhouPlatformServiceImpl implements ThirdPartyPlatformService {
QueryStopChargeVO vo = new QueryStopChargeVO();
String orderCode = dto.getStartChargeSeq();
ThirdPartySecretInfoVO wangKuaiDianPlatformSecretInfo = getChangZhouSecretInfo();
ThirdPartySecretInfoVO thirdPartySecretInfoVO = getChangZhouSecretInfo();
// 根据订单号查询订单信息
OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);
if (orderInfo == null) {
@@ -634,7 +662,7 @@ public class ChangZhouPlatformServiceImpl implements ThirdPartyPlatformService {
vo.setFailReason(0);
vo.setStartChargeSeq(orderCode);
log.info("返回参数:{}", JSON.toJSONString(vo));
return ThirdPartyPlatformUtils.generateResultMap(vo, wangKuaiDianPlatformSecretInfo);
return ThirdPartyPlatformUtils.generateResultMap(vo, thirdPartySecretInfoVO);
}
@@ -732,6 +760,12 @@ public class ChangZhouPlatformServiceImpl implements ThirdPartyPlatformService {
if (chargeEndTime == null) {
chargeEndTime = orderBasicInfo.getCreateTime();
}
if (orderDetail == null) {
return null;
}
List<BillingPriceVO> billingList = pileBillingTemplateService.queryBillingPrice(orderBasicInfo.getStationId());
List<SupChargeDetails> chargeDetails = transformSupChargeDetails(orderDetail, billingList);
JSONObject json = new JSONObject();
json.put("StartChargeSeq", orderCode);
@@ -743,6 +777,7 @@ public class ChangZhouPlatformServiceImpl implements ThirdPartyPlatformService {
json.put("TotalSeviceMoney", orderDetail.getTotalServiceAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
json.put("TotalMoney", orderDetail.getTotalOrderAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
json.put("StopReason", 2); // 2BMS 停止充电
json.put("ChargeDetails", chargeDetails);
String jsonString = JSON.toJSONString(json);
log.info("请求参数:{}", jsonString);
@@ -754,6 +789,88 @@ public class ChangZhouPlatformServiceImpl implements ThirdPartyPlatformService {
}
/**
* 转换时段充电明细
*
* @param orderDetail
* @param billingList
* @return
*/
private List<SupChargeDetails> transformSupChargeDetails(OrderDetail orderDetail, List<BillingPriceVO> billingList) {
List<SupChargeDetails> resultList = Lists.newArrayList();
SupChargeDetails detail;
for (BillingPriceVO billingPriceVO : billingList) {
detail = new SupChargeDetails();
String startTime = convertTime(billingPriceVO.getStartTime());
String endTime = convertTime(billingPriceVO.getEndTime());
if (StringUtils.equals(billingPriceVO.getTimeType(), BillingTimeTypeEnum.SHARP.getValue())) {
// 尖时段
detail.setDetailStartTime(startTime);
detail.setDetailEndTime(endTime);
detail.setElecPrice(new BigDecimal(billingPriceVO.getElectricityPrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
detail.setSevicePrice(new BigDecimal(billingPriceVO.getServicePrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
detail.setDetailPower(orderDetail.getSharpUsedElectricity());
detail.setDetailElecMoney(orderDetail.getSharpElectricityPrice());
detail.setDetailSeviceMoney(orderDetail.getSharpServicePrice());
} else if (StringUtils.equals(billingPriceVO.getTimeType(), BillingTimeTypeEnum.PEAK.getValue())) {
// 峰时段
detail.setDetailStartTime(startTime);
detail.setDetailEndTime(endTime);
detail.setElecPrice(new BigDecimal(billingPriceVO.getElectricityPrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
detail.setSevicePrice(new BigDecimal(billingPriceVO.getServicePrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
detail.setDetailPower(orderDetail.getPeakUsedElectricity());
detail.setDetailElecMoney(orderDetail.getPeakElectricityPrice());
detail.setDetailSeviceMoney(orderDetail.getPeakServicePrice());
} else if (StringUtils.equals(billingPriceVO.getTimeType(), BillingTimeTypeEnum.FLAT.getValue())) {
// 平时段
detail.setDetailStartTime(startTime);
detail.setDetailEndTime(endTime);
detail.setElecPrice(new BigDecimal(billingPriceVO.getElectricityPrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
detail.setSevicePrice(new BigDecimal(billingPriceVO.getServicePrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
detail.setDetailPower(orderDetail.getFlatUsedElectricity());
detail.setDetailElecMoney(orderDetail.getFlatElectricityPrice());
detail.setDetailSeviceMoney(orderDetail.getFlatServicePrice());
} else if (StringUtils.equals(billingPriceVO.getTimeType(), BillingTimeTypeEnum.VALLEY.getValue())) {
// 谷时段
detail.setDetailStartTime(startTime);
detail.setDetailEndTime(endTime);
detail.setElecPrice(new BigDecimal(billingPriceVO.getElectricityPrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
detail.setSevicePrice(new BigDecimal(billingPriceVO.getServicePrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
detail.setDetailPower(orderDetail.getValleyUsedElectricity());
detail.setDetailElecMoney(orderDetail.getValleyElectricityPrice());
detail.setDetailSeviceMoney(orderDetail.getValleyServicePrice());
}
resultList.add(detail);
}
return resultList;
}
public static String convertTime(String timeStr) {
try {
// 1. 解析输入的 HH:mm 为 LocalTime
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
LocalTime localTime = LocalTime.parse(timeStr, timeFormatter);
// 2. 获取当前日期(年、月、日)
LocalDate currentDate = LocalDate.now();
// 3. 合并日期和时间为 LocalDateTime
LocalDateTime dateTime = LocalDateTime.of(currentDate, localTime);
// 4. 格式化为目标格式 yyyy-MM-dd HH:mm:ss
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return dateTime.format(outputFormatter);
} catch (Exception e) {
throw new IllegalArgumentException("时间格式错误,应为 HH:mm", e);
}
}
/**
* 获取配置密钥信息
*