2023-03-04 16:29:55 +08:00
package com.jsowell.service ;
import com.github.pagehelper.PageHelper ;
import com.github.pagehelper.PageInfo ;
import com.google.common.collect.Lists ;
import com.jsowell.common.constant.Constants ;
import com.jsowell.common.core.domain.ykc.RealTimeMonitorData ;
import com.jsowell.common.core.page.PageResponse ;
import com.jsowell.common.enums.ykc.BusinessTypeEnum ;
2023-03-11 10:32:18 +08:00
import com.jsowell.common.enums.ykc.OrderPayModeEnum ;
2023-03-04 16:29:55 +08:00
import com.jsowell.common.enums.ykc.OrderStatusEnum ;
import com.jsowell.common.enums.ykc.ReturnCodeEnum ;
import com.jsowell.common.exception.BusinessException ;
import com.jsowell.common.response.RestApiResponse ;
import com.jsowell.common.util.DateUtils ;
import com.jsowell.common.util.SecurityUtils ;
import com.jsowell.common.util.StringUtils ;
import com.jsowell.common.util.id.SnUtils ;
import com.jsowell.pile.domain.* ;
import com.jsowell.pile.dto.BatchCreatePileDTO ;
import com.jsowell.pile.dto.MemberRegisterAndLoginDTO ;
import com.jsowell.pile.dto.PileMemberBindingDTO ;
import com.jsowell.pile.dto.QueryPersonPileDTO ;
import com.jsowell.pile.service.* ;
import com.jsowell.pile.transaction.dto.PileTransactionDTO ;
import com.jsowell.pile.transaction.service.TransactionService ;
import com.jsowell.pile.vo.base.ConnectorInfoVO ;
import com.jsowell.pile.vo.base.MerchantInfoVO ;
import com.jsowell.pile.vo.base.PileInfoVO ;
import com.jsowell.pile.vo.uniapp.* ;
import com.jsowell.pile.vo.web.PileStationVO ;
import org.apache.commons.collections4.CollectionUtils ;
2023-03-13 17:01:07 +08:00
import org.apache.commons.lang3.RandomStringUtils ;
2023-03-04 16:29:55 +08:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.stereotype.Service ;
import javax.annotation.Resource ;
import java.math.BigDecimal ;
import java.util.* ;
import java.util.concurrent.CompletableFuture ;
import java.util.concurrent.ExecutionException ;
import java.util.stream.Collectors ;
@Service
public class PileService {
private final Logger log = LoggerFactory . getLogger ( this . getClass ( ) ) ;
@Autowired
private TransactionService pileTransactionService ;
@Resource
private SnUtils snUtils ;
@Autowired
private IPileBasicInfoService pileBasicInfoService ;
@Autowired
private IPileConnectorInfoService pileConnectorInfoService ;
@Autowired
private IPileStationInfoService pileStationInfoService ;
@Autowired
private IPileMerchantInfoService pileMerchantInfoService ;
@Autowired
private IPileBillingTemplateService pileBillingTemplateService ;
@Autowired
private IPileMemberRelationService pileMemberRelationService ;
@Autowired
private IMemberBasicInfoService memberBasicInfoService ;
@Autowired
private MemberService memberService ;
@Autowired
private IOrderBasicInfoService orderBasicInfoService ;
/ * *
* 查询设备信息
*
* @param pileConnectorCode 充电枪编号 880000000000000101
* @return 设备信息集合
* /
public PileConnectorDetailVO queryPileConnectorDetail ( String pileConnectorCode ) {
return pileBasicInfoService . queryPileConnectorDetail ( pileConnectorCode ) ;
}
/ * *
* 查询设备信息
*
* @param pileSn 充电枪编号 8800000000000001
* @param connectorCode 充电枪口号 01
* @return 设备信息集合
* /
public PileConnectorDetailVO queryPileConnectorDetail ( String pileSn , String connectorCode ) {
return queryPileConnectorDetail ( pileSn + connectorCode ) ;
}
public int batchCreatePile ( BatchCreatePileDTO dto ) {
// 批量生成sn号
List < String > snList = snUtils . generateSN ( dto . getNum ( ) ) ;
//
List < PileBasicInfo > basicInfoList = Lists . newArrayList ( ) ;
List < PileConnectorInfo > connectorInfoList = Lists . newArrayList ( ) ;
PileBasicInfo basicInfo = null ;
PileConnectorInfo connectorInfo = null ;
for ( String sn : snList ) {
// 组装pile_basic_info表数据
basicInfo = new PileBasicInfo ( ) ;
basicInfo . setSn ( sn ) ; // sn号
2023-03-13 17:01:07 +08:00
basicInfo . setBusinessType ( dto . getChargerPileType ( ) ) ; // 经营类型 1-运营桩; 2-个人桩
if ( StringUtils . equals ( BusinessTypeEnum . INDIVIDUAL_PILE . getValue ( ) , dto . getChargerPileType ( ) ) ) {
// 个人桩生成一个八位的密钥(字母加数字)
String secretKey = RandomStringUtils . randomAlphanumeric ( 8 ) . toUpperCase ( Locale . ROOT ) ;
basicInfo . setSecretKey ( secretKey ) ;
}
2023-03-04 16:29:55 +08:00
basicInfo . setSoftwareProtocol ( dto . getSoftwareProtocol ( ) ) ; // 软件协议
basicInfo . setMerchantId ( Long . valueOf ( dto . getMerchantId ( ) ) ) ; // 运营商id
basicInfo . setStationId ( Long . valueOf ( dto . getStationId ( ) ) ) ; // 站点id
basicInfo . setModelId ( Long . valueOf ( dto . getModelId ( ) ) ) ; // 型号id
basicInfo . setProductionDate ( dto . getProductionDate ( ) ) ; // 生产日期
basicInfo . setLicenceId ( null ) ; // TODO 证书编号
basicInfo . setSimId ( null ) ; // TODO sim卡
basicInfo . setRemark ( dto . getRemark ( ) ) ; // 备注
basicInfo . setCreateBy ( SecurityUtils . getUsername ( ) ) ; // 创建人
basicInfo . setDelFlag ( Constants . DEL_FLAG_NORMAL ) ; // 删除标识
basicInfoList . add ( basicInfo ) ;
for ( int i = 1 ; i < dto . getConnectorNum ( ) + 1 ; i + + ) {
// 组装pile_connector_info表数据
connectorInfo = new PileConnectorInfo ( ) ;
connectorInfo . setPileSn ( sn ) ; // sn号
String connectorCode = String . format ( " %1$02d " , i ) ;
connectorInfo . setPileConnectorCode ( sn + connectorCode ) ; // 枪口号
connectorInfo . setStatus ( Constants . ZERO ) ; //状态,默认 0-离网
connectorInfo . setCreateBy ( SecurityUtils . getUsername ( ) ) ; // 创建人
connectorInfo . setDelFlag ( Constants . DEL_FLAG_NORMAL ) ; // 删除标识
connectorInfoList . add ( connectorInfo ) ;
}
}
// 批量入库
PileTransactionDTO transactionDTO = PileTransactionDTO . builder ( )
. pileBasicInfoList ( basicInfoList )
. pileConnectorInfoList ( connectorInfoList )
. build ( ) ;
return pileTransactionService . doCreatePileTransaction ( transactionDTO ) ;
}
/ * *
* 前端扫码跳转接口
* /
public PileConnectorVO getPileDetailByPileSn ( String param ) throws ExecutionException , InterruptedException {
if ( StringUtils . isBlank ( param ) ) {
throw new BusinessException ( ReturnCodeEnum . CODE_PARAM_NOT_NULL_ERROR ) ;
}
String pileSn ;
if ( param . length ( ) = = 16 ) {
pileSn = StringUtils . substring ( param , 0 , param . length ( ) - 2 ) ;
} else {
pileSn = param ;
}
// 查询充电桩信息
PileInfoVO pileInfoVO = pileBasicInfoService . selectPileInfoBySn ( pileSn ) ;
if ( pileInfoVO = = null ) {
return null ;
}
// 查询充电桩下枪口信息
CompletableFuture < List < ConnectorInfoVO > > connectorInfoListFuture = CompletableFuture . supplyAsync ( ( ) - > pileConnectorInfoService . selectConnectorInfoList ( pileSn ) ) ;
// 查计费模板信息
CompletableFuture < List < BillingPriceVO > > billingPriceFuture = CompletableFuture . supplyAsync ( ( ) - > pileBillingTemplateService . queryBillingPrice ( pileInfoVO . getStationId ( ) ) ) ;
// 查询站点信息
CompletableFuture < PileStationVO > pileStationVOFuture = CompletableFuture . supplyAsync ( ( ) - > pileStationInfoService . getStationInfo ( pileInfoVO . getStationId ( ) ) ) ;
// 查询运营商信息
CompletableFuture < MerchantInfoVO > merchantInfoVOFuture = CompletableFuture . supplyAsync ( ( ) - > pileMerchantInfoService . getMerchantInfo ( pileInfoVO . getMerchantId ( ) ) ) ;
CompletableFuture < Void > all = CompletableFuture . allOf ( connectorInfoListFuture , pileStationVOFuture , merchantInfoVOFuture , billingPriceFuture ) ;
// .join()和.get()都会阻塞并获取线程的执行情况
// .join()会抛出未经检查的异常,不会强制开发者处理异常 .get()会抛出检查异常,需要开发者处理
all . join ( ) ;
all . get ( ) ;
List < ConnectorInfoVO > connectorInfoList = connectorInfoListFuture . get ( ) ;
PileStationVO pileStationVO = pileStationVOFuture . get ( ) ;
MerchantInfoVO merchantInfoVO = merchantInfoVOFuture . get ( ) ;
List < BillingPriceVO > billingPriceVOS = billingPriceFuture . get ( ) ;
PileConnectorVO vo = PileConnectorVO . builder ( )
. pileInfo ( pileInfoVO )
. connectorInfoList ( connectorInfoList )
. merchantInfo ( merchantInfoVO )
. stationInfo ( pileStationVO )
. billingPriceList ( billingPriceVOS )
. build ( ) ;
return vo ;
}
public PileConnectorVO getConnectorDetail ( String pileConnectorCode ) throws ExecutionException , InterruptedException {
PileConnectorDetailVO pileConnectorDetailVO = queryPileConnectorDetail ( pileConnectorCode ) ;
if ( pileConnectorDetailVO = = null ) {
return null ;
}
String pileSn = pileConnectorDetailVO . getPileSn ( ) ;
PileConnectorVO resultVO = getPileDetailByPileSn ( pileSn ) ;
List < ConnectorInfoVO > connectorInfoList = resultVO . getConnectorInfoList ( ) ;
if ( connectorInfoList . size ( ) > 1 ) {
List < ConnectorInfoVO > list = Lists . newArrayList ( ) ;
// 枪口大于1个, 此充电桩非单枪设备, 根据参数展示对应枪口的信息
for ( ConnectorInfoVO connectorInfoVO : connectorInfoList ) {
if ( StringUtils . equals ( pileConnectorCode , pileSn + connectorInfoVO . getConnectorCode ( ) ) ) {
list . add ( connectorInfoVO ) ;
}
}
resultVO . setConnectorInfoList ( list ) ;
}
return resultVO ;
}
public PileInfoVO selectPileInfoBySn ( String pileSn ) {
return pileBasicInfoService . selectPileInfoBySn ( pileSn ) ;
}
/ * *
* 用户绑定个人桩
*
* @param dto
* @return
* /
public int pileMemberBinding ( PileMemberBindingDTO dto ) {
// 校验短信验证码
MemberRegisterAndLoginDTO registerAndLoginDTO = MemberRegisterAndLoginDTO . builder ( )
. mobileNumber ( dto . getPhoneNumber ( ) )
. verificationCode ( dto . getVerificationCode ( ) )
. build ( ) ;
memberService . checkVerificationCode ( registerAndLoginDTO ) ;
// 检查桩是否已经被绑定
PileMemberRelation pileMemberRelation = new PileMemberRelation ( ) ;
pileMemberRelation . setPileSn ( dto . getPileSn ( ) ) ;
List < PileMemberRelation > list = pileMemberRelationService . selectPileMemberRelationList ( pileMemberRelation ) ;
if ( CollectionUtils . isNotEmpty ( list ) ) {
// 说明已经被绑定过,抛出异常
throw new BusinessException ( ReturnCodeEnum . CODE_PILE_HAS_BEEN_BINDING_ERROR ) ;
}
2023-03-13 17:01:07 +08:00
// 如果没被绑定,先校验桩密钥是否一致
PileBasicInfo pileBasicInfo = pileBasicInfoService . selectPileBasicInfoBySN ( dto . getPileSn ( ) ) ;
if ( pileBasicInfo = = null ) {
// 未查到则说明没有此桩
throw new BusinessException ( ReturnCodeEnum . CODE_PILE_NOT_INFO ) ;
}
if ( ! StringUtils . equals ( pileBasicInfo . getSecretKey ( ) , dto . getSecretKey ( ) ) ) {
// 错误的密钥信息
throw new BusinessException ( ReturnCodeEnum . CODE_SECRET_KEY_ERROR ) ;
}
// 密钥正确,且桩未被绑定,则此用户为管理员
2023-03-04 16:29:55 +08:00
pileMemberRelation . setMemberId ( dto . getMemberId ( ) ) ;
pileMemberRelation . setType ( " 1 " ) ; // 1-管理员
return pileMemberRelationService . insertPileMemberRelation ( pileMemberRelation ) ;
}
/ * *
* 个人桩管理员下发给其他用户使用
*
* @param dto
* /
public void adminIssuePile ( PileMemberBindingDTO dto ) {
List < PileMemberRelation > relationList = pileMemberRelationService . selectPileMemberRelationByPileSn ( dto . getPileSn ( ) ) ;
if ( CollectionUtils . isEmpty ( relationList ) ) {
// 充电桩没有绑定任何人
}
List < String > adminList = relationList . stream ( )
. filter ( x - > x . getType ( ) . equals ( " 1 " ) )
. map ( PileMemberRelation : : getMemberId )
. collect ( Collectors . toList ( ) ) ;
if ( CollectionUtils . isEmpty ( adminList ) ) {
// 没有管理员
}
// 校验身份
if ( ! adminList . contains ( dto . getMemberId ( ) ) ) {
// 如果为空,说明此用户身份有误,不是管理员,抛出异常
throw new BusinessException ( ReturnCodeEnum . CODE_AUTHENTICATION_ERROR ) ;
}
List < String > userList = relationList . stream ( )
. filter ( x - > ! x . getType ( ) . equals ( " 1 " ) )
. map ( PileMemberRelation : : getMemberId )
. collect ( Collectors . toList ( ) ) ;
// 通过前端传的手机号查询是否有此用户
MemberBasicInfo memberBasicInfo = memberBasicInfoService . selectInfoByMobileNumber ( dto . getPhoneNumber ( ) ) ;
if ( memberBasicInfo = = null ) {
// 为空说明此用户未注册平台账号
throw new BusinessException ( ReturnCodeEnum . CODE_USER_IS_NOT_REGISTER ) ;
}
if ( userList . contains ( memberBasicInfo . getMemberId ( ) ) ) {
// 不为空说明已绑定
throw new BusinessException ( ReturnCodeEnum . CODE_USER_HAS_BEEN_THIS_PILE ) ;
} else {
// 进行绑定,此用户为普通用户
PileMemberRelation info = new PileMemberRelation ( ) ;
info . setPileSn ( dto . getPileSn ( ) ) ;
info . setMemberId ( memberBasicInfo . getMemberId ( ) ) ;
info . setType ( " 2 " ) ;
pileMemberRelationService . insertPileMemberRelation ( info ) ;
}
}
/ * *
* 获取枪口实时数据
* @param dto
* @return
* /
public PersonPileRealTimeVO getConnectorRealTimeInfo ( QueryPersonPileDTO dto ) {
// 根据memberId查出该用户 正在充电、个人桩启动(白名单支付方式)的订单号
OrderBasicInfo orderBasicInfo = OrderBasicInfo . builder ( )
. memberId ( dto . getMemberId ( ) )
. orderStatus ( OrderStatusEnum . IN_THE_CHARGING . getValue ( ) )
. pileConnectorCode ( dto . getPileConnectorCode ( ) )
2023-03-11 10:32:18 +08:00
. payMode ( OrderPayModeEnum . PAYMENT_OF_WHITELIST . getValue ( ) ) // 3- 白名单支付
2023-03-04 16:29:55 +08:00
. build ( ) ;
OrderBasicInfo basicInfo = orderBasicInfoService . getOrderBasicInfo ( orderBasicInfo ) ;
if ( basicInfo = = null ) {
throw new BusinessException ( ReturnCodeEnum . CODE_NO_CHARGING_ORDER_ERROR ) ;
}
String orderCode = basicInfo . getOrderCode ( ) ;
// 根据订单号从redis中获取实时数据信息(默认时间倒叙排列,所以取第一条)
List < RealTimeMonitorData > chargingRealTimeData = orderBasicInfoService . getChargingRealTimeData ( orderCode ) ;
if ( CollectionUtils . isEmpty ( chargingRealTimeData ) ) {
throw new BusinessException ( ReturnCodeEnum . CODE_NO_REAL_TIME_INFO ) ;
}
RealTimeMonitorData realTimeMonitorData = chargingRealTimeData . get ( 0 ) ;
// 将需要的数据set
PersonPileRealTimeVO vo = PersonPileRealTimeVO . builder ( )
. chargingDegree ( realTimeMonitorData . getChargingDegree ( ) )
. chargingTime ( realTimeMonitorData . getSumChargingTime ( ) )
. startTime ( DateUtils . formatDateTime ( orderBasicInfo . getChargeStartTime ( ) ) )
. instantCurrent ( realTimeMonitorData . getOutputCurrent ( ) )
. instantVoltage ( realTimeMonitorData . getOutputVoltage ( ) )
. instantPower ( realTimeMonitorData . getOutputPower ( ) )
. build ( ) ;
return vo ;
}
/ * *
* 获取某枪口某段时间内累计信息
* @param dto
* @return
* /
public PersonPileConnectorSumInfoVO getAccumulativeInfo ( QueryPersonPileDTO dto ) {
List < PersonPileConnectorSumInfoVO > accumulativeInfo = orderBasicInfoService . getAccumulativeInfo ( dto ) ;
if ( CollectionUtils . isEmpty ( accumulativeInfo ) ) {
2023-03-13 17:01:07 +08:00
throw new BusinessException ( ReturnCodeEnum . CODE_QUERY_ORDER_INFO_IS_NULL ) ;
2023-03-04 16:29:55 +08:00
}
// BigDecimal sumChargingTime = BigDecimal.ZERO;
// BigDecimal sumUsedElectricity = BigDecimal.ZERO;
// // 将返回的结果进行for循环, 将总充电量、总充电时长进行累加( 充电时长需要通过 充电开始时间 和 充电结束时间 进行计算)
// for (PersonPileConnectorSumInfoVO personPileConnectorSumInfoVO : accumulativeInfo) {
// if (StringUtils.isNotBlank(personPileConnectorSumInfoVO.getChargeStartTime()) && StringUtils.isNotBlank(personPileConnectorSumInfoVO.getChargeEndTime())){
// long longChargingTime = DateUtils.intervalTime(personPileConnectorSumInfoVO.getChargeStartTime(), personPileConnectorSumInfoVO.getChargeEndTime());
// BigDecimal chargingTime = new BigDecimal(String.valueOf(longChargingTime));
// sumChargingTime = sumChargingTime.add(chargingTime);
// }
// BigDecimal chargingDegree = StringUtils.isBlank(personPileConnectorSumInfoVO.getSumChargingDegree())
// ? BigDecimal.ZERO
// : new BigDecimal(personPileConnectorSumInfoVO.getSumChargingDegree());
// sumUsedElectricity = sumUsedElectricity.add(chargingDegree);
// }
Map < String , String > sumInfo = getSumInfo ( accumulativeInfo ) ;
// set 对象
PersonPileConnectorSumInfoVO vo = new PersonPileConnectorSumInfoVO ( ) ;
vo . setStartTime ( dto . getStartTime ( ) ) ;
vo . setEndTime ( dto . getEndTime ( ) ) ;
vo . setMemberId ( dto . getMemberId ( ) ) ;
vo . setSumChargingDegree ( sumInfo . get ( " sumUsedElectricity " ) ) ;
vo . setSumChargingTime ( sumInfo . get ( " sumChargingTime " ) ) ;
return vo ;
}
/ * *
* 获取充电记录 ( 默认30天 )
*
* @param dto
* /
public PageResponse getChargingRecord ( QueryPersonPileDTO dto ) {
int pageNum = dto . getPageNum ( ) = = 0 ? 1 : dto . getPageNum ( ) ;
int pageSize = dto . getPageSize ( ) = = 0 ? 10 : dto . getPageSize ( ) ;
// 获取三十天前的数据
Date date = DateUtils . addMonths ( new Date ( ) , - 1 ) ;
String dateStr = DateUtils . parseDateToStr ( DateUtils . YYYY_MM_DD_HH_MM_SS , date ) ;
dto . setStartTime ( dateStr ) ;
dto . setEndTime ( DateUtils . parseDateToStr ( DateUtils . YYYY_MM_DD_HH_MM_SS , new Date ( ) ) ) ;
// 分页查询
PageHelper . startPage ( pageNum , pageSize ) ;
List < PersonPileConnectorSumInfoVO > accumulativeInfo = orderBasicInfoService . getAccumulativeInfo ( dto ) ;
if ( CollectionUtils . isEmpty ( accumulativeInfo ) ) {
2023-03-13 17:01:07 +08:00
throw new BusinessException ( ReturnCodeEnum . CODE_QUERY_ORDER_INFO_IS_NULL ) ;
2023-03-04 16:29:55 +08:00
}
PageInfo < PersonPileConnectorSumInfoVO > pageInfo = new PageInfo < > ( accumulativeInfo ) ;
for ( PersonPileConnectorSumInfoVO personPileConnectorSumInfoVO : pageInfo . getList ( ) ) {
if ( StringUtils . isNotBlank ( personPileConnectorSumInfoVO . getChargeStartTime ( ) ) & & StringUtils . isNotBlank ( personPileConnectorSumInfoVO . getChargeEndTime ( ) ) ) {
String datePoor = DateUtils . getDatePoor ( DateUtils . parseDate ( personPileConnectorSumInfoVO . getChargeEndTime ( ) ) ,
DateUtils . parseDate ( personPileConnectorSumInfoVO . getChargeStartTime ( ) ) ) ;
personPileConnectorSumInfoVO . setSumChargingTime ( datePoor ) ;
}
}
return PageResponse . builder ( )
. pageNum ( pageInfo . getPageNum ( ) )
. pageSize ( pageInfo . getPageSize ( ) )
. list ( pageInfo . getList ( ) )
. pages ( pageInfo . getPages ( ) )
. total ( pageInfo . getTotal ( ) )
. build ( ) ;
}
/ * *
* 获取总充电时长 、 总充电量
*
* @param accumulativeInfo
* @return
* /
private Map < String , String > getSumInfo ( List < PersonPileConnectorSumInfoVO > accumulativeInfo ) {
Map < String , String > resultMap = new HashMap < > ( ) ;
BigDecimal sumChargingTime = BigDecimal . ZERO ;
BigDecimal sumUsedElectricity = BigDecimal . ZERO ;
// 将返回的结果进行for循环, 将总充电量、总充电时长进行累加( 充电时长需要通过 充电开始时间 和 充电结束时间 进行计算)
for ( PersonPileConnectorSumInfoVO personPileConnectorSumInfoVO : accumulativeInfo ) {
if ( StringUtils . isNotBlank ( personPileConnectorSumInfoVO . getChargeStartTime ( ) ) & & StringUtils . isNotBlank ( personPileConnectorSumInfoVO . getChargeEndTime ( ) ) ) {
long longChargingTime = DateUtils . intervalTime ( personPileConnectorSumInfoVO . getChargeStartTime ( ) , personPileConnectorSumInfoVO . getChargeEndTime ( ) ) ;
BigDecimal chargingTime = new BigDecimal ( String . valueOf ( longChargingTime ) ) ;
sumChargingTime = sumChargingTime . add ( chargingTime ) ;
}
BigDecimal chargingDegree = StringUtils . isBlank ( personPileConnectorSumInfoVO . getSumChargingDegree ( ) )
? BigDecimal . ZERO
: new BigDecimal ( personPileConnectorSumInfoVO . getSumChargingDegree ( ) ) ;
sumUsedElectricity = sumUsedElectricity . add ( chargingDegree ) ;
}
resultMap . put ( " sumChargingTime " , String . valueOf ( sumChargingTime ) ) ;
resultMap . put ( " sumUsedElectricity " , String . valueOf ( sumUsedElectricity ) ) ;
return resultMap ;
}
}