package com.kym.service.impl; import cn.dev33.satoken.stp.StpUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.github.yulichang.toolkit.JoinWrappers; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.kym.common.exception.BusinessException; import com.kym.common.utils.CommUtil; import com.kym.common.utils.OrderUtils; import com.kym.entity.Account; import com.kym.entity.User; import com.kym.entity.WashOrder; import com.kym.entity.WashStation; import com.kym.entity.common.PageBean; import com.kym.entity.common.PageParams; import com.kym.entity.queryParams.DeviceQueryParams; import com.kym.entity.queryParams.StatQueryParam; import com.kym.entity.queryParams.WashOrderQueryParams; import com.kym.entity.vo.StationTrendVo; import com.kym.entity.vo.WashOrderVo; import com.kym.mapper.WashOrderMapper; import com.kym.service.AccountService; import com.kym.service.UserService; import com.kym.service.WashOrderService; import com.kym.service.WashStationService; import com.kym.service.awoara.AwoaraService; import com.kym.service.cache.KymCache; import com.kym.service.mybatisplus.MyBaseServiceImpl; import org.springframework.beans.BeanUtils; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.temporal.TemporalAdjusters; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** *

* 洗车订单表 服务实现类 *

* * @author skyline * @since 2024-09-11 */ @Service public class WashOrderServiceImpl extends MyBaseServiceImpl implements WashOrderService { private final AwoaraService awoaraService; private final AccountService accountService; private final WashStationService washStationService; private final UserService userService; public WashOrderServiceImpl(AwoaraService awoaraService, AccountService accountService, @Lazy WashStationService washStationService, UserService userService) { this.awoaraService = awoaraService; this.accountService = accountService; this.washStationService = washStationService; this.userService = userService; } /** * 创建订单(启动洗车机) * * @param params * @return */ @Override public String createOrder(DeviceQueryParams params) { // 校验余额 var account = accountService.getAccountByUserId(StpUtil.getLoginIdAsLong()); if (account.getBalance() < Account.MIN_BALANCE) { throw new BusinessException("余额不足,请保持余额不低于2元!"); } // 校验用户是否有未完结的订单 var unfinishedOrder = lambdaQuery() .eq(WashOrder::getUserId, StpUtil.getLoginIdAsLong()) .eq(WashOrder::getOrderStatus, WashOrder.ORDER_STATUS_开机) .or() .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_未支付) .list(); if (!unfinishedOrder.isEmpty()) { throw new BusinessException("您有未完结的订单!"); } var memberName = StpUtil.getSession().getString(User.ST_SESSION_KEY_MOBILE); var orderId = OrderUtils.getOrderNo(); // 请求阿里云lot var createOrder = awoaraService.createOrder(params.getProductKey(), params.getDeviceName(), orderId, memberName, account.getBalance(), Account.NO_DISCOUNT, // 本次开机最大消费金额,减去0.5元,防止延时导致超消费 account.getBalance() - 50); var washOrder = new WashOrder() .setUserId(StpUtil.getLoginIdAsLong()) .setStationId(params.getStationId()) .setProductKey(params.getProductKey()) .setDeviceName(params.getDeviceName()) .setShortId(KymCache.INSTANCE.getShortIdByProductKeyAndDeviceName(params.getProductKey(), params.getDeviceName())) .setOpenType(WashOrder.START_CLOSE_TYPE_网络) .setOrderId(orderId) .setOrderIdLocal(createOrder.getOrder_id_local()) .setMemberDiscount(Account.NO_DISCOUNT) .setPrepayMoney(account.getBalance() - 50) .setStartTime(LocalDateTime.now()) .setOrderStatus(WashOrder.ORDER_STATUS_开机) .setPayStatus(WashOrder.PAY_STATUS_未支付) .setIsCross(!StpUtil.getSession().getString("stationId").equals(params.getStationId())); save(washOrder); return orderId; } @Override public void closeOrder(DeviceQueryParams params) { var order = lambdaQuery() .eq(WashOrder::getProductKey, params.getProductKey()) .eq(WashOrder::getDeviceName, params.getDeviceName()) .eq(WashOrder::getOrderStatus, WashOrder.ORDER_STATUS_开机) .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_未支付) .one(); if (order != null) { if (order.getUserId() == StpUtil.getLoginIdAsLong()) { awoaraService.closeOrder(params.getProductKey(), params.getDeviceName(), order.getOrderId()); } else { throw new BusinessException("您没有权限关闭该订单!"); } } } /** * 查询订单详情 * * @param params * @return */ @Override public WashOrder queryOrder(WashOrderQueryParams params) { // 非实时数据 WashOrder order = lambdaQuery() .eq(WashOrder::getOrderId, params.getOrderId()) .one(); if (null != params.getUserId()) { CommUtil.asserts(null != order && order.getUserId().equals(StpUtil.getLoginIdAsLong()), "订单不存在或您没有权限查看该订单!"); } return order; } /** * 查询停车减免订单 * * @param unionid * @return */ @Override public String getParkingDiscounts(String unionid) { var user = userService.lambdaQuery().eq(User::getUnionid, unionid).one(); CommUtil.asserts(null != user, "用户信息异常:无此用户"); // 查询用户24小时内的订单 var orders = lambdaQuery() .eq(WashOrder::getUserId, user.getId()) .ge(WashOrder::getStartTime, LocalDateTime.now().minusHours(24)) .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_已支付) .orderByDesc(WashOrder::getId) .list(); CommUtil.asserts(CommUtil.isEmptyOrNull(orders) && (orders.stream().mapToInt(WashOrder::getAmount).sum() >= 0), "抱歉:无停车场洗车记录"); return washStationService.lambdaQuery().eq(WashStation::getStationId, orders.get(0).getStationId()).one().getParkingQrCode(); } /** * 当前用户订单列表 * * @param params * @return */ @Override public PageBean listMyWashOrder(PageParams params) { PageHelper.startPage(params.getPageNum(), params.getPageSize()); var res = lambdaQuery() .eq(WashOrder::getUserId, StpUtil.getLoginIdAsLong()) .orderByDesc(WashOrder::getId) .list(); PageInfo pages = new PageInfo<>(res); var voList = pages.getList().stream().map(order -> { var vo = new WashOrderVo(); BeanUtils.copyProperties(order, vo); return vo; }).toList(); PageBean bean = new PageBean<>(voList); bean.setPages(pages.getPages()); bean.setPageNum(pages.getPageNum()); bean.setPageSize(pages.getPageSize()); bean.setTotal(pages.getTotal()); return bean; } //region 管理后台 @Override public PageBean list(WashOrderQueryParams params) { PageHelper.startPage(params.getPageNum(), params.getPageSize()); MPJLambdaWrapper wrapper = JoinWrappers.lambda(WashOrder.class) .selectAsClass(WashOrder.class, WashOrderVo.class) .selectAs(User::getMobilePhone, WashOrderVo::getMobilePhone) .leftJoin(User.class, User::getId, WashOrder::getUserId) .eq(CommUtil.isNotEmptyAndNull(params.getUserId()), WashOrder::getUserId, params.getUserId()) .eq(CommUtil.isNotEmptyAndNull(params.getMobilePhone()), User::getMobilePhone, params.getMobilePhone()) .eq(CommUtil.isNotEmptyAndNull(params.getOrderStatus()), WashOrder::getOrderStatus, params.getOrderStatus()) .eq(CommUtil.isNotEmptyAndNull(params.getPayStatus()), WashOrder::getPayStatus, params.getPayStatus()) .orderByDesc(WashOrder::getId); //连表查询 返回自定义ResultType List list = selectJoinList(WashOrderVo.class, wrapper); list.forEach(item -> { item.setStationName(KymCache.INSTANCE.getStationNameById(item.getStationId())); item.setUserStationId(KymCache.INSTANCE.getUserStationId(item.getUserId())); item.setUserStationName(KymCache.INSTANCE.getStationNameById(item.getUserStationId())); }); return new PageBean<>(list); } @Override public WashOrder detail(long id) { return getById(id); } /** * 统计指定日期各站点消费金额 * * @param statDay * @return */ @Override public Map sumAmountByDate(LocalDate statDay) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.select(WashOrder::getAmount, WashOrder::getStationId); wrapper.ge(WashOrder::getStartTime, LocalDateTime.of(statDay, LocalTime.MIN)); wrapper.gt(WashOrder::getStartTime, LocalDateTime.of(statDay, LocalTime.MAX)); var list = list(wrapper); // 按照站点分组统计金额 return list.stream().collect(Collectors.groupingBy(WashOrder::getStationId, Collectors.summingInt(WashOrder::getAmount))); } /** * 统计指定日期当月各站点总消费金额 * * @param statDay * @return */ @Override public Map sumMonthAmount(LocalDate statDay) { var startTime = statDay.with(TemporalAdjusters.firstDayOfMonth()).atTime(LocalTime.MIN); var endTime = statDay.with(TemporalAdjusters.lastDayOfMonth()).atTime(LocalTime.MAX); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.select(WashOrder::getAmount, WashOrder::getStationId); wrapper.ge(WashOrder::getStartTime, startTime); wrapper.lt(WashOrder::getStartTime, endTime); var list = list(wrapper); // 按照站点分组统计金额 return list.stream().collect(Collectors.groupingBy(WashOrder::getStationId, Collectors.summingInt(WashOrder::getAmount))); } /** * 统计指定日期订单数量 * * @param statDay * @return */ @Override public Map countDailyOrders(LocalDate statDay) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.ge(WashOrder::getStartTime, LocalDateTime.of(statDay, LocalTime.MIN)); wrapper.lt(WashOrder::getStartTime, LocalDateTime.of(statDay, LocalTime.MAX)); // 按照站点分组统计订单数量 return list(wrapper).stream().collect(Collectors.groupingBy(WashOrder::getStationId, Collectors.summingInt(o -> 1))); } /** * 统计指定日期订单数量 * * @param statDay * @return */ @Override public Map countMonthOrders(LocalDate statDay) { var startTime = statDay.with(TemporalAdjusters.firstDayOfMonth()).atTime(LocalTime.MIN); var endTime = statDay.with(TemporalAdjusters.lastDayOfMonth()).atTime(LocalTime.MAX); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.select(WashOrder::getStationId); wrapper.ge(WashOrder::getStartTime, startTime); wrapper.lt(WashOrder::getStartTime, endTime); // 按照站点分组统计订单数量 return list(wrapper).stream().collect(Collectors.groupingBy(WashOrder::getStationId, Collectors.summingInt(o -> 1))); } @Override public WashOrder getOrderInProgressByUserId(long userId) { return lambdaQuery() .eq(WashOrder::getUserId, userId) .eq(WashOrder::getPayStatus, WashOrder.PAY_STATUS_未支付) .one(); } @Override public List stationTrend(StatQueryParam params) { return baseMapper.StationTrend(params); } //endregion }