diff --git a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java index e4f4d116a..a4272634c 100644 --- a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java +++ b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java @@ -666,4 +666,21 @@ public class TempController extends BaseController { } return response; } + + /** + * 手动接口, 执行新的分账方法 + * https://localhost:8080/temp/realTimeOrderSplit + */ + @PostMapping("/realTimeOrderSplit") + public RestApiResponse splitTheBillForOrderTemp(@RequestBody AfterSettleOrderDTO afterSettleOrderDTO) { + RestApiResponse response; + try { + orderBasicInfoService.realTimeOrderSplit(afterSettleOrderDTO); + response = new RestApiResponse<>(); + } catch (Exception e) { + logger.error("手动接口, 执行新的分账方法error", e); + response = new RestApiResponse<>("00200005", "手动分账接口失败"); + } + return response; + } } diff --git a/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/MemberBasicInfoController.java b/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/MemberBasicInfoController.java index 8c3eaf449..0c0f83a8c 100644 --- a/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/MemberBasicInfoController.java +++ b/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/MemberBasicInfoController.java @@ -7,6 +7,7 @@ import com.jsowell.common.annotation.Log; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.controller.BaseController; import com.jsowell.common.core.domain.AjaxResult; +import com.jsowell.common.core.domain.vo.AuthorizedDeptVO; import com.jsowell.common.core.page.TableDataInfo; import com.jsowell.common.enums.BusinessType; import com.jsowell.common.enums.uniapp.BalanceChangesEnum; @@ -14,12 +15,11 @@ import com.jsowell.common.enums.ykc.ReturnCodeEnum; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.response.RestApiResponse; import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.poi.ExcelUtil; import com.jsowell.pile.domain.MemberBasicInfo; import com.jsowell.pile.domain.MemberPlateNumberRelation; -import com.jsowell.pile.dto.CreateMerchantVipDTO; -import com.jsowell.pile.dto.PlatformTesterDTO; -import com.jsowell.pile.dto.QueryMemberInfoDTO; -import com.jsowell.pile.dto.UniAppQueryMemberBalanceDTO; +import com.jsowell.pile.domain.PileMerchantInfo; +import com.jsowell.pile.dto.*; import com.jsowell.pile.service.MemberBasicInfoService; import com.jsowell.pile.service.MemberPlateNumberRelationService; import com.jsowell.pile.service.MemberTransactionRecordService; @@ -29,6 +29,7 @@ import com.jsowell.pile.vo.uniapp.customer.MemberVO; import com.jsowell.pile.vo.uniapp.customer.MemberWalletLogVO; import com.jsowell.pile.vo.uniapp.customer.MerchantVipVO; import com.jsowell.pile.vo.web.MemberTransactionVO; +import com.jsowell.pile.vo.web.OrderListVO; import com.jsowell.pile.vo.web.PlatformTesterVO; import com.jsowell.pile.vo.web.UpdateMemberBalanceDTO; import org.apache.commons.collections4.CollectionUtils; @@ -36,6 +37,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; @@ -262,6 +264,24 @@ public class MemberBasicInfoController extends BaseController { return toAjax(i); } + /** + * 导出会员钱包列表 + */ + @PreAuthorize("@ss.hasPermi('member:info:export')") + @Log(title = "钱包数据", businessType = BusinessType.EXPORT) + @PostMapping("/exportWalletList") + public void exportWalletList(HttpServletResponse response, UniAppQueryMemberBalanceDTO dto) { + // 权限过滤 + AuthorizedDeptVO authorizedMap = UserUtils.getAuthorizedMap(); + if (authorizedMap == null) { + // 为空表示没有权限,返回空数组 + return; + } + List list = memberBasicInfoService.getMemberWalletDetail(dto); + ExcelUtil util = new ExcelUtil(MemberWalletLogVO.class); + util.exportExcel(response, list, "会员钱包数据"); + } + /** * 修改平台测试员状态 * http://localhost:8080/member/info/updatePlatformTester diff --git a/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java b/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java index 1b47baf73..1540aca9f 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java +++ b/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java @@ -195,6 +195,11 @@ public class CacheConstants { */ public static final String THIRD_PARTY_TOKEN_BY_OPERATOR_SECRET = "third_party_token_by_operator_secret:"; + /** + * 推送设备充电状态信息数据缓存 + */ + public static final String NOTIFICATION_EQUIP_CHARGE_STATUS_BY_ORDER_CODE = "notification_equip_charge_status_by_order_code:"; + /** * 充电桩状态前缀 */ diff --git a/jsowell-common/src/main/java/com/jsowell/common/core/domain/parking/ParkingCommonParam.java b/jsowell-common/src/main/java/com/jsowell/common/core/domain/parking/ParkingCommonParam.java new file mode 100644 index 000000000..b1f142d08 --- /dev/null +++ b/jsowell-common/src/main/java/com/jsowell/common/core/domain/parking/ParkingCommonParam.java @@ -0,0 +1,41 @@ +package com.jsowell.common.core.domain.parking; + +import lombok.Data; + +import java.util.Map; + +/** + * 停车场公告参数 + */ +@Data +public class ParkingCommonParam { + /** + * 服务名称 + */ + private String service; + + /** + * 版本 + */ + private String version; + + /** + * 消息ID(唯一) + */ + private String msgId; + + /** + * 机构ID(分配) + */ + private String orgId; + + /** + * 具体业务接口json对象 + */ + private Map data; + + /** + * 请求签名 + */ + private String sign; +} diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/ParkingUtil.java b/jsowell-common/src/main/java/com/jsowell/common/util/ParkingUtil.java new file mode 100644 index 000000000..3cf7e4ebc --- /dev/null +++ b/jsowell-common/src/main/java/com/jsowell/common/util/ParkingUtil.java @@ -0,0 +1,60 @@ +package com.jsowell.common.util; + +import com.jsowell.common.util.sign.MD5Util; + +import java.util.HashMap; +import java.util.Map; + +/** + * 停车平台工具类 + */ +public class ParkingUtil { + + /** + * 计算sign + */ + public static String generateSign(Map publicParams, Map businessParams, String secretKey) { + // Step 1: 过滤空值并按照ASCII码排序公共参数 + StringBuilder stringA = new StringBuilder(); + publicParams.entrySet().stream() + .filter(entry -> entry.getValue() != null && !entry.getValue().isEmpty()) + .sorted(Map.Entry.comparingByKey()) + .forEach(entry -> stringA.append(entry.getKey()).append("=").append(entry.getValue()).append("|")); + + // Step 2: 过滤空值并按照ASCII码排序业务参数 + StringBuilder stringB = new StringBuilder(); + businessParams.entrySet().stream() + .filter(entry -> entry.getValue() != null && !entry.getValue().isEmpty()) + .sorted(Map.Entry.comparingByKey()) + .forEach(entry -> stringB.append(entry.getKey()).append("=").append(entry.getValue()).append("|")); + + // Step 3: 拼接字符串A、B和机构密钥 + String stringC = stringA.toString() + stringB.toString() + secretKey; + + // Step 4: 对字符串C进行MD5加密并返回小写的签名 + return MD5Util.MD5Encode(stringC).toLowerCase(); + } + + public static void main(String[] args) { + // 模拟公共请求参数 + Map publicParams = new HashMap<>(); + publicParams.put("service", "getOwner"); + publicParams.put("version", "01"); + publicParams.put("msgId", "f719b06d-210b-4989-9c7f-02e85f22fe01"); + publicParams.put("orgId", "BTTEST01"); + + // 模拟业务请求参数 + Map businessParams = new HashMap<>(); + businessParams.put("parkId", "11609"); + businessParams.put("phone", "13148762240"); + businessParams.put("name", "pasika"); + businessParams.put("address", "测试"); + + // 机构密钥 + String secretKey = "K9OGNA7CIY8N5GXD8HF3WVDMEZNFKL3F"; + + // 计算签名 + String sign = generateSign(publicParams, businessParams, secretKey); + System.out.println("Generated Sign: " + sign); + } +} diff --git a/jsowell-pile/src/main/java/com/jsowell/mq/OrderRabbitListener.java b/jsowell-pile/src/main/java/com/jsowell/mq/OrderRabbitListener.java index 791136059..cba7f1cde 100644 --- a/jsowell-pile/src/main/java/com/jsowell/mq/OrderRabbitListener.java +++ b/jsowell-pile/src/main/java/com/jsowell/mq/OrderRabbitListener.java @@ -1,5 +1,6 @@ package com.jsowell.mq; +import com.alibaba.fastjson2.JSON; import com.huifu.adapay.core.exception.BaseAdaPayException; import com.jsowell.common.constant.RabbitConstants; import com.jsowell.common.util.YKCUtils; @@ -30,9 +31,10 @@ public class OrderRabbitListener { */ @RabbitListener(queues = RabbitConstants.QUEUE_CHARGE_ORDER_DATA) public void receiveChargeOrderData(AfterSettleOrderDTO afterSettleOrderDTO, Channel channel, Message message) throws IOException { - log.info("接收到订单结算数据:{}", afterSettleOrderDTO); + log.info("接收到订单结算数据:{}", JSON.toJSONString(afterSettleOrderDTO)); List newLogicStationIdList = YKCUtils.getNewLogicStationIdList(); if (newLogicStationIdList.contains(afterSettleOrderDTO.getStationId())) { + log.info("realTimeOrderSplit-订单{}开始执行新分账方法", afterSettleOrderDTO.getOrderCode()); try { orderBasicInfoService.realTimeOrderSplit(afterSettleOrderDTO); } catch (BaseAdaPayException e) { diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/dto/UniAppQueryMemberBalanceDTO.java b/jsowell-pile/src/main/java/com/jsowell/pile/dto/UniAppQueryMemberBalanceDTO.java index bcf472840..5f91ef48b 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/dto/UniAppQueryMemberBalanceDTO.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/dto/UniAppQueryMemberBalanceDTO.java @@ -37,6 +37,8 @@ public class UniAppQueryMemberBalanceDTO extends BaseMemberDTO{ */ private String walletCode; + private String memberId; + @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.JSON_STYLE) diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java index 0f57829f3..4445bca39 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java @@ -1663,9 +1663,10 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { // 校验订单支付金额,消费金额,退款金额 BigDecimal orderPayAmount = afterSettleOrderDTO.getOrderPayAmount(); // 支付金额 BigDecimal orderConsumeAmount = afterSettleOrderDTO.getOrderConsumeAmount(); // 消费金额 + BigDecimal orderSettleAmount = afterSettleOrderDTO.getOrderSettleAmount(); BigDecimal orderRefundAmount = afterSettleOrderDTO.getOrderRefundAmount(); // 退款金额 - if (orderConsumeAmount.add(orderRefundAmount).compareTo(orderPayAmount) != 0) { - logger.info("订单支付金额与消费金额+退款金额不相等"); + if (orderSettleAmount.add(orderRefundAmount).compareTo(orderPayAmount) != 0) { + logger.info("realTimeOrderSplit-订单:{}, 支付金额与结算金额+退款金额不相等", afterSettleOrderDTO.getOrderCode()); return null; } @@ -1720,7 +1721,7 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { BigDecimal orderSettleAmount = afterSettleOrderDTO.getOrderSettleAmount() == null ? BigDecimal.ZERO : afterSettleOrderDTO.getOrderSettleAmount(); // 订单是否需要分账, 结算金额必须大于0 if (orderSettleAmount.compareTo(BigDecimal.ZERO) <= 0) { - logger.info("订单结算金额必须大于0"); + logger.info("realTimeOrderSplit-订单结算金额必须大于0"); return null; } // 校验分账 @@ -1731,9 +1732,10 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { List splitDataList = calculationSplitDataList(stationSplitConfigList, afterSettleOrderDTO); List divMemberList = transformDivMemberList(splitDataList); // List divMemberList = calculationOfSplitAmount(stationSplitConfigList, afterSettleOrderDTO); + logger.info("realTimeOrderSplit-订单:{}, 分账信息:{}", afterSettleOrderDTO.getOrderCode(), JSON.toJSONString(splitDataList)); // 执行分账 if (CollectionUtils.isEmpty(divMemberList)) { - logger.info("分账信息为空"); + logger.info("realTimeOrderSplit-分账信息为空"); return null; } String orderCode = afterSettleOrderDTO.getOrderCode(); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/customer/MemberWalletLogVO.java b/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/customer/MemberWalletLogVO.java index 8ecf0f18a..827c51b2b 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/customer/MemberWalletLogVO.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/customer/MemberWalletLogVO.java @@ -1,5 +1,6 @@ package com.jsowell.pile.vo.uniapp.customer; +import com.jsowell.common.annotation.Excel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -18,6 +19,7 @@ public class MemberWalletLogVO { /** * 会员id */ + @Excel(name = "会员id") private String memberId; /** @@ -28,6 +30,7 @@ public class MemberWalletLogVO { /** * 子类型 10-充值, 11-赠送, 12-订单结算退款,20-后管扣款, 21-订单付款, 22-用户退款 */ + @Excel(name = "操作类型(10-充值, 11-赠送, 12-订单结算退款,20-后管扣款, 21-订单付款, 22-用户退款)") private String subType; /** @@ -38,6 +41,7 @@ public class MemberWalletLogVO { /** * 交易时间 */ + @Excel(name = "交易时间") private String transactionTime; /** @@ -53,16 +57,19 @@ public class MemberWalletLogVO { /** * 支付金额 */ + @Excel(name = "支付金额") private BigDecimal payAmount; /** * 订单金额 */ + @Excel(name = "订单金额") private BigDecimal orderAmount; /** * 退款金额 */ + @Excel(name = "退款金额") private BigDecimal refundAmount; /** diff --git a/jsowell-pile/src/main/resources/mapper/pile/MemberWalletLogMapper.xml b/jsowell-pile/src/main/resources/mapper/pile/MemberWalletLogMapper.xml index 9d559012c..d822ac76b 100644 --- a/jsowell-pile/src/main/resources/mapper/pile/MemberWalletLogMapper.xml +++ b/jsowell-pile/src/main/resources/mapper/pile/MemberWalletLogMapper.xml @@ -490,11 +490,23 @@ t1.create_time as transactionTime from member_wallet_log t1 left join order_basic_info t2 on t1.related_order_code = t2.order_code - where t1.member_id = #{dto.memberId,jdbcType=VARCHAR} - and t1.wallet_code = #{dto.walletCode,jdbcType=VARCHAR} - and t1.create_time = ]]> #{dto.tradeDate,jdbcType=VARCHAR} - and t1.create_time #{dto.endDate,jdbcType=VARCHAR} - and t1.sub_type != '12' + where t1.sub_type != '12' + + and t1.member_id = #{dto.memberId,jdbcType=VARCHAR} + + + and t1.wallet_code = #{dto.walletCode,jdbcType=VARCHAR} + + + and t1.create_time = ]]> #{dto.tradeDate,jdbcType=VARCHAR} + + + and t1.create_time #{dto.endDate,jdbcType=VARCHAR} + + + + + order by t1.create_time desc diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/GuangXiPlatformServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/GuangXiPlatformServiceImpl.java index def8fa1fe..e41ee3fba 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/GuangXiPlatformServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/GuangXiPlatformServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.github.pagehelper.PageInfo; import com.google.common.collect.Lists; +import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ykc.RealTimeMonitorData; import com.jsowell.common.core.redis.RedisCache; @@ -604,8 +605,12 @@ public class GuangXiPlatformServiceImpl implements ThirdPartyPlatformService { */ @Override public String notificationEquipChargeStatus(String orderCode) { - // 根据订单号查询订单信息 - OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); + // 先查缓存中是否有数据 + String redisKey = CacheConstants.NOTIFICATION_EQUIP_CHARGE_STATUS_BY_ORDER_CODE + orderCode; + Object cacheObject = redisCache.getCacheObject(redisKey); + if (cacheObject != null) { + return "距上次推送未超过5分钟,本次不予推送"; + } // 查询相关配置信息 ThirdPartySecretInfoVO thirdPartySecretInfoVO = getGuangXiSecretInfo(); @@ -616,6 +621,8 @@ public class GuangXiPlatformServiceImpl implements ThirdPartyPlatformService { String dataSecretIv = thirdPartySecretInfoVO.getTheirDataSecretIv(); String urlAddress = thirdPartySecretInfoVO.getTheirUrlPrefix(); + // 根据订单号查询订单信息 + OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); // 查询枪口实时状态 List chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(orderInfo.getTransactionCode()); RealTimeMonitorData realTimeMonitorData; @@ -653,20 +660,14 @@ public class GuangXiPlatformServiceImpl implements ThirdPartyPlatformService { SupEquipChargeStatusInfo supEquipChargeStatusInfo = SupEquipChargeStatusInfo.builder() .startChargeSeq(startChargeSeq) .startChargeSeqStat(Integer.parseInt(orderStatus)) - // .startChargeSeqStat(2) .connectorID(orderInfo.getPileConnectorCode()) .connectorStatus(Integer.parseInt(realTimeMonitorData.getConnectorStatus())) // 3-充电中 - // .connectorStatus(3) // 3-充电中 .currentA(current.setScale(1, RoundingMode.HALF_UP)) - // .currentA(new BigDecimal("20.3")) .voltageA(voltage.setScale(1, RoundingMode.HALF_UP)) - // .voltageA(new BigDecimal("260.7")) .soc(new BigDecimal(soc)) - // .soc(new BigDecimal("79")) .startTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderInfo.getChargeStartTime())) .endTime(dateTime) .totalPower(new BigDecimal(realTimeMonitorData.getChargingDegree())) - // .totalPower(new BigDecimal("5292.21")) .build(); @@ -677,6 +678,10 @@ public class GuangXiPlatformServiceImpl implements ThirdPartyPlatformService { // 获取令牌 String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret); String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret); + if (StringUtils.equals("成功", result)) { + // 将数据存入缓存,5分钟失效 + redisCache.setCacheObject(redisKey, result, 5, TimeUnit.MINUTES); + } return result; } diff --git a/jsowell-ui/src/api/member/info.js b/jsowell-ui/src/api/member/info.js index e92553b77..ffb3a783d 100644 --- a/jsowell-ui/src/api/member/info.js +++ b/jsowell-ui/src/api/member/info.js @@ -148,3 +148,12 @@ export function getMemberBalanceChangesV2(data) { data: data }); } + +// 导出会员钱包明细 +export function exportWalletList(data) { + return request({ + url: '/member/info/exportWalletList', + method: 'post', + data: data + }); +} diff --git a/jsowell-ui/src/views/member/merchantVIP/index.vue b/jsowell-ui/src/views/member/merchantVIP/index.vue index 03f919bcf..e22b513f0 100644 --- a/jsowell-ui/src/views/member/merchantVIP/index.vue +++ b/jsowell-ui/src/views/member/merchantVIP/index.vue @@ -175,6 +175,12 @@ 搜索 + 导出 {{ totalRechargeAmount }} @@ -473,7 +479,7 @@ export default { }, /** 导出按钮操作 */ handleExport() { - this.download('member/info/export', { + this.download('member/info/exportWalletList', { ...this.queryParams }, `info_${new Date().getTime()}.xlsx`) },