WashOrderServiceImpl.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. package com.kym.service.impl;
  2. import cn.dev33.satoken.stp.StpUtil;
  3. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  4. import com.github.pagehelper.PageHelper;
  5. import com.github.pagehelper.PageInfo;
  6. import com.github.yulichang.toolkit.JoinWrappers;
  7. import com.github.yulichang.wrapper.MPJLambdaWrapper;
  8. import com.kym.common.exception.BusinessException;
  9. import com.kym.common.utils.CommUtil;
  10. import com.kym.common.utils.OrderUtils;
  11. import com.kym.entity.Account;
  12. import com.kym.entity.User;
  13. import com.kym.entity.WashOrder;
  14. import com.kym.entity.WashStation;
  15. import com.kym.entity.common.PageBean;
  16. import com.kym.entity.common.PageParams;
  17. import com.kym.entity.queryParams.DeviceQueryParams;
  18. import com.kym.entity.queryParams.StatQueryParam;
  19. import com.kym.entity.queryParams.WashOrderQueryParams;
  20. import com.kym.entity.vo.StationTrendVo;
  21. import com.kym.entity.vo.WashOrderVo;
  22. import com.kym.mapper.WashOrderMapper;
  23. import com.kym.service.AccountService;
  24. import com.kym.service.UserService;
  25. import com.kym.service.WashOrderService;
  26. import com.kym.service.WashStationService;
  27. import com.kym.service.awoara.AwoaraService;
  28. import com.kym.service.cache.KymCache;
  29. import com.kym.service.mybatisplus.MyBaseServiceImpl;
  30. import org.springframework.beans.BeanUtils;
  31. import org.springframework.context.annotation.Lazy;
  32. import org.springframework.stereotype.Service;
  33. import java.time.LocalDate;
  34. import java.time.LocalDateTime;
  35. import java.time.LocalTime;
  36. import java.time.temporal.TemporalAdjusters;
  37. import java.util.List;
  38. import java.util.Map;
  39. import java.util.stream.Collectors;
  40. /**
  41. * <p>
  42. * 洗车订单表 服务实现类
  43. * </p>
  44. *
  45. * @author skyline
  46. * @since 2024-09-11
  47. */
  48. @Service
  49. public class WashOrderServiceImpl extends MyBaseServiceImpl<WashOrderMapper, WashOrder> implements WashOrderService {
  50. private final AwoaraService awoaraService;
  51. private final AccountService accountService;
  52. private final WashStationService washStationService;
  53. private final UserService userService;
  54. public WashOrderServiceImpl(AwoaraService awoaraService, AccountService accountService, @Lazy WashStationService washStationService, UserService userService) {
  55. this.awoaraService = awoaraService;
  56. this.accountService = accountService;
  57. this.washStationService = washStationService;
  58. this.userService = userService;
  59. }
  60. /**
  61. * 创建订单(启动洗车机)
  62. *
  63. * @param params
  64. * @return
  65. */
  66. @Override
  67. public String createOrder(DeviceQueryParams params) {
  68. // 校验余额
  69. var account = accountService.getAccountByUserId(StpUtil.getLoginIdAsLong());
  70. if (account.getBalance() < Account.MIN_BALANCE) {
  71. throw new BusinessException("余额不足,请保持余额不低于2元!");
  72. }
  73. // 校验用户是否有未完结的订单
  74. var unfinishedOrder = lambdaQuery()
  75. .eq(WashOrder::getUserId, StpUtil.getLoginIdAsLong())
  76. .eq(WashOrder::getOrderStatus, WashOrder.ORDER_STATUS_开机)
  77. .or()
  78. .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_未支付)
  79. .list();
  80. if (!unfinishedOrder.isEmpty()) {
  81. throw new BusinessException("您有未完结的订单!");
  82. }
  83. var memberName = StpUtil.getSession().getString(User.ST_SESSION_KEY_MOBILE);
  84. var orderId = OrderUtils.getOrderNo();
  85. // 请求阿里云lot
  86. var createOrder = awoaraService.createOrder(params.getProductKey(), params.getDeviceName(),
  87. orderId,
  88. memberName,
  89. account.getBalance(),
  90. Account.NO_DISCOUNT,
  91. // 本次开机最大消费金额,减去0.5元,防止延时导致超消费
  92. account.getBalance() - 50);
  93. var washOrder = new WashOrder()
  94. .setUserId(StpUtil.getLoginIdAsLong())
  95. .setStationId(params.getStationId())
  96. .setProductKey(params.getProductKey())
  97. .setDeviceName(params.getDeviceName())
  98. .setShortId(KymCache.INSTANCE.getShortIdByProductKeyAndDeviceName(params.getProductKey(), params.getDeviceName()))
  99. .setOpenType(WashOrder.START_CLOSE_TYPE_网络)
  100. .setOrderId(orderId)
  101. .setOrderIdLocal(createOrder.getOrder_id_local())
  102. .setMemberDiscount(Account.NO_DISCOUNT)
  103. .setPrepayMoney(account.getBalance() - 50)
  104. .setStartTime(LocalDateTime.now())
  105. .setOrderStatus(WashOrder.ORDER_STATUS_开机)
  106. .setPayStatus(WashOrder.PAY_STATUS_未支付)
  107. .setIsCross(!StpUtil.getSession().getString("stationId").equals(params.getStationId()));
  108. save(washOrder);
  109. return orderId;
  110. }
  111. @Override
  112. public void closeOrder(DeviceQueryParams params) {
  113. var order = lambdaQuery()
  114. .eq(WashOrder::getProductKey, params.getProductKey())
  115. .eq(WashOrder::getDeviceName, params.getDeviceName())
  116. .eq(WashOrder::getOrderStatus, WashOrder.ORDER_STATUS_开机)
  117. .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_未支付)
  118. .one();
  119. if (order != null) {
  120. if (order.getUserId() == StpUtil.getLoginIdAsLong()) {
  121. awoaraService.closeOrder(params.getProductKey(), params.getDeviceName(), order.getOrderId());
  122. } else {
  123. throw new BusinessException("您没有权限关闭该订单!");
  124. }
  125. }
  126. }
  127. /**
  128. * 查询订单详情
  129. *
  130. * @param params
  131. * @return
  132. */
  133. @Override
  134. public WashOrder queryOrder(WashOrderQueryParams params) {
  135. // 非实时数据
  136. WashOrder order = lambdaQuery()
  137. .eq(WashOrder::getOrderId, params.getOrderId())
  138. .one();
  139. if (null != params.getUserId()) {
  140. CommUtil.asserts(null != order && order.getUserId().equals(StpUtil.getLoginIdAsLong()),
  141. "订单不存在或您没有权限查看该订单!");
  142. }
  143. return order;
  144. }
  145. /**
  146. * 查询停车减免订单
  147. *
  148. * @param unionid
  149. * @return
  150. */
  151. @Override
  152. public String getParkingDiscounts(String unionid) {
  153. var user = userService.lambdaQuery().eq(User::getUnionid, unionid).one();
  154. CommUtil.asserts(null != user, "用户信息异常:无此用户");
  155. // 查询用户24小时内的订单
  156. var orders = lambdaQuery()
  157. .eq(WashOrder::getUserId, user.getId())
  158. .ge(WashOrder::getStartTime, LocalDateTime.now().minusHours(24))
  159. .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_已支付)
  160. .orderByDesc(WashOrder::getId)
  161. .list();
  162. CommUtil.asserts(CommUtil.isEmptyOrNull(orders) && (orders.stream().mapToInt(WashOrder::getAmount).sum() >= 0),
  163. "抱歉:无停车场洗车记录");
  164. return washStationService.lambdaQuery().eq(WashStation::getStationId, orders.get(0).getStationId()).one().getParkingQrCode();
  165. }
  166. /**
  167. * 当前用户订单列表
  168. *
  169. * @param params
  170. * @return
  171. */
  172. @Override
  173. public PageBean<WashOrderVo> listMyWashOrder(PageParams params) {
  174. PageHelper.startPage(params.getPageNum(), params.getPageSize());
  175. var res = lambdaQuery()
  176. .eq(WashOrder::getUserId, StpUtil.getLoginIdAsLong())
  177. .orderByDesc(WashOrder::getId)
  178. .list();
  179. PageInfo<WashOrder> pages = new PageInfo<>(res);
  180. var voList = pages.getList().stream().map(order -> {
  181. var vo = new WashOrderVo();
  182. BeanUtils.copyProperties(order, vo);
  183. return vo;
  184. }).toList();
  185. PageBean<WashOrderVo> bean = new PageBean<>(voList);
  186. bean.setPages(pages.getPages());
  187. bean.setPageNum(pages.getPageNum());
  188. bean.setPageSize(pages.getPageSize());
  189. bean.setTotal(pages.getTotal());
  190. return bean;
  191. }
  192. //region 管理后台
  193. @Override
  194. public PageBean<WashOrderVo> list(WashOrderQueryParams params) {
  195. PageHelper.startPage(params.getPageNum(), params.getPageSize());
  196. MPJLambdaWrapper<WashOrder> wrapper = JoinWrappers.lambda(WashOrder.class)
  197. .selectAsClass(WashOrder.class, WashOrderVo.class)
  198. .selectAs(User::getMobilePhone, WashOrderVo::getMobilePhone)
  199. .leftJoin(User.class, User::getId, WashOrder::getUserId)
  200. .eq(CommUtil.isNotEmptyAndNull(params.getUserId()), WashOrder::getUserId, params.getUserId())
  201. .eq(CommUtil.isNotEmptyAndNull(params.getMobilePhone()), User::getMobilePhone, params.getMobilePhone())
  202. .eq(CommUtil.isNotEmptyAndNull(params.getOrderStatus()), WashOrder::getOrderStatus, params.getOrderStatus())
  203. .eq(CommUtil.isNotEmptyAndNull(params.getPayStatus()), WashOrder::getPayStatus, params.getPayStatus())
  204. .orderByDesc(WashOrder::getId);
  205. //连表查询 返回自定义ResultType
  206. List<WashOrderVo> list = selectJoinList(WashOrderVo.class, wrapper);
  207. list.forEach(item -> {
  208. item.setStationName(KymCache.INSTANCE.getStationNameById(item.getStationId()));
  209. item.setUserStationId(KymCache.INSTANCE.getUserStationId(item.getUserId()));
  210. item.setUserStationName(KymCache.INSTANCE.getStationNameById(item.getUserStationId()));
  211. });
  212. return new PageBean<>(list);
  213. }
  214. @Override
  215. public WashOrder detail(long id) {
  216. return getById(id);
  217. }
  218. /**
  219. * 统计指定日期各站点消费金额
  220. *
  221. * @param statDay
  222. * @return
  223. */
  224. @Override
  225. public Map<String, Integer> sumAmountByDate(LocalDate statDay) {
  226. LambdaQueryWrapper<WashOrder> wrapper = new LambdaQueryWrapper<>();
  227. wrapper.select(WashOrder::getAmount, WashOrder::getStationId);
  228. wrapper.ge(WashOrder::getStartTime, LocalDateTime.of(statDay, LocalTime.MIN));
  229. wrapper.gt(WashOrder::getStartTime, LocalDateTime.of(statDay, LocalTime.MAX));
  230. var list = list(wrapper);
  231. // 按照站点分组统计金额
  232. return list.stream().collect(Collectors.groupingBy(WashOrder::getStationId, Collectors.summingInt(WashOrder::getAmount)));
  233. }
  234. /**
  235. * 统计指定日期当月各站点总消费金额
  236. *
  237. * @param statDay
  238. * @return
  239. */
  240. @Override
  241. public Map<String, Integer> sumMonthAmount(LocalDate statDay) {
  242. var startTime = statDay.with(TemporalAdjusters.firstDayOfMonth()).atTime(LocalTime.MIN);
  243. var endTime = statDay.with(TemporalAdjusters.lastDayOfMonth()).atTime(LocalTime.MAX);
  244. LambdaQueryWrapper<WashOrder> wrapper = new LambdaQueryWrapper<>();
  245. wrapper.select(WashOrder::getAmount, WashOrder::getStationId);
  246. wrapper.ge(WashOrder::getStartTime, startTime);
  247. wrapper.lt(WashOrder::getStartTime, endTime);
  248. var list = list(wrapper);
  249. // 按照站点分组统计金额
  250. return list.stream().collect(Collectors.groupingBy(WashOrder::getStationId, Collectors.summingInt(WashOrder::getAmount)));
  251. }
  252. /**
  253. * 统计指定日期订单数量
  254. *
  255. * @param statDay
  256. * @return
  257. */
  258. @Override
  259. public Map<String, Integer> countDailyOrders(LocalDate statDay) {
  260. LambdaQueryWrapper<WashOrder> wrapper = new LambdaQueryWrapper<>();
  261. wrapper.ge(WashOrder::getStartTime, LocalDateTime.of(statDay, LocalTime.MIN));
  262. wrapper.lt(WashOrder::getStartTime, LocalDateTime.of(statDay, LocalTime.MAX));
  263. // 按照站点分组统计订单数量
  264. return list(wrapper).stream().collect(Collectors.groupingBy(WashOrder::getStationId, Collectors.summingInt(o -> 1)));
  265. }
  266. /**
  267. * 统计指定日期订单数量
  268. *
  269. * @param statDay
  270. * @return
  271. */
  272. @Override
  273. public Map<String, Integer> countMonthOrders(LocalDate statDay) {
  274. var startTime = statDay.with(TemporalAdjusters.firstDayOfMonth()).atTime(LocalTime.MIN);
  275. var endTime = statDay.with(TemporalAdjusters.lastDayOfMonth()).atTime(LocalTime.MAX);
  276. LambdaQueryWrapper<WashOrder> wrapper = new LambdaQueryWrapper<>();
  277. wrapper.select(WashOrder::getStationId);
  278. wrapper.ge(WashOrder::getStartTime, startTime);
  279. wrapper.lt(WashOrder::getStartTime, endTime);
  280. // 按照站点分组统计订单数量
  281. return list(wrapper).stream().collect(Collectors.groupingBy(WashOrder::getStationId, Collectors.summingInt(o -> 1)));
  282. }
  283. @Override
  284. public WashOrder getOrderInProgressByUserId(long userId) {
  285. return lambdaQuery()
  286. .eq(WashOrder::getUserId, userId)
  287. .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_未支付)
  288. .one();
  289. }
  290. @Override
  291. public List<StationTrendVo> stationTrend(StatQueryParam params) {
  292. return baseMapper.StationTrend(params);
  293. }
  294. //endregion
  295. }