|
|
@@ -12,11 +12,13 @@ import org.springframework.transaction.annotation.Transactional;
|
|
|
import shop.alien.entity.store.*;
|
|
|
import shop.alien.entity.store.dto.UserReservationDTO;
|
|
|
import shop.alien.entity.store.vo.StoreMainInfoVo;
|
|
|
+import shop.alien.entity.store.vo.StoreReservationListVo;
|
|
|
import shop.alien.entity.store.vo.UserReservationVo;
|
|
|
import shop.alien.mapper.UserReservationMapper;
|
|
|
import shop.alien.mapper.UserReservationTableMapper;
|
|
|
import shop.alien.store.service.*;
|
|
|
|
|
|
+import java.text.ParseException;
|
|
|
import java.text.SimpleDateFormat;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
|
@@ -43,6 +45,8 @@ public class UserReservationServiceImpl extends ServiceImpl<UserReservationMappe
|
|
|
|
|
|
private final StoreInfoService storeInfoService;
|
|
|
|
|
|
+ private final UserReservationOrderService userReservationOrderService;
|
|
|
+
|
|
|
/** 预约状态:待确认 */
|
|
|
private static final int STATUS_PENDING = 0;
|
|
|
/** 预约状态:已取消(不参与约满统计与展示) */
|
|
|
@@ -275,6 +279,237 @@ public class UserReservationServiceImpl extends ServiceImpl<UserReservationMappe
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public List<StoreReservationListVo> getStoreReservationList(Integer storeId, Integer status, Date dateFrom, Date dateTo, Integer orderStatus) {
|
|
|
+ log.info("UserReservationServiceImpl.getStoreReservationList?storeId={}, status={}, dateFrom={}, dateTo={}, orderStatus={}",
|
|
|
+ storeId, status, dateFrom, dateTo, orderStatus);
|
|
|
+
|
|
|
+ if (storeId == null) {
|
|
|
+ throw new RuntimeException("门店ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ return baseMapper.getStoreReservationList(storeId, status, dateFrom, dateTo, orderStatus);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean cancelReservationByStore(Integer reservationId) {
|
|
|
+ log.info("UserReservationServiceImpl.cancelReservationByStore?reservationId={}", reservationId);
|
|
|
+
|
|
|
+ if (reservationId == null) {
|
|
|
+ throw new RuntimeException("预约ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询预约信息
|
|
|
+ UserReservation reservation = this.getById(reservationId);
|
|
|
+ if (reservation == null) {
|
|
|
+ throw new RuntimeException("预约不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查预约状态,已取消的不能再次取消
|
|
|
+ if (reservation.getStatus() != null && reservation.getStatus() == STATUS_CANCELLED) {
|
|
|
+ throw new RuntimeException("预约已取消,不能重复取消");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询关联的订单信息
|
|
|
+ LambdaQueryWrapper<UserReservationOrder> orderWrapper = new LambdaQueryWrapper<>();
|
|
|
+ orderWrapper.eq(UserReservationOrder::getReservationId, reservationId);
|
|
|
+ UserReservationOrder order = userReservationOrderService.getOne(orderWrapper);
|
|
|
+
|
|
|
+ if (order == null) {
|
|
|
+ // 如果没有订单,直接更新预约状态为3(已取消)
|
|
|
+ reservation.setStatus(STATUS_CANCELLED); // STATUS_CANCELLED = 3
|
|
|
+ boolean updateResult = this.updateById(reservation);
|
|
|
+ if (!updateResult) {
|
|
|
+ throw new RuntimeException("更新预约状态失败");
|
|
|
+ }
|
|
|
+ log.info("商家端取消预约成功(无订单),reservationId={}", reservationId);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断订单费用类型:0-免费, 1-收费
|
|
|
+ Integer orderCostType = order.getOrderCostType();
|
|
|
+ if (orderCostType == null) {
|
|
|
+ // 如果订单费用类型为空,默认按免费处理
|
|
|
+ orderCostType = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (orderCostType == 0) {
|
|
|
+ // 免费订单:更新订单状态为4(已取消),更新预约状态为3(已取消)
|
|
|
+ order.setOrderStatus(4); // 4:已取消
|
|
|
+ boolean orderUpdateResult = userReservationOrderService.updateById(order);
|
|
|
+ if (!orderUpdateResult) {
|
|
|
+ throw new RuntimeException("更新订单状态失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ reservation.setStatus(STATUS_CANCELLED); // STATUS_CANCELLED = 3:已取消
|
|
|
+ boolean reservationUpdateResult = this.updateById(reservation);
|
|
|
+ if (!reservationUpdateResult) {
|
|
|
+ throw new RuntimeException("更新预约状态失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("商家端取消预约成功(免费订单),reservationId={}, orderId={}", reservationId, order.getId());
|
|
|
+ return true;
|
|
|
+ } else if (orderCostType == 1) {
|
|
|
+ // 付费订单:功能预留(暂不更新状态,等待后续实现退款逻辑)
|
|
|
+ throw new RuntimeException("付费订单取消功能暂未实现,请稍后再试");
|
|
|
+ } else {
|
|
|
+ throw new RuntimeException("订单费用类型异常,orderCostType=" + orderCostType);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean deleteReservationByStore(Integer reservationId) {
|
|
|
+ log.info("UserReservationServiceImpl.deleteReservationByStore?reservationId={}", reservationId);
|
|
|
+
|
|
|
+ if (reservationId == null) {
|
|
|
+ throw new RuntimeException("预约ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询预约信息
|
|
|
+ UserReservation reservation = this.getById(reservationId);
|
|
|
+ if (reservation == null) {
|
|
|
+ throw new RuntimeException("预约不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询关联的订单信息
|
|
|
+ LambdaQueryWrapper<UserReservationOrder> orderWrapper = new LambdaQueryWrapper<>();
|
|
|
+ orderWrapper.eq(UserReservationOrder::getReservationId, reservationId);
|
|
|
+ UserReservationOrder order = userReservationOrderService.getOne(orderWrapper);
|
|
|
+
|
|
|
+ if (order == null) {
|
|
|
+ // 如果没有订单,直接删除预约记录
|
|
|
+ boolean deleteResult = this.removeById(reservationId);
|
|
|
+ if (!deleteResult) {
|
|
|
+ throw new RuntimeException("删除预约记录失败");
|
|
|
+ }
|
|
|
+ log.info("商家端删除预订信息成功(无订单),reservationId={}", reservationId);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断订单状态:只有已取消(4)、已退款(7)、已完成(2)状态才能删除
|
|
|
+ Integer orderStatus = order.getOrderStatus();
|
|
|
+ if (orderStatus == null) {
|
|
|
+ throw new RuntimeException("订单状态异常,无法删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 定义可删除的订单状态:2:已完成, 4:已取消, 7:已退款
|
|
|
+ boolean canDelete = orderStatus == 2 || orderStatus == 4 || orderStatus == 7;
|
|
|
+
|
|
|
+ if (!canDelete) {
|
|
|
+ String statusText = getOrderStatusText(orderStatus);
|
|
|
+ throw new RuntimeException("订单状态为" + statusText + ",不允许删除。只有已取消、已退款、已完成状态的订单可以删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除订单记录(逻辑删除)
|
|
|
+ boolean orderDeleteResult = userReservationOrderService.removeById(order.getId());
|
|
|
+ if (!orderDeleteResult) {
|
|
|
+ throw new RuntimeException("删除订单记录失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除预约记录(逻辑删除)
|
|
|
+ boolean reservationDeleteResult = this.removeById(reservationId);
|
|
|
+ if (!reservationDeleteResult) {
|
|
|
+ throw new RuntimeException("删除预约记录失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("商家端删除预订信息成功,reservationId={}, orderId={}, orderStatus={}",
|
|
|
+ reservationId, order.getId(), orderStatus);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取订单状态文本
|
|
|
+ */
|
|
|
+ private String getOrderStatusText(Integer orderStatus) {
|
|
|
+ if (orderStatus == null) {
|
|
|
+ return "未知";
|
|
|
+ }
|
|
|
+ switch (orderStatus) {
|
|
|
+ case 0: return "待支付";
|
|
|
+ case 1: return "待使用";
|
|
|
+ case 2: return "已完成";
|
|
|
+ case 3: return "已过期";
|
|
|
+ case 4: return "已取消";
|
|
|
+ case 5: return "已关闭";
|
|
|
+ case 6: return "退款中";
|
|
|
+ case 7: return "已退款";
|
|
|
+ case 8: return "商家预订";
|
|
|
+ default: return "未知";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean addTimeByStore(Integer reservationId, String addTimeStart, Integer addTimeMinutes) {
|
|
|
+ log.info("UserReservationServiceImpl.addTimeByStore?reservationId={}, addTimeStart={}, addTimeMinutes={}",
|
|
|
+ reservationId, addTimeStart, addTimeMinutes);
|
|
|
+
|
|
|
+ if (reservationId == null) {
|
|
|
+ throw new RuntimeException("预约ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (addTimeStart == null || addTimeStart.trim().isEmpty()) {
|
|
|
+ throw new RuntimeException("加时开始时间不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (addTimeMinutes == null || addTimeMinutes <= 0) {
|
|
|
+ throw new RuntimeException("加时分钟数必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证时间格式 HH:mm
|
|
|
+ if (!addTimeStart.matches("^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$")) {
|
|
|
+ throw new RuntimeException("加时开始时间格式错误,应为HH:mm格式");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询预约信息
|
|
|
+ UserReservation reservation = this.getById(reservationId);
|
|
|
+ if (reservation == null) {
|
|
|
+ throw new RuntimeException("预约不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存原结束时间用于日志
|
|
|
+ String oldEndTime = reservation.getEndTime();
|
|
|
+
|
|
|
+ // 计算新的结束时间:加时开始时间 + 加时分钟数
|
|
|
+ String newEndTime = calculateNewEndTime(addTimeStart, addTimeMinutes);
|
|
|
+
|
|
|
+ // 更新预约结束时间
|
|
|
+ reservation.setEndTime(newEndTime);
|
|
|
+ boolean updateResult = this.updateById(reservation);
|
|
|
+ if (!updateResult) {
|
|
|
+ throw new RuntimeException("更新预约结束时间失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("商家端加时成功,reservationId={}, 原结束时间={}, 加时开始时间={}, 加时分钟数={}, 新结束时间={}",
|
|
|
+ reservationId, oldEndTime, addTimeStart, addTimeMinutes, newEndTime);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算新的结束时间:加时开始时间 + 加时分钟数
|
|
|
+ *
|
|
|
+ * @param addTimeStart 加时开始时间(HH:mm格式)
|
|
|
+ * @param addTimeMinutes 加时分钟数
|
|
|
+ * @return 新的结束时间(HH:mm格式)
|
|
|
+ */
|
|
|
+ private String calculateNewEndTime(String addTimeStart, Integer addTimeMinutes) {
|
|
|
+ try {
|
|
|
+ // 解析加时开始时间
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
|
|
|
+ Date startDate = sdf.parse(addTimeStart);
|
|
|
+
|
|
|
+ // 加上加时分钟数
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
+ calendar.setTime(startDate);
|
|
|
+ calendar.add(Calendar.MINUTE, addTimeMinutes);
|
|
|
+
|
|
|
+ // 格式化为HH:mm
|
|
|
+ return sdf.format(calendar.getTime());
|
|
|
+ } catch (ParseException e) {
|
|
|
+ log.error("计算新的结束时间失败,addTimeStart={}, addTimeMinutes={}", addTimeStart, addTimeMinutes, e);
|
|
|
+ throw new RuntimeException("时间计算失败:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private static String generateReservationNo() {
|
|
|
return "RV" + System.currentTimeMillis() + ThreadLocalRandom.current().nextInt(1000, 9999);
|
|
|
}
|