mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-04-30 08:00:00 +08:00
commit
This commit is contained in:
@@ -0,0 +1,264 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.pile.domain.MemberBasicInfo;
|
||||
import com.jsowell.pile.domain.MemberWalletInfo;
|
||||
import com.jsowell.pile.domain.MemberWalletLog;
|
||||
import com.jsowell.pile.mapper.MemberBasicInfoMapper;
|
||||
import com.jsowell.pile.mapper.MemberWalletInfoMapper;
|
||||
import com.jsowell.pile.mapper.MemberWalletLogMapper;
|
||||
import com.jsowell.pile.mapper.PileBasicInfoMapper;
|
||||
import com.jsowell.pile.service.IMemberBasicInfoService;
|
||||
import com.jsowell.pile.service.IPileBasicInfoService;
|
||||
import com.jsowell.pile.vo.uniapp.MemberVO;
|
||||
import com.jsowell.pile.vo.uniapp.MemberWalletLogVO;
|
||||
import com.jsowell.pile.vo.uniapp.PersonalPileInfoVO;
|
||||
import com.jsowell.pile.vo.web.UpdateMemberBalanceDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会员基础信息Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2022-10-12
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MemberBasicInfoServiceImpl implements IMemberBasicInfoService {
|
||||
@Autowired
|
||||
private MemberBasicInfoMapper memberBasicInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private MemberWalletInfoMapper memberWalletInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private MemberWalletLogMapper memberWalletLogMapper;
|
||||
|
||||
@Autowired
|
||||
private IPileBasicInfoService pileBasicInfoService;
|
||||
/**
|
||||
* 查询会员基础信息
|
||||
*
|
||||
* @param id 会员基础信息主键
|
||||
* @return 会员基础信息
|
||||
*/
|
||||
@Override
|
||||
public MemberBasicInfo selectMemberBasicInfoById(Integer id) {
|
||||
return memberBasicInfoMapper.selectMemberBasicInfoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询会员基础信息列表
|
||||
*
|
||||
* @param memberBasicInfo 会员基础信息
|
||||
* @return 会员基础信息
|
||||
*/
|
||||
/*@Override
|
||||
public List<MemberVO> selectMemberBasicInfoList(MemberBasicInfo memberBasicInfo) {
|
||||
List<MemberVO> voList = memberBasicInfoMapper.selectMemberList(memberBasicInfo.getMobileNumber(), memberBasicInfo.getNickName());
|
||||
for (MemberVO memberVO : voList) {
|
||||
memberVO.setPrincipalBalance(memberVO.getPrincipalBalance() == null ? BigDecimal.ZERO : memberVO.getPrincipalBalance());
|
||||
memberVO.setGiftBalance(memberVO.getGiftBalance() == null ? BigDecimal.ZERO : memberVO.getGiftBalance());
|
||||
}
|
||||
return voList;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 新增会员基础信息
|
||||
*
|
||||
* @param memberBasicInfo 会员基础信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertMemberBasicInfo(MemberBasicInfo memberBasicInfo) {
|
||||
memberBasicInfo.setCreateTime(DateUtils.getNowDate());
|
||||
return memberBasicInfoMapper.insertMemberBasicInfo(memberBasicInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改会员基础信息
|
||||
*
|
||||
* @param memberBasicInfo 会员基础信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateMemberBasicInfo(MemberBasicInfo memberBasicInfo) {
|
||||
memberBasicInfo.setUpdateTime(DateUtils.getNowDate());
|
||||
return memberBasicInfoMapper.updateMemberBasicInfo(memberBasicInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除会员基础信息
|
||||
*
|
||||
* @param ids 需要删除的会员基础信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteMemberBasicInfoByIds(List<Integer> ids) {
|
||||
return memberBasicInfoMapper.deleteMemberBasicInfoByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过物理卡号查询会员基本信息
|
||||
*
|
||||
* @param physicsCard 物理卡号
|
||||
* @return 会员基本信息
|
||||
*/
|
||||
@Override
|
||||
public MemberVO selectInfoByPhysicsCard(String physicsCard) {
|
||||
return memberBasicInfoMapper.selectInfoByPhysicsCard(physicsCard);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据手机号和运营商id查询会员信息
|
||||
* @param mobileNumber 手机号
|
||||
* @param merchantId 运营商id
|
||||
* @return 会员信息
|
||||
*/
|
||||
public MemberBasicInfo selectInfoByMobileNumberAndMerchantId(String mobileNumber, String merchantId) {
|
||||
return memberBasicInfoMapper.selectInfoByMobileNumberAndMerchantId(mobileNumber, merchantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemberBasicInfo selectInfoByMobileNumber(String mobileNumber) {
|
||||
return selectInfoByMobileNumberAndMerchantId(mobileNumber, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemberBasicInfo selectInfoByMemberId(String memberId) {
|
||||
return memberBasicInfoMapper.selectInfoByMemberId(memberId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户余额 唯一方法
|
||||
* 接收的金额都是正数,通过操作类型判断 充值还是扣减
|
||||
*/
|
||||
@Override
|
||||
public int updateMemberBalance(UpdateMemberBalanceDTO dto) {
|
||||
String memberId = dto.getMemberId();
|
||||
BigDecimal updateGiftBalance = dto.getUpdateGiftBalance();
|
||||
BigDecimal updatePrincipalBalance = dto.getUpdatePrincipalBalance();
|
||||
log.info("修改用户余额 memberId:{}, updatePrincipalBalance:{}, updateGiftBalance:{}", memberId, updatePrincipalBalance, updateGiftBalance);
|
||||
// 查询用户余额
|
||||
MemberWalletInfo info = memberWalletInfoMapper.selectByMemberId(memberId);
|
||||
if (info == null) {
|
||||
log.warn("根据会员id:{}, 查询会员信息为空", memberId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 记录流水
|
||||
List<MemberWalletLog> logList = Lists.newArrayList();
|
||||
// 计算新的余额
|
||||
BigDecimal newPrincipalBalance = null;
|
||||
BigDecimal newGiftBalance = null;
|
||||
|
||||
// 更新本金金额
|
||||
if (updatePrincipalBalance != null) {
|
||||
if (StringUtils.equals(dto.getType(), "2")) {
|
||||
// 扣款 转为负数
|
||||
updatePrincipalBalance = updatePrincipalBalance.negate();
|
||||
}
|
||||
// 会员老的余额
|
||||
BigDecimal oldPrincipalBalance = info.getPrincipalBalance() == null
|
||||
? BigDecimal.ZERO
|
||||
: info.getPrincipalBalance();
|
||||
newPrincipalBalance = oldPrincipalBalance.add(updatePrincipalBalance);
|
||||
if (newPrincipalBalance.compareTo(BigDecimal.ZERO) < 0) {
|
||||
log.warn("新本金余额不能为负数");
|
||||
return 0;
|
||||
}
|
||||
// 记流水
|
||||
logList.add(MemberWalletLog.builder()
|
||||
.memberId(dto.getMemberId())
|
||||
.type(dto.getType())
|
||||
.subType(dto.getSubType())
|
||||
.amount(updatePrincipalBalance)
|
||||
.category("1")
|
||||
.relatedOrderCode(dto.getRelatedOrderCode())
|
||||
.createBy(dto.getMemberId())
|
||||
.build());
|
||||
}
|
||||
|
||||
// 更新赠送金额
|
||||
if (updateGiftBalance != null) {
|
||||
if (StringUtils.equals(dto.getType(), "2")) {
|
||||
// 扣款 转为负数
|
||||
updateGiftBalance = updateGiftBalance.negate();
|
||||
}
|
||||
BigDecimal oldGiftBalance = info.getGiftBalance() == null
|
||||
? BigDecimal.ZERO
|
||||
: info.getGiftBalance();
|
||||
newGiftBalance = oldGiftBalance.add(updateGiftBalance);
|
||||
// 余额不能为负数
|
||||
if (newGiftBalance.compareTo(BigDecimal.ZERO) < 0) {
|
||||
log.warn("新赠送余额不能为负数");
|
||||
return 0;
|
||||
}
|
||||
// 记流水
|
||||
logList.add(MemberWalletLog.builder()
|
||||
.memberId(dto.getMemberId())
|
||||
.type(dto.getType())
|
||||
.subType(dto.getSubType())
|
||||
.amount(updateGiftBalance)
|
||||
.category("2")
|
||||
.relatedOrderCode(dto.getRelatedOrderCode())
|
||||
.createBy(dto.getMemberId())
|
||||
.build());
|
||||
}
|
||||
|
||||
// 修改数据库
|
||||
int i = 0;
|
||||
if (newPrincipalBalance != null || newGiftBalance != null) {
|
||||
i = memberBasicInfoMapper.updateMemberBalance(memberId, newPrincipalBalance, newGiftBalance, info.getVersion());
|
||||
if (i == 0) {
|
||||
log.warn("修改余额失败, memberId:{}", memberId);
|
||||
}
|
||||
}
|
||||
// 插入 member_wallet_log 表
|
||||
if (CollectionUtils.isNotEmpty(logList)) {
|
||||
memberWalletLogMapper.batchInsert(logList);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemberVO queryMemberInfoByMemberId(String memberId) {
|
||||
// 加缓存
|
||||
MemberVO vo = memberBasicInfoMapper.queryMemberInfoByMemberId(memberId);
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MemberVO> selectMemberList(String mobileNumber, String nickName) {
|
||||
return memberBasicInfoMapper.selectMemberList(mobileNumber, nickName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户账户余额变动信息
|
||||
* @param memberId 会员id
|
||||
* @param type 1-进账;2-出账 不传查全部
|
||||
*/
|
||||
@Override
|
||||
public List<MemberWalletLogVO> getMemberBalanceChanges(String memberId, String type) {
|
||||
return memberWalletLogMapper.getMemberBalanceChanges(memberId, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过memberId查询会员的个人桩信息
|
||||
* @param memberId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<PersonalPileInfoVO> getMemberPersonPileInfo(String memberId) {
|
||||
return pileBasicInfoService.getPileInfoByMemberId(memberId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jsowell.common.util.bean.BeanUtils;
|
||||
import com.jsowell.pile.domain.MemberTransactionRecord;
|
||||
import com.jsowell.pile.mapper.MemberTransactionRecordMapper;
|
||||
import com.jsowell.pile.service.IMemberTransactionRecordService;
|
||||
import com.jsowell.pile.vo.web.MemberTransactionVO;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class MemberTransactionRecordServiceImpl implements IMemberTransactionRecordService {
|
||||
|
||||
@Resource
|
||||
private MemberTransactionRecordMapper memberTransactionRecordMapper;
|
||||
|
||||
@Override
|
||||
public int insertSelective(MemberTransactionRecord record) {
|
||||
return memberTransactionRecordMapper.insertSelective(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MemberTransactionVO> selectMemberTransactionRecordList(String memberId) {
|
||||
List<MemberTransactionRecord> list = memberTransactionRecordMapper.selectByMemberId(memberId);
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
List<MemberTransactionVO> resultList = Lists.newArrayList();
|
||||
for (MemberTransactionRecord memberTransactionRecord : list) {
|
||||
MemberTransactionVO vo = new MemberTransactionVO();
|
||||
BeanUtils.copyBeanProp(vo, memberTransactionRecord);
|
||||
resultList.add(vo);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.jsowell.pile.domain.MemberWalletInfo;
|
||||
import com.jsowell.pile.mapper.MemberWalletInfoMapper;
|
||||
import com.jsowell.pile.service.IMemberWalletInfoService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class MemberWalletInfoServiceImpl implements IMemberWalletInfoService {
|
||||
|
||||
@Resource
|
||||
private MemberWalletInfoMapper memberWalletInfoMapper;
|
||||
|
||||
@Override
|
||||
public int deleteByPrimaryKey(Integer id) {
|
||||
return memberWalletInfoMapper.deleteByPrimaryKey(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insert(MemberWalletInfo record) {
|
||||
return memberWalletInfoMapper.insert(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertSelective(MemberWalletInfo record) {
|
||||
return memberWalletInfoMapper.insertSelective(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemberWalletInfo selectByPrimaryKey(Integer id) {
|
||||
return memberWalletInfoMapper.selectByPrimaryKey(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateByPrimaryKeySelective(MemberWalletInfo record) {
|
||||
return memberWalletInfoMapper.updateByPrimaryKeySelective(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateByPrimaryKey(MemberWalletInfo record) {
|
||||
return memberWalletInfoMapper.updateByPrimaryKey(record);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.jsowell.pile.domain.MemberWalletLog;
|
||||
import com.jsowell.pile.mapper.MemberWalletLogMapper;
|
||||
import com.jsowell.pile.service.IMemberWalletLogService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class MemberWalletLogServiceImpl implements IMemberWalletLogService {
|
||||
|
||||
@Resource
|
||||
private MemberWalletLogMapper memberWalletLogMapper;
|
||||
|
||||
// @Override
|
||||
// public int deleteByPrimaryKey(Integer id) {
|
||||
// return memberWalletLogMapper.deleteByPrimaryKey(id);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int insert(MemberWalletLog record) {
|
||||
// return memberWalletLogMapper.insert(record);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int insertSelective(MemberWalletLog record) {
|
||||
// return memberWalletLogMapper.insertSelective(record);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public MemberWalletLog selectByPrimaryKey(Integer id) {
|
||||
// return memberWalletLogMapper.selectByPrimaryKey(id);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int updateByPrimaryKeySelective(MemberWalletLog record) {
|
||||
// return memberWalletLogMapper.updateByPrimaryKeySelective(record);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int updateByPrimaryKey(MemberWalletLog record) {
|
||||
// return memberWalletLogMapper.updateByPrimaryKey(record);
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.jsowell.pile.domain.OrderAbnormalRecord;
|
||||
import com.jsowell.pile.mapper.OrderAbnormalRecordMapper;
|
||||
import com.jsowell.pile.service.IOrderAbnormalRecordService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 订单异常记录Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2023-02-13
|
||||
*/
|
||||
@Service
|
||||
public class OrderAbnormalRecordServiceImpl implements IOrderAbnormalRecordService {
|
||||
@Autowired
|
||||
private OrderAbnormalRecordMapper orderAbnormalRecordMapper;
|
||||
|
||||
/**
|
||||
* 查询订单异常记录
|
||||
*
|
||||
* @param id 订单异常记录主键
|
||||
* @return 订单异常记录
|
||||
*/
|
||||
@Override
|
||||
public OrderAbnormalRecord selectOrderAbnormalRecordById(Integer id) {
|
||||
return orderAbnormalRecordMapper.selectOrderAbnormalRecordById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询订单异常记录列表
|
||||
*
|
||||
* @param orderAbnormalRecord 订单异常记录
|
||||
* @return 订单异常记录
|
||||
*/
|
||||
@Override
|
||||
public List<OrderAbnormalRecord> selectOrderAbnormalRecordList(OrderAbnormalRecord orderAbnormalRecord) {
|
||||
return orderAbnormalRecordMapper.selectOrderAbnormalRecordList(orderAbnormalRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增订单异常记录
|
||||
*
|
||||
* @param orderAbnormalRecord 订单异常记录
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertOrderAbnormalRecord(OrderAbnormalRecord orderAbnormalRecord) {
|
||||
// orderAbnormalRecord.setCreateTime(DateUtils.getNowDate());
|
||||
return orderAbnormalRecordMapper.insertOrderAbnormalRecord(orderAbnormalRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改订单异常记录
|
||||
*
|
||||
* @param orderAbnormalRecord 订单异常记录
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateOrderAbnormalRecord(OrderAbnormalRecord orderAbnormalRecord) {
|
||||
return orderAbnormalRecordMapper.updateOrderAbnormalRecord(orderAbnormalRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除订单异常记录
|
||||
*
|
||||
* @param ids 需要删除的订单异常记录主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteOrderAbnormalRecordByIds(Integer[] ids) {
|
||||
return orderAbnormalRecordMapper.deleteOrderAbnormalRecordByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除订单异常记录信息
|
||||
*
|
||||
* @param id 订单异常记录主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteOrderAbnormalRecordById(Integer id) {
|
||||
return orderAbnormalRecordMapper.deleteOrderAbnormalRecordById(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,852 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.jsowell.common.annotation.DataScope;
|
||||
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.domain.ykc.TransactionRecordsData;
|
||||
import com.jsowell.common.core.redis.RedisCache;
|
||||
import com.jsowell.common.enums.MemberWalletEnum;
|
||||
import com.jsowell.common.enums.ykc.OrderPayModeEnum;
|
||||
import com.jsowell.common.enums.ykc.OrderPayStatusEnum;
|
||||
import com.jsowell.common.enums.ykc.OrderStatusEnum;
|
||||
import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum;
|
||||
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
|
||||
import com.jsowell.common.exception.BusinessException;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.common.util.bean.BeanUtils;
|
||||
import com.jsowell.common.util.id.SnowflakeIdWorker;
|
||||
import com.jsowell.pile.domain.OrderAbnormalRecord;
|
||||
import com.jsowell.pile.domain.OrderBasicInfo;
|
||||
import com.jsowell.pile.domain.OrderDetail;
|
||||
import com.jsowell.pile.domain.OrderPayRecord;
|
||||
import com.jsowell.pile.domain.WxpayCallbackRecord;
|
||||
import com.jsowell.pile.dto.IndexQueryDTO;
|
||||
import com.jsowell.pile.dto.QueryOrderDTO;
|
||||
import com.jsowell.pile.dto.QueryPersonPileDTO;
|
||||
import com.jsowell.pile.mapper.OrderBasicInfoMapper;
|
||||
import com.jsowell.pile.service.IMemberBasicInfoService;
|
||||
import com.jsowell.pile.service.IOrderAbnormalRecordService;
|
||||
import com.jsowell.pile.service.IOrderBasicInfoService;
|
||||
import com.jsowell.pile.service.IOrderPayRecordService;
|
||||
import com.jsowell.pile.service.IPileConnectorInfoService;
|
||||
import com.jsowell.pile.service.WechatPayService;
|
||||
import com.jsowell.pile.service.WxpayCallbackRecordService;
|
||||
import com.jsowell.pile.transaction.dto.OrderTransactionDTO;
|
||||
import com.jsowell.pile.transaction.service.TransactionService;
|
||||
import com.jsowell.pile.vo.uniapp.*;
|
||||
import com.jsowell.pile.vo.web.IndexOrderInfoVO;
|
||||
import com.jsowell.pile.vo.web.OrderListVO;
|
||||
import com.jsowell.pile.vo.web.OrderTotalDataVO;
|
||||
import com.jsowell.pile.vo.web.PileConnectorInfoVO;
|
||||
import com.jsowell.pile.vo.web.UpdateMemberBalanceDTO;
|
||||
import com.jsowell.wxpay.common.WeChatPayParameter;
|
||||
import com.jsowell.wxpay.dto.WeChatRefundDTO;
|
||||
import com.jsowell.wxpay.dto.WechatSendMsgDTO;
|
||||
import com.jsowell.wxpay.response.WechatPayRefundRequest;
|
||||
import com.jsowell.wxpay.response.WechatPayRefundResponse;
|
||||
import com.jsowell.wxpay.service.WxAppletRemoteService;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 订单Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2022-09-30
|
||||
*/
|
||||
@Service
|
||||
public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private OrderBasicInfoMapper orderBasicInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private TransactionService transactionService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Autowired
|
||||
private IOrderPayRecordService orderPayRecordService;
|
||||
|
||||
@Autowired
|
||||
private IMemberBasicInfoService memberBasicInfoService;
|
||||
|
||||
@Autowired
|
||||
private WxpayCallbackRecordService wxpayCallbackRecordService;
|
||||
|
||||
@Autowired
|
||||
private WechatPayService wechatPayService;
|
||||
|
||||
@Autowired
|
||||
private IOrderAbnormalRecordService orderAbnormalRecordService;
|
||||
|
||||
@Autowired
|
||||
private WxAppletRemoteService wxAppletRemoteService;
|
||||
|
||||
@Autowired
|
||||
private IPileConnectorInfoService pileConnectorInfoService;
|
||||
|
||||
/**
|
||||
* 查询订单
|
||||
*
|
||||
* @param id 订单主键
|
||||
* @return 订单
|
||||
*/
|
||||
@Override
|
||||
public OrderBasicInfo selectOrderBasicInfoById(Long id) {
|
||||
return orderBasicInfoMapper.selectOrderBasicInfoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查询订单基本信息
|
||||
* @param info
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public OrderBasicInfo getOrderBasicInfo(OrderBasicInfo info) {
|
||||
return orderBasicInfoMapper.getOrderBasicInfo(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询订单列表
|
||||
*
|
||||
* @param dto 订单
|
||||
* @return 订单
|
||||
*/
|
||||
@Override
|
||||
@DataScope(deptAlias = "t3")
|
||||
public List<OrderListVO> selectOrderBasicInfoList(QueryOrderDTO dto) {
|
||||
List<OrderListVO> orderListVOS = orderBasicInfoMapper.selectOrderBasicInfoList(dto);
|
||||
if (CollectionUtils.isNotEmpty(orderListVOS)) {
|
||||
for (OrderListVO orderListVO : orderListVOS) {
|
||||
// 如果是微信支付,通过订单号查询微信支付单号
|
||||
if (StringUtils.equals(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue(), orderListVO.getPayMode())) {
|
||||
WxpayCallbackRecord wxpayCallbackRecord = wxpayCallbackRecordService.selectByOrderCode(orderListVO.getOrderCode());
|
||||
orderListVO.setOutTradeNo(wxpayCallbackRecord.getOutTradeNo());
|
||||
}
|
||||
orderListVO.setPileConnectorCode(orderListVO.getPileSn() + orderListVO.getConnectorCode());
|
||||
|
||||
// 订单状态描述
|
||||
String orderStatus = orderListVO.getOrderStatus(); // 订单状态
|
||||
String payStatus = orderListVO.getPayStatus(); // 支付状态
|
||||
String orderStatusDescribe;
|
||||
if (StringUtils.equals(orderStatus, OrderStatusEnum.NOT_START.getValue())) {
|
||||
// 未启动还有两种情况 待支付 / 支付成功
|
||||
if (StringUtils.equals(payStatus, OrderPayStatusEnum.paid.getValue())) {
|
||||
// 支付成功,未启动
|
||||
orderStatusDescribe = OrderPayStatusEnum.paid.getLabel() + ", " + OrderStatusEnum.getOrderStatus(orderStatus);
|
||||
} else {
|
||||
// 待支付
|
||||
orderStatusDescribe = OrderPayStatusEnum.unpaid.getLabel();
|
||||
}
|
||||
} else {
|
||||
orderStatusDescribe = OrderStatusEnum.getOrderStatus(orderStatus);
|
||||
}
|
||||
orderListVO.setOrderStatusDescribe(orderStatusDescribe);
|
||||
}
|
||||
}
|
||||
return orderListVOS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询时间段内订单总金额和总用电量
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@DataScope(deptAlias = "t3")
|
||||
public OrderTotalDataVO getOrderTotalData(QueryOrderDTO dto) {
|
||||
OrderTotalDataVO vo = new OrderTotalDataVO();
|
||||
dto.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());
|
||||
List<OrderListVO> list = orderBasicInfoMapper.selectOrderBasicInfoList(dto);
|
||||
BigDecimal sumOrderAmount = BigDecimal.ZERO;
|
||||
BigDecimal sumUsedElectricity = BigDecimal.ZERO;
|
||||
vo.setDateDescription(dto.getStartTime() + " - " + dto.getEndTime());
|
||||
if (CollectionUtils.isNotEmpty(list)) {
|
||||
for (OrderListVO orderListVO : list) {
|
||||
BigDecimal orderAmount = StringUtils.isBlank(orderListVO.getOrderAmount())
|
||||
? BigDecimal.ZERO
|
||||
: new BigDecimal(orderListVO.getOrderAmount());
|
||||
sumOrderAmount = sumOrderAmount.add(orderAmount);
|
||||
|
||||
BigDecimal chargingDegree = StringUtils.isBlank(orderListVO.getChargingDegree())
|
||||
? BigDecimal.ZERO
|
||||
: new BigDecimal(orderListVO.getChargingDegree());
|
||||
sumUsedElectricity = sumUsedElectricity.add(chargingDegree);
|
||||
}
|
||||
}
|
||||
vo.setSumOrderAmount(sumOrderAmount);
|
||||
vo.setSumUsedElectricity(sumUsedElectricity);
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过订单号查询订单信息(小程序发送消息用)
|
||||
* @param orderCode
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public SendMessageVO selectOrderInfoByOrderCode(String orderCode) {
|
||||
return orderBasicInfoMapper.selectOrderInfoByOrderCode(orderCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 充电桩启动失败
|
||||
* @param orderCode
|
||||
* @param failedReasonMsg
|
||||
*/
|
||||
@Override
|
||||
public void chargingPileFailedToStart(String orderCode, String failedReasonMsg) {
|
||||
OrderBasicInfo orderInfo = getOrderInfoByOrderCode(orderCode);
|
||||
if (orderInfo == null) {
|
||||
return;
|
||||
}
|
||||
// 启动失败原因
|
||||
orderInfo.setReason(failedReasonMsg);
|
||||
// 订单退款(结算订单)
|
||||
TransactionRecordsData data = TransactionRecordsData.builder()
|
||||
.orderCode(orderInfo.getOrderCode())
|
||||
.consumptionAmount(String.valueOf(orderInfo.getOrderAmount()))
|
||||
.stopReasonMsg(failedReasonMsg)
|
||||
.totalElectricity(Constants.ZERO)
|
||||
.sharpUsedElectricity(Constants.ZERO)
|
||||
.peakUsedElectricity(Constants.ZERO)
|
||||
.flatUsedElectricity(Constants.ZERO)
|
||||
.valleyUsedElectricity(Constants.ZERO)
|
||||
.build();
|
||||
settleOrder(data, orderInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 充电桩启动成功
|
||||
* @param orderCode
|
||||
*/
|
||||
@Override
|
||||
public void chargingPileStartedSuccessfully(String orderCode) {
|
||||
OrderBasicInfo orderInfo = getOrderInfoByOrderCode(orderCode);
|
||||
if (orderInfo == null) {
|
||||
return;
|
||||
}
|
||||
// 启动成功,订单状态改为充电中
|
||||
orderInfo.setOrderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue());
|
||||
if (orderInfo.getChargeStartTime() == null) {
|
||||
orderInfo.setChargeStartTime(new Date());
|
||||
}
|
||||
updateOrderBasicInfo(orderInfo);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Date date = DateUtils.addMinute(new Date(), -10);
|
||||
System.out.println(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, date));
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
if (currentTimeMillis - date.getTime() > 1000 * 60 * 15) {
|
||||
// 已经支付超过15分钟
|
||||
System.out.println("已经支付超过15分钟");
|
||||
} else {
|
||||
System.out.println("已经支付, 不到15分钟");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeStartFailedOrder(String startTime, String endTime) {
|
||||
List<OrderBasicInfo> orderList = orderBasicInfoMapper.selectOrderListByTimeRangeAndStatus(startTime, endTime, OrderStatusEnum.NOT_START.getValue(), OrderPayStatusEnum.paid.getValue());
|
||||
List<String> orderCodeList = orderList.stream().map(OrderBasicInfo::getOrderCode).collect(Collectors.toList());
|
||||
logger.info("{}-{}期间,共{}条,支付成功未启动订单,订单号:{}", startTime, endTime, orderList.size(), orderCodeList);
|
||||
if (CollectionUtils.isEmpty(orderList)) {
|
||||
return;
|
||||
}
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
// 判断支付成功时间距当前时间是否大于15分钟
|
||||
for (OrderBasicInfo orderBasicInfo : orderList) {
|
||||
String orderCode = orderBasicInfo.getOrderCode();
|
||||
Date payTime = orderBasicInfo.getPayTime();
|
||||
if (payTime == null) {
|
||||
continue;
|
||||
}
|
||||
long time = payTime.getTime();
|
||||
if (currentTimeMillis - time < 1000 * 60 * 15) {
|
||||
continue;
|
||||
}
|
||||
// 已经支付超过15分钟 判断充电桩的状态
|
||||
String pileConnectorCode = orderBasicInfo.getPileSn() + orderBasicInfo.getConnectorCode();
|
||||
PileConnectorInfoVO connector = pileConnectorInfoService.getPileConnectorInfoByConnectorCode(pileConnectorCode);
|
||||
// 充电桩不在线,则不做处理。请联系管理员操作
|
||||
if (PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue().equals(String.valueOf(connector.getStatus()))) {
|
||||
logger.info("订单号:{}已经支付超过15分钟,充电桩:{}未启动,但是该桩为离线状态,请联系管理员处理", orderCode, pileConnectorCode);
|
||||
continue;
|
||||
}
|
||||
// 获取订单的实时检测数据,有实时数据说明充电了,没有实时数据说明桩确实没有充电
|
||||
List<RealTimeMonitorData> chargingRealTimeData = getChargingRealTimeData(orderCode);
|
||||
if (CollectionUtils.isEmpty(chargingRealTimeData)) {
|
||||
// 充电桩在线,并且没有0x13实时数据,则执行结算退款操作
|
||||
chargingPileFailedToStart(orderCode, "充电桩启动失败,执行退款处理");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询充电中的订单,没有数据权限校验,后管不要用
|
||||
*
|
||||
* @param pileSn
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<OrderListVO> selectChargingOrder(String pileSn) {
|
||||
QueryOrderDTO dto = QueryOrderDTO.builder()
|
||||
.pileSn(pileSn)
|
||||
.orderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue())
|
||||
.build();
|
||||
return orderBasicInfoMapper.selectOrderBasicInfoList(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改订单
|
||||
*
|
||||
* @param orderBasicInfo 订单
|
||||
* @return 结果
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public int updateOrderBasicInfo(OrderBasicInfo orderBasicInfo) {
|
||||
// 清缓存
|
||||
String redisKey = CacheConstants.GET_ORDER_INFO_BY_ORDER_CODE + orderBasicInfo.getOrderCode();
|
||||
redisCache.deleteObject(redisKey);
|
||||
return orderBasicInfoMapper.updateOrderBasicInfo(orderBasicInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除订单
|
||||
*
|
||||
* @param ids 需要删除的订单主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public int deleteOrderBasicInfoByIds(Long[] ids) {
|
||||
orderBasicInfoMapper.deleteOrderDetailByOrderCodes(ids);
|
||||
return orderBasicInfoMapper.deleteOrderBasicInfoByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过订单号查询订单信息
|
||||
*
|
||||
* @param orderCode 订单号
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public OrderBasicInfo getOrderInfoByOrderCode(String orderCode) {
|
||||
String redisKey = CacheConstants.GET_ORDER_INFO_BY_ORDER_CODE + orderCode;
|
||||
OrderBasicInfo orderBasicInfo = redisCache.getCacheObject(redisKey);
|
||||
if (orderBasicInfo == null) {
|
||||
// 查数据库
|
||||
orderBasicInfo = orderBasicInfoMapper.getOrderInfoByOrderCode(orderCode);
|
||||
// 放缓存
|
||||
if (orderBasicInfo != null) {
|
||||
redisCache.setCacheObject(redisKey, orderBasicInfo, 5, TimeUnit.MINUTES);
|
||||
}
|
||||
}
|
||||
logger.info("通过订单号:{}, 查询订单信息:{}", orderCode, JSON.toJSONString(orderBasicInfo));
|
||||
return orderBasicInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据充电桩编号和枪口号查询正在充电中的订单
|
||||
* @param pileSn 桩编号
|
||||
* @param connectorCode 枪口号
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public OrderBasicInfo queryChargingByPileSnAndConnectorCode(String pileSn, String connectorCode) {
|
||||
return orderBasicInfoMapper.queryOrderBasicInfo(pileSn, connectorCode, OrderStatusEnum.IN_THE_CHARGING.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据枪口编号查询正在充电中的订单
|
||||
* @param pileConnectorCode
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public OrderBasicInfo queryChargingByPileConnectorCode(String pileConnectorCode) {
|
||||
if (StringUtils.isBlank(pileConnectorCode)) {
|
||||
return null;
|
||||
}
|
||||
String pileSn = pileConnectorCode.substring(0, pileConnectorCode.length() - 2);
|
||||
String connectorCode = pileConnectorCode.substring(pileConnectorCode.length() - 2);
|
||||
return queryChargingByPileSnAndConnectorCode(pileSn, connectorCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结算订单逻辑
|
||||
*
|
||||
* @param data 交易记录数据
|
||||
* @param orderBasicInfo 订单主表信息,由调用方传过来
|
||||
*/
|
||||
@Override
|
||||
public void settleOrder(TransactionRecordsData data, OrderBasicInfo orderBasicInfo) {
|
||||
logger.info("结算订单start data:{}, orderBasicInfo:{}", data.toString(), orderBasicInfo.toString());
|
||||
String orderCode = data.getOrderCode();
|
||||
|
||||
// 判断订单状态
|
||||
if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) {
|
||||
logger.info("结算订单:{}, 是订单完成状态", orderCode);
|
||||
return;
|
||||
}
|
||||
// 消费金额就是订单总金额
|
||||
BigDecimal orderAmount = new BigDecimal(data.getConsumptionAmount());
|
||||
|
||||
// 付款金额 - 实际消费金额,如果有剩余,需要走退款操作 当使用余额支付时payAmount = principalPay + giftPay
|
||||
BigDecimal payAmount = orderBasicInfo.getPayAmount();
|
||||
|
||||
// 有时候充电桩到达金额停止充电会多出一点金额,比如实际需要充50元的电,充电桩传来的消费金额为50.01元,在后台记录的时候需要舍去
|
||||
if (orderAmount.compareTo(payAmount) > 0) {
|
||||
logger.info("结算订单:【{}】充电桩传来的消费金额:【{}】大于付款金额:【{}】, 消费金额设置为付款金额相等数据", orderBasicInfo.getOrderCode(), orderAmount, payAmount);
|
||||
orderAmount = payAmount;
|
||||
}
|
||||
|
||||
// 剩余需要退回的金额 residue
|
||||
BigDecimal residue = payAmount.subtract(orderAmount);
|
||||
if (residue.compareTo(BigDecimal.ZERO) > 0) {
|
||||
// 查支付记录
|
||||
List<OrderPayRecord> payRecordList = orderPayRecordService.getOrderPayRecordList(orderBasicInfo.getOrderCode());
|
||||
// 更新订单支付记录
|
||||
List<OrderPayRecord> updatePayRecordList = Lists.newArrayList();
|
||||
// 根据支付方式不同,走不同渠道退款
|
||||
String payMode = orderBasicInfo.getPayMode();
|
||||
if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { // 余额支付
|
||||
Map<String, OrderPayRecord> payRecordMap = payRecordList.stream()
|
||||
.collect(Collectors.toMap(OrderPayRecord::getPayMode, Function.identity(), (k1, k2) -> k1));
|
||||
// 取出本金支付金额,赠送支付金额
|
||||
BigDecimal principalPay = null;
|
||||
BigDecimal giftPay = null;
|
||||
|
||||
OrderPayRecord principalPayRecord = payRecordMap.get("1");
|
||||
if (principalPayRecord != null) {
|
||||
principalPay = principalPayRecord.getPayAmount();
|
||||
}
|
||||
|
||||
OrderPayRecord giftPayRecord = payRecordMap.get("2");
|
||||
if (giftPayRecord != null) {
|
||||
giftPay = giftPayRecord.getPayAmount();
|
||||
}
|
||||
|
||||
Map<String, BigDecimal> returnAmountMap = calculateReturnAmount(principalPay, giftPay, orderAmount);
|
||||
logger.info("结算订单:{}, 剩余金额退回余额, 订单消费金额:{}, 本金支付金额:{}, 赠送支付金额:{}, 退回金额map:{}",
|
||||
orderCode, orderAmount, principalPay, giftPay, JSONObject.toJSONString(returnAmountMap));
|
||||
// 更新会员钱包
|
||||
BigDecimal returnPrincipal = returnAmountMap.get("returnPrincipal");
|
||||
if (returnPrincipal != null && principalPayRecord != null) {
|
||||
principalPayRecord.setRefundAmount(returnPrincipal);
|
||||
updatePayRecordList.add(principalPayRecord);
|
||||
}
|
||||
BigDecimal returnGift = returnAmountMap.get("returnGift");
|
||||
if (returnGift != null && giftPayRecord != null) {
|
||||
giftPayRecord.setRefundAmount(returnGift);
|
||||
updatePayRecordList.add(giftPayRecord);
|
||||
}
|
||||
UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder()
|
||||
.memberId(orderBasicInfo.getMemberId())
|
||||
.type(MemberWalletEnum.TYPE_IN.getValue()) // 进账
|
||||
.subType(MemberWalletEnum.SUBTYPE_ORDER_SETTLEMENT_REFUND.getValue()) // 订单结算退款
|
||||
.updatePrincipalBalance(returnPrincipal)
|
||||
.updateGiftBalance(returnGift)
|
||||
.relatedOrderCode(orderCode)
|
||||
.build();
|
||||
memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO);
|
||||
} else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) { // 微信支付
|
||||
// 微信退款逻辑
|
||||
WeChatRefundDTO weChatRefundDTO = new WeChatRefundDTO();
|
||||
weChatRefundDTO.setOrderCode(orderCode);
|
||||
weChatRefundDTO.setRefundType("1");
|
||||
weChatRefundDTO.setRefundAmount(residue);
|
||||
this.weChatRefund(weChatRefundDTO);
|
||||
// 订单支付记录
|
||||
OrderPayRecord orderPayRecord = payRecordList.get(0);
|
||||
orderPayRecord.setRefundAmount(residue);
|
||||
updatePayRecordList.add(orderPayRecord);
|
||||
} else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_ALIPAY.getValue())) { // 支付宝支付
|
||||
// 支付宝退款逻辑
|
||||
} else {
|
||||
// 白名单支付
|
||||
logger.info("订单:{}使用白名单支付,不进行退款处理", orderBasicInfo.getOrderCode());
|
||||
}
|
||||
|
||||
// 更新order_pay_record
|
||||
if (CollectionUtils.isNotEmpty(updatePayRecordList)) {
|
||||
for (OrderPayRecord orderPayRecord : updatePayRecordList) {
|
||||
orderPayRecordService.updateByPrimaryKeySelective(orderPayRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 修改订单数据
|
||||
// 查询订单详情
|
||||
OrderDetail orderDetail = getOrderDetailByOrderCode(orderCode);
|
||||
|
||||
// 把交易记录中的用电量,金额等信息 更新到orderBasicInfo和orderDetail
|
||||
orderBasicInfo.setOrderAmount(orderAmount); // 订单总金额
|
||||
orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());
|
||||
orderBasicInfo.setReason(data.getStopReasonMsg()); // 充电停止原因
|
||||
orderBasicInfo.setSettlementTime(DateUtils.getNowDate()); // 结算时间
|
||||
orderBasicInfo.setRefundAmount(residue); // 结算退款金额
|
||||
|
||||
orderDetail.setTotalUsedElectricity(new BigDecimal(data.getTotalElectricity())); // 总用电量
|
||||
orderDetail.setTotalOrderAmount(orderAmount); // 订单总金额
|
||||
orderDetail.setSharpUsedElectricity(new BigDecimal(data.getSharpUsedElectricity())); // 尖时段用电量
|
||||
orderDetail.setPeakUsedElectricity(new BigDecimal(data.getPeakUsedElectricity())); // 峰时段用电量
|
||||
orderDetail.setFlatUsedElectricity(new BigDecimal(data.getFlatUsedElectricity())); // 平时段用电量
|
||||
orderDetail.setValleyUsedElectricity(new BigDecimal(data.getValleyUsedElectricity())); // 谷时段用电量
|
||||
OrderTransactionDTO dto = new OrderTransactionDTO();
|
||||
dto.setOrderBasicInfo(orderBasicInfo);
|
||||
dto.setOrderDetail(orderDetail);
|
||||
transactionService.doUpdateOrder(dto);
|
||||
logger.info("结算订单 end OrderTransactionDTO:{}", JSONObject.toJSONString(dto));
|
||||
|
||||
try {
|
||||
// uniApp 发送停止充电订阅消息
|
||||
WechatSendMsgDTO wechatSendMsgDTO = new WechatSendMsgDTO();
|
||||
wechatSendMsgDTO.setOrderCode(orderCode);
|
||||
Map<String, String> resultMap = wxAppletRemoteService.stopChargingSendMsg(wechatSendMsgDTO);
|
||||
logger.info("小程序发送充电停止推送消息 result:{}", JSON.toJSONString(resultMap));
|
||||
}catch (Exception e) {
|
||||
logger.error("小程序发送充电停止推送消息 error", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 余额支付 计算需要退回的金额
|
||||
*
|
||||
* @param principalPay
|
||||
* @param giftPay
|
||||
* @param orderAmount
|
||||
* @return
|
||||
*/
|
||||
private Map<String, BigDecimal> calculateReturnAmount(BigDecimal principalPay, BigDecimal giftPay, BigDecimal orderAmount) {
|
||||
Map<String, BigDecimal> resultMap = Maps.newHashMap();
|
||||
|
||||
// 消费金额优先使用本金
|
||||
BigDecimal returnPrincipal = null; // 退回本金金额
|
||||
BigDecimal returnGift = null; // 退回赠送金额
|
||||
|
||||
// 余额支付 有3种情况
|
||||
if (principalPay != null && giftPay == null) {
|
||||
// 只有本金支付
|
||||
BigDecimal subtract = principalPay.subtract(orderAmount);
|
||||
if (subtract.compareTo(BigDecimal.ZERO) > 0) {
|
||||
returnPrincipal = subtract;
|
||||
}
|
||||
}
|
||||
if (principalPay == null && giftPay != null) {
|
||||
// 只有赠送金额支付
|
||||
BigDecimal subtract = giftPay.subtract(orderAmount);
|
||||
if (subtract.compareTo(BigDecimal.ZERO) > 0) {
|
||||
returnGift = subtract;
|
||||
}
|
||||
}
|
||||
if (principalPay != null && giftPay != null) {
|
||||
// 本金+赠送支付
|
||||
BigDecimal subtract = principalPay.subtract(orderAmount);
|
||||
if (subtract.compareTo(BigDecimal.ZERO) > 0) {
|
||||
// 本金减掉订单金额后还有剩余,那就把剩余的退回,赠送原封不动退回
|
||||
returnPrincipal = subtract;
|
||||
returnGift = giftPay;
|
||||
} else if (subtract.compareTo(BigDecimal.ZERO) == 0) {
|
||||
// 本金刚好够,那赠送金额支付的原封不动退回
|
||||
returnGift = giftPay;
|
||||
} else {
|
||||
returnGift = giftPay.subtract(subtract.negate());
|
||||
}
|
||||
}
|
||||
|
||||
resultMap.put("returnPrincipal", returnPrincipal);
|
||||
resultMap.put("returnGift", returnGift);
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 结算订单退款和用户余额退款调这个方法
|
||||
*
|
||||
* @param dto
|
||||
*/
|
||||
@Override
|
||||
public void weChatRefund(WeChatRefundDTO dto) {
|
||||
// 退款有两种情况 1-订单结算退款 2-用户余额退款
|
||||
String refundType = dto.getRefundType();
|
||||
if (StringUtils.equals(refundType, "1")) {
|
||||
WechatPayRefundResponse response = refundForOrder(dto);
|
||||
logger.info("订单结算退款 result:{}", JSONObject.toJSONString(response));
|
||||
} else if (StringUtils.equals(refundType, "2")) {
|
||||
WechatPayRefundResponse response = refundForBalance(dto);
|
||||
logger.info("用户余额退款 result:{}", JSONObject.toJSONString(response));
|
||||
} else {
|
||||
logger.warn("没有找到退款处理逻辑");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAbnormalOrder(TransactionRecordsData data) {
|
||||
OrderAbnormalRecord record = new OrderAbnormalRecord();
|
||||
BeanUtils.copyBeanProp(record, data);
|
||||
orderAbnormalRecordService.insertOrderAbnormalRecord(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单编号获取充电实时数据 时间倒序
|
||||
* 订单只有在充电中,才会把实时数据保存到redis
|
||||
* @param orderCode 订单编号
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<RealTimeMonitorData> getChargingRealTimeData(String orderCode) {
|
||||
List<RealTimeMonitorData> resultList = Lists.newArrayList();
|
||||
if (StringUtils.isBlank(orderCode)) {
|
||||
return resultList;
|
||||
}
|
||||
String pileConnectorCode = orderCode.substring(0, 16);
|
||||
String redisKey = CacheConstants.PILE_REAL_TIME_MONITOR_DATA + pileConnectorCode + "_" + orderCode;
|
||||
// 拿到所有数据
|
||||
Map<Object, Object> map = redisCache.hmget(redisKey);
|
||||
if (map != null && !map.isEmpty()) {
|
||||
List<String> keyList = map.keySet().stream()
|
||||
.map(x -> (String) x)
|
||||
.sorted(Comparator.reverseOrder()) // 对keyList排序 时间倒序
|
||||
.collect(Collectors.toList());
|
||||
for (String s : keyList) {
|
||||
Object o = map.get(s);
|
||||
RealTimeMonitorData data = JSONObject.parseObject((String) o, RealTimeMonitorData.class);
|
||||
resultList.add(data);
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页订单数据展示
|
||||
*
|
||||
* @param dto 首页信息查询dto
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<IndexOrderInfoVO> getIndexOrderInfo(IndexQueryDTO dto) {
|
||||
return orderBasicInfoMapper.getIndexOrderInfo(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取超过15分钟的待支付状态订单
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<OrderBasicInfo> getUnpaidOrderListOver15Min() {
|
||||
Date now = DateUtils.addMinute(new Date(), -15);
|
||||
String nowString = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);
|
||||
return orderBasicInfoMapper.getUnpaidOrderListOver15Min(nowString);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据orderId批量修改订单状态
|
||||
*
|
||||
* @param orderIds
|
||||
* @param orderStatus
|
||||
*/
|
||||
@Override
|
||||
public void updateOrderStatusById(List<String> orderIds, String orderStatus) {
|
||||
orderBasicInfoMapper.updateOrderStatusById(orderIds, orderStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int close15MinutesOfUnpaidOrders() {
|
||||
List<OrderBasicInfo> orderList = getUnpaidOrderListOver15Min();
|
||||
if (CollectionUtils.isNotEmpty(orderList)) {
|
||||
List<String> orderIdList = orderList.stream()
|
||||
.map(x -> String.valueOf(x.getId()))
|
||||
.collect(Collectors.toList());
|
||||
// 修改订单状态
|
||||
updateOrderStatusById(orderIdList, OrderStatusEnum.ORDER_CLOSE_TIMEOUT.getValue());
|
||||
}
|
||||
return orderList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单退款处理逻辑
|
||||
*/
|
||||
private WechatPayRefundResponse refundForOrder(WeChatRefundDTO dto) {
|
||||
// 查到orderCode对应的支付订单
|
||||
// OrderBasicInfo orderInfo = this.getOrderInfoByOrderCode(dto.getOrderCode());
|
||||
// // 校验订单
|
||||
// if (Objects.isNull(orderInfo)) {
|
||||
// logger.warn("orderCode:{}, 订单退款处理逻辑, 查询订单为空!", dto.getOrderCode());
|
||||
// throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_NULL_ERROR);
|
||||
// }
|
||||
// // 判断退款金额,不能大于支付金额
|
||||
// BigDecimal payAmount = orderInfo.getPayAmount();
|
||||
// // BigDecimal orderAmount = orderInfo.getOrderAmount();
|
||||
// // BigDecimal amountToBeRefunded = payAmount.subtract(orderAmount); // 可退金额
|
||||
// BigDecimal amountToBeRefunded = dto.getRefundAmount(); // 可退金额
|
||||
// logger.info("订单:{}, 支付金额:{}, 需退款金额:{}", dto.getOrderCode(), payAmount, amountToBeRefunded);
|
||||
// if (dto.getRefundAmount().compareTo(amountToBeRefunded) > 0) {
|
||||
// // 退款金额,大于可退金额 抛出异常
|
||||
// logger.warn("退款金额:{},大于可退金额{}, 抛出异常", dto.getRefundAmount(), amountToBeRefunded);
|
||||
// throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_AMOUNT_ERROR);
|
||||
// }
|
||||
// 查出来原来的支付信息
|
||||
WxpayCallbackRecord record = wxpayCallbackRecordService.selectByOrderCode(dto.getOrderCode());
|
||||
if (Objects.isNull(record)) {
|
||||
logger.warn("orderCode:{}, 订单退款处理逻辑, 查询订单微信支付记录为空!", dto.getOrderCode());
|
||||
throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_CALLBACK_RECORD_ERROR);
|
||||
}
|
||||
|
||||
// 判断支付金额和退款金额
|
||||
int refundAmountInt = dto.getRefundAmount().multiply(new BigDecimal("100")).intValue();
|
||||
int payerTotalInt = Integer.parseInt(record.getPayerTotal());
|
||||
if (refundAmountInt > payerTotalInt) {
|
||||
logger.warn("订单号:{}, 退款金额:{}(分),大于可退金额{}(分), 抛出异常", dto.getOrderCode(), refundAmountInt, payerTotalInt);
|
||||
throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_AMOUNT_ERROR);
|
||||
}
|
||||
|
||||
// 调微信退款接口
|
||||
WechatPayRefundRequest request = new WechatPayRefundRequest();
|
||||
request.setTransaction_id(record.getTransactionId()); // 微信支付单号
|
||||
request.setOut_trade_no(record.getOutTradeNo()); // 商户订单号
|
||||
// 生成退款单号
|
||||
request.setOut_refund_no(SnowflakeIdWorker.getSnowflakeId()); // 商户退款单号
|
||||
request.setNotify_url(WeChatPayParameter.refundNotifyUrl); // 回调接口
|
||||
WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount();
|
||||
amount.setRefund(refundAmountInt); // 退款金额
|
||||
amount.setTotal(payerTotalInt); // 原订单金额
|
||||
request.setAmount(amount);
|
||||
request.setReason("订单结算退款");
|
||||
request.setFunds_account("AVAILABLE");
|
||||
try {
|
||||
return wechatPayService.ApplyForWechatPayRefundV3(request);
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.error("调微信退款API发生异常", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 余额退款处理逻辑
|
||||
*
|
||||
* @param dto
|
||||
*/
|
||||
private WechatPayRefundResponse refundForBalance(WeChatRefundDTO dto) {
|
||||
// 查会员余额
|
||||
MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId());
|
||||
if (memberVO == null) {
|
||||
throw new BusinessException(ReturnCodeEnum.CODE_SELECT_MEMBER_NULL_ERROR);
|
||||
}
|
||||
// 校验退款金额
|
||||
BigDecimal principalBalance = memberVO.getPrincipalBalance();
|
||||
BigDecimal refundAmount = dto.getRefundAmount();
|
||||
if (refundAmount.compareTo(principalBalance) > 0) {
|
||||
throw new BusinessException(ReturnCodeEnum.CODE_REFUND_MEMBER_BALANCE_ERROR);
|
||||
}
|
||||
// 退款金额 元转分 123
|
||||
int totalCents = refundAmount.multiply(new BigDecimal(100)).intValue();
|
||||
// 查询最近一年余额充值订单
|
||||
List<WxpayCallbackRecord> recordList = wxpayCallbackRecordService.queryBalanceRechargeRecordOfTheLatestYear(dto.getMemberId());
|
||||
// 也许需要多笔支付订单才够退款
|
||||
List<WechatPayRefundRequest> requestList = Lists.newArrayList();
|
||||
WechatPayRefundRequest request;
|
||||
for (WxpayCallbackRecord record : recordList) {
|
||||
int payerTotal = Integer.parseInt(record.getPayerTotal()); // 该笔支付订单的支付金额,单位分
|
||||
totalCents = totalCents - payerTotal; // 123 - 100
|
||||
request = new WechatPayRefundRequest();
|
||||
request.setTransaction_id(record.getTransactionId()); // 微信支付单号
|
||||
request.setOut_trade_no(record.getOutTradeNo()); // 商户订单号
|
||||
request.setOut_refund_no(SnowflakeIdWorker.getSnowflakeId()); // 商户退款单号
|
||||
request.setNotify_url(WeChatPayParameter.refundNotifyUrl); // 回调接口
|
||||
request.setReason("用户余额退款");
|
||||
request.setFunds_account("AVAILABLE");
|
||||
if (totalCents > 0) {
|
||||
// 如果大于0说明,这笔单退完也不够
|
||||
WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount();
|
||||
amount.setRefund(payerTotal); // 退款金额
|
||||
amount.setTotal(payerTotal); // 原订单金额
|
||||
request.setAmount(amount);
|
||||
requestList.add(request);
|
||||
} else {
|
||||
// 如果小于0,这笔单退一部分
|
||||
// 生成退款单号
|
||||
WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount();
|
||||
// 部分退
|
||||
int i = payerTotal + totalCents;
|
||||
amount.setRefund(i); // 退款金额
|
||||
amount.setTotal(payerTotal); // 原订单金额
|
||||
request.setAmount(amount);
|
||||
requestList.add(request);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 调微信退款api
|
||||
if (CollectionUtils.isNotEmpty(requestList)) {
|
||||
for (WechatPayRefundRequest refundRequest : requestList) {
|
||||
try {
|
||||
return wechatPayService.ApplyForWechatPayRefundV3(refundRequest);
|
||||
// logger.info("调微信退款API退款====={}", JSONObject.toJSONString(refundRequest));
|
||||
} catch (Exception e) {
|
||||
logger.error("调微信退款API发生异常", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过订单号查询订单详情
|
||||
*
|
||||
* @param orderCode 订单号
|
||||
* @return 订单详情
|
||||
*/
|
||||
@Override
|
||||
public OrderDetail getOrderDetailByOrderCode(String orderCode) {
|
||||
return orderBasicInfoMapper.getOrderDetailByOrderCode(orderCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过会员Id和订单状态查询订单信息
|
||||
*
|
||||
* @param memberId 会员id
|
||||
* @param orderStatusList 订单状态集合
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<OrderVO> getListByMemberIdAndOrderStatus(String memberId, List<String> orderStatusList) {
|
||||
return orderBasicInfoMapper.getListByMemberIdAndOrderStatus(memberId, orderStatusList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 个人桩查询充电数据
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<PersonPileConnectorSumInfoVO> getAccumulativeInfo(QueryPersonPileDTO dto) {
|
||||
return orderBasicInfoMapper.getAccumulativeInfo(dto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.jsowell.pile.domain.OrderPayRecord;
|
||||
import com.jsowell.pile.mapper.OrderPayRecordMapper;
|
||||
import com.jsowell.pile.service.IOrderPayRecordService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class OrderPayRecordServiceImpl implements IOrderPayRecordService {
|
||||
|
||||
@Resource
|
||||
private OrderPayRecordMapper orderPayRecordMapper;
|
||||
|
||||
|
||||
// @Override
|
||||
// public int deleteByPrimaryKey(Integer id) {
|
||||
// return orderPayRecordMapper.deleteByPrimaryKey(id);
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// public int insert(OrderPayRecord record) {
|
||||
// return orderPayRecordMapper.insert(record);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int insertSelective(OrderPayRecord record) {
|
||||
// return orderPayRecordMapper.insertSelective(record);
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// public OrderPayRecord selectByPrimaryKey(Integer id) {
|
||||
// return orderPayRecordMapper.selectByPrimaryKey(id);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public int updateByPrimaryKeySelective(OrderPayRecord record) {
|
||||
return orderPayRecordMapper.updateByPrimaryKeySelective(record);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public int updateByPrimaryKey(OrderPayRecord record) {
|
||||
// return orderPayRecordMapper.updateByPrimaryKey(record);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public int batchInsert(List<OrderPayRecord> payRecordList) {
|
||||
return orderPayRecordMapper.batchInsert(payRecordList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OrderPayRecord> getOrderPayRecordList(String orderCode) {
|
||||
return orderPayRecordMapper.getOrderPayRecordList(orderCode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,566 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jsowell.common.annotation.DataScope;
|
||||
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.domain.ykc.YKCFrameTypeCode;
|
||||
import com.jsowell.common.core.redis.RedisCache;
|
||||
import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum;
|
||||
import com.jsowell.common.enums.ykc.PileConnectorStatusEnum;
|
||||
import com.jsowell.common.util.BytesUtil;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.common.util.PageUtils;
|
||||
import com.jsowell.common.util.SecurityUtils;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.pile.domain.PileBasicInfo;
|
||||
import com.jsowell.pile.domain.PileConnectorInfo;
|
||||
import com.jsowell.pile.domain.PileSimInfo;
|
||||
import com.jsowell.pile.dto.IndexQueryDTO;
|
||||
import com.jsowell.pile.dto.QueryPileDTO;
|
||||
import com.jsowell.pile.dto.ReplaceMerchantStationDTO;
|
||||
import com.jsowell.pile.mapper.PileBasicInfoMapper;
|
||||
import com.jsowell.pile.mapper.PileMemberRelationMapper;
|
||||
import com.jsowell.pile.service.*;
|
||||
import com.jsowell.pile.vo.base.MerchantInfoVO;
|
||||
import com.jsowell.pile.vo.base.PileInfoVO;
|
||||
import com.jsowell.pile.vo.uniapp.PersonalPileInfoVO;
|
||||
import com.jsowell.pile.vo.uniapp.PileConnectorDetailVO;
|
||||
import com.jsowell.pile.vo.web.IndexGeneralSituationVO;
|
||||
import com.jsowell.pile.vo.web.PileDetailVO;
|
||||
import com.jsowell.pile.vo.web.PileModelInfoVO;
|
||||
import com.jsowell.pile.vo.web.SimCardVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 设备管理Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2022-08-26
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PileBasicInfoServiceImpl implements IPileBasicInfoService {
|
||||
@Autowired
|
||||
private PileBasicInfoMapper pileBasicInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private IPileConnectorInfoService pileConnectorInfoService;
|
||||
|
||||
@Autowired
|
||||
private IPileModelInfoService pileModelInfoService;
|
||||
|
||||
@Autowired
|
||||
private IPileMerchantInfoService pileMerchantInfoService;
|
||||
|
||||
@Autowired
|
||||
private IPileSimInfoService pileSimInfoService;
|
||||
|
||||
@Autowired
|
||||
private SimCardService simCardService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Value("${qrcodeurl.prefix}")
|
||||
private String QRCODE_URL_PREFIX;
|
||||
|
||||
/**
|
||||
* 查询设备管理
|
||||
*
|
||||
* @param id 设备管理主键
|
||||
* @return 设备管理
|
||||
*/
|
||||
@Override
|
||||
public PileBasicInfo selectPileBasicInfoById(Long id) {
|
||||
return pileBasicInfoMapper.selectPileBasicInfoById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PileBasicInfo selectPileBasicInfoBySN(String pileSn) {
|
||||
return pileBasicInfoMapper.selectPileBasicInfoBySn(pileSn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备管理列表
|
||||
*
|
||||
* @param pileBasicInfo 设备管理
|
||||
* @return 设备管理
|
||||
*/
|
||||
@Override
|
||||
public List<PileBasicInfo> selectPileBasicInfoList(PileBasicInfo pileBasicInfo) {
|
||||
return pileBasicInfoMapper.selectPileBasicInfoList(pileBasicInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增设备管理
|
||||
*
|
||||
* @param pileBasicInfo 设备管理
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertPileBasicInfo(PileBasicInfo pileBasicInfo) {
|
||||
pileBasicInfo.setCreateBy(SecurityUtils.getUsername());
|
||||
pileBasicInfo.setCreateTime(DateUtils.getNowDate());
|
||||
return pileBasicInfoMapper.insertPileBasicInfo(pileBasicInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改设备管理
|
||||
*
|
||||
* @param pileBasicInfo 设备管理
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updatePileBasicInfo(PileBasicInfo pileBasicInfo) {
|
||||
// pileBasicInfo.setUpdateBy(SecurityUtils.getUsername());
|
||||
pileBasicInfo.setUpdateTime(DateUtils.getNowDate());
|
||||
return pileBasicInfoMapper.updatePileBasicInfo(pileBasicInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除设备管理
|
||||
*
|
||||
* @param ids 需要删除的设备管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileBasicInfoByIds(Long[] ids) {
|
||||
return pileBasicInfoMapper.deletePileBasicInfoByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除设备管理信息
|
||||
*
|
||||
* @param id 设备管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileBasicInfoById(Long id) {
|
||||
return pileBasicInfoMapper.deletePileBasicInfoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询充电桩信息
|
||||
*
|
||||
* @param dto 前台参数
|
||||
* @return 充电桩信息集合
|
||||
*/
|
||||
@Override
|
||||
@DataScope(deptAlias = "t2")
|
||||
public List<PileDetailVO> queryPileInfos(QueryPileDTO dto) {
|
||||
log.info("queryPileInfos dto:{}", JSONObject.toJSONString(dto));
|
||||
// 首先不分页查询所有符合条件的充电桩
|
||||
List<PileDetailVO> pileInfoVOS = queryPileInfoList(dto);
|
||||
// 获取桩sn列表
|
||||
List<String> pileSnList = pileInfoVOS.stream().map(PileDetailVO::getPileSn).collect(Collectors.toList());
|
||||
// log.info("获取桩sn列表:{}", JSONObject.toJSONString(pileSnList));
|
||||
// 批量获取桩状态 key:桩编号; value:状态
|
||||
Map<String, String> pileStatusMap = pileConnectorInfoService.getPileStatus(pileSnList);
|
||||
// log.info("批量获取桩状态:{}", JSONObject.toJSONString(pileStatusMap));
|
||||
// 根据状态过滤
|
||||
List<String> snList = Lists.newArrayList();
|
||||
if (StringUtils.isNotBlank(dto.getStatus())) {
|
||||
for (Map.Entry<String, String> entry : pileStatusMap.entrySet()) {
|
||||
String pileSn = entry.getKey();
|
||||
String pileStatus = entry.getValue();
|
||||
if (StringUtils.equals(dto.getStatus(), pileStatus)) {
|
||||
snList.add(pileSn);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 不根据状态过滤,snList就等于pileSnList
|
||||
snList = pileSnList;
|
||||
// 根据状态排序
|
||||
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(snList)) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
// 使用snList查询 分页
|
||||
if (dto.getPageNum() != 0) {
|
||||
PageUtils.startPage();
|
||||
}
|
||||
QueryPileDTO queryPileDTO = new QueryPileDTO();
|
||||
queryPileDTO.setPileSns(snList);
|
||||
pileInfoVOS = queryPileInfoList(queryPileDTO);
|
||||
|
||||
for (PileDetailVO pileInfoVO : pileInfoVOS) {
|
||||
pileInfoVO.setStatus(pileStatusMap.get(pileInfoVO.getPileSn()));
|
||||
}
|
||||
return pileInfoVOS;
|
||||
}
|
||||
|
||||
@Override
|
||||
// @DataScope(deptAlias = "t1")
|
||||
public List<PileDetailVO> queryPileInfoList(QueryPileDTO queryPileDTO) {
|
||||
return pileBasicInfoMapper.queryPileInfos(queryPileDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过pileId更改运营商、站点信息
|
||||
*
|
||||
* @param dto 前台参数
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int replaceMerchantStationByPileIds(ReplaceMerchantStationDTO dto) {
|
||||
dto.setUpdateBy(SecurityUtils.getUsername());
|
||||
dto.setUpdateTime(DateUtils.getNowDate());
|
||||
int num = pileBasicInfoMapper.replaceMerchantStationByPileIds(dto);
|
||||
// 修改枪口信息
|
||||
if (dto.getConnectorNum() != null && dto.getConnectorNum() > 0) {
|
||||
// 先删后插
|
||||
pileConnectorInfoService.deletePileConnectorInfoByPileSnList(dto.getPileSnList());
|
||||
List<PileConnectorInfo> connectorInfoList = Lists.newArrayList();
|
||||
for (String pileSn : dto.getPileSnList()) {
|
||||
for (int i = 1; i < dto.getConnectorNum() + 1; i++) {
|
||||
// 组装pile_connector_info表数据
|
||||
PileConnectorInfo connectorInfo = new PileConnectorInfo();
|
||||
connectorInfo.setPileSn(pileSn); // sn号
|
||||
String connectorCode = String.format("%1$02d", i);
|
||||
connectorInfo.setPileConnectorCode(pileSn + connectorCode); // 枪口编号
|
||||
connectorInfo.setStatus(Constants.ZERO); //状态,默认 0-离网
|
||||
connectorInfo.setCreateBy(SecurityUtils.getUsername()); // 创建人
|
||||
connectorInfo.setDelFlag(Constants.DEL_FLAG_NORMAL); // 删除标识
|
||||
connectorInfoList.add(connectorInfo);
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(connectorInfoList)) {
|
||||
pileConnectorInfoService.batchInsertConnectorInfo(connectorInfoList);
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过桩id查询basic信息
|
||||
*
|
||||
* @param id 桩id
|
||||
* @return 结果集合
|
||||
*/
|
||||
@Override
|
||||
public PileDetailVO selectBasicInfoById(Long id) {
|
||||
PileDetailVO pileInfoVO = pileBasicInfoMapper.selectBasicInfoById(id);
|
||||
if (pileInfoVO == null) {
|
||||
return null;
|
||||
}
|
||||
// 获取桩状态
|
||||
Map<String, String> pileStatusMap = pileConnectorInfoService.getPileStatus(Lists.newArrayList(pileInfoVO.getPileSn()));
|
||||
pileInfoVO.setStatus(pileStatusMap.get(pileInfoVO.getPileSn()));
|
||||
// String url = "http://localhost:8080/uniapp/pile/pileDetail/";
|
||||
String pileQrCodeUrl = getPileQrCodeUrl(pileInfoVO.getPileSn());
|
||||
pileInfoVO.setQrCodeURL(pileQrCodeUrl);
|
||||
// 额定功率 瓦改为千瓦(2023.2.8发现数据库中型号表已经存的单位是 kw,因此注释掉)
|
||||
// pileInfoVO.setRatedPower(pileInfoVO.getRatedPower() / 1000);
|
||||
return pileInfoVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PileInfoVO selectPileInfoBySn(String pileSn) {
|
||||
PileBasicInfo basicInfo = pileBasicInfoMapper.selectPileBasicInfoBySn(pileSn);
|
||||
if (basicInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PileInfoVO pileInfoVO = PileInfoVO.builder()
|
||||
.pileId(String.valueOf(basicInfo.getId()))
|
||||
.pileSn(basicInfo.getSn())
|
||||
.stationId(String.valueOf(basicInfo.getStationId()))
|
||||
.merchantId(String.valueOf(basicInfo.getMerchantId()))
|
||||
.build();
|
||||
// 查站点信息
|
||||
MerchantInfoVO merchantInfo = pileMerchantInfoService.getMerchantInfo(String.valueOf(basicInfo.getMerchantId()));
|
||||
if (merchantInfo != null) {
|
||||
pileInfoVO.setMerchantName(merchantInfo.getMerchantName());
|
||||
}
|
||||
|
||||
// 查询充电桩额定功率
|
||||
PileModelInfoVO pileModelInfoVO = pileModelInfoService.getPileModelInfoByPileSn(pileSn);
|
||||
if (pileModelInfoVO != null) {
|
||||
pileInfoVO.setRatedPower(pileModelInfoVO.getRatedPower());
|
||||
pileInfoVO.setRatedCurrent(pileModelInfoVO.getRatedCurrent());
|
||||
pileInfoVO.setRatedVoltage(pileModelInfoVO.getRatedVoltage());
|
||||
}
|
||||
return pileInfoVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PileDetailVO> selectPileListByStationIds(List<Long> stationIdList) {
|
||||
// 加缓存
|
||||
List<PileDetailVO> pileInfoVOS = pileBasicInfoMapper.selectPileListByStationIds(stationIdList);
|
||||
if (CollectionUtils.isEmpty(pileInfoVOS)) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
List<String> pileSnList = pileInfoVOS.stream().map(PileDetailVO::getPileSn).collect(Collectors.toList());
|
||||
Map<String, String> pileStatusMap = pileConnectorInfoService.getPileStatus(pileSnList);
|
||||
for (PileDetailVO pileInfoVO : pileInfoVOS) {
|
||||
pileInfoVO.setStatus(pileStatusMap.get(pileInfoVO.getPileSn()));
|
||||
}
|
||||
return pileInfoVOS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过桩sn号查询站点id
|
||||
*
|
||||
* @param sn 桩sn号
|
||||
* @return 站点id
|
||||
*/
|
||||
// @Override
|
||||
// public String selectStationIdBySn(String sn) {
|
||||
// return pileBasicInfoMapper.selectStationIdBySn(sn);
|
||||
// }
|
||||
|
||||
/**
|
||||
* uniApp通过桩号查询桩详情
|
||||
*
|
||||
* @param pileSn 桩号
|
||||
* @return
|
||||
*/
|
||||
// @Override
|
||||
// public PileDetailVO uniAppGetPileDetailByPileSn(String pileSn) {
|
||||
// PileDetailVO pileDetailVO = pileBasicInfoMapper.uniAppGetPileDetailByPileSn(pileSn);
|
||||
// // 查询计费模板
|
||||
// BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn);
|
||||
// if (Objects.nonNull(billingTemplateVO)) {
|
||||
// pileDetailVO.setBillingTemplate(billingTemplateVO);
|
||||
//
|
||||
// }
|
||||
// // 查询枪口相关信息
|
||||
// List<ConnectorVO> connectorList = new ArrayList<>();
|
||||
//
|
||||
// return pileDetailVO;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 修改状态
|
||||
* 用于登陆协议,心跳包协议,上传实时数据协议 更新状态的方法
|
||||
* 数据库状态
|
||||
* 充电枪:0-离线;1-空闲;2-占用(未充电);3-占用(充电中);4-占用(预约锁定);255-故障
|
||||
* <p>
|
||||
* 充电枪口状态在以下情况会改变
|
||||
* 1.登陆成功后,设置为【1-空闲】
|
||||
* 2.心跳包传0x01故障,设置为【255-故障】
|
||||
* 3.上传实时数据,枪状态传0x00离线,设置为【0-离线】
|
||||
* 4.上传实时数据,枪状态传0x01故障,设置为【255-故障】
|
||||
* 5.上传实时数据,枪状态传0x02空闲,并且为插枪状态,设置为【2-占用(未充电)】
|
||||
* 6.上传实时数据,枪状态传0x02空闲,并且为未插枪状态,设置为【1-空闲】
|
||||
* 7.上传实时数据,枪状态传0x03充电,设置为【3-占用(充电中)】
|
||||
*/
|
||||
@Override
|
||||
public void updateStatus(String frameType, String pileSn, String connectorCode, String status, String putGunType) {
|
||||
// log.info("updateStatus传参:帧类型:{}, 桩编号:{}, 枪口号:{}, 状态:{}, 插拔枪:{}", "0x" + frameType, pileSn, connectorCode, status, putGunType);
|
||||
/*
|
||||
0x01 登陆认证
|
||||
登陆成功,把充电桩和枪口的状态都更新为【在线】
|
||||
*/
|
||||
if (StringUtils.equals(frameType, String.valueOf(YKCFrameTypeCode.LOGIN_CODE.getCode()))) {
|
||||
// 枪口状态设置为【空闲】
|
||||
pileConnectorInfoService.updateConnectorStatusByPileSn(pileSn, PileConnectorDataBaseStatusEnum.FREE.getValue());
|
||||
}
|
||||
|
||||
/*
|
||||
0x03 心跳包 枪口状态 0-正常 1-故障
|
||||
心跳包会传过来枪口的状态,由枪口状态推导出来充电桩的状态。任意一个枪口状态为故障,则充电桩状态也是故障
|
||||
*/
|
||||
if (StringUtils.equals(frameType, BytesUtil.bcd2Str(YKCFrameTypeCode.HEART_BEAT_CODE.getBytes()))) {
|
||||
// log.info("心跳包的修改状态逻辑 桩号:{}, 枪号:{}, 枪状态:{}", pileSn, connectorCode, status);
|
||||
|
||||
/*
|
||||
更新充电桩接口的数据库状态
|
||||
传入的状态为【1-故障】,就把枪口数据库改为故障
|
||||
*/
|
||||
if (StringUtils.equals(status, Constants.ONE)) {
|
||||
// 故障
|
||||
pileConnectorInfoService.updateConnectorStatus(pileSn + connectorCode, PileConnectorDataBaseStatusEnum.FAULT.getValue());
|
||||
} else {
|
||||
// 正常
|
||||
// List<PileConnectorInfo> connectorInfoList = pileConnectorInfoService.selectPileConnectorInfoList(pileSn);
|
||||
// for (PileConnectorInfo connectorInfo : connectorInfoList) {
|
||||
// // 收到心跳包,只有在离线或故障时,修改为空闲状态
|
||||
// if (StringUtils.equals(connectorInfo.getStatus(), PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue())
|
||||
// || StringUtils.equals(connectorInfo.getStatus(), PileConnectorDataBaseStatusEnum.FAULT.getValue())) {
|
||||
// pileConnectorInfoService.updateConnectorStatus(pileSn + connectorCode, PileConnectorDataBaseStatusEnum.FREE.getValue());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
0x13 上传实时数据 枪口状态 0x00:离线 0x01:故障 0x02:空闲 0x03:充电
|
||||
根据传来的枪状态和是否插枪,判断状态
|
||||
*/
|
||||
if (StringUtils.equals(frameType, BytesUtil.bcd2Str(YKCFrameTypeCode.UPLOAD_REAL_TIME_MONITOR_DATA_CODE.getBytes()))
|
||||
|| StringUtils.equals(frameType, BytesUtil.bcd2Str(YKCFrameTypeCode.UPLOAD_REAL_TIME_MONITOR_DATA_OLD_VERSION_CODE.getBytes()))) {
|
||||
// log.info("上传实时数据中的修改状态逻辑 桩号:{}, 枪号:{}, 枪状态{}, 是否插枪:{}", pileSn, connectorCode, status, putGunType);
|
||||
/**
|
||||
* 更新枪状态
|
||||
* connectorStatus 桩传过来的枪口状态: 0x00:离线 0x01:故障 0x02:空闲 0x03:充电
|
||||
* 数据库状态:0:离网 (默认);1:空闲;2:占用(未充电);3:占用(充电中);4:占用(预约锁定) ;255:故障
|
||||
*/
|
||||
String statusDataBase = ""; // 传给数据库的状态
|
||||
if (StringUtils.equals(status, PileConnectorStatusEnum.OFF_NETWORK.getValue())) { // 离线
|
||||
statusDataBase = PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue();
|
||||
} else if (StringUtils.equals(status, PileConnectorStatusEnum.FAULT.getValue())) { // 故障
|
||||
statusDataBase = PileConnectorDataBaseStatusEnum.FAULT.getValue();
|
||||
} else if (StringUtils.equals(status, PileConnectorStatusEnum.FREE.getValue())) { // 空闲
|
||||
//是否插枪 0x00:否 0x01:是
|
||||
if (StringUtils.equals(putGunType, Constants.ZERO_ONE)) {
|
||||
// 空闲并插枪 设置为【占用(未充电)】
|
||||
statusDataBase = PileConnectorDataBaseStatusEnum.OCCUPIED_NOT_CHARGED.getValue();
|
||||
} else {
|
||||
// 空闲没插枪 设置为【空闲】
|
||||
statusDataBase = PileConnectorDataBaseStatusEnum.FREE.getValue();
|
||||
}
|
||||
} else if (StringUtils.equals(status, PileConnectorStatusEnum.OCCUPIED_CHARGING.getValue())) { // 充电
|
||||
// 设置为【占用(充电中)】
|
||||
statusDataBase = PileConnectorDataBaseStatusEnum.OCCUPIED_CHARGING.getValue();
|
||||
}
|
||||
pileConnectorInfoService.updateConnectorStatus(pileSn + connectorCode, statusDataBase);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 充电桩正在充电时的实时数据存到redis
|
||||
* @param realTimeMonitorData 实时数据
|
||||
*/
|
||||
@Override
|
||||
public void saveRealTimeMonitorData2Redis(RealTimeMonitorData realTimeMonitorData) {
|
||||
// 保存到redis
|
||||
String redisKey = CacheConstants.PILE_REAL_TIME_MONITOR_DATA + realTimeMonitorData.getPileConnectorCode() + "_" + realTimeMonitorData.getOrderCode();
|
||||
|
||||
// 设置接收到实时数据的时间
|
||||
Date now = new Date();
|
||||
realTimeMonitorData.setDateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now));
|
||||
// 计算功率,后面查询要用
|
||||
String power = new BigDecimal(realTimeMonitorData.getOutputVoltage())
|
||||
.multiply(new BigDecimal(realTimeMonitorData.getOutputCurrent())).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
|
||||
realTimeMonitorData.setOutputPower(power);
|
||||
// 保存json字符串
|
||||
String jsonMsg = JSONObject.toJSONString(realTimeMonitorData);
|
||||
// 上传实时数据每10秒发送一次,1分钟6次,在同一分钟内,只保留最后一条实时数据
|
||||
redisCache.hset(redisKey, DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:00", now), jsonMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PileConnectorDetailVO queryPileConnectorDetail(String pileConnectorCode) {
|
||||
return pileBasicInfoMapper.queryPileConnectorDetail(pileConnectorCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回充电桩二维码
|
||||
* @param pileSn 如充电桩编号为空,则返回前缀 https://api.jsowellcloud.com/app-xcx-h5/pile/pileDetail/
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getPileQrCodeUrl(String pileSn) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append(QRCODE_URL_PREFIX);
|
||||
stringBuilder.append("/app-xcx-h5/pile/pileDetail/");
|
||||
if (StringUtils.isNotEmpty(pileSn)) {
|
||||
if (!stringBuilder.toString().endsWith("/")) {
|
||||
stringBuilder.append("/");
|
||||
}
|
||||
stringBuilder.append(pileSn);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePileSimInfo(String pileSn, String iccid) {
|
||||
PileBasicInfo basicInfo = selectPileBasicInfoBySN(pileSn);
|
||||
if (basicInfo == null) {
|
||||
return;
|
||||
}
|
||||
// 通过iccid查pile_sim_info
|
||||
PileSimInfo simInfo = pileSimInfoService.getBasicInfoByIccId(iccid);
|
||||
if (simInfo == null) {
|
||||
SimCardVO simCardVO = simCardService.searchByLoop(iccid);
|
||||
// pile_sim_info 新增数据
|
||||
if (simCardVO != null) {
|
||||
simInfo = PileSimInfo.builder()
|
||||
.iccid(iccid)
|
||||
.name(simCardVO.getName())
|
||||
.simSupplier(simCardVO.getSimCardFactory())
|
||||
.expireTime(DateUtils.parseDate(simCardVO.getExpiredTime()))
|
||||
.operator(simCardVO.getSimCardOperator())
|
||||
.status(simCardVO.getSimCardStatus())
|
||||
.surplusData(String.valueOf(simCardVO.getResidualFlowRate()))
|
||||
.totalData(String.valueOf(simCardVO.getPackageCapacity()))
|
||||
.build();
|
||||
}else {
|
||||
// 卡商未查到信息,记录为新卡,只存卡号
|
||||
simInfo = PileSimInfo.builder()
|
||||
.iccid(iccid)
|
||||
.build();
|
||||
}
|
||||
pileSimInfoService.insertPileSimInfo(simInfo);
|
||||
// 拿到id
|
||||
Long simId = simInfo.getId();
|
||||
log.info("新保存的sim卡id:{}", simId);
|
||||
// sim_id 更新到pile_basic_info
|
||||
basicInfo.setSimId(simId);
|
||||
} else {
|
||||
// sim信息已经存库了 然后更新充电桩的sim卡
|
||||
basicInfo.setSimId(simInfo.getId());
|
||||
}
|
||||
updatePileBasicInfo(basicInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 后管首页基本信息查询
|
||||
*
|
||||
* @param dto 站点Id
|
||||
* @return 首页基本信息
|
||||
*/
|
||||
@Override
|
||||
public IndexGeneralSituationVO getGeneralSituation(IndexQueryDTO dto) {
|
||||
//
|
||||
return pileBasicInfoMapper.getGeneralSituation(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过会员id查询个人桩列表
|
||||
* @param memberId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<PersonalPileInfoVO> getPileInfoByMemberId(String memberId) {
|
||||
List<PersonalPileInfoVO> list = pileBasicInfoMapper.getPileInfoByMemberId(memberId);
|
||||
if(CollectionUtils.isEmpty(list)){
|
||||
return null;
|
||||
}
|
||||
|
||||
for (PersonalPileInfoVO personalPileInfoVO : list) {
|
||||
String pileSn = personalPileInfoVO.getPileSn();
|
||||
|
||||
// 获取桩状态
|
||||
Map<String, String> pileStatus = pileConnectorInfoService.getPileStatus(Lists.newArrayList(pileSn));
|
||||
personalPileInfoVO.setPileStatus(pileStatus.get(pileSn));
|
||||
if (StringUtils.equals("1", personalPileInfoVO.getType())) {
|
||||
personalPileInfoVO.setType("管理员用户");
|
||||
}else {
|
||||
personalPileInfoVO.setType("普通用户");
|
||||
}
|
||||
if (StringUtils.equals("1", personalPileInfoVO.getSpeedType())) {
|
||||
personalPileInfoVO.setSpeedType("快充");
|
||||
}else {
|
||||
personalPileInfoVO.setSpeedType("慢充");
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,619 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.jsowell.common.constant.Constants;
|
||||
import com.jsowell.common.enums.DelFlagEnum;
|
||||
import com.jsowell.common.enums.ykc.BillingTimeEnum;
|
||||
import com.jsowell.common.util.BytesUtil;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.common.util.SecurityUtils;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.common.util.YKCUtils;
|
||||
import com.jsowell.common.util.id.Seq;
|
||||
import com.jsowell.pile.domain.PileBillingDetail;
|
||||
import com.jsowell.pile.domain.PileBillingRelation;
|
||||
import com.jsowell.pile.domain.PileBillingTemplate;
|
||||
import com.jsowell.pile.dto.BillingTimeDTO;
|
||||
import com.jsowell.pile.dto.CreateOrUpdateBillingTemplateDTO;
|
||||
import com.jsowell.pile.dto.ImportBillingTemplateDTO;
|
||||
import com.jsowell.pile.mapper.PileBillingTemplateMapper;
|
||||
import com.jsowell.pile.service.IPileBasicInfoService;
|
||||
import com.jsowell.pile.service.IPileBillingTemplateService;
|
||||
import com.jsowell.pile.transaction.dto.BillingTemplateTransactionDTO;
|
||||
import com.jsowell.pile.transaction.service.TransactionService;
|
||||
import com.jsowell.pile.vo.uniapp.BillingPriceVO;
|
||||
import com.jsowell.pile.vo.uniapp.CurrentTimePriceDetails;
|
||||
import com.jsowell.pile.vo.web.BillingDetailVO;
|
||||
import com.jsowell.pile.vo.web.BillingTemplateVO;
|
||||
import com.jsowell.pile.vo.web.EchoBillingTemplateVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 计费模板Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2022-09-20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PileBillingTemplateServiceImpl implements IPileBillingTemplateService {
|
||||
@Autowired
|
||||
private PileBillingTemplateMapper pileBillingTemplateMapper;
|
||||
|
||||
@Autowired
|
||||
private TransactionService transactionService;
|
||||
|
||||
@Autowired
|
||||
private IPileBasicInfoService pileBasicInfoService;
|
||||
|
||||
/**
|
||||
* 查询计费模板
|
||||
*
|
||||
* @param id 计费模板主键
|
||||
* @return 计费模板
|
||||
*/
|
||||
@Override
|
||||
public PileBillingTemplate selectPileBillingTemplateById(Long id) {
|
||||
return pileBillingTemplateMapper.selectPileBillingTemplateById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询计费模板列表
|
||||
*
|
||||
* @param pileBillingTemplate 计费模板
|
||||
* @return 计费模板
|
||||
*/
|
||||
@Override
|
||||
public List<PileBillingTemplate> selectPileBillingTemplateList(PileBillingTemplate pileBillingTemplate) {
|
||||
return pileBillingTemplateMapper.selectPileBillingTemplateList(pileBillingTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增计费模板
|
||||
*
|
||||
* @param pileBillingTemplate 计费模板
|
||||
* @return 结果
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public int insertPileBillingTemplate(PileBillingTemplate pileBillingTemplate) {
|
||||
pileBillingTemplate.setCreateTime(DateUtils.getNowDate());
|
||||
int rows = pileBillingTemplateMapper.insertPileBillingTemplate(pileBillingTemplate);
|
||||
insertPileBillingDetail(pileBillingTemplate);
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改计费模板
|
||||
*
|
||||
* @param pileBillingTemplate 计费模板
|
||||
* @return 结果
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public int updatePileBillingTemplate(PileBillingTemplate pileBillingTemplate) {
|
||||
return pileBillingTemplateMapper.updatePileBillingTemplate(pileBillingTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除计费模板
|
||||
*
|
||||
* @param ids 需要删除的计费模板主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public int deletePileBillingTemplateByIds(Long[] ids) {
|
||||
// 查询计费模板详情列表
|
||||
List<PileBillingDetail> pileBillingDetails = pileBillingTemplateMapper.queryBillingDetailByTemplateIds(ids);
|
||||
if (CollectionUtils.isNotEmpty(pileBillingDetails)) {
|
||||
List<String> templateCodes = pileBillingDetails.stream().map(PileBillingDetail::getTemplateCode).collect(Collectors.toList());
|
||||
pileBillingTemplateMapper.deletePileBillingDetailByTemplateCodes(templateCodes);
|
||||
}
|
||||
return pileBillingTemplateMapper.deletePileBillingTemplateByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除计费模板信息
|
||||
*
|
||||
* @param id 计费模板主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public int deletePileBillingTemplateById(Long id) {
|
||||
// pileBillingTemplateMapper.deletePileBillingDetailByTemplateCode(id);
|
||||
return pileBillingTemplateMapper.deletePileBillingTemplateById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createBillingTemplate(CreateOrUpdateBillingTemplateDTO dto) {
|
||||
// 生成计费模板编号
|
||||
String templateCode = Seq.getId();
|
||||
// 组装入库参数
|
||||
PileBillingTemplate billingTemplate = new PileBillingTemplate();
|
||||
billingTemplate.setName(dto.getName());
|
||||
billingTemplate.setType(String.valueOf(dto.getType()));
|
||||
billingTemplate.setRemark(dto.getRemark());
|
||||
billingTemplate.setTemplateCode(templateCode);
|
||||
billingTemplate.setCreateBy(SecurityUtils.getUsername());
|
||||
billingTemplate.setDelFlag(DelFlagEnum.normal.getValue());
|
||||
if (StringUtils.isBlank(dto.getStationId())) {
|
||||
// 公共模板标识(0-私有;1-公共)
|
||||
billingTemplate.setPublicFlag(Constants.ONE);
|
||||
} else {
|
||||
billingTemplate.setPublicFlag(Constants.ZERO);
|
||||
}
|
||||
|
||||
// key为时间类型,value为时间描述
|
||||
Map<String, List<BillingTimeDTO>> map = dto.getTimeArray().stream()
|
||||
.collect(Collectors.groupingBy(BillingTimeDTO::getType));
|
||||
|
||||
// 计费模板详情
|
||||
List<PileBillingDetail> detailList = Lists.newArrayList();
|
||||
PileBillingDetail detail = null;
|
||||
for (BillingTimeEnum billingTimeEnum : BillingTimeEnum.values()) {
|
||||
detail = new PileBillingDetail();
|
||||
detail.setTemplateCode(templateCode);
|
||||
String type = billingTimeEnum.getValue(); // 时段类型
|
||||
detail.setTimeType(type);
|
||||
Map<String, BigDecimal> priceMap = getPriceMap(dto, type);
|
||||
detail.setElectricityPrice(priceMap.get("electricityPrice"));
|
||||
detail.setServicePrice(priceMap.get("servicePrice"));
|
||||
List<BillingTimeDTO> entryValue = map.get(type);
|
||||
String applyTime = "";
|
||||
if (CollectionUtils.isNotEmpty(entryValue)) {
|
||||
applyTime = entryValue.stream()
|
||||
.map(x -> x.getStartTime() + "-" + x.getEndTime())
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
detail.setApplyTime(applyTime);
|
||||
detail.setCreateBy(SecurityUtils.getUsername());
|
||||
detailList.add(detail);
|
||||
}
|
||||
|
||||
BillingTemplateTransactionDTO build = BillingTemplateTransactionDTO.builder()
|
||||
.billingTemplate(billingTemplate)
|
||||
.detailList(detailList)
|
||||
.build();
|
||||
// 入库
|
||||
transactionService.doCreateBillingTemplate(build);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBillingTemplate(CreateOrUpdateBillingTemplateDTO dto) {
|
||||
PileBillingTemplate billingTemplate = selectPileBillingTemplateById(Long.valueOf(dto.getBillingTemplateId()));
|
||||
if (billingTemplate == null) {
|
||||
log.info("根据计费模板id:{},查询为null。无法修改直接返回", dto.getBillingTemplateId());
|
||||
return;
|
||||
}
|
||||
billingTemplate.setName(dto.getName());
|
||||
billingTemplate.setType(String.valueOf(dto.getType()));
|
||||
billingTemplate.setRemark(dto.getRemark());
|
||||
billingTemplate.setUpdateBy(SecurityUtils.getUsername());
|
||||
|
||||
// key为时间类型,value为时间描述
|
||||
Map<String, List<BillingTimeDTO>> map = dto.getTimeArray().stream()
|
||||
.collect(Collectors.groupingBy(BillingTimeDTO::getType));
|
||||
|
||||
// 计费模板详情
|
||||
List<PileBillingDetail> detailList = Lists.newArrayList();
|
||||
PileBillingDetail detail = null;
|
||||
for (BillingTimeEnum billingTimeEnum : BillingTimeEnum.values()) {
|
||||
detail = new PileBillingDetail();
|
||||
detail.setTemplateCode(billingTemplate.getTemplateCode());
|
||||
String type = billingTimeEnum.getValue(); // 时段类型
|
||||
detail.setTimeType(type);
|
||||
Map<String, BigDecimal> priceMap = getPriceMap(dto, type);
|
||||
detail.setElectricityPrice(priceMap.get("electricityPrice"));
|
||||
detail.setServicePrice(priceMap.get("servicePrice"));
|
||||
List<BillingTimeDTO> entryValue = map.get(type);
|
||||
String applyTime = "";
|
||||
if (CollectionUtils.isNotEmpty(entryValue)) {
|
||||
applyTime = entryValue.stream()
|
||||
.map(x -> x.getStartTime() + "-" + x.getEndTime())
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
detail.setApplyTime(applyTime);
|
||||
detail.setCreateBy(SecurityUtils.getUsername());
|
||||
detailList.add(detail);
|
||||
}
|
||||
|
||||
BillingTemplateTransactionDTO build = BillingTemplateTransactionDTO.builder()
|
||||
.billingTemplate(billingTemplate)
|
||||
.detailList(detailList)
|
||||
.build();
|
||||
// 入库
|
||||
transactionService.doUpdateBillingTemplate(build);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EchoBillingTemplateVO queryPileBillingTemplateById(Long id) {
|
||||
PileBillingTemplate pileBillingTemplate = selectPileBillingTemplateById(id);
|
||||
if (pileBillingTemplate == null) {
|
||||
return null;
|
||||
}
|
||||
EchoBillingTemplateVO result = new EchoBillingTemplateVO();
|
||||
result.setBillingTemplateId(String.valueOf(id));
|
||||
result.setName(pileBillingTemplate.getName());
|
||||
result.setRemark(pileBillingTemplate.getRemark());
|
||||
result.setType(pileBillingTemplate.getType());
|
||||
|
||||
// 查计费模板详情
|
||||
List<PileBillingDetail> detailList = pileBillingTemplateMapper.queryBillingDetailByTemplateIds(new Long[]{id});
|
||||
if (CollectionUtils.isNotEmpty(detailList)) {
|
||||
List<BillingTimeDTO> timeArray = Lists.newArrayList();
|
||||
// 取出4个时间段类型
|
||||
for (PileBillingDetail billingDetail : detailList) {
|
||||
String type = billingDetail.getTimeType();
|
||||
BigDecimal electricityPrice = billingDetail.getElectricityPrice();
|
||||
BigDecimal servicePrice = billingDetail.getServicePrice();
|
||||
if (StringUtils.equals(type, BillingTimeEnum.SHARP.getValue())) {
|
||||
result.setElectricityPriceA(electricityPrice);
|
||||
result.setServicePriceA(servicePrice);
|
||||
} else if (StringUtils.equals(type, BillingTimeEnum.PEAK.getValue())) {
|
||||
result.setElectricityPriceB(electricityPrice);
|
||||
result.setServicePriceB(servicePrice);
|
||||
} else if (StringUtils.equals(type, BillingTimeEnum.FLAT.getValue())) {
|
||||
result.setElectricityPriceC(electricityPrice);
|
||||
result.setServicePriceC(servicePrice);
|
||||
} else if (StringUtils.equals(type, BillingTimeEnum.VALLEY.getValue())) {
|
||||
result.setElectricityPriceD(electricityPrice);
|
||||
result.setServicePriceD(servicePrice);
|
||||
}
|
||||
// 逗号拼接的时间段 00:00-01:30,01:30-04:00,23:30-24:00
|
||||
String applyTime = billingDetail.getApplyTime();
|
||||
if (StringUtils.isBlank(applyTime)) {
|
||||
continue;
|
||||
}
|
||||
List<String> list = Lists.newArrayList(applyTime.split(","));
|
||||
BillingTimeDTO timeDTO;
|
||||
for (String s : list) {
|
||||
String[] split = s.split("-");
|
||||
timeDTO = new BillingTimeDTO();
|
||||
timeDTO.setType(type);
|
||||
timeDTO.setStartTime(split[0]);
|
||||
timeDTO.setEndTime(split[1]);
|
||||
timeArray.add(timeDTO);
|
||||
}
|
||||
}
|
||||
// timeArray重新排序
|
||||
result.setTimeArray(timeArray.stream().sorted(Comparator.comparing(BillingTimeDTO::getStartTime)).collect(Collectors.toList()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过站点id查询当前时间的收费详情
|
||||
*
|
||||
* @param stationId 站点id
|
||||
*/
|
||||
@Override
|
||||
public CurrentTimePriceDetails getCurrentTimePriceDetails(String stationId) {
|
||||
CurrentTimePriceDetails result = null;
|
||||
// 查询当前时段电费
|
||||
LocalTime localTime = LocalTime.now();
|
||||
String now = LocalTime.of(localTime.getHour(), localTime.getMinute(), localTime.getSecond()).toString();
|
||||
// 通过站点id查询计费模板
|
||||
BillingTemplateVO billingTemplateVO = pileBillingTemplateMapper.selectBillingTemplateByStationId(stationId);
|
||||
if (Objects.nonNull(billingTemplateVO)) {
|
||||
result = new CurrentTimePriceDetails();
|
||||
result.setTemplateCode(billingTemplateVO.getTemplateCode());
|
||||
result.setStationId(stationId);
|
||||
result.setDateTime(localTime.toString());
|
||||
|
||||
List<BillingDetailVO> billingDetailList = billingTemplateVO.getBillingDetailList();
|
||||
for (BillingDetailVO detailVO : billingDetailList) {
|
||||
List<String> applyTimeList = detailVO.getApplyTime();
|
||||
for (String applyTime : applyTimeList) {
|
||||
boolean b = DateUtils.checkTime(now + "-" + now, applyTime);
|
||||
if (b) {
|
||||
// 将桩的费率存入stationVO
|
||||
BigDecimal electricityPrice = detailVO.getElectricityPrice();
|
||||
BigDecimal servicePrice = detailVO.getServicePrice();
|
||||
|
||||
result.setElectricityPrice(electricityPrice.toString());
|
||||
result.setServicePrice(servicePrice.toString());
|
||||
result.setTotalPrice(electricityPrice.add(servicePrice).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BillingTemplateVO> queryPublicBillingTemplateList() {
|
||||
return pileBillingTemplateMapper.queryPublicBillingTemplateList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BillingTemplateVO> queryStationBillingTemplateList(String stationId) {
|
||||
if (StringUtils.isBlank(stationId)) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
return pileBillingTemplateMapper.queryStationBillingTemplateList(stationId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询正在使用中的计费模板
|
||||
* 1 发布时间不为null
|
||||
* 2 最近发布的为正在使用中的
|
||||
* @param stationId 站点id
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public BillingTemplateVO queryUsedBillingTemplate(String stationId) {
|
||||
List<BillingTemplateVO> list = queryStationBillingTemplateList(stationId);
|
||||
Optional<BillingTemplateVO> max = list.stream()
|
||||
.filter(x -> StringUtils.isNotBlank(x.getPublishTime()))
|
||||
.max(Comparator.comparing(BillingTemplateVO::getPublishTime));
|
||||
return max.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BillingPriceVO> queryBillingPrice(String stationId) {
|
||||
BillingTemplateVO billingTemplateVO = queryUsedBillingTemplate(stationId);
|
||||
if (billingTemplateVO == null) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
EchoBillingTemplateVO echoBillingTemplateVO = queryPileBillingTemplateById(Long.parseLong(billingTemplateVO.getTemplateId()));
|
||||
List<BillingTimeDTO> timeArray = echoBillingTemplateVO.getTimeArray();
|
||||
log.info("计费模板时段:{}", JSONObject.toJSONString(timeArray));
|
||||
|
||||
List<BillingPriceVO> resultList = Lists.newArrayList();
|
||||
for (BillingTimeDTO billingTimeDTO : timeArray) {
|
||||
BillingPriceVO vo = new BillingPriceVO();
|
||||
String type = billingTimeDTO.getType();
|
||||
if (StringUtils.equals(type, BillingTimeEnum.SHARP.getValue())) {
|
||||
vo.setElectricityPrice(billingTemplateVO.getSharpElectricityPrice().toString());
|
||||
vo.setServicePrice(billingTemplateVO.getSharpServicePrice().toString());
|
||||
} else if (StringUtils.equals(type, BillingTimeEnum.PEAK.getValue())) {
|
||||
vo.setElectricityPrice(billingTemplateVO.getPeakElectricityPrice().toString());
|
||||
vo.setServicePrice(billingTemplateVO.getPeakServicePrice().toString());
|
||||
} else if (StringUtils.equals(type, BillingTimeEnum.FLAT.getValue())) {
|
||||
vo.setElectricityPrice(billingTemplateVO.getFlatElectricityPrice().toString());
|
||||
vo.setServicePrice(billingTemplateVO.getFlatServicePrice().toString());
|
||||
} else if (StringUtils.equals(type, BillingTimeEnum.VALLEY.getValue())) {
|
||||
vo.setElectricityPrice(billingTemplateVO.getValleyElectricityPrice().toString());
|
||||
vo.setServicePrice(billingTemplateVO.getValleyServicePrice().toString());
|
||||
}
|
||||
// 总费用
|
||||
vo.setTotalPrice(new BigDecimal(vo.getElectricityPrice()).add(new BigDecimal(vo.getServicePrice())).toString());
|
||||
// 开始时间
|
||||
vo.setStartTime(billingTimeDTO.getStartTime());
|
||||
// 结束时间
|
||||
String endTime = StringUtils.equals("24:00", billingTimeDTO.getEndTime()) ? "23:59" : billingTimeDTO.getEndTime();
|
||||
vo.setEndTime(endTime);
|
||||
// 时段类型
|
||||
vo.setTimeType(type);
|
||||
// 是否当前时间
|
||||
boolean in = DateUtils.isIn(LocalTime.now(), LocalTime.parse(vo.getStartTime()), LocalTime.parse(vo.getEndTime()));
|
||||
vo.setIsCurrentTime(in ? Constants.ONE : Constants.ZERO);
|
||||
resultList.add(vo);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 21:30-23:00
|
||||
String startTime = "01:30";
|
||||
String endTime = "23:00";
|
||||
boolean in = DateUtils.isIn(LocalTime.now(), LocalTime.parse(startTime), LocalTime.parse(endTime));
|
||||
System.out.println(in);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过桩sn号查询计费模板
|
||||
*
|
||||
* @param pileSn 桩sn
|
||||
* @return 计费模板编号
|
||||
*/
|
||||
@Override
|
||||
public BillingTemplateVO selectBillingTemplateDetailByPileSn(String pileSn) {
|
||||
return pileBillingTemplateMapper.selectBillingTemplateByPileSn(pileSn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stationImportBillingTemplate(ImportBillingTemplateDTO dto) {
|
||||
// 查询公共计费模板是否存在
|
||||
PileBillingTemplate pileBillingTemplate = pileBillingTemplateMapper.selectPileBillingTemplateById(Long.valueOf(dto.getBillingTemplateId()));
|
||||
if (pileBillingTemplate == null) {
|
||||
log.warn("根据计费模板id:{},查询为空", dto.getBillingTemplateId());
|
||||
return false;
|
||||
}
|
||||
List<PileBillingDetail> billingDetailList = pileBillingTemplate.getPileBillingDetailList();
|
||||
// 复制计费模板
|
||||
PileBillingTemplate stationBillingTemplate = new PileBillingTemplate();
|
||||
|
||||
String templateCode = Seq.getId(); // 生成计费模板编号
|
||||
BeanUtils.copyProperties(pileBillingTemplate, stationBillingTemplate, "id", "createBy", "createTime", "updateBy", "updateTime");
|
||||
stationBillingTemplate.setStationId(Long.valueOf(dto.getStationId())); // 站点id
|
||||
stationBillingTemplate.setPublicFlag(Constants.ZERO); // 站点私有计费模板
|
||||
stationBillingTemplate.setTemplateCode(templateCode);
|
||||
stationBillingTemplate.setCreateBy(SecurityUtils.getUsername());
|
||||
stationBillingTemplate.setDelFlag(DelFlagEnum.normal.getValue());
|
||||
// 复制计费模板详情
|
||||
List<PileBillingDetail> stationBillingDetailList = Lists.newArrayList();
|
||||
PileBillingDetail pileBillingDetail;
|
||||
for (PileBillingDetail detail : billingDetailList) {
|
||||
pileBillingDetail = new PileBillingDetail();
|
||||
BeanUtils.copyProperties(detail, pileBillingDetail, "id", "templateCode", "createBy", "createTime", "updateBy", "updateTime");
|
||||
pileBillingDetail.setTemplateCode(templateCode);
|
||||
pileBillingDetail.setCreateBy(SecurityUtils.getUsername());
|
||||
pileBillingDetail.setDelFlag(DelFlagEnum.normal.getValue());
|
||||
stationBillingDetailList.add(pileBillingDetail);
|
||||
}
|
||||
// 入库
|
||||
BillingTemplateTransactionDTO billingTemplateTransactionDTO = new BillingTemplateTransactionDTO();
|
||||
billingTemplateTransactionDTO.setBillingTemplate(stationBillingTemplate);
|
||||
billingTemplateTransactionDTO.setDetailList(stationBillingDetailList);
|
||||
transactionService.doCreateBillingTemplate(billingTemplateTransactionDTO);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] generateBillingTemplateMsgBody(String pileSn, BillingTemplateVO billingTemplateVO) {
|
||||
if (StringUtils.isBlank(pileSn) || billingTemplateVO == null) {
|
||||
log.error("生成发给充电桩的计费模板msgBody 参数不能为空");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 桩编码
|
||||
byte[] pileSnByte = BytesUtil.str2Bcd(pileSn);
|
||||
|
||||
// 计费模型编号 固定值: 01 00
|
||||
byte[] billingTemplateCode = new byte[]{0x01, 0x00};
|
||||
|
||||
// 尖时段电费
|
||||
byte[] sharpElectricityPrice = YKCUtils.getPriceByte(billingTemplateVO.getSharpElectricityPrice().toString(), 5);
|
||||
// 尖时段服务费
|
||||
byte[] sharpServicePrice = YKCUtils.getPriceByte(billingTemplateVO.getSharpServicePrice().toString(), 5);
|
||||
|
||||
// 峰时段电费
|
||||
byte[] peakElectricityPrice = YKCUtils.getPriceByte(billingTemplateVO.getPeakElectricityPrice().toString(), 5);
|
||||
// 峰时段服务费
|
||||
byte[] peakServicePrice = YKCUtils.getPriceByte(billingTemplateVO.getPeakServicePrice().toString(), 5);
|
||||
|
||||
// 平时段电费
|
||||
byte[] flatElectricityPrice = YKCUtils.getPriceByte(billingTemplateVO.getFlatElectricityPrice().toString(), 5);
|
||||
// 平时段服务费
|
||||
byte[] flatServicePrice = YKCUtils.getPriceByte(billingTemplateVO.getFlatServicePrice().toString(), 5);
|
||||
|
||||
// 谷时段电费
|
||||
byte[] valleyElectricityPrice = YKCUtils.getPriceByte(billingTemplateVO.getValleyElectricityPrice().toString(), 5);
|
||||
// 谷时段服务费
|
||||
byte[] valleyServicePrice = YKCUtils.getPriceByte(billingTemplateVO.getValleyServicePrice().toString(), 5);
|
||||
// 计损比例(目前置0)
|
||||
byte[] PlanLossRatio = Constants.zeroByteArray;
|
||||
|
||||
// 48个时段费率(半小时为一个时段)
|
||||
Map<Integer, List<String>> timeMap = billingTemplateVO.getTimeMap();
|
||||
List<String> periodOfTime = DateUtils.getPeriodOfTime();
|
||||
byte[] timeArray = new byte[periodOfTime.size()];
|
||||
for (int i = 0; i < periodOfTime.size(); i++) {
|
||||
// 对比时间段
|
||||
byte timeType = getTimeType(periodOfTime.get(i), timeMap);
|
||||
// log.info("时间段:{}, 对应费率类型:{}", periodOfTime.get(i), timeType);
|
||||
timeArray[i] = timeType;
|
||||
}
|
||||
|
||||
// 消息体
|
||||
byte[] msgBody = Bytes.concat(pileSnByte, billingTemplateCode, sharpElectricityPrice, sharpServicePrice,
|
||||
peakElectricityPrice, peakServicePrice, flatElectricityPrice, flatServicePrice, valleyElectricityPrice,
|
||||
valleyServicePrice, PlanLossRatio, timeArray);
|
||||
log.warn("generateBillingTemplateMsgBody:{}", BytesUtil.binary(msgBody, 16));
|
||||
return msgBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取时段费率号
|
||||
*
|
||||
* @param timeRange 时间段 例如:07:30:00-10:30:00
|
||||
* @param timeMap 尖峰平谷4个类型的时间段,每个类型都包含一个时间段集合
|
||||
* @return
|
||||
*/
|
||||
private byte getTimeType(String timeRange, Map<Integer, List<String>> timeMap) {
|
||||
byte b = 5;
|
||||
// 这里的timeRange是00:00-00:30 这样的格式
|
||||
String[] split = timeRange.split("-");
|
||||
LocalTime startTime1 = DateUtils.getLocalTime(split[0]);
|
||||
LocalTime endTime1 = DateUtils.getLocalTime(split[1]);
|
||||
|
||||
for (Map.Entry<Integer, List<String>> entry : timeMap.entrySet()) {
|
||||
List<String> value = entry.getValue().stream().filter(StringUtils::isNotBlank).collect(Collectors.toList()); // 每个类型时间段集合
|
||||
if (CollectionUtils.isEmpty(value)) {
|
||||
continue;
|
||||
}
|
||||
for (String s : value) {
|
||||
// 这里的s是07:30-10:30 这样的格式
|
||||
List<String> list = Lists.newArrayList(s.split("-"));
|
||||
LocalTime startTime2 = DateUtils.getLocalTime(list.get(0));
|
||||
LocalTime endTime2 = DateUtils.getLocalTime(list.get(1));
|
||||
|
||||
boolean overlap = DateUtils.isOverlap(startTime1, endTime1, startTime2, endTime2, false);
|
||||
if (overlap) {
|
||||
return (byte) entry.getKey().intValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BillingTemplateVO selectBillingTemplateByTemplateId(String templateId) {
|
||||
return pileBillingTemplateMapper.selectBillingTemplateByTemplateId(templateId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertPileBillingRelation(List<PileBillingRelation> relationList) {
|
||||
if (CollectionUtils.isEmpty(relationList)) {
|
||||
return;
|
||||
}
|
||||
// 根据桩号删除计费模板关系
|
||||
List<String> pileSnList = relationList.stream().map(PileBillingRelation::getPileSn).collect(Collectors.toList());
|
||||
pileBillingTemplateMapper.deleteRelationByPileSn(pileSnList);
|
||||
pileBillingTemplateMapper.insertPileBillingRelation(relationList);
|
||||
}
|
||||
|
||||
private Map<String, BigDecimal> getPriceMap(CreateOrUpdateBillingTemplateDTO dto, String type) {
|
||||
BigDecimal electricityPrice = null;
|
||||
BigDecimal servicePrice = null;
|
||||
if (StringUtils.equals(type, "1")) {
|
||||
electricityPrice = dto.getElectricityPriceA();
|
||||
servicePrice = dto.getServicePriceA();
|
||||
} else if (StringUtils.equals(type, "2")) {
|
||||
electricityPrice = dto.getElectricityPriceB();
|
||||
servicePrice = dto.getServicePriceB();
|
||||
} else if (StringUtils.equals(type, "3")) {
|
||||
electricityPrice = dto.getElectricityPriceC();
|
||||
servicePrice = dto.getServicePriceC();
|
||||
} else if (StringUtils.equals(type, "4")) {
|
||||
electricityPrice = dto.getElectricityPriceD();
|
||||
servicePrice = dto.getServicePriceD();
|
||||
}
|
||||
Map<String, BigDecimal> resultMap = Maps.newHashMap();
|
||||
resultMap.put("electricityPrice", electricityPrice);
|
||||
resultMap.put("servicePrice", servicePrice);
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增计费模板详情信息
|
||||
*
|
||||
* @param pileBillingTemplate 计费模板对象
|
||||
*/
|
||||
public void insertPileBillingDetail(PileBillingTemplate pileBillingTemplate) {
|
||||
List<PileBillingDetail> pileBillingDetailList = pileBillingTemplate.getPileBillingDetailList();
|
||||
String templateCode = pileBillingTemplate.getTemplateCode();
|
||||
if (StringUtils.isNotNull(pileBillingDetailList)) {
|
||||
List<PileBillingDetail> list = new ArrayList<PileBillingDetail>();
|
||||
for (PileBillingDetail pileBillingDetail : pileBillingDetailList) {
|
||||
pileBillingDetail.setTemplateCode(templateCode);
|
||||
list.add(pileBillingDetail);
|
||||
}
|
||||
if (list.size() > 0) {
|
||||
pileBillingTemplateMapper.batchPileBillingDetail(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,562 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.jsowell.common.constant.CacheConstants;
|
||||
import com.jsowell.common.core.domain.ykc.RealTimeMonitorData;
|
||||
import com.jsowell.common.core.page.PageResponse;
|
||||
import com.jsowell.common.core.redis.RedisCache;
|
||||
import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum;
|
||||
import com.jsowell.common.enums.ykc.PileStatusEnum;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.pile.domain.OrderBasicInfo;
|
||||
import com.jsowell.pile.domain.PileBasicInfo;
|
||||
import com.jsowell.pile.domain.PileConnectorInfo;
|
||||
import com.jsowell.pile.dto.QueryConnectorDTO;
|
||||
import com.jsowell.pile.dto.QueryConnectorListDTO;
|
||||
import com.jsowell.pile.mapper.PileBasicInfoMapper;
|
||||
import com.jsowell.pile.mapper.PileConnectorInfoMapper;
|
||||
import com.jsowell.pile.service.IOrderBasicInfoService;
|
||||
import com.jsowell.pile.service.IPileBasicInfoService;
|
||||
import com.jsowell.pile.service.IPileConnectorInfoService;
|
||||
import com.jsowell.pile.service.IPileModelInfoService;
|
||||
import com.jsowell.pile.vo.base.ConnectorInfoVO;
|
||||
import com.jsowell.pile.vo.web.PileConnectorInfoVO;
|
||||
import com.jsowell.pile.vo.web.PileDetailVO;
|
||||
import com.jsowell.pile.vo.web.PileModelInfoVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 充电桩枪口信息Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2022-08-31
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PileConnectorInfoServiceImpl implements IPileConnectorInfoService {
|
||||
@Autowired
|
||||
private PileConnectorInfoMapper pileConnectorInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private PileBasicInfoMapper pileBasicInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private IPileBasicInfoService pileBasicInfoService;
|
||||
|
||||
@Autowired
|
||||
private IPileModelInfoService pileModelInfoService;
|
||||
|
||||
@Autowired
|
||||
private IOrderBasicInfoService orderBasicInfoService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
private final String URL = "http://localhost/pileConnectorInfo&code=";
|
||||
|
||||
@Value("${qrcodeurl.prefix}")
|
||||
private String QRCODE_URL_PREFIX;
|
||||
|
||||
/**
|
||||
* 查询充电桩枪口信息
|
||||
*
|
||||
* @param id 充电桩枪口信息主键
|
||||
* @return 充电桩枪口信息
|
||||
*/
|
||||
@Override
|
||||
public PileConnectorInfo selectPileConnectorInfoById(Integer id) {
|
||||
return pileConnectorInfoMapper.selectPileConnectorInfoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询充电桩枪口信息列表
|
||||
*
|
||||
* @param pileConnectorInfo 充电桩枪口信息
|
||||
* @return 充电桩枪口信息
|
||||
*/
|
||||
@Override
|
||||
public List<PileConnectorInfo> selectPileConnectorInfoList(PileConnectorInfo pileConnectorInfo) {
|
||||
return pileConnectorInfoMapper.selectPileConnectorInfoList(pileConnectorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过充电桩号查询枪口信息列表 加缓存
|
||||
*
|
||||
* @param pileSn 桩编号
|
||||
* @return 枪口信息列表
|
||||
*/
|
||||
@Override
|
||||
public List<PileConnectorInfo> selectPileConnectorInfoList(String pileSn) {
|
||||
// 取缓存
|
||||
String redisKey = CacheConstants.SELECT_PILE_CONNECTOR_INFO_LIST + pileSn;
|
||||
List<PileConnectorInfo> result = redisCache.getCacheObject(redisKey);
|
||||
if (CollectionUtils.isEmpty(result)) {
|
||||
// 缓存为空,查数据库
|
||||
PileConnectorInfo pileConnectorInfo = new PileConnectorInfo();
|
||||
pileConnectorInfo.setPileSn(pileSn);
|
||||
result = selectPileConnectorInfoList(pileConnectorInfo);
|
||||
if (CollectionUtils.isNotEmpty(result)) {
|
||||
// 查询数据库不为空,存redis 2分钟
|
||||
redisCache.setCacheObject(redisKey, result, 2, TimeUnit.MINUTES);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 公共方法 根据桩编号删除redis缓存
|
||||
*/
|
||||
private void deleteRedisByPileSn(String pileSn) {
|
||||
List<String> keys = Lists.newArrayList();
|
||||
// 删除枪口信息缓存
|
||||
keys.add(CacheConstants.SELECT_PILE_CONNECTOR_INFO_LIST + pileSn);
|
||||
// 删除充电桩详情缓存
|
||||
keys.add(CacheConstants.PILE_DETAIL_KEY + pileSn);
|
||||
// 删除充电桩枪口状态缓存
|
||||
Set<String> scan = redisCache.scan(CacheConstants.PILE_CONNECTOR_STATUS_KEY + pileSn + "*");
|
||||
if (CollectionUtils.isNotEmpty(scan)) {
|
||||
keys.addAll(scan);
|
||||
}
|
||||
// 批量删除
|
||||
// log.debug("批量删除缓存 pileSn:{}, keys:{}", pileSn, keys);
|
||||
redisCache.deleteObject(keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增充电桩枪口信息
|
||||
*
|
||||
* @param pileConnectorInfo 充电桩枪口信息
|
||||
* @return 结果
|
||||
*/
|
||||
// @Override
|
||||
// public int insertPileConnectorInfo(PileConnectorInfo pileConnectorInfo) {
|
||||
// pileConnectorInfo.setCreateTime(DateUtils.getNowDate());
|
||||
// return pileConnectorInfoMapper.insertPileConnectorInfo(pileConnectorInfo);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 修改充电桩枪口信息
|
||||
*
|
||||
* @param pileConnectorInfo 充电桩枪口信息
|
||||
* @return 结果
|
||||
*/
|
||||
// @Override
|
||||
// public int updatePileConnectorInfo(PileConnectorInfo pileConnectorInfo) {
|
||||
// pileConnectorInfo.setUpdateTime(DateUtils.getNowDate());
|
||||
// deleteRedisByPileSn(pileConnectorInfo.getPileSn());
|
||||
// return pileConnectorInfoMapper.updatePileConnectorInfo(pileConnectorInfo);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 批量删除充电桩枪口信息
|
||||
*
|
||||
* @param ids 需要删除的充电桩枪口信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
// @Override
|
||||
// public int deletePileConnectorInfoByIds(Integer[] ids) {
|
||||
// return pileConnectorInfoMapper.deletePileConnectorInfoByIds(ids);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public int deletePileConnectorInfoByPileSnList(List<String> pileSnList) {
|
||||
return pileConnectorInfoMapper.deletePileConnectorInfoByPileSnList(pileSnList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int batchInsertConnectorInfo(List<PileConnectorInfo> pileConnectorInfoList) {
|
||||
return pileConnectorInfoMapper.batchInsertConnectorInfo(pileConnectorInfoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 充电接口相关信息
|
||||
*
|
||||
* @param dto 前台参数
|
||||
* @return 充电接口对象结果集
|
||||
*/
|
||||
@Override
|
||||
public List<PileConnectorInfoVO> getConnectorInfoListByParams(QueryConnectorDTO dto) {
|
||||
List<PileConnectorInfoVO> list = pileConnectorInfoMapper.getConnectorInfoList(dto);
|
||||
// 二维码、电量、设备订单号、平台订单暂时未传
|
||||
if (Objects.nonNull(list)) {
|
||||
for (PileConnectorInfoVO p : list) {
|
||||
// p.setConnectorQrCodeUrl(URL + p.getPileConnectorCode());
|
||||
p.setConnectorQrCodeUrl(getPileConnectorQrCodeUrl(p.getPileConnectorCode()));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过充电站id查询充电枪信息
|
||||
*
|
||||
* @param stationId 充电站id
|
||||
* @return 充电接口信息集合
|
||||
*/
|
||||
@Override
|
||||
public List<PileConnectorInfoVO> selectConnectorListByStationId(Long stationId) {
|
||||
return pileConnectorInfoMapper.selectConnectorListByStationId(stationId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过入参查询枪口数据
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<PileConnectorInfoVO> getConnectorInfoListByParams(QueryConnectorListDTO dto) {
|
||||
int pageNum = dto.getPageNum() == 0 ? 1 : dto.getPageNum();
|
||||
int pageSize = dto.getPageSize() == 0 ? 10 : dto.getPageSize();
|
||||
List<String> pileSns = Lists.newArrayList();
|
||||
List<Long> connectorIds = dto.getConnectorIdList();
|
||||
List<Long> stationIdList = dto.getStationIdList();
|
||||
List<String> connectorCodeList = dto.getConnectorCodeList();
|
||||
|
||||
// 通过运营商查询站点
|
||||
if (StringUtils.isNotBlank(dto.getMerchantId())) {
|
||||
// 查询站点idList
|
||||
List<Long> queryStationIdList = Lists.newArrayList();
|
||||
if (CollectionUtils.isNotEmpty(queryStationIdList)) {
|
||||
if (CollectionUtils.isEmpty(stationIdList)) {
|
||||
stationIdList = Lists.newArrayList();
|
||||
}
|
||||
stationIdList.addAll(queryStationIdList);
|
||||
}
|
||||
}
|
||||
|
||||
// 站点不为空,拿到站点下所有的充电桩id
|
||||
if (CollectionUtils.isNotEmpty(stationIdList)) {
|
||||
List<PileDetailVO> pileInfoVOS = pileBasicInfoService.selectPileListByStationIds(stationIdList);
|
||||
if (CollectionUtils.isNotEmpty(pileInfoVOS)) {
|
||||
pileSns.addAll(pileInfoVOS.stream().map(PileDetailVO::getPileSn).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
||||
// 通过充电桩id查询
|
||||
if (CollectionUtils.isNotEmpty(dto.getPileIds())) {
|
||||
// 批量查
|
||||
List<PileBasicInfo> pileList = pileBasicInfoMapper.selectByIdList(dto.getPileIds());
|
||||
if (CollectionUtils.isNotEmpty(pileList)) {
|
||||
pileSns.addAll(pileList.stream().map(PileBasicInfo::getSn).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isEmpty(pileSns) && CollectionUtils.isEmpty(connectorIds) && CollectionUtils.isEmpty(connectorCodeList)) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
|
||||
List<PileConnectorInfoVO> pileConnectorInfoList = pileConnectorInfoMapper.getPileConnectorInfoList(pileSns, connectorIds, connectorCodeList);
|
||||
|
||||
// 查询枪口当前订单
|
||||
for (PileConnectorInfoVO pileConnectorInfoVO : pileConnectorInfoList) {
|
||||
String pileConnectorCode = pileConnectorInfoVO.getPileConnectorCode();
|
||||
pileConnectorInfoVO.setConnectorQrCodeUrl(getPileConnectorQrCodeUrl(pileConnectorCode)); // 枪口号二维码
|
||||
OrderBasicInfo order = orderBasicInfoService.queryChargingByPileConnectorCode(pileConnectorCode);
|
||||
if (order != null) {
|
||||
pileConnectorInfoVO.setOrderCode(order.getOrderCode());
|
||||
}
|
||||
}
|
||||
|
||||
queryRealTimeData(pileConnectorInfoList);
|
||||
return pileConnectorInfoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 充电桩枪口的二维码
|
||||
* @param pileConnectorCode 枪口编号 如枪口编号为空,则返回前缀 https://api.jsowellcloud.com/app-xcx-h5/pile/connectorDetail/
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getPileConnectorQrCodeUrl(String pileConnectorCode) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append(QRCODE_URL_PREFIX);
|
||||
stringBuilder.append("/app-xcx-h5/pile/connectorDetail/");
|
||||
if (StringUtils.isNotBlank(pileConnectorCode)) {
|
||||
if (!stringBuilder.toString().endsWith("/")) {
|
||||
stringBuilder.append("/");
|
||||
}
|
||||
stringBuilder.append(pileConnectorCode);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* uniapp通过入参查询枪口数据
|
||||
*
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public PageResponse getUniAppConnectorInfoListByParams(QueryConnectorListDTO dto) {
|
||||
int pageNum = dto.getPageNum() == 0 ? 1 : dto.getPageNum();
|
||||
int pageSize = dto.getPageSize() == 0 ? 10 : dto.getPageSize();
|
||||
|
||||
List<String> pileSns = Lists.newArrayList();
|
||||
List<Long> connectorIds = dto.getConnectorIdList();
|
||||
List<Long> stationIdList = dto.getStationIdList();
|
||||
List<String> connectorCodeList = dto.getConnectorCodeList();
|
||||
|
||||
// 通过运营商查询站点
|
||||
if (StringUtils.isNotBlank(dto.getMerchantId())) {
|
||||
// 查询站点idList
|
||||
List<Long> queryStationIdList = Lists.newArrayList();
|
||||
if (CollectionUtils.isNotEmpty(queryStationIdList)) {
|
||||
if (CollectionUtils.isEmpty(stationIdList)) {
|
||||
stationIdList = Lists.newArrayList();
|
||||
}
|
||||
stationIdList.addAll(queryStationIdList);
|
||||
}
|
||||
}
|
||||
|
||||
// 站点不为空,拿到站点下所有的充电桩id
|
||||
if (CollectionUtils.isNotEmpty(stationIdList)) {
|
||||
List<PileDetailVO> pileInfoVOS = pileBasicInfoService.selectPileListByStationIds(stationIdList);
|
||||
if (CollectionUtils.isNotEmpty(pileInfoVOS)) {
|
||||
pileSns.addAll(pileInfoVOS.stream().map(PileDetailVO::getPileSn).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
||||
// 通过充电桩id查询
|
||||
if (CollectionUtils.isNotEmpty(dto.getPileIds())) {
|
||||
// 批量查
|
||||
List<PileBasicInfo> pileList = pileBasicInfoMapper.selectByIdList(dto.getPileIds());
|
||||
if (CollectionUtils.isNotEmpty(pileList)) {
|
||||
pileSns.addAll(pileList.stream().map(PileBasicInfo::getSn).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isEmpty(pileSns) && CollectionUtils.isEmpty(connectorIds) && CollectionUtils.isEmpty(connectorCodeList)) {
|
||||
return new PageResponse();
|
||||
}
|
||||
// 分页
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
|
||||
List<PileConnectorInfoVO> pileConnectorInfoList = pileConnectorInfoMapper.getPileConnectorInfoList(pileSns, connectorIds, connectorCodeList);
|
||||
|
||||
PageInfo<PileConnectorInfoVO> pageInfo = new PageInfo<>(pileConnectorInfoList);
|
||||
|
||||
queryRealTimeData(pageInfo.getList());
|
||||
|
||||
// 返回结果集
|
||||
PageResponse pageResponse = PageResponse.builder()
|
||||
.pageNum(pageNum)
|
||||
.pageSize(pageSize)
|
||||
.list(pageInfo.getList())
|
||||
.pages(pageInfo.getPages())
|
||||
.total(pageInfo.getTotal())
|
||||
.build();
|
||||
return pageResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* uniApp通过站点id查询枪口列表信息
|
||||
*
|
||||
* @param stationId 站点id
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<ConnectorInfoVO> getUniAppConnectorList(Long stationId) {
|
||||
// TODO 加缓存
|
||||
return pileConnectorInfoMapper.getUniAppConnectorList(stationId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConnectorInfoVO> selectConnectorInfoList(String pileSn) {
|
||||
// 查询充电桩型号信息
|
||||
PileModelInfoVO pileModelInfoVO = pileModelInfoService.getPileModelInfoByPileSn(pileSn);
|
||||
|
||||
List<PileConnectorInfo> connectorList = selectPileConnectorInfoList(pileSn);
|
||||
List<ConnectorInfoVO> connectorInfoList = Lists.newArrayList();
|
||||
if (CollectionUtils.isNotEmpty(connectorList)) {
|
||||
for (PileConnectorInfo connectorInfo : connectorList) {
|
||||
ConnectorInfoVO infoVO = ConnectorInfoVO.builder()
|
||||
.connectorCode(StringUtils.replace(connectorInfo.getPileConnectorCode(), pileSn, ""))
|
||||
.pileConnectorCode(connectorInfo.getPileConnectorCode())
|
||||
.connectorStatus(connectorInfo.getStatus())
|
||||
.build();
|
||||
if (pileModelInfoVO != null) {
|
||||
infoVO.setChargingType(pileModelInfoVO.getSpeedType());
|
||||
infoVO.setRatedPower(pileModelInfoVO.getRatedPower());
|
||||
}
|
||||
connectorInfoList.add(infoVO);
|
||||
}
|
||||
}
|
||||
return connectorInfoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询充电枪口的实时数据
|
||||
*/
|
||||
private void queryRealTimeData(List<PileConnectorInfoVO> pileConnectorInfoList) {
|
||||
if (CollectionUtils.isEmpty(pileConnectorInfoList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取枪口的日志记录
|
||||
for (PileConnectorInfoVO pileConnectorInfoVO : pileConnectorInfoList) {
|
||||
// 从redis中获取实时数据信息
|
||||
if (StringUtils.isNotBlank(pileConnectorInfoVO.getOrderCode())) {
|
||||
List<RealTimeMonitorData> chargingRealTimeDataList = orderBasicInfoService.getChargingRealTimeData(pileConnectorInfoVO.getOrderCode());
|
||||
RealTimeMonitorData realTimeMonitorData = chargingRealTimeDataList.get(0);
|
||||
BigDecimal outputVoltage = new BigDecimal(realTimeMonitorData.getOutputVoltage());
|
||||
pileConnectorInfoVO.setVoltage(outputVoltage);
|
||||
BigDecimal outputCurrent = new BigDecimal(realTimeMonitorData.getOutputCurrent());
|
||||
pileConnectorInfoVO.setCurrent(outputCurrent);
|
||||
pileConnectorInfoVO.setSOC(realTimeMonitorData.getSOC()); // 充电百分比
|
||||
pileConnectorInfoVO.setChargingAmount(new BigDecimal(realTimeMonitorData.getChargingAmount()));
|
||||
pileConnectorInfoVO.setChargingDegree(new BigDecimal(realTimeMonitorData.getChargingDegree()));
|
||||
pileConnectorInfoVO.setGunLineTemperature(realTimeMonitorData.getGunLineTemperature()); // 枪线温度
|
||||
pileConnectorInfoVO.setTimeRemaining(realTimeMonitorData.getTimeRemaining());
|
||||
pileConnectorInfoVO.setChargingTime(realTimeMonitorData.getSumChargingTime());
|
||||
// 计算实时功率(单位:kw)
|
||||
BigDecimal instantPowerTemp = outputVoltage.multiply(outputCurrent);
|
||||
BigDecimal instantPower = instantPowerTemp.divide(new BigDecimal(1000));
|
||||
pileConnectorInfoVO.setInstantPower(instantPower.setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
log.info("枪口实时数据:{}", JSONObject.toJSONString(pileConnectorInfoVO));
|
||||
}
|
||||
|
||||
if (checkPileOffLine(pileConnectorInfoVO.getPileSn())) {
|
||||
// 最后收到消息的时间在1分钟前,则返回给前端枪口离线
|
||||
pileConnectorInfoVO.setStatus(Integer.valueOf(PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue()));
|
||||
// 并修改数据库状态为离线
|
||||
updateConnectorStatusByPileSn(pileConnectorInfoVO.getPileSn(), PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过桩编号修改枪口状态
|
||||
* 仅用于登录逻辑使用
|
||||
*
|
||||
* @param pileSn 充电桩编号
|
||||
* @param status 充电桩枪口状态
|
||||
*/
|
||||
public int updateConnectorStatusByPileSn(String pileSn, String status) {
|
||||
if (StringUtils.isBlank(pileSn) || StringUtils.isBlank(status)) {
|
||||
return 0;
|
||||
}
|
||||
// 通过pileSn查询枪口列表
|
||||
List<PileConnectorInfo> connectorInfoList = selectPileConnectorInfoList(pileSn);
|
||||
if (CollectionUtils.isEmpty(connectorInfoList)) {
|
||||
return 0;
|
||||
}
|
||||
int i = 0;
|
||||
for (PileConnectorInfo connectorInfo : connectorInfoList) {
|
||||
i = i + updateConnectorStatus(connectorInfo.getPileConnectorCode(), status);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改枪口状态
|
||||
* 所有修改枪口状态的都要使用这个方法,和数据库交互只有这一个口子
|
||||
*
|
||||
* @param connectorCode 枪口号 桩编号+枪口号
|
||||
* @param status 状态 0:离网 (默认);1:空闲;2:占用(未充电);3:占用(充电中);4:占用(预约锁定) ;255:故障
|
||||
*/
|
||||
@Override
|
||||
public int updateConnectorStatus(String connectorCode, String status) {
|
||||
int num = 0;
|
||||
if (StringUtils.isBlank(connectorCode) || StringUtils.isBlank(status)) {
|
||||
return num;
|
||||
}
|
||||
String redisKey = CacheConstants.PILE_CONNECTOR_STATUS_KEY + connectorCode;
|
||||
String redisStatus = redisCache.getCacheObject(redisKey);
|
||||
// log.info("修改充电桩枪口状态 缓存状态:{}, 传来的状态:{}", redisStatus, status);
|
||||
if (!StringUtils.equals(redisStatus, status)) {
|
||||
log.info("更新枪口状态 枪口号:{}, 缓存状态:{}, 状态值:{}, 状态:{}", connectorCode, redisStatus, status, PileConnectorDataBaseStatusEnum.getStatusDescription(status));
|
||||
String pileSn = connectorCode.substring(0, connectorCode.length() - 2);
|
||||
// 只修改一个枪口的状态
|
||||
num = pileConnectorInfoMapper.updateConnectorStatus(connectorCode, status);
|
||||
deleteRedisByPileSn(pileSn);
|
||||
redisCache.setCacheObject(redisKey, status);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取桩状态
|
||||
* 桩的状态有 在线 离线 故障
|
||||
*
|
||||
* @param pileSnList 桩编号列表
|
||||
* @return key:桩编号; value:状态
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getPileStatus(List<String> pileSnList) {
|
||||
Map<String, String> resultMap = Maps.newHashMap();
|
||||
for (String pileSn : pileSnList) {
|
||||
String pileStatus = "";
|
||||
|
||||
// 标识桩故障或者离线
|
||||
boolean flag = false;
|
||||
|
||||
// 判断故障状态
|
||||
List<PileConnectorInfo> connectorList = selectPileConnectorInfoList(pileSn); // 获取枪口信息
|
||||
List<String> connectorStatusList = connectorList.stream().map(PileConnectorInfo::getStatus).collect(Collectors.toList());
|
||||
// 桩下面的枪口,任意一个故障,桩的状态就是故障
|
||||
if (connectorStatusList.contains(PileConnectorDataBaseStatusEnum.FAULT.getValue())) {
|
||||
pileStatus = PileStatusEnum.FAULT.getValue();
|
||||
flag = true;
|
||||
}
|
||||
|
||||
// 判断离线状态 显示优先级 离线>故障
|
||||
// if (checkPileOffLine(pileSn)) {
|
||||
// pileStatus = PileStatusEnum.OFF_LINE.getValue();
|
||||
// flag = true;
|
||||
// }
|
||||
|
||||
// 2023年1月10日11点32分 改成如果枪口离线,那么充电桩就是离线
|
||||
if (connectorStatusList.contains(PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue())) {
|
||||
pileStatus = PileStatusEnum.OFF_LINE.getValue();
|
||||
flag = true;
|
||||
}
|
||||
|
||||
// 没有故障或者离线,就是在线状态
|
||||
if (!flag) {
|
||||
pileStatus = PileStatusEnum.ON_LINE.getValue();
|
||||
}
|
||||
|
||||
resultMap.put(pileSn, pileStatus);
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PileConnectorInfoVO getPileConnectorInfoByConnectorCode(String pileConnectorCode) {
|
||||
return pileConnectorInfoMapper.getPileConnectorInfoByConnectorCode(pileConnectorCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断充电桩是否离线
|
||||
*
|
||||
* @param pileSn 桩编号
|
||||
* @return true离线
|
||||
*/
|
||||
private boolean checkPileOffLine(String pileSn) {
|
||||
// 获取桩最后连接时间,最后连接到平台的时间在1分钟之前,判定为离线
|
||||
String lastConnectionTime = redisCache.getCacheObject(CacheConstants.PILE_LAST_CONNECTION + pileSn);
|
||||
if (StringUtils.isBlank(lastConnectionTime)) {
|
||||
// 没有最后连接时间,返回离线
|
||||
return true;
|
||||
}
|
||||
long l = DateUtils.intervalTime(lastConnectionTime, DateUtils.getTime());
|
||||
return l >= 1L;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.pile.domain.PileLicenceInfo;
|
||||
import com.jsowell.pile.mapper.PileLicenceInfoMapper;
|
||||
import com.jsowell.pile.service.IPileLicenceInfoService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 充电桩证书信息Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2022-08-27
|
||||
*/
|
||||
@Service
|
||||
public class PileLicenceInfoServiceImpl implements IPileLicenceInfoService
|
||||
{
|
||||
@Autowired
|
||||
private PileLicenceInfoMapper pileLicenceInfoMapper;
|
||||
|
||||
/**
|
||||
* 查询充电桩证书信息
|
||||
*
|
||||
* @param id 充电桩证书信息主键
|
||||
* @return 充电桩证书信息
|
||||
*/
|
||||
@Override
|
||||
public PileLicenceInfo selectPileLicenceInfoById(Long id)
|
||||
{
|
||||
|
||||
return pileLicenceInfoMapper.selectPileLicenceInfoById(id);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String applyTime = "00:00-05:00,10:00-13:00,10:00-13:00,10:00-13:00";
|
||||
List<String> timeList = Lists.newArrayList(applyTime.split(","));
|
||||
System.out.println(timeList);
|
||||
for (String s : timeList) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询充电桩证书信息列表
|
||||
*
|
||||
* @param pileLicenceInfo 充电桩证书信息
|
||||
* @return 充电桩证书信息
|
||||
*/
|
||||
@Override
|
||||
public List<PileLicenceInfo> selectPileLicenceInfoList(PileLicenceInfo pileLicenceInfo)
|
||||
{
|
||||
return pileLicenceInfoMapper.selectPileLicenceInfoList(pileLicenceInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增充电桩证书信息
|
||||
*
|
||||
* @param pileLicenceInfo 充电桩证书信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertPileLicenceInfo(PileLicenceInfo pileLicenceInfo)
|
||||
{
|
||||
pileLicenceInfo.setCreateTime(DateUtils.getNowDate());
|
||||
return pileLicenceInfoMapper.insertPileLicenceInfo(pileLicenceInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改充电桩证书信息
|
||||
*
|
||||
* @param pileLicenceInfo 充电桩证书信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updatePileLicenceInfo(PileLicenceInfo pileLicenceInfo)
|
||||
{
|
||||
pileLicenceInfo.setUpdateTime(DateUtils.getNowDate());
|
||||
return pileLicenceInfoMapper.updatePileLicenceInfo(pileLicenceInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除充电桩证书信息
|
||||
*
|
||||
* @param ids 需要删除的充电桩证书信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileLicenceInfoByIds(Long[] ids)
|
||||
{
|
||||
return pileLicenceInfoMapper.deletePileLicenceInfoByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除充电桩证书信息信息
|
||||
*
|
||||
* @param id 充电桩证书信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileLicenceInfoById(Long id)
|
||||
{
|
||||
return pileLicenceInfoMapper.deletePileLicenceInfoById(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.pile.domain.PileMemberRelation;
|
||||
import com.jsowell.pile.mapper.PileMemberRelationMapper;
|
||||
import com.jsowell.pile.service.IPileConnectorInfoService;
|
||||
import com.jsowell.pile.service.IPileMemberRelationService;
|
||||
import com.jsowell.pile.vo.uniapp.PersonalPileInfoVO;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 桩与用户绑定关系Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2023-02-21
|
||||
*/
|
||||
@Service
|
||||
public class PileMemberRelationServiceImpl implements IPileMemberRelationService {
|
||||
@Autowired
|
||||
private PileMemberRelationMapper pileMemberRelationMapper;
|
||||
|
||||
@Autowired
|
||||
private IPileConnectorInfoService pileConnectorInfoService;
|
||||
/**
|
||||
* 查询桩与用户绑定关系
|
||||
*
|
||||
* @param id 桩与用户绑定关系主键
|
||||
* @return 桩与用户绑定关系
|
||||
*/
|
||||
@Override
|
||||
public PileMemberRelation selectPileMemberRelationById(Integer id) {
|
||||
return pileMemberRelationMapper.selectPileMemberRelationById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询桩与用户绑定关系列表
|
||||
*
|
||||
* @param pileMemberRelation 桩与用户绑定关系
|
||||
* @return 桩与用户绑定关系
|
||||
*/
|
||||
@Override
|
||||
public List<PileMemberRelation> selectPileMemberRelationList(PileMemberRelation pileMemberRelation) {
|
||||
return pileMemberRelationMapper.selectPileMemberRelationList(pileMemberRelation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查询桩与用户绑定关系
|
||||
*
|
||||
* @param pileMemberRelation 桩与用户绑定关系
|
||||
* @return 桩与用户绑定关系对象
|
||||
*/
|
||||
@Override
|
||||
public PileMemberRelation selectPileMemberRelation(PileMemberRelation pileMemberRelation) {
|
||||
return pileMemberRelationMapper.selectPileMemberRelation(pileMemberRelation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增桩与用户绑定关系
|
||||
*
|
||||
* @param pileMemberRelation 桩与用户绑定关系
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertPileMemberRelation(PileMemberRelation pileMemberRelation) {
|
||||
pileMemberRelation.setCreateTime(DateUtils.getNowDate());
|
||||
return pileMemberRelationMapper.insertPileMemberRelation(pileMemberRelation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改桩与用户绑定关系
|
||||
*
|
||||
* @param pileMemberRelation 桩与用户绑定关系
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updatePileMemberRelation(PileMemberRelation pileMemberRelation) {
|
||||
return pileMemberRelationMapper.updatePileMemberRelation(pileMemberRelation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除桩与用户绑定关系
|
||||
*
|
||||
* @param ids 需要删除的桩与用户绑定关系主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileMemberRelationByIds(Integer[] ids) {
|
||||
return pileMemberRelationMapper.deletePileMemberRelationByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除桩与用户绑定关系信息
|
||||
*
|
||||
* @param id 桩与用户绑定关系主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileMemberRelationById(Integer id) {
|
||||
return pileMemberRelationMapper.deletePileMemberRelationById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PileMemberRelation> selectPileMemberRelationByPileSn(String pileSn) {
|
||||
PileMemberRelation pileMemberRelation = new PileMemberRelation();
|
||||
pileMemberRelation.setPileSn(pileSn);
|
||||
return selectPileMemberRelationList(pileMemberRelation);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.jsowell.common.annotation.DataScope;
|
||||
import com.jsowell.common.constant.Constants;
|
||||
import com.jsowell.common.core.domain.entity.SysDept;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.common.util.DictUtils;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.pile.domain.PileMerchantInfo;
|
||||
import com.jsowell.pile.mapper.PileMerchantInfoMapper;
|
||||
import com.jsowell.pile.service.IPileMerchantInfoService;
|
||||
import com.jsowell.pile.vo.base.MerchantInfoVO;
|
||||
import com.jsowell.system.service.SysDeptService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 充电桩运营商信息Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2022-08-27
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PileMerchantInfoServiceImpl implements IPileMerchantInfoService {
|
||||
@Autowired
|
||||
private PileMerchantInfoMapper pileMerchantInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private SysDeptService sysDeptService;
|
||||
|
||||
@Value("${weixin.login.appid}")
|
||||
private String appid;
|
||||
|
||||
/**
|
||||
* 查询充电桩运营商信息
|
||||
*
|
||||
* @param id 充电桩运营商信息主键
|
||||
* @return 充电桩运营商信息
|
||||
*/
|
||||
@Override
|
||||
public PileMerchantInfo selectPileMerchantInfoById(Long id) {
|
||||
return pileMerchantInfoMapper.selectPileMerchantInfoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询充电桩运营商信息列表
|
||||
*
|
||||
* @param pileMerchantInfo 充电桩运营商信息
|
||||
* @return 充电桩运营商信息
|
||||
*/
|
||||
@Override
|
||||
@DataScope(deptAlias = "t")
|
||||
public List<PileMerchantInfo> selectPileMerchantInfoList(PileMerchantInfo pileMerchantInfo) {
|
||||
List<PileMerchantInfo> list = pileMerchantInfoMapper.selectPileMerchantInfoList(pileMerchantInfo);
|
||||
if (Objects.nonNull(list)) {
|
||||
for (PileMerchantInfo p:list) {
|
||||
String status = p.getStatus();
|
||||
String merchant_status = DictUtils.getDictLabel("merchant_status", status);
|
||||
p.setStatus(merchant_status);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增充电桩运营商信息
|
||||
*
|
||||
* @param pileMerchantInfo 充电桩运营商信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public int insertPileMerchantInfo(PileMerchantInfo pileMerchantInfo) {
|
||||
// 1. 新增sys_dept
|
||||
SysDept dept = new SysDept();
|
||||
dept.setParentId(100L);
|
||||
dept.setOrderNum(0);
|
||||
dept.setDeptName(pileMerchantInfo.getMerchantName());
|
||||
dept.setLeader(pileMerchantInfo.getManagerName());
|
||||
dept.setPhone(pileMerchantInfo.getManagerPhone());
|
||||
dept.setStatus("0");
|
||||
sysDeptService.insertDept(dept);
|
||||
|
||||
// 2. 新增pile_merchant_info
|
||||
Long deptId = dept.getDeptId();
|
||||
// pileMerchantInfo.setId(deptId);
|
||||
pileMerchantInfo.setDeptId(String.valueOf(deptId));
|
||||
pileMerchantInfo.setStatus(Constants.ONE);
|
||||
String appId = StringUtils.isBlank(pileMerchantInfo.getAppId())
|
||||
? appid
|
||||
: pileMerchantInfo.getAppId();
|
||||
pileMerchantInfo.setAppId(appId);
|
||||
return pileMerchantInfoMapper.insertPileMerchantInfo(pileMerchantInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改充电桩运营商信息
|
||||
*
|
||||
* @param pileMerchantInfo 充电桩运营商信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updatePileMerchantInfo(PileMerchantInfo pileMerchantInfo) {
|
||||
pileMerchantInfo.setUpdateTime(DateUtils.getNowDate());
|
||||
return pileMerchantInfoMapper.updatePileMerchantInfo(pileMerchantInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除充电桩运营商信息
|
||||
*
|
||||
* @param ids 需要删除的充电桩运营商信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileMerchantInfoByIds(Long[] ids) {
|
||||
return pileMerchantInfoMapper.deletePileMerchantInfoByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除充电桩运营商信息信息
|
||||
*
|
||||
* @param id 充电桩运营商信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileMerchantInfoById(Long id) {
|
||||
return pileMerchantInfoMapper.deletePileMerchantInfoById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMerchantIdByAppId(String appId) {
|
||||
if (StringUtils.isBlank(appId)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
PileMerchantInfo pileMerchantInfo = pileMerchantInfoMapper.selectPileMerchantInfoByAppId(appId);
|
||||
if (pileMerchantInfo != null) {
|
||||
return pileMerchantInfo.getId().toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("通过appid获取运营商id error", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MerchantInfoVO getMerchantInfo(String merchantId) {
|
||||
PileMerchantInfo pileMerchantInfo = selectPileMerchantInfoById(Long.parseLong(merchantId));
|
||||
if (pileMerchantInfo == null) {
|
||||
return null;
|
||||
}
|
||||
MerchantInfoVO vo = MerchantInfoVO.builder()
|
||||
.merchantId(merchantId)
|
||||
.merchantName(pileMerchantInfo.getMerchantName())
|
||||
.merchantTel(pileMerchantInfo.getServicePhone())
|
||||
.deptId(pileMerchantInfo.getDeptId())
|
||||
.build();
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.pile.domain.PileModelInfo;
|
||||
import com.jsowell.pile.mapper.PileModelInfoMapper;
|
||||
import com.jsowell.pile.service.IPileModelInfoService;
|
||||
import com.jsowell.pile.vo.web.PileModelInfoVO;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 充电桩型号信息Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2022-08-26
|
||||
*/
|
||||
@Service
|
||||
public class PileModelInfoServiceImpl implements IPileModelInfoService {
|
||||
@Autowired
|
||||
private PileModelInfoMapper pileModelInfoMapper;
|
||||
|
||||
/**
|
||||
* 查询充电桩型号信息
|
||||
*
|
||||
* @param id 充电桩型号信息主键
|
||||
* @return 充电桩型号信息
|
||||
*/
|
||||
@Override
|
||||
public PileModelInfo selectPileModelInfoById(Long id) {
|
||||
return pileModelInfoMapper.selectPileModelInfoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询充电桩型号信息列表
|
||||
*
|
||||
* @param pileModelInfo 充电桩型号信息
|
||||
* @return 充电桩型号信息
|
||||
*/
|
||||
@Override
|
||||
public List<PileModelInfo> selectPileModelInfoList(PileModelInfo pileModelInfo) {
|
||||
return pileModelInfoMapper.selectPileModelInfoList(pileModelInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增充电桩型号信息
|
||||
*
|
||||
* @param pileModelInfo 充电桩型号信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertPileModelInfo(PileModelInfo pileModelInfo) {
|
||||
pileModelInfo.setCreateTime(DateUtils.getNowDate());
|
||||
return pileModelInfoMapper.insertPileModelInfo(pileModelInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改充电桩型号信息
|
||||
*
|
||||
* @param pileModelInfo 充电桩型号信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updatePileModelInfo(PileModelInfo pileModelInfo) {
|
||||
pileModelInfo.setUpdateTime(DateUtils.getNowDate());
|
||||
return pileModelInfoMapper.updatePileModelInfo(pileModelInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除充电桩型号信息
|
||||
*
|
||||
* @param ids 需要删除的充电桩型号信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileModelInfoByIds(Long[] ids) {
|
||||
return pileModelInfoMapper.deletePileModelInfoByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除充电桩型号信息信息
|
||||
*
|
||||
* @param id 充电桩型号信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileModelInfoById(Long id) {
|
||||
return pileModelInfoMapper.deletePileModelInfoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过桩编号集合获取型号表中数据
|
||||
*
|
||||
* @param pileSns 桩编号集合
|
||||
* @return PileModelInfo对象
|
||||
*/
|
||||
@Override
|
||||
public List<PileModelInfoVO> getPileModelInfoByPileSnList(List<String> pileSns) {
|
||||
return pileModelInfoMapper.getPileModelInfoByPileSnList(pileSns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PileModelInfoVO getPileModelInfoByPileSn(String pileSn) {
|
||||
List<PileModelInfoVO> list = getPileModelInfoByPileSnList(Lists.newArrayList(pileSn));
|
||||
if (CollectionUtils.isNotEmpty(list)) {
|
||||
return list.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode;
|
||||
import com.jsowell.common.core.page.PageResponse;
|
||||
import com.jsowell.common.util.BytesUtil;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.common.util.YKCUtils;
|
||||
import com.jsowell.pile.domain.PileMsgRecord;
|
||||
import com.jsowell.pile.dto.QueryPileDTO;
|
||||
import com.jsowell.pile.mapper.PileMsgRecordMapper;
|
||||
import com.jsowell.pile.service.IPileMsgRecordService;
|
||||
import com.jsowell.pile.vo.web.PileCommunicationLogVO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PileMsgRecordServiceImpl implements IPileMsgRecordService {
|
||||
|
||||
@Autowired
|
||||
private PileMsgRecordMapper pileMsgRecordMapper;
|
||||
|
||||
@Override
|
||||
public void save(String pileSn, String connectorCode, String frameType, String jsonMsg, String originalMsg) {
|
||||
PileMsgRecord pileMsgRecord = PileMsgRecord.builder()
|
||||
.pileSn(pileSn)
|
||||
.connectorCode(connectorCode)
|
||||
.jsonMsg(jsonMsg)
|
||||
.frameType(frameType)
|
||||
.originalMsg(originalMsg)
|
||||
.build();
|
||||
pileMsgRecordMapper.insertSelective(pileMsgRecord);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public List<PileMsgRecord> getByConnectorCodeList(List<String> connectorCodeList) {
|
||||
// if (CollectionUtils.isEmpty(connectorCodeList)) {
|
||||
// return Lists.newArrayList();
|
||||
// }
|
||||
// return pileMsgRecordMapper.getByConnectorCodeList(connectorCodeList);
|
||||
// }
|
||||
|
||||
public static void main(String[] args) {
|
||||
String type = BytesUtil.bcd2Str(YKCFrameTypeCode.TRANSACTION_RECORDS_CODE.getBytes());
|
||||
System.out.println(type);
|
||||
String binary = BytesUtil.binary(YKCFrameTypeCode.TRANSACTION_RECORDS_CODE.getBytes(), 16);
|
||||
System.out.println(binary);
|
||||
String s = YKCUtils.frameType2Str(YKCFrameTypeCode.TRANSACTION_RECORDS_CODE.getBytes());
|
||||
System.out.println(s);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResponse getPileFeedList(QueryPileDTO dto) {
|
||||
// 分页
|
||||
PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
|
||||
List<PileMsgRecord> pileFeedList = pileMsgRecordMapper.getPileFeedList(dto.getPileSn());
|
||||
PageInfo<PileMsgRecord> pageInfo = new PageInfo<>(pileFeedList);
|
||||
|
||||
List<PileCommunicationLogVO> list = new ArrayList<>();
|
||||
for (PileMsgRecord pileMsgRecord : pageInfo.getList()) {
|
||||
PileCommunicationLogVO vo = new PileCommunicationLogVO();
|
||||
String frameType = pileMsgRecord.getFrameType();
|
||||
|
||||
String frameTypeStr = YKCFrameTypeCode.getFrameTypeStr(frameType);
|
||||
if (StringUtils.isNotBlank(frameTypeStr)) {
|
||||
vo.setDescription(frameTypeStr);
|
||||
} else {
|
||||
vo.setDescription(pileMsgRecord.getJsonMsg());
|
||||
}
|
||||
// if (StringUtils.equals(YKCUtils.frameType2Str(YKCFrameTypeCode.LOGIN_CODE.getBytes()), frameType)) {
|
||||
// // 登录
|
||||
// vo.setDescription("充电桩登录认证");
|
||||
// } else if (StringUtils.equals(YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_RESTART_CODE.getBytes()), frameType)) {
|
||||
// // 远程重启
|
||||
// vo.setDescription("远程重启");
|
||||
// } else if (StringUtils.equals(YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_CONTROL_START_CODE.getBytes()), frameType)) {
|
||||
// // 远程启动充电
|
||||
// vo.setDescription("运营平台远程控制启机");
|
||||
// }else if (StringUtils.equals(YKCUtils.frameType2Str(YKCFrameTypeCode.REMOTE_STOP_CHARGING_CODE.getBytes()), frameType)) {
|
||||
// // 远程停机
|
||||
// vo.setDescription("运营平台远程停机");
|
||||
// }else if (StringUtils.equals(YKCUtils.frameType2Str(YKCFrameTypeCode.TRANSACTION_RECORDS_CODE.getBytes()), frameType)) {
|
||||
// // 交易记录
|
||||
// vo.setDescription("交易结算");
|
||||
// }else if (StringUtils.equals(YKCUtils.frameType2Str(YKCFrameTypeCode.PILE_LOG_OUT.getBytes()), frameType)) {
|
||||
// // 退出
|
||||
// vo.setDescription("充电桩退出");
|
||||
// }
|
||||
vo.setPileSn(pileMsgRecord.getPileSn());
|
||||
vo.setCreateTime(pileMsgRecord.getCreateTime());
|
||||
vo.setFrameType(frameType);
|
||||
list.add(vo);
|
||||
}
|
||||
|
||||
PageResponse pageResponse = PageResponse.builder()
|
||||
.pageNum(pageInfo.getPageNum())
|
||||
.pageSize(pageInfo.getPageSize())
|
||||
.list(list)
|
||||
.total(pageInfo.getTotal())
|
||||
.pages(pageInfo.getPages())
|
||||
.build();
|
||||
return pageResponse;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.pile.domain.PileSimInfo;
|
||||
import com.jsowell.pile.dto.QuerySimInfoDTO;
|
||||
import com.jsowell.pile.mapper.PileSimInfoMapper;
|
||||
import com.jsowell.pile.service.IPileSimInfoService;
|
||||
import com.jsowell.pile.vo.web.SimCardInfoVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 充电桩SIM卡信息Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2022-08-26
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PileSimInfoServiceImpl implements IPileSimInfoService {
|
||||
@Autowired
|
||||
private PileSimInfoMapper pileSimInfoMapper;
|
||||
|
||||
/**
|
||||
* 查询充电桩SIM卡信息
|
||||
*
|
||||
* @param id 充电桩SIM卡信息主键
|
||||
* @return 充电桩SIM卡信息
|
||||
*/
|
||||
@Override
|
||||
public PileSimInfo selectPileSimInfoById(Long id) {
|
||||
return pileSimInfoMapper.selectPileSimInfoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询充电桩SIM卡信息列表
|
||||
*
|
||||
* @param pileSimInfo 充电桩SIM卡信息
|
||||
* @return 充电桩SIM卡信息
|
||||
*/
|
||||
@Override
|
||||
public List<PileSimInfo> selectPileSimInfoList(PileSimInfo pileSimInfo) {
|
||||
return pileSimInfoMapper.selectPileSimInfoList(pileSimInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 后管查询sim卡信息列表
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<SimCardInfoVO> getSimInfoList(QuerySimInfoDTO dto) {
|
||||
return pileSimInfoMapper.getSimInfoList(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增充电桩SIM卡信息
|
||||
*
|
||||
* @param pileSimInfo 充电桩SIM卡信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertPileSimInfo(PileSimInfo pileSimInfo) {
|
||||
pileSimInfo.setCreateTime(DateUtils.getNowDate());
|
||||
log.info("新增充电桩SIM卡信息 PileSimInfo:{}", JSON.toJSONString(pileSimInfo));
|
||||
return pileSimInfoMapper.insertPileSimInfo(pileSimInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改充电桩SIM卡信息
|
||||
*
|
||||
* @param pileSimInfo 充电桩SIM卡信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updatePileSimInfo(PileSimInfo pileSimInfo) {
|
||||
pileSimInfo.setUpdateTime(DateUtils.getNowDate());
|
||||
return pileSimInfoMapper.updatePileSimInfo(pileSimInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除充电桩SIM卡信息
|
||||
*
|
||||
* @param ids 需要删除的充电桩SIM卡信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileSimInfoByIds(Long[] ids) {
|
||||
return pileSimInfoMapper.deletePileSimInfoByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除充电桩SIM卡信息信息
|
||||
*
|
||||
* @param id 充电桩SIM卡信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileSimInfoById(Long id) {
|
||||
return pileSimInfoMapper.deletePileSimInfoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过桩编码查询sim卡信息
|
||||
*
|
||||
* @param pileSn 桩编码
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public SimCardInfoVO querySimCardInfoByPileSn(String pileSn) {
|
||||
return pileSimInfoMapper.querySimCardInfoByPileSn(pileSn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过卡号批量查询sim卡信息
|
||||
*
|
||||
* @param iccIds 卡号
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<PileSimInfo> selectSimInfoByIccIds(List<String> iccIds) {
|
||||
return pileSimInfoMapper.selectSimInfoByIccIds(iccIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过卡号查询sim卡信息
|
||||
*
|
||||
* @param iccId 卡号
|
||||
* @return
|
||||
*/
|
||||
public PileSimInfo getBasicInfoByIccId(String iccId) {
|
||||
return pileSimInfoMapper.getBasicInfoByIccId(iccId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jsowell.common.annotation.DataScope;
|
||||
import com.jsowell.common.constant.Constants;
|
||||
import com.jsowell.common.core.domain.entity.SysDept;
|
||||
import com.jsowell.common.core.page.PageResponse;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.common.util.DistanceUtils;
|
||||
import com.jsowell.common.util.SecurityUtils;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.common.util.ip.AddressUtils;
|
||||
import com.jsowell.pile.domain.PileStationInfo;
|
||||
import com.jsowell.pile.dto.FastCreateStationDTO;
|
||||
import com.jsowell.pile.dto.QueryStationDTO;
|
||||
import com.jsowell.pile.mapper.PileStationInfoMapper;
|
||||
import com.jsowell.pile.service.IPileBillingTemplateService;
|
||||
import com.jsowell.pile.service.IPileConnectorInfoService;
|
||||
import com.jsowell.pile.service.IPileMerchantInfoService;
|
||||
import com.jsowell.pile.service.IPileStationInfoService;
|
||||
import com.jsowell.pile.vo.base.ConnectorInfoVO;
|
||||
import com.jsowell.pile.vo.base.MerchantInfoVO;
|
||||
import com.jsowell.pile.vo.base.StationInfoVO;
|
||||
import com.jsowell.pile.vo.uniapp.CurrentTimePriceDetails;
|
||||
import com.jsowell.pile.vo.web.PileStationVO;
|
||||
import com.jsowell.system.service.SysDeptService;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 充电站信息Service业务层处理
|
||||
*
|
||||
* @author jsowell
|
||||
* @date 2022-08-30
|
||||
*/
|
||||
@Service
|
||||
public class PileStationInfoServiceImpl implements IPileStationInfoService {
|
||||
@Autowired
|
||||
private PileStationInfoMapper pileStationInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private IPileConnectorInfoService pileConnectorInfoService;
|
||||
|
||||
@Autowired
|
||||
private IPileBillingTemplateService pileBillingTemplateService;
|
||||
|
||||
@Autowired
|
||||
private IPileMerchantInfoService pileMerchantInfoService;
|
||||
|
||||
@Autowired
|
||||
private SysDeptService sysDeptService;
|
||||
|
||||
/**
|
||||
* 查询充电站信息
|
||||
*
|
||||
* @param id 充电站信息主键
|
||||
* @return 充电站信息
|
||||
*/
|
||||
@Override
|
||||
public PileStationInfo selectPileStationInfoById(Long id) {
|
||||
return pileStationInfoMapper.selectPileStationInfoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询站点基本资料
|
||||
* @param stationId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public PileStationVO getStationInfo(String stationId) {
|
||||
PileStationVO vo = new PileStationVO();
|
||||
PileStationInfo pileStationInfo = selectPileStationInfoById(Long.parseLong(stationId));
|
||||
// 查计费模板
|
||||
CurrentTimePriceDetails currentTimePriceDetails = pileBillingTemplateService.getCurrentTimePriceDetails(stationId);
|
||||
if (currentTimePriceDetails != null) {
|
||||
vo.setElectricityPrice(new BigDecimal(currentTimePriceDetails.getElectricityPrice()));
|
||||
vo.setServicePrice(new BigDecimal(currentTimePriceDetails.getServicePrice()));
|
||||
}
|
||||
|
||||
if (pileStationInfo != null) {
|
||||
vo.setMerchantId(pileStationInfo.getMerchantId().toString());
|
||||
vo.setStationName(pileStationInfo.getStationName());
|
||||
vo.setId(pileStationInfo.getId().toString());
|
||||
vo.setAreaCode(pileStationInfo.getAreaCode());
|
||||
vo.setAddress(pileStationInfo.getAddress());
|
||||
vo.setMerchantId(pileStationInfo.getMerchantId().toString());
|
||||
// vo.setMerchantName(pileStationInfo.getmer());
|
||||
vo.setMerchantAdminName(pileStationInfo.getStationAdminName());
|
||||
vo.setStationStatus(Integer.parseInt(pileStationInfo.getStationStatus()));
|
||||
vo.setStationType(pileStationInfo.getStationType());
|
||||
vo.setCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, pileStationInfo.getCreateTime()));
|
||||
vo.setStationTel(pileStationInfo.getStationTel());
|
||||
vo.setMatchCars(pileStationInfo.getMatchCars());
|
||||
if (StringUtils.isNotBlank(pileStationInfo.getMatchCars())) {
|
||||
vo.setSelectMatchCars(Lists.newArrayList(pileStationInfo.getMatchCars().split(",")));
|
||||
}
|
||||
vo.setStationLat(pileStationInfo.getStationLat());
|
||||
vo.setStationLng(pileStationInfo.getStationLng());
|
||||
vo.setConstruction(pileStationInfo.getConstruction());
|
||||
vo.setBusinessHours(pileStationInfo.getBusinessHours());
|
||||
// vo.setOrganizationCode(pileStationInfo.getor);
|
||||
vo.setPublicFlag(pileStationInfo.getPublicFlag());
|
||||
vo.setOpenFlag(pileStationInfo.getOpenFlag());
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询充电站信息列表
|
||||
*
|
||||
* @param pileStationInfo 充电站信息
|
||||
* @return 充电站信息
|
||||
*/
|
||||
@Override
|
||||
public List<PileStationInfo> selectPileStationInfoList(PileStationInfo pileStationInfo) {
|
||||
return pileStationInfoMapper.selectPileStationInfoList(pileStationInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过运营商id查询站点信息
|
||||
*
|
||||
* @param merchantId 运营商id
|
||||
* @return 站点信息列表
|
||||
*/
|
||||
@Override
|
||||
public List<PileStationInfo> selectStationListByMerchantId(Long merchantId) {
|
||||
return pileStationInfoMapper.selectStationListByMerchantId(merchantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增充电站信息
|
||||
*
|
||||
* @param pileStationInfo 充电站信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
|
||||
public int insertPileStationInfo(PileStationInfo pileStationInfo) {
|
||||
pileStationInfo.setCreateTime(DateUtils.getNowDate());
|
||||
pileStationInfo.setCreateBy(SecurityUtils.getUsername());
|
||||
return pileStationInfoMapper.insertPileStationInfo(pileStationInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 快速建站
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int fastCreateStation(FastCreateStationDTO dto) {
|
||||
MerchantInfoVO merchantInfo = pileMerchantInfoService.getMerchantInfo(dto.getMerchantId());
|
||||
if (merchantInfo == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 1. 新增sys_dept
|
||||
SysDept dept = new SysDept();
|
||||
// 根据运营商Id查询到对应的部门id
|
||||
dept.setParentId(Long.parseLong(merchantInfo.getDeptId()));
|
||||
dept.setOrderNum(0);
|
||||
dept.setDeptName(dto.getStationName());
|
||||
dept.setLeader(dto.getStationAdminName());
|
||||
dept.setPhone(dto.getStationTel());
|
||||
dept.setStatus("0");
|
||||
sysDeptService.insertDept(dept);
|
||||
|
||||
PileStationInfo pileStationInfo = new PileStationInfo();
|
||||
// pileStationInfo.setId(dept.getDeptId());
|
||||
pileStationInfo.setDeptId(String.valueOf(dept.getDeptId()));
|
||||
// 前端输入信息
|
||||
pileStationInfo.setMerchantId(Long.valueOf(dto.getMerchantId()));
|
||||
pileStationInfo.setStationName(dto.getStationName());
|
||||
pileStationInfo.setAddress(dto.getAddress());
|
||||
pileStationInfo.setAreaCode(dto.getAreaCode());
|
||||
pileStationInfo.setCapacity(BigDecimal.ZERO); // 容量
|
||||
pileStationInfo.setStationTel(dto.getStationTel());
|
||||
pileStationInfo.setStationAdminName(dto.getStationAdminName());
|
||||
// 获取经纬度
|
||||
Map<String, String> longitudeAndLatitude = AddressUtils.getLongitudeAndLatitude(dto.getAreaCode(), dto.getAddress());
|
||||
if (longitudeAndLatitude != null) {
|
||||
pileStationInfo.setStationLng(longitudeAndLatitude.get("lng"));
|
||||
pileStationInfo.setStationLat(longitudeAndLatitude.get("lat"));
|
||||
}
|
||||
pileStationInfo.setCreateBy(SecurityUtils.getUsername());
|
||||
int i = pileStationInfoMapper.insertPileStationInfo(pileStationInfo);
|
||||
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改充电站信息
|
||||
*
|
||||
* @param pileStationInfo 充电站信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updatePileStationInfo(PileStationInfo pileStationInfo) {
|
||||
pileStationInfo.setUpdateBy(SecurityUtils.getUsername());
|
||||
pileStationInfo.setUpdateTime(DateUtils.getNowDate());
|
||||
return pileStationInfoMapper.updatePileStationInfo(pileStationInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除充电站信息
|
||||
*
|
||||
* @param ids 需要删除的充电站信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deletePileStationInfoByIds(Long[] ids) {
|
||||
return pileStationInfoMapper.deletePileStationInfoByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 充电站列表信息
|
||||
* @param dto 前台参数
|
||||
* @return 充电站对象集合
|
||||
*/
|
||||
@Override
|
||||
@DataScope(deptAlias = "t3")
|
||||
public List<PileStationVO> queryStationInfos(QueryStationDTO dto) {
|
||||
List<PileStationVO> list = pileStationInfoMapper.queryStationInfos(dto);
|
||||
// if (Objects.nonNull(list)){
|
||||
// for (PileStationVO p:list) {
|
||||
// String station_type = p.getStationType();
|
||||
// p.setStationType(DictUtils.getDictLabel("station_type", station_type));
|
||||
// }
|
||||
// }
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* uniApp查询充电站信息并通过经纬度排序
|
||||
*
|
||||
* @param dto 前台参数
|
||||
* @return 充电站对象集合
|
||||
*/
|
||||
@Override
|
||||
public PageResponse uniAppQueryStationInfoList(QueryStationDTO dto) {
|
||||
int pageNum = dto.getPageNum() == 0 ? 1 : dto.getPageNum();
|
||||
int pageSize = dto.getPageSize() == 0 ? 10 : dto.getPageSize();
|
||||
|
||||
// 小程序站点列表页只展示对外开放的站点
|
||||
dto.setPublicFlag(Constants.ONE);
|
||||
// 根据前台参数分页
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<PileStationVO> list = pileStationInfoMapper.queryStationInfos(dto);
|
||||
PageInfo<PileStationVO> pageInfo = new PageInfo<>(list);
|
||||
if (CollectionUtils.isEmpty(pageInfo.getList())) {
|
||||
return PageResponse.builder()
|
||||
.pageNum(pageInfo.getPageNum())
|
||||
.pageSize(pageInfo.getPageSize())
|
||||
.list(Lists.newArrayList())
|
||||
.pages(pageInfo.getPages())
|
||||
.total(pageInfo.getTotal())
|
||||
.build();
|
||||
}
|
||||
|
||||
List<StationInfoVO> stationVOList = Lists.newArrayList();
|
||||
StationInfoVO stationVO = null;
|
||||
String stationLng = dto.getStationLng();
|
||||
String stationLat = dto.getStationLat();
|
||||
double distance = 0d;
|
||||
for (PileStationVO pileStationVO : pageInfo.getList()) {
|
||||
stationVO = new StationInfoVO();
|
||||
if (StringUtils.isNotEmpty(stationLng) && StringUtils.isNotEmpty(stationLat)) {
|
||||
try{
|
||||
// 计算当前经纬度和站点之间的距离
|
||||
distance = DistanceUtils.getDistance(Double.parseDouble(stationLng), Double.parseDouble(stationLat),
|
||||
Double.parseDouble(pileStationVO.getStationLng()), Double.parseDouble(pileStationVO.getStationLat()));
|
||||
// 保留两位小数
|
||||
stationVO.setDistance(String.format("%.2f", distance));
|
||||
}catch (Exception e){
|
||||
stationVO.setDistance("0.00");
|
||||
}
|
||||
|
||||
}
|
||||
stationVO.setStationId(pileStationVO.getId());
|
||||
stationVO.setStationName(pileStationVO.getStationName());
|
||||
stationVO.setStationAddress(pileStationVO.getAddress());
|
||||
stationVO.setStationLat(pileStationVO.getStationLat());
|
||||
stationVO.setStationLng(pileStationVO.getStationLng());
|
||||
|
||||
// 站点图片
|
||||
if (StringUtils.isNotBlank(pileStationVO.getPictures())) {
|
||||
stationVO.setStationImgList(Lists.newArrayList(pileStationVO.getPictures().split(",")));
|
||||
}
|
||||
// 枪口数量
|
||||
int fastTotal = 0;
|
||||
int fastFree = 0;
|
||||
int slowTotal = 0;
|
||||
int slowFree = 0;
|
||||
List<ConnectorInfoVO> connectorList = pileConnectorInfoService.getUniAppConnectorList(Long.parseLong(pileStationVO.getId()));
|
||||
for (ConnectorInfoVO connectorVO : connectorList) {
|
||||
if (StringUtils.equals(connectorVO.getChargingType(), Constants.ONE)) {
|
||||
// 快充
|
||||
fastTotal += 1;
|
||||
if (StringUtils.equals(connectorVO.getConnectorStatus(), Constants.ONE)) {
|
||||
fastFree += 1;
|
||||
}
|
||||
} else {
|
||||
// 慢充
|
||||
slowTotal += 1;
|
||||
if (StringUtils.equals(connectorVO.getConnectorStatus(), Constants.ONE)) {
|
||||
slowFree += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
stationVO.setFastTotal(fastTotal);
|
||||
stationVO.setFastFree(fastFree);
|
||||
stationVO.setSlowTotal(slowTotal);
|
||||
stationVO.setSlowFree(slowFree);
|
||||
|
||||
// 查询当前时段电费
|
||||
CurrentTimePriceDetails currentTimePriceDetails = pileBillingTemplateService.getCurrentTimePriceDetails(stationVO.getStationId());
|
||||
if (currentTimePriceDetails != null) {
|
||||
stationVO.setElectricityPrice(currentTimePriceDetails.getElectricityPrice());
|
||||
stationVO.setServicePrice(currentTimePriceDetails.getServicePrice());
|
||||
stationVO.setTotalPrice(currentTimePriceDetails.getTotalPrice());
|
||||
}
|
||||
stationVOList.add(stationVO);
|
||||
}
|
||||
|
||||
if (distance != 0.00) {
|
||||
// 对集合按照距离排序,距离小的在前
|
||||
stationVOList.sort((o1, o2) -> {
|
||||
Double a = Double.valueOf(o1.getDistance());
|
||||
Double b = Double.valueOf(o2.getDistance());
|
||||
return a.compareTo(b);
|
||||
});
|
||||
}
|
||||
|
||||
// 返回结果集
|
||||
return PageResponse.builder()
|
||||
.pageNum(pageInfo.getPageNum())
|
||||
.pageSize(pageInfo.getPageSize())
|
||||
.list(stationVOList)
|
||||
.pages(pageInfo.getPages())
|
||||
.total(pageInfo.getTotal())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.jsowell.common.enums.MemberWalletEnum;
|
||||
import com.jsowell.common.enums.ykc.ActionTypeEnum;
|
||||
import com.jsowell.common.enums.ykc.PayModeEnum;
|
||||
import com.jsowell.common.enums.ykc.ScenarioEnum;
|
||||
import com.jsowell.common.util.DateUtils;
|
||||
import com.jsowell.common.util.StringUtils;
|
||||
import com.jsowell.common.util.id.SnowflakeIdWorker;
|
||||
import com.jsowell.pile.domain.MemberTransactionRecord;
|
||||
import com.jsowell.pile.domain.WxpayCallbackRecord;
|
||||
import com.jsowell.pile.domain.WxpayRefundCallback;
|
||||
import com.jsowell.pile.dto.PaymentScenarioDTO;
|
||||
import com.jsowell.pile.dto.WeixinPayDTO;
|
||||
import com.jsowell.pile.service.IMemberBasicInfoService;
|
||||
import com.jsowell.pile.service.IMemberTransactionRecordService;
|
||||
import com.jsowell.pile.service.WechatPayService;
|
||||
import com.jsowell.pile.service.WxpayCallbackRecordService;
|
||||
import com.jsowell.pile.service.WxpayRefundCallbackService;
|
||||
import com.jsowell.pile.vo.web.UpdateMemberBalanceDTO;
|
||||
import com.jsowell.wxpay.common.WeChatPayParameter;
|
||||
import com.jsowell.wxpay.response.WechatPayNotifyParameter;
|
||||
import com.jsowell.wxpay.response.WechatPayNotifyResource;
|
||||
import com.jsowell.wxpay.response.WechatPayRefundNotifyResource;
|
||||
import com.jsowell.wxpay.response.WechatPayRefundRequest;
|
||||
import com.jsowell.wxpay.response.WechatPayRefundResponse;
|
||||
import com.jsowell.wxpay.utils.AesUtil;
|
||||
import com.jsowell.wxpay.utils.HttpUtils;
|
||||
import com.jsowell.wxpay.utils.WechatPayUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.math.BigDecimal;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 微信支付
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class WechatPayServiceImpl implements WechatPayService {
|
||||
|
||||
@Autowired
|
||||
private WxpayCallbackRecordService wxpayCallbackRecordService;
|
||||
|
||||
@Autowired
|
||||
private WxpayRefundCallbackService wxpayRefundCallbackService;
|
||||
|
||||
@Autowired
|
||||
private IMemberBasicInfoService memberBasicInfoService;
|
||||
|
||||
@Autowired
|
||||
private IMemberTransactionRecordService memberTransactionRecordService;
|
||||
|
||||
@Override
|
||||
public Map<String, Object> weixinPayV3(WeixinPayDTO dto) throws Exception {
|
||||
String openId = dto.getOpenId();
|
||||
//封装请求参数
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
// 支付的产品(小程序或者公众号,主要需要和微信支付绑定哦)
|
||||
paramMap.put("appid", WeChatPayParameter.appId);
|
||||
// 支付的商户号
|
||||
paramMap.put("mchid", WeChatPayParameter.mchId);
|
||||
// 商品描述
|
||||
paramMap.put("description", dto.getDescription());
|
||||
// 商户订单号
|
||||
paramMap.put("out_trade_no", SnowflakeIdWorker.getSnowflakeId());
|
||||
// 交易结束时间
|
||||
paramMap.put("time_expire", getTimeExpire());
|
||||
// 附加数据
|
||||
paramMap.put("attach", dto.getAttach());
|
||||
// 通知地址
|
||||
paramMap.put("notify_url", WeChatPayParameter.notifyUrl);
|
||||
|
||||
Map<String, Object> amountMap = Maps.newHashMap();
|
||||
//订单金额 单位分
|
||||
amountMap.put("total", Integer.parseInt(getMoney(dto.getAmount())));
|
||||
amountMap.put("currency", "CNY");
|
||||
paramMap.put("amount", amountMap);
|
||||
// 设置小程序所需的openid
|
||||
Map<String, Object> payerMap = Maps.newHashMap();
|
||||
payerMap.put("openid", openId);
|
||||
paramMap.put("payer", payerMap);
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String body = objectMapper.writeValueAsString(paramMap);
|
||||
log.info("支付的相关参数是:{}", body);
|
||||
|
||||
Map<String, Object> stringObjectMap = HttpUtils.doPostWexin(WeChatPayParameter.unifiedOrderUrlJS, body);
|
||||
try {
|
||||
return WechatPayUtils.getTokenWeixin(WeChatPayParameter.appId, String.valueOf(stringObjectMap.get("prepay_id")));
|
||||
} catch (Exception e) {
|
||||
log.error("微信支付v3 error", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取过期时间
|
||||
* @return
|
||||
*/
|
||||
private String getTimeExpire() {
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
currentTimeMillis = currentTimeMillis + (30 * 60 * 1000);
|
||||
return DateUtils.timeStampToRfc3339(currentTimeMillis);
|
||||
}
|
||||
|
||||
/**
|
||||
* 元转换成分
|
||||
*
|
||||
* @param amount
|
||||
* @return
|
||||
*/
|
||||
public static String getMoney(String amount) {
|
||||
if (amount == null) {
|
||||
return "";
|
||||
}
|
||||
// 金额转化为分为单位
|
||||
// 处理包含, ¥ 或者$的金额
|
||||
String currency = amount.replaceAll("\\$|\\¥|\\,", "");
|
||||
int index = currency.indexOf(".");
|
||||
int length = currency.length();
|
||||
Long amLong = 0L;
|
||||
if (index == -1) {
|
||||
amLong = Long.valueOf(currency + "00");
|
||||
} else if (length - index >= 3) {
|
||||
amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
|
||||
} else if (length - index == 2) {
|
||||
amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
|
||||
} else {
|
||||
amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
|
||||
}
|
||||
return amLong.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付回调
|
||||
* @param request
|
||||
* @param body
|
||||
* @throws Exception
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> wechatPayCallbackInfo(HttpServletRequest request, WechatPayNotifyParameter body) throws Exception {
|
||||
Map<String, Object> resultMap = Maps.newHashMap();
|
||||
//1:获取微信支付回调的获取签名信息
|
||||
String timestamp = request.getHeader("Wechatpay-Timestamp");
|
||||
String nonce = request.getHeader("Wechatpay-Nonce");
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
// 2: 开始解析报文体
|
||||
String data = objectMapper.writeValueAsString(body);
|
||||
String message = timestamp + "\n" + nonce + "\n" + data + "\n";
|
||||
//3:获取应答签名
|
||||
String sign = request.getHeader("Wechatpay-Signature");
|
||||
//4:获取平台对应的证书
|
||||
String serialNo = request.getHeader("Wechatpay-Serial");
|
||||
if (!WeChatPayParameter.certificateMap.containsKey(serialNo)) {
|
||||
WeChatPayParameter.certificateMap = WechatPayUtils.refreshCertificate();
|
||||
}
|
||||
X509Certificate x509Certificate = WeChatPayParameter.certificateMap.get(serialNo);
|
||||
if (!WechatPayUtils.verify(x509Certificate, message.getBytes(), sign)) {
|
||||
throw new IllegalArgumentException("微信支付签名验证失败:" + message);
|
||||
}
|
||||
// log.info("签名验证成功");
|
||||
WechatPayNotifyParameter.Resource resource = body.getResource();
|
||||
// 5:回调报文解密
|
||||
AesUtil aesUtil = new AesUtil(WeChatPayParameter.v3Key.getBytes());
|
||||
// 解密后json字符串
|
||||
String decryptToString = aesUtil.decryptToString(
|
||||
resource.getAssociated_data().getBytes(),
|
||||
resource.getNonce().getBytes(),
|
||||
resource.getCiphertext());
|
||||
log.info("2-->decryptToString====>{}", decryptToString);
|
||||
|
||||
//6:获取微信支付返回的信息
|
||||
WechatPayNotifyResource wechatPayNotifyResource = JSON.parseObject(decryptToString, WechatPayNotifyResource.class);
|
||||
//7: 支付状态的判断 如果是success就代表支付成功
|
||||
if (StringUtils.equals(wechatPayNotifyResource.getTrade_state(), "SUCCESS")) {
|
||||
// 8:获取支付的交易单号,流水号,和附属参数
|
||||
String out_trade_no = wechatPayNotifyResource.getOut_trade_no();
|
||||
// 微信支付单号
|
||||
String transaction_id = wechatPayNotifyResource.getTransaction_id();
|
||||
String attach = wechatPayNotifyResource.getAttach();
|
||||
log.info("3-->微信支付成功,商户订单号是:{}, 支付订单号:{}, 附属参数是:{}", out_trade_no, transaction_id, attach);
|
||||
// 转换附属参数
|
||||
PaymentScenarioDTO paymentScenarioDTO = JSONObject.parseObject(attach, PaymentScenarioDTO.class);
|
||||
String type = paymentScenarioDTO.getType();
|
||||
BigDecimal amount = new BigDecimal(wechatPayNotifyResource.getAmount().getTotal());
|
||||
if (StringUtils.equals(type, ScenarioEnum.ORDER.getValue())) {
|
||||
// 1-订单支付
|
||||
resultMap.put("orderCode", paymentScenarioDTO.getOrderCode());
|
||||
resultMap.put("memberId", paymentScenarioDTO.getMemberId());
|
||||
resultMap.put("amount", amount);
|
||||
resultMap.put("type", type);
|
||||
} else if (StringUtils.equals(type, ScenarioEnum.BALANCE.getValue())) {
|
||||
// 2-充值余额
|
||||
resultMap.put("memberId", paymentScenarioDTO.getMemberId());
|
||||
resultMap.put("amount", amount);
|
||||
resultMap.put("type", type);
|
||||
}
|
||||
resultMap.put("out_trade_no", out_trade_no);
|
||||
resultMap.put("transaction_id", transaction_id);
|
||||
// 保存微信支付记录
|
||||
WxpayCallbackRecord record = new WxpayCallbackRecord();
|
||||
record.setPayScenario(type);
|
||||
record.setMemberId(paymentScenarioDTO.getMemberId());
|
||||
record.setOrderCode(paymentScenarioDTO.getOrderCode());
|
||||
record.setOutTradeNo(out_trade_no);
|
||||
record.setTransactionId(transaction_id);
|
||||
record.setMchId(wechatPayNotifyResource.getMchid());
|
||||
record.setAppId(wechatPayNotifyResource.getAppid());
|
||||
record.setTradeType(wechatPayNotifyResource.getTrade_type());
|
||||
record.setTradeState(wechatPayNotifyResource.getTrade_state());
|
||||
record.setTradeStateDesc(wechatPayNotifyResource.getTrade_state_desc());
|
||||
record.setBankType(wechatPayNotifyResource.getBank_type());
|
||||
record.setAttach(wechatPayNotifyResource.getAttach());
|
||||
record.setSuccessTime(DateUtils.toLocalDateTime(wechatPayNotifyResource.getSuccess_time(), DateUtils.RFC3339));
|
||||
record.setPayerOpenId(wechatPayNotifyResource.getPayer().getOpenid());
|
||||
record.setPayerTotal(wechatPayNotifyResource.getAmount().getPayer_total());
|
||||
wxpayCallbackRecordService.insertSelective(record);
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取微信退款回调信息
|
||||
*
|
||||
* @param request
|
||||
* @param body
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> wechatPayRefundCallbackInfo(HttpServletRequest request, WechatPayNotifyParameter body) throws Exception {
|
||||
//1:获取微信支付回调的获取签名信息
|
||||
String timestamp = request.getHeader("Wechatpay-Timestamp");
|
||||
String nonce = request.getHeader("Wechatpay-Nonce");
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
// 2: 开始解析报文体
|
||||
String data = objectMapper.writeValueAsString(body);
|
||||
String message = timestamp + "\n" + nonce + "\n" + data + "\n";
|
||||
//3:获取应答签名
|
||||
String sign = request.getHeader("Wechatpay-Signature");
|
||||
//4:获取平台对应的证书
|
||||
String serialNo = request.getHeader("Wechatpay-Serial");
|
||||
if (!WeChatPayParameter.certificateMap.containsKey(serialNo)) {
|
||||
WeChatPayParameter.certificateMap = WechatPayUtils.refreshCertificate();
|
||||
}
|
||||
X509Certificate x509Certificate = WeChatPayParameter.certificateMap.get(serialNo);
|
||||
if (!WechatPayUtils.verify(x509Certificate, message.getBytes(), sign)) {
|
||||
throw new IllegalArgumentException("微信支付签名验证失败:" + message);
|
||||
}
|
||||
// log.info("签名验证成功");
|
||||
WechatPayNotifyParameter.Resource resource = body.getResource();
|
||||
// 5:回调报文解密
|
||||
AesUtil aesUtil = new AesUtil(WeChatPayParameter.v3Key.getBytes());
|
||||
// 解密后json字符串
|
||||
String decryptToString = aesUtil.decryptToString(
|
||||
resource.getAssociated_data().getBytes(),
|
||||
resource.getNonce().getBytes(),
|
||||
resource.getCiphertext());
|
||||
log.info("微信退款回调信息:{}", decryptToString);
|
||||
|
||||
WechatPayRefundNotifyResource refundNotifyResource = JSONObject.parseObject(decryptToString, WechatPayRefundNotifyResource.class);
|
||||
if (refundNotifyResource == null) {
|
||||
return null;
|
||||
}
|
||||
// 查询原支付信息,获取是订单结算退款还是余额退款
|
||||
String out_trade_no = refundNotifyResource.getOut_trade_no();
|
||||
String out_refund_no = refundNotifyResource.getOut_refund_no();
|
||||
String transaction_id = refundNotifyResource.getTransaction_id();
|
||||
String refund_id = refundNotifyResource.getRefund_id();
|
||||
|
||||
WxpayCallbackRecord wxpayCallbackRecord = wxpayCallbackRecordService.selectByOutTradeNo(out_trade_no);
|
||||
if (wxpayCallbackRecord == null) {
|
||||
log.info("查询原支付信息为空 OutTradeNo:{}", out_trade_no);
|
||||
return null;
|
||||
}
|
||||
|
||||
String memberId = wxpayCallbackRecord.getMemberId();
|
||||
String orderCode = wxpayCallbackRecord.getOrderCode();
|
||||
// 退款金额 单位分
|
||||
int payer_refund = refundNotifyResource.getAmount().getPayer_refund();
|
||||
// 分转成元
|
||||
BigDecimal refundAmount = new BigDecimal(payer_refund).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
|
||||
if (StringUtils.equals(wxpayCallbackRecord.getPayScenario(), ScenarioEnum.BALANCE.getValue())) {
|
||||
// 这笔支付订单原来是充值余额的,退款成功了,需要扣掉会员的本金金额
|
||||
UpdateMemberBalanceDTO dto = new UpdateMemberBalanceDTO();
|
||||
dto.setMemberId(memberId);
|
||||
dto.setUpdatePrincipalBalance(refundAmount); // 更新会员本金金额,单位元
|
||||
dto.setType(MemberWalletEnum.TYPE_OUT.getValue());
|
||||
dto.setSubType(MemberWalletEnum.SUBTYPE_USER_REFUND.getValue());
|
||||
memberBasicInfoService.updateMemberBalance(dto);
|
||||
}
|
||||
|
||||
// 保存微信退款回调信息
|
||||
WxpayRefundCallback record = WxpayRefundCallback.builder()
|
||||
.memberId(memberId)
|
||||
.orderCode(orderCode)
|
||||
.outTradeNo(out_trade_no)
|
||||
.outRefundNo(out_refund_no)
|
||||
.transactionId(transaction_id)
|
||||
.mchId(refundNotifyResource.getMchid())
|
||||
.refundId(refund_id)
|
||||
.refundStatus(refundNotifyResource.getRefund_status())
|
||||
.successTime(refundNotifyResource.getSuccess_time())
|
||||
.userReceivedAccount(refundNotifyResource.getUser_received_account())
|
||||
.payerTotal(refundNotifyResource.getAmount().getPayer_total() + "")
|
||||
.payerRefund(payer_refund + "") // 微信支付接收单位分
|
||||
.amountTotal(refundNotifyResource.getAmount().getTotal() + "")
|
||||
.amountRefund(refundNotifyResource.getAmount().getRefund() + "")
|
||||
.build();
|
||||
wxpayRefundCallbackService.insertSelective(record);
|
||||
|
||||
// 余额支付订单 记录会员交易流水
|
||||
MemberTransactionRecord memberTransactionRecord = MemberTransactionRecord.builder()
|
||||
.orderCode(orderCode)
|
||||
.scenarioType(wxpayCallbackRecord.getPayScenario())
|
||||
.memberId(memberId)
|
||||
.actionType(ActionTypeEnum.REVERSE.getValue())
|
||||
.payMode(PayModeEnum.PAYMENT_OF_WECHATPAY.getValue())
|
||||
.amount(refundAmount) // 记录会员交易流水,单位元
|
||||
.outTradeNo(out_trade_no)
|
||||
.transactionId(transaction_id)
|
||||
.outRefundNo(out_refund_no)
|
||||
.refundId(refund_id)
|
||||
.build();
|
||||
memberTransactionRecordService.insertSelective(memberTransactionRecord);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付 申请退款接口
|
||||
*/
|
||||
@Override
|
||||
public WechatPayRefundResponse ApplyForWechatPayRefundV3(WechatPayRefundRequest request) throws JsonProcessingException {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String body = objectMapper.writeValueAsString(request);
|
||||
log.info("申请退款的相关参数是:{}", body);
|
||||
Map<String, Object> stringObjectMap = HttpUtils.doPostWexin(WeChatPayParameter.refundJsUrl, body);
|
||||
log.info("申请退款的返回参数是:{}", stringObjectMap);
|
||||
return JSON.parseObject(JSON.toJSONString(stringObjectMap), WechatPayRefundResponse.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.jsowell.pile.domain.WxpayCallbackRecord;
|
||||
import com.jsowell.pile.mapper.WxpayCallbackRecordMapper;
|
||||
import com.jsowell.pile.service.WxpayCallbackRecordService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class WxpayCallbackRecordServiceImpl implements WxpayCallbackRecordService {
|
||||
|
||||
@Resource
|
||||
private WxpayCallbackRecordMapper wxpayCallbackRecordMapper;
|
||||
|
||||
@Override
|
||||
public int deleteByPrimaryKey(Integer id) {
|
||||
return wxpayCallbackRecordMapper.deleteByPrimaryKey(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insert(WxpayCallbackRecord record) {
|
||||
return wxpayCallbackRecordMapper.insert(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertSelective(WxpayCallbackRecord record) {
|
||||
return wxpayCallbackRecordMapper.insertSelective(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxpayCallbackRecord selectByPrimaryKey(Integer id) {
|
||||
return wxpayCallbackRecordMapper.selectByPrimaryKey(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateByPrimaryKeySelective(WxpayCallbackRecord record) {
|
||||
return wxpayCallbackRecordMapper.updateByPrimaryKeySelective(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateByPrimaryKey(WxpayCallbackRecord record) {
|
||||
return wxpayCallbackRecordMapper.updateByPrimaryKey(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxpayCallbackRecord selectByOrderCode(String orderCode) {
|
||||
WxpayCallbackRecord wxpayCallbackRecord = null;
|
||||
try {
|
||||
wxpayCallbackRecord = wxpayCallbackRecordMapper.selectByOrderCode(orderCode);
|
||||
} catch (Exception e) {
|
||||
log.error("根据订单号查询微信支付记录:{}", orderCode, e);
|
||||
}
|
||||
return wxpayCallbackRecord;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxpayCallbackRecord selectByOutTradeNo(String outTradeNo) {
|
||||
return wxpayCallbackRecordMapper.selectByOutTradeNo(outTradeNo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WxpayCallbackRecord> queryBalanceRechargeRecordOfTheLatestYear(String memberId) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDate localDate = now.minusYears(1).toLocalDate();
|
||||
LocalTime localTime = now.toLocalTime();
|
||||
LocalDateTime lastYear = LocalDateTime.of(localDate, localTime);
|
||||
// 查询最近一年的余额充值记录
|
||||
return wxpayCallbackRecordMapper.selectBalanceRechargeRecord(memberId, lastYear);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDate localDate = now.minusYears(1).toLocalDate();
|
||||
LocalTime localTime = now.toLocalTime();
|
||||
LocalDateTime of = LocalDateTime.of(localDate, localTime);
|
||||
System.out.println(of);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.jsowell.pile.service.impl;
|
||||
|
||||
import com.jsowell.pile.domain.WxpayRefundCallback;
|
||||
import com.jsowell.pile.mapper.WxpayRefundCallbackMapper;
|
||||
import com.jsowell.pile.service.WxpayRefundCallbackService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class WxpayRefundCallbackServiceImpl implements WxpayRefundCallbackService {
|
||||
|
||||
@Resource
|
||||
private WxpayRefundCallbackMapper wxpayRefundCallbackMapper;
|
||||
|
||||
@Override
|
||||
public int deleteByPrimaryKey(Integer id) {
|
||||
return wxpayRefundCallbackMapper.deleteByPrimaryKey(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertSelective(WxpayRefundCallback record) {
|
||||
return wxpayRefundCallbackMapper.insertSelective(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxpayRefundCallback selectByPrimaryKey(Integer id) {
|
||||
return wxpayRefundCallbackMapper.selectByPrimaryKey(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateByPrimaryKeySelective(WxpayRefundCallback record) {
|
||||
return wxpayRefundCallbackMapper.updateByPrimaryKeySelective(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateByPrimaryKey(WxpayRefundCallback record) {
|
||||
return wxpayRefundCallbackMapper.updateByPrimaryKey(record);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user