ChargeOrderInfoServiceImpl.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. package com.zsElectric.boot.business.service.impl;
  2. import cn.hutool.core.util.ObjectUtil;
  3. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  4. import com.zsElectric.boot.business.mapper.*;
  5. import com.zsElectric.boot.business.model.entity.*;
  6. import com.zsElectric.boot.business.model.form.applet.AppInvokeChargeForm;
  7. import com.zsElectric.boot.business.model.form.applet.AppStopChargeForm;
  8. import com.zsElectric.boot.business.model.query.applet.AppChargeOrderInfoQuery;
  9. import com.zsElectric.boot.business.model.vo.applet.AppChargeVO;
  10. import com.zsElectric.boot.business.model.vo.applet.AppUserInfoVO;
  11. import com.zsElectric.boot.business.service.AppletHomeService;
  12. import com.zsElectric.boot.business.service.UserAccountService;
  13. import com.zsElectric.boot.charging.dto.StartChargingRequestDTO;
  14. import com.zsElectric.boot.charging.dto.StartChargingResponseVO;
  15. import com.zsElectric.boot.charging.service.ChargingBusinessService;
  16. import com.zsElectric.boot.charging.vo.EquipmentAuthResponseVO;
  17. import com.zsElectric.boot.charging.vo.StopChargingOperationResponseVO;
  18. import com.zsElectric.boot.common.constant.ConnectivityConstants;
  19. import com.zsElectric.boot.common.constant.SystemConstants;
  20. import com.zsElectric.boot.core.exception.BusinessException;
  21. import com.zsElectric.boot.security.util.SecurityUtils;
  22. import lombok.RequiredArgsConstructor;
  23. import lombok.extern.slf4j.Slf4j;
  24. import org.springframework.stereotype.Service;
  25. import com.baomidou.mybatisplus.core.metadata.IPage;
  26. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  27. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  28. import com.zsElectric.boot.business.service.ChargeOrderInfoService;
  29. import com.zsElectric.boot.business.model.form.ChargeOrderInfoForm;
  30. import com.zsElectric.boot.business.model.query.ChargeOrderInfoQuery;
  31. import com.zsElectric.boot.business.model.vo.ChargeOrderInfoVO;
  32. import com.zsElectric.boot.business.converter.ChargeOrderInfoConverter;
  33. import java.math.BigDecimal;
  34. import java.text.SimpleDateFormat;
  35. import java.util.Arrays;
  36. import java.util.Date;
  37. import java.util.List;
  38. import java.util.Objects;
  39. import cn.hutool.core.lang.Assert;
  40. import cn.hutool.core.util.StrUtil;
  41. /**
  42. * 充电订单信息服务实现类
  43. *
  44. * @author zsElectric
  45. * @since 2025-12-17 19:13
  46. */
  47. @Slf4j
  48. @Service
  49. @RequiredArgsConstructor
  50. public class ChargeOrderInfoServiceImpl extends ServiceImpl<ChargeOrderInfoMapper, ChargeOrderInfo> implements ChargeOrderInfoService {
  51. private final ChargeOrderInfoConverter chargeOrderInfoConverter;
  52. private final ChargingBusinessService chargingBusinessService;
  53. private final UserInfoMapper userInfoMapper;
  54. private final FirmInfoMapper firmInfoMapper;
  55. private final CouponMapper couponMapper;
  56. private final CouponTemplateMapper couponTemplateMapper;
  57. private final UserAccountService userAccountService;
  58. private final AppletHomeService appletHomeService;
  59. //充电订单号前缀
  60. private final String ORDER_NO_PREFIX = "CD";
  61. //设备流水号前缀
  62. private final String EQUIPMENT_NO_PREFIX = "SB";
  63. /**
  64. * 获取充电订单信息分页列表
  65. *
  66. * @param queryParams 查询参数
  67. * @return {@link IPage<ChargeOrderInfoVO>} 充电订单信息分页列表
  68. */
  69. @Override
  70. public IPage<ChargeOrderInfoVO> getChargeOrderInfoPage(ChargeOrderInfoQuery queryParams) {
  71. Page<ChargeOrderInfoVO> pageVO = this.baseMapper.getChargeOrderInfoPage(
  72. new Page<>(queryParams.getPageNum(), queryParams.getPageSize()),
  73. queryParams
  74. );
  75. return pageVO;
  76. }
  77. /**
  78. * 获取充电订单信息表单数据
  79. *
  80. * @param id 充电订单信息ID
  81. * @return 充电订单信息表单数据
  82. */
  83. @Override
  84. public ChargeOrderInfoForm getChargeOrderInfoFormData(Long id) {
  85. ChargeOrderInfo entity = this.getById(id);
  86. return chargeOrderInfoConverter.toForm(entity);
  87. }
  88. /**
  89. * 新增充电订单信息
  90. *
  91. * @param formData 充电订单信息表单对象
  92. * @return 是否新增成功
  93. */
  94. @Override
  95. public boolean saveChargeOrderInfo(ChargeOrderInfoForm formData) {
  96. ChargeOrderInfo entity = chargeOrderInfoConverter.toEntity(formData);
  97. return this.save(entity);
  98. }
  99. /**
  100. * 更新充电订单信息
  101. *
  102. * @param id 充电订单信息ID
  103. * @param formData 充电订单信息表单对象
  104. * @return 是否修改成功
  105. */
  106. @Override
  107. public boolean updateChargeOrderInfo(Long id,ChargeOrderInfoForm formData) {
  108. ChargeOrderInfo entity = chargeOrderInfoConverter.toEntity(formData);
  109. return this.updateById(entity);
  110. }
  111. /**
  112. * 删除充电订单信息
  113. *
  114. * @param ids 充电订单信息ID,多个以英文逗号(,)分割
  115. * @return 是否删除成功
  116. */
  117. @Override
  118. public boolean deleteChargeOrderInfos(String ids) {
  119. Assert.isTrue(StrUtil.isNotBlank(ids), "删除的充电订单信息数据为空");
  120. // 逻辑删除
  121. List<Long> idList = Arrays.stream(ids.split(","))
  122. .map(Long::parseLong)
  123. .toList();
  124. return this.removeByIds(idList);
  125. }
  126. @Override
  127. public IPage<ChargeOrderInfoVO> getPage(AppChargeOrderInfoQuery queryParams) {
  128. queryParams.setUserId(SecurityUtils.getUserId());
  129. Page<ChargeOrderInfoVO> pageVO = this.baseMapper.getPage(
  130. new Page<>(queryParams.getPageNum(), queryParams.getPageSize()),
  131. queryParams
  132. );
  133. return pageVO;
  134. }
  135. @Override
  136. public AppChargeVO invokeCharge(AppInvokeChargeForm formData) {
  137. log.info("启动充电开始,用户ID:{},设备认证流水号:{},充电桩编号:{}", SecurityUtils.getUserId(), formData.getEquipAuthSeq(), formData.getEquipmentId());
  138. try {
  139. AppChargeVO appInvokeChargeVO = new AppChargeVO();
  140. //必要校验
  141. Long userId = SecurityUtils.getUserId();
  142. Assert.isTrue(userId != null, "用户ID不能为空");
  143. AppUserInfoVO userInfo = userInfoMapper.getAppletUserInfo(userId);
  144. Assert.isTrue(userInfo != null, "用户信息不存在");
  145. //判断有没有正在进行中的订单
  146. 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));
  147. Assert.isTrue(count == 0, "您有正在进行中的订单,请等待完成!");
  148. //生成系统充电订单号及互联互通充电订单号
  149. assert userId != null;
  150. String chargeOrderNo = generateNo(ORDER_NO_PREFIX, userId);
  151. String startChargeSeq = ConnectivityConstants.OPERATOR_ID + chargeOrderNo;
  152. //请求设备认证
  153. EquipmentAuthResponseVO equipmentAuthResponseVO = chargingBusinessService.queryEquipAuth(startChargeSeq,
  154. formData.getConnectorId());
  155. if (!Objects.equals(equipmentAuthResponseVO.getSuccStat(), SystemConstants.STATUS_ONE)) {
  156. throw new BusinessException("设备认证失败");
  157. }
  158. //生成设备流水号(格式"运营商ID+唯一编号")
  159. String equipAuthSeq = ConnectivityConstants.OPERATOR_ID + generateNo(EQUIPMENT_NO_PREFIX, userId);
  160. //创建订单
  161. ChargeOrderInfo chargeOrderInfo = new ChargeOrderInfo();
  162. chargeOrderInfo.setUserId(userId);
  163. chargeOrderInfo.setEquipmentId(formData.getEquipmentId());
  164. chargeOrderInfo.setEquipAuthSeq(equipAuthSeq);
  165. chargeOrderInfo.setChargeOrderNo(chargeOrderNo);
  166. chargeOrderInfo.setStartChargeSeq(startChargeSeq);
  167. chargeOrderInfo.setPhoneNum(userInfo.getPhone());
  168. chargeOrderInfo.setThirdPartyStationId(formData.getStationId());
  169. chargeOrderInfo.setOrderType(formData.getOrderType());
  170. //预支付金额
  171. BigDecimal preAmt = appletHomeService.calculateAvailableChargingAmount(formData.getConnectorId());
  172. chargeOrderInfo.setPreAmt(preAmt);
  173. //判断用户是否绑定企业
  174. if (ObjectUtil.isNotEmpty(userInfo.getFirmId())) {
  175. FirmInfo firmInfo = firmInfoMapper.selectById(userInfo.getFirmId());
  176. if(firmInfo != null && Objects.equals(firmInfo.getStatus(), SystemConstants.STATUS_ONE)) {
  177. chargeOrderInfo.setFirmId(firmInfo.getId());
  178. chargeOrderInfo.setOrderType(SystemConstants.STATUS_ONE);
  179. }
  180. }
  181. //优惠券
  182. if(ObjectUtil.isNotEmpty(formData.getCouponId())) {
  183. Coupon coupon = couponMapper.selectById(formData.getCouponId());
  184. if(coupon != null && Objects.equals(coupon.getStatus(), SystemConstants.STATUS_ONE)) {
  185. CouponTemplate couponTemplate = couponTemplateMapper.selectById(coupon.getTemplateId());
  186. chargeOrderInfo.setCouponId(coupon.getId());
  187. chargeOrderInfo.setCouponPrice(couponTemplate.getDiscountPrice());
  188. }
  189. }
  190. //启动充电
  191. StartChargingRequestDTO requestDTO = new StartChargingRequestDTO();
  192. requestDTO
  193. .setStartChargeSeq(startChargeSeq)
  194. .setConnectorID(formData.getConnectorId())
  195. .setPhoneNum(userInfo.getPhone())
  196. //预支付金额
  197. .setChargingAmt(preAmt.toString())
  198. ;
  199. StartChargingResponseVO startChargingResponseVO = chargingBusinessService.startCharging(requestDTO);
  200. if (!Objects.equals(startChargingResponseVO.getSuccStat(), SystemConstants.STATUS_ZERO)) {
  201. throw new BusinessException("启动充电失败");
  202. }
  203. //保存订单
  204. this.save(chargeOrderInfo);
  205. appInvokeChargeVO.setChargeOrderNo(chargeOrderNo);
  206. appInvokeChargeVO.setChargeOrderId(chargeOrderInfo.getId());
  207. return appInvokeChargeVO;
  208. } catch (Exception e) {
  209. throw new BusinessException("启动充电失败,系统错误,请联系客服处理!");
  210. }
  211. }
  212. @Override
  213. public AppChargeVO stopCharge(AppStopChargeForm formData) {
  214. try {
  215. AppChargeVO appInvokeChargeVO = new AppChargeVO();
  216. //订单
  217. ChargeOrderInfo chargeOrderInfo = this.getById(formData.getChargeOrderId());
  218. if(ObjectUtil.isEmpty(chargeOrderInfo)){
  219. throw new BusinessException("订单不存在");
  220. }
  221. StopChargingOperationResponseVO stopChargingOperationResponseVO = chargingBusinessService.stopCharging(chargeOrderInfo.getStartChargeSeq(), chargeOrderInfo.getConnectorId());
  222. if (!Objects.equals(stopChargingOperationResponseVO.getSuccStat(), SystemConstants.STATUS_ZERO)) {
  223. throw new BusinessException("停止充电失败");
  224. }
  225. //保存订单
  226. this.save(chargeOrderInfo);
  227. appInvokeChargeVO.setChargeOrderId(chargeOrderInfo.getId());
  228. appInvokeChargeVO.setChargeOrderNo(chargeOrderInfo.getChargeOrderNo());
  229. return appInvokeChargeVO;
  230. } catch (Exception e) {
  231. throw new BusinessException("停止充电失败,系统错误,请联系客服处理!");
  232. }
  233. }
  234. @Override
  235. public void orderSettlement(Long chargeOrderId) {
  236. ChargeOrderInfo chargeOrderInfo = this.getById(chargeOrderId);
  237. Long userId = chargeOrderInfo.getUserId();
  238. //平台收费总金额
  239. BigDecimal totalCharge = chargeOrderInfo.getRealCost();
  240. //加积分
  241. userAccountService.update(Wrappers.lambdaUpdate(UserAccount.class)
  242. .eq(UserAccount::getUserId, userId)
  243. .setSql("`integral` = `integral` +" + totalCharge)
  244. );
  245. //账户变动及日志记录
  246. userAccountService.updateAccountBalanceAndLog(
  247. userId,
  248. totalCharge,
  249. SystemConstants.CHANGE_TYPE_REDUCE,
  250. "充电扣款",
  251. chargeOrderInfo.getId()
  252. );
  253. }
  254. /**
  255. * 创建商户订单号
  256. * 要求 32个字符内,只能是数字、大小写字母_-|*且在同一个商户号下唯一
  257. * 组成 两位前缀 + 17位时间戳 + 9位id补零 + 4位随机数 合计32位
  258. *
  259. * @param head 例如 商品-SP 退款-TK 等等
  260. * @param id 用户id
  261. * @return
  262. */
  263. public String generateNo(String head, Long id) {
  264. StringBuilder uid = new StringBuilder(id.toString());
  265. Date date = new Date();
  266. SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
  267. int length = uid.length();
  268. for (int i = 0; i < 9 - length; i++) {
  269. uid.insert(0, "0");
  270. }
  271. return head + sdf.format(date) + uid + (int) ((Math.random() * 9 + 1) * 1000);
  272. }
  273. }