package com.zsElectric.boot.business.service.impl; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.zsElectric.boot.business.mapper.*; import com.zsElectric.boot.business.model.entity.*; import com.zsElectric.boot.business.model.form.applet.AppInvokeChargeForm; import com.zsElectric.boot.business.model.form.applet.AppStopChargeForm; import com.zsElectric.boot.business.model.query.applet.AppChargeOrderInfoQuery; import com.zsElectric.boot.business.model.vo.applet.AppChargeVO; import com.zsElectric.boot.business.model.vo.applet.AppUserInfoVO; import com.zsElectric.boot.business.service.UserAccountService; import com.zsElectric.boot.charging.dto.StartChargingRequestDTO; import com.zsElectric.boot.charging.dto.StartChargingResponseVO; import com.zsElectric.boot.charging.service.ChargingBusinessService; import com.zsElectric.boot.charging.vo.EquipmentAuthResponseVO; import com.zsElectric.boot.charging.vo.StopChargingOperationResponseVO; import com.zsElectric.boot.common.constant.ConnectivityConstants; import com.zsElectric.boot.common.constant.SystemConstants; import com.zsElectric.boot.core.exception.BusinessException; import com.zsElectric.boot.security.util.SecurityUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.zsElectric.boot.business.service.ChargeOrderInfoService; import com.zsElectric.boot.business.model.form.ChargeOrderInfoForm; import com.zsElectric.boot.business.model.query.ChargeOrderInfoQuery; import com.zsElectric.boot.business.model.vo.ChargeOrderInfoVO; import com.zsElectric.boot.business.converter.ChargeOrderInfoConverter; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Objects; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; /** * 充电订单信息服务实现类 * * @author zsElectric * @since 2025-12-17 19:13 */ @Slf4j @Service @RequiredArgsConstructor public class ChargeOrderInfoServiceImpl extends ServiceImpl implements ChargeOrderInfoService { private final ChargeOrderInfoConverter chargeOrderInfoConverter; private final ChargingBusinessService chargingBusinessService; private final UserInfoMapper userInfoMapper; private final FirmInfoMapper firmInfoMapper; private final CouponMapper couponMapper; private final CouponTemplateMapper couponTemplateMapper; private final UserAccountService userAccountService; //充电订单号前缀 private final String ORDER_NO_PREFIX = "CD"; //设备流水号前缀 private final String EQUIPMENT_NO_PREFIX = "SB"; /** * 获取充电订单信息分页列表 * * @param queryParams 查询参数 * @return {@link IPage} 充电订单信息分页列表 */ @Override public IPage getChargeOrderInfoPage(ChargeOrderInfoQuery queryParams) { Page pageVO = this.baseMapper.getChargeOrderInfoPage( new Page<>(queryParams.getPageNum(), queryParams.getPageSize()), queryParams ); return pageVO; } /** * 获取充电订单信息表单数据 * * @param id 充电订单信息ID * @return 充电订单信息表单数据 */ @Override public ChargeOrderInfoForm getChargeOrderInfoFormData(Long id) { ChargeOrderInfo entity = this.getById(id); return chargeOrderInfoConverter.toForm(entity); } /** * 新增充电订单信息 * * @param formData 充电订单信息表单对象 * @return 是否新增成功 */ @Override public boolean saveChargeOrderInfo(ChargeOrderInfoForm formData) { ChargeOrderInfo entity = chargeOrderInfoConverter.toEntity(formData); return this.save(entity); } /** * 更新充电订单信息 * * @param id 充电订单信息ID * @param formData 充电订单信息表单对象 * @return 是否修改成功 */ @Override public boolean updateChargeOrderInfo(Long id,ChargeOrderInfoForm formData) { ChargeOrderInfo entity = chargeOrderInfoConverter.toEntity(formData); return this.updateById(entity); } /** * 删除充电订单信息 * * @param ids 充电订单信息ID,多个以英文逗号(,)分割 * @return 是否删除成功 */ @Override public boolean deleteChargeOrderInfos(String ids) { Assert.isTrue(StrUtil.isNotBlank(ids), "删除的充电订单信息数据为空"); // 逻辑删除 List idList = Arrays.stream(ids.split(",")) .map(Long::parseLong) .toList(); return this.removeByIds(idList); } @Override public IPage getPage(AppChargeOrderInfoQuery queryParams) { queryParams.setUserId(SecurityUtils.getUserId()); Page pageVO = this.baseMapper.getPage( new Page<>(queryParams.getPageNum(), queryParams.getPageSize()), queryParams ); return pageVO; } @Override public AppChargeVO invokeCharge(AppInvokeChargeForm formData) { log.info("启动充电开始,用户ID:{},设备认证流水号:{},充电桩编号:{}", SecurityUtils.getUserId(), formData.getEquipAuthSeq(), formData.getEquipmentId()); try { AppChargeVO appInvokeChargeVO = new AppChargeVO(); //必要校验 Long userId = SecurityUtils.getUserId(); Assert.isTrue(userId != null, "用户ID不能为空"); AppUserInfoVO userInfo = userInfoMapper.getAppletUserInfo(userId); Assert.isTrue(userInfo != null, "用户信息不存在"); //判断有没有正在进行中的订单 Long count = this.baseMapper.selectCount(Wrappers.lambdaQuery(ChargeOrderInfo.class).eq(ChargeOrderInfo::getUserId, userId).in(ChargeOrderInfo::getStatus, SystemConstants.STATUS_ZERO, SystemConstants.STATUS_ONE, SystemConstants.STATUS_TWO)); Assert.isTrue(count == 0, "您有正在进行中的订单,请等待完成!"); //请求设备认证 EquipmentAuthResponseVO equipmentAuthResponseVO = chargingBusinessService.queryEquipAuth(formData.getEquipAuthSeq(), formData.getConnectorID()); if (!Objects.equals(equipmentAuthResponseVO.getSuccStat(), SystemConstants.STATUS_ONE)) { throw new BusinessException("设备认证失败"); } //生成系统充电订单号及互联互通充电订单号 assert userId != null; String chargeOrderNo = generateNo(ORDER_NO_PREFIX, userId); String startChargeSeq = ConnectivityConstants.OPERATOR_ID + chargeOrderNo; //生成设备流水号(格式"运营商ID+唯一编号") String equipAuthSeq = ConnectivityConstants.OPERATOR_ID + generateNo(EQUIPMENT_NO_PREFIX, userId); //创建订单 ChargeOrderInfo chargeOrderInfo = new ChargeOrderInfo(); chargeOrderInfo.setUserId(userId); chargeOrderInfo.setEquipmentId(formData.getEquipmentId()); chargeOrderInfo.setEquipAuthSeq(equipAuthSeq); chargeOrderInfo.setChargeOrderNo(chargeOrderNo); chargeOrderInfo.setStartChargeSeq(startChargeSeq); chargeOrderInfo.setPhoneNum(userInfo.getPhone()); chargeOrderInfo.setThirdPartyStationId(formData.getStationId()); chargeOrderInfo.setOrderType(formData.getOrderType()); //todo 预支付金额 //chargeOrderInfo.setPreAmt(); //判断用户是否绑定企业 if (ObjectUtil.isNotEmpty(userInfo.getFirmId())) { FirmInfo firmInfo = firmInfoMapper.selectById(userInfo.getFirmId()); if(firmInfo != null && Objects.equals(firmInfo.getStatus(), SystemConstants.STATUS_ONE)) { chargeOrderInfo.setFirmId(firmInfo.getId()); chargeOrderInfo.setOrderType(SystemConstants.STATUS_ONE); } } //优惠券 if(ObjectUtil.isNotEmpty(formData.getCouponId())) { Coupon coupon = couponMapper.selectById(formData.getCouponId()); if(coupon != null && Objects.equals(coupon.getStatus(), SystemConstants.STATUS_ONE)) { CouponTemplate couponTemplate = couponTemplateMapper.selectById(coupon.getTemplateId()); chargeOrderInfo.setCouponId(coupon.getId()); chargeOrderInfo.setCouponPrice(couponTemplate.getDiscountPrice()); } } //启动充电 StartChargingRequestDTO requestDTO = new StartChargingRequestDTO(); requestDTO .setStartChargeSeq(startChargeSeq) .setConnectorID(formData.getConnectorID()) .setPhoneNum(userInfo.getPhone()) //预支付金额 //.setChargingAmt() ; StartChargingResponseVO startChargingResponseVO = chargingBusinessService.startCharging(requestDTO); if (!Objects.equals(startChargingResponseVO.getSuccStat(), SystemConstants.STATUS_ZERO)) { throw new BusinessException("启动充电失败"); } //保存订单 this.save(chargeOrderInfo); appInvokeChargeVO.setChargeOrderNo(chargeOrderNo); appInvokeChargeVO.setChargeOrderId(chargeOrderInfo.getId()); return appInvokeChargeVO; } catch (Exception e) { throw new BusinessException("启动充电失败,系统错误,请联系客服处理!"); } } @Override public AppChargeVO stopCharge(AppStopChargeForm formData) { try { AppChargeVO appInvokeChargeVO = new AppChargeVO(); //订单 ChargeOrderInfo chargeOrderInfo = this.getById(formData.getChargeOrderId()); if(ObjectUtil.isEmpty(chargeOrderInfo)){ throw new BusinessException("订单不存在"); } StopChargingOperationResponseVO stopChargingOperationResponseVO = chargingBusinessService.stopCharging(chargeOrderInfo.getStartChargeSeq(), chargeOrderInfo.getConnectorId()); if (!Objects.equals(stopChargingOperationResponseVO.getSuccStat(), SystemConstants.STATUS_ZERO)) { throw new BusinessException("停止充电失败"); } //保存订单 this.save(chargeOrderInfo); appInvokeChargeVO.setChargeOrderId(chargeOrderInfo.getId()); appInvokeChargeVO.setChargeOrderNo(chargeOrderInfo.getChargeOrderNo()); return appInvokeChargeVO; } catch (Exception e) { throw new BusinessException("停止充电失败,系统错误,请联系客服处理!"); } } @Override public void orderSettlement(Long chargeOrderId) { Long userId = SecurityUtils.getUserId(); ChargeOrderInfo chargeOrderInfo = this.getById(chargeOrderId); //平台收费总金额 BigDecimal totalCharge = chargeOrderInfo.getRealCost(); //账户变动及日志记录 userAccountService.updateAccountBalanceAndLog( userId, totalCharge, SystemConstants.CHANGE_TYPE_REDUCE, "充电扣款", chargeOrderInfo.getId() ); } /** * 创建商户订单号 * 要求 32个字符内,只能是数字、大小写字母_-|*且在同一个商户号下唯一 * 组成 两位前缀 + 17位时间戳 + 9位id补零 + 4位随机数 合计32位 * * @param head 例如 商品-SP 退款-TK 等等 * @param id 用户id * @return */ public String generateNo(String head, Long id) { StringBuilder uid = new StringBuilder(id.toString()); Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); int length = uid.length(); for (int i = 0; i < 9 - length; i++) { uid.insert(0, "0"); } return head + sdf.format(date) + uid + (int) ((Math.random() * 9 + 1) * 1000); } }