|
|
@@ -0,0 +1,234 @@
|
|
|
+package shop.alien.store.service.impl;
|
|
|
+
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import shop.alien.entity.store.*;
|
|
|
+import shop.alien.mapper.UserReservationTableMapper;
|
|
|
+import shop.alien.store.service.*;
|
|
|
+import shop.alien.store.vo.ReservationOrderPageVo;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 预订订单页面展示服务实现
|
|
|
+ *
|
|
|
+ * @author system
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class ReservationOrderPageServiceImpl implements ReservationOrderPageService {
|
|
|
+
|
|
|
+ private static final int PAYMENT_DEADLINE_MINUTES = 15;
|
|
|
+ private static final int ORDER_STATUS_UNPAID = 0;
|
|
|
+ private static final int CANCELLATION_FREE = 0;
|
|
|
+ private static final int CANCELLATION_NOT_FREE = 1;
|
|
|
+ private static final int CANCELLATION_CONDITIONAL = 2;
|
|
|
+
|
|
|
+ private final UserReservationOrderService userReservationOrderService;
|
|
|
+ private final StoreInfoService storeInfoService;
|
|
|
+ private final UserReservationService userReservationService;
|
|
|
+ private final UserReservationTableMapper userReservationTableMapper;
|
|
|
+ private final StoreBookingTableService storeBookingTableService;
|
|
|
+ private final StoreBookingCategoryService storeBookingCategoryService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ReservationOrderPageVo getPageByOrderId(Integer orderId) {
|
|
|
+ if (orderId == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ UserReservationOrder order = userReservationOrderService.getById(orderId);
|
|
|
+ if (order == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return buildPageVo(order.getStoreId(), order);
|
|
|
+ }
|
|
|
+
|
|
|
+ private ReservationOrderPageVo buildPageVo(Integer storeId, UserReservationOrder order) {
|
|
|
+ ReservationOrderPageVo vo = new ReservationOrderPageVo();
|
|
|
+ vo.setOrderId(order.getId());
|
|
|
+ vo.setOrderSn(order.getOrderSn());
|
|
|
+ vo.setOrderStatus(order.getOrderStatus());
|
|
|
+ vo.setPaymentStatus(derivePaymentStatus(order.getOrderStatus()));
|
|
|
+ vo.setPayAmount(order.getDepositAmount() != null ? order.getDepositAmount() : BigDecimal.ZERO);
|
|
|
+ vo.setPaymentDeadlineMinutes(PAYMENT_DEADLINE_MINUTES);
|
|
|
+
|
|
|
+ // 支付倒计时
|
|
|
+ vo.setPaymentDeadline(order.getPaymentDeadline());
|
|
|
+ int secondsLeft = computePaymentSecondsLeft(order);
|
|
|
+ vo.setPaymentSecondsLeft(secondsLeft);
|
|
|
+ vo.setCanContinuePay(Boolean.valueOf(ORDER_STATUS_UNPAID == order.getOrderStatus() && secondsLeft > 0));
|
|
|
+
|
|
|
+ // 页面标题后缀
|
|
|
+ vo.setPageTitleSuffix(buildPageTitleSuffix(order.getCancellationPolicyType()));
|
|
|
+
|
|
|
+ // 门店
|
|
|
+ if (storeId != null) {
|
|
|
+ StoreInfo store = storeInfoService.getById(storeId);
|
|
|
+ if (store != null) {
|
|
|
+ vo.setStoreId(storeId);
|
|
|
+ vo.setStoreName(store.getStoreName());
|
|
|
+ vo.setStoreAddress(store.getStoreAddress());
|
|
|
+ vo.setStoreTel(store.getStoreTel());
|
|
|
+ vo.setStorePosition(store.getStorePosition());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 预约信息
|
|
|
+ if (order.getReservationId() != null) {
|
|
|
+ UserReservation reservation = userReservationService.getById(order.getReservationId());
|
|
|
+ if (reservation != null) {
|
|
|
+ vo.setReservationDate(reservation.getReservationDate());
|
|
|
+ vo.setReservationDateText(formatDateWithToday(reservation.getReservationDate()));
|
|
|
+ vo.setGuestCount(reservation.getGuestCount());
|
|
|
+ vo.setDiningTimeSlotText(buildDiningTimeSlot(reservation.getStartTime(), reservation.getEndTime()));
|
|
|
+ vo.setDiningTimeText(buildDiningTimeSlot(reservation.getStartTime(), reservation.getEndTime()));
|
|
|
+
|
|
|
+ List<Integer> tableIds = listTableIdsByReservationId(reservation.getId());
|
|
|
+ List<StoreBookingTable> tables = new ArrayList<>();
|
|
|
+ String categoryName = null;
|
|
|
+ for (Integer tableId : tableIds) {
|
|
|
+ StoreBookingTable t = storeBookingTableService.getById(tableId);
|
|
|
+ if (t != null) {
|
|
|
+ tables.add(t);
|
|
|
+ if (categoryName == null && t.getCategoryId() != null) {
|
|
|
+ StoreBookingCategory cat = storeBookingCategoryService.getById(t.getCategoryId());
|
|
|
+ if (cat != null) {
|
|
|
+ categoryName = cat.getCategoryName();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String tableNumbersText = tables.stream().map(StoreBookingTable::getTableNumber).filter(Objects::nonNull).collect(Collectors.joining(","));
|
|
|
+ vo.setTableNumbersText(tableNumbersText.isEmpty() ? null : tableNumbersText);
|
|
|
+ vo.setGuestAndCategoryText(buildGuestAndCategoryText(categoryName, reservation.getGuestCount(), tables));
|
|
|
+ vo.setLocationTableText(buildLocationTableText(categoryName, tableNumbersText));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用凭证
|
|
|
+ vo.setVerificationCode(order.getVerificationCode());
|
|
|
+ vo.setVerificationUrl(order.getVerificationUrl());
|
|
|
+
|
|
|
+ // 预订说明
|
|
|
+ vo.setLateArrivalGraceMinutes(order.getLateArrivalGraceMinutes() != null ? order.getLateArrivalGraceMinutes() : 0);
|
|
|
+ vo.setSeatRetentionText(order.getLateArrivalGraceMinutes() != null && order.getLateArrivalGraceMinutes() > 0
|
|
|
+ ? "未按时到店座位保留" + order.getLateArrivalGraceMinutes() + "分钟"
|
|
|
+ : null);
|
|
|
+ vo.setDepositAmount(order.getDepositAmount());
|
|
|
+ vo.setDepositText(order.getDepositAmount() != null && order.getDepositAmount().compareTo(BigDecimal.ZERO) > 0
|
|
|
+ ? "需支付¥" + order.getDepositAmount().stripTrailingZeros().toPlainString() + "订金"
|
|
|
+ : null);
|
|
|
+ vo.setDepositRefundRule(order.getDepositRefundRule());
|
|
|
+ vo.setCancellationPolicyType(order.getCancellationPolicyType());
|
|
|
+ vo.setFreeCancellationDeadline(order.getFreeCancellationDeadline());
|
|
|
+ vo.setFreeCancellationDeadlineText(formatFreeCancellationDeadline(order.getFreeCancellationDeadline()));
|
|
|
+ vo.setCancellationPolicyText(buildCancellationPolicyText(order));
|
|
|
+
|
|
|
+ // 订单信息
|
|
|
+ vo.setOrderCreatedTime(order.getCreatedTime());
|
|
|
+ vo.setOrderCreatedTimeText(order.getCreatedTime() != null ? formatDateWithToday(order.getCreatedTime()) : null);
|
|
|
+ vo.setContactName(null);
|
|
|
+ vo.setContactPhone(null);
|
|
|
+ vo.setContactText(null);
|
|
|
+
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Integer> listTableIdsByReservationId(Integer reservationId) {
|
|
|
+ return userReservationTableMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<UserReservationTable>()
|
|
|
+ .eq(UserReservationTable::getReservationId, reservationId)
|
|
|
+ .orderByAsc(UserReservationTable::getSort)
|
|
|
+ .orderByAsc(UserReservationTable::getId)
|
|
|
+ ).stream().map(UserReservationTable::getTableId).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ private int computePaymentSecondsLeft(UserReservationOrder order) {
|
|
|
+ if (order.getOrderStatus() == null || order.getOrderStatus() != ORDER_STATUS_UNPAID || order.getPaymentDeadline() == null) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ long now = System.currentTimeMillis();
|
|
|
+ long deadline = order.getPaymentDeadline().getTime();
|
|
|
+ long diff = (deadline - now) / 1000;
|
|
|
+ return diff > 0 ? (int) diff : 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String buildPageTitleSuffix(Integer cancellationPolicyType) {
|
|
|
+ if (cancellationPolicyType == null) {
|
|
|
+ return "不可免责取消";
|
|
|
+ }
|
|
|
+ if (cancellationPolicyType == CANCELLATION_FREE) {
|
|
|
+ return "免费预订";
|
|
|
+ }
|
|
|
+ if (cancellationPolicyType == CANCELLATION_CONDITIONAL) {
|
|
|
+ return "分情况是否免责";
|
|
|
+ }
|
|
|
+ return "不可免责取消";
|
|
|
+ }
|
|
|
+
|
|
|
+ private String buildDiningTimeSlot(String startTime, String endTime) {
|
|
|
+ if (startTime == null && endTime == null) return null;
|
|
|
+ if (startTime != null && endTime != null) return startTime + "-" + endTime;
|
|
|
+ return startTime != null ? startTime : endTime;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String buildGuestAndCategoryText(String categoryName, Integer guestCount, List<StoreBookingTable> tables) {
|
|
|
+ int capacity = tables.stream().mapToInt(t -> t.getSeatingCapacity() != null ? t.getSeatingCapacity() : 0).max().orElse(guestCount != null ? guestCount : 0);
|
|
|
+ if (capacity <= 0 && guestCount != null) capacity = guestCount;
|
|
|
+ String part = categoryName != null ? categoryName : "预订";
|
|
|
+ return part + (capacity > 0 ? capacity + "人" : "");
|
|
|
+ }
|
|
|
+
|
|
|
+ private String buildLocationTableText(String categoryName, String tableNumbersText) {
|
|
|
+ if (categoryName != null && tableNumbersText != null && !tableNumbersText.isEmpty()) {
|
|
|
+ return categoryName + "|" + tableNumbersText;
|
|
|
+ }
|
|
|
+ if (tableNumbersText != null && !tableNumbersText.isEmpty()) return tableNumbersText;
|
|
|
+ return categoryName;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String formatDateWithToday(Date date) {
|
|
|
+ if (date == null) return null;
|
|
|
+ SimpleDateFormat f = new SimpleDateFormat("MM月dd日", Locale.CHINA);
|
|
|
+ String s = f.format(date);
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
+ Calendar d = Calendar.getInstance();
|
|
|
+ d.setTime(date);
|
|
|
+ if (cal.get(Calendar.YEAR) == d.get(Calendar.YEAR) && cal.get(Calendar.DAY_OF_YEAR) == d.get(Calendar.DAY_OF_YEAR)) {
|
|
|
+ s += " 今天";
|
|
|
+ }
|
|
|
+ return s;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String formatFreeCancellationDeadline(Date deadline) {
|
|
|
+ if (deadline == null) return null;
|
|
|
+ SimpleDateFormat f = new SimpleDateFormat("MM月dd日 HH:mm", Locale.CHINA);
|
|
|
+ return f.format(deadline) + "前可免责取消";
|
|
|
+ }
|
|
|
+
|
|
|
+ private String buildCancellationPolicyText(UserReservationOrder order) {
|
|
|
+ Integer type = order.getCancellationPolicyType();
|
|
|
+ if (type == null) return "取消将收取订金";
|
|
|
+ if (type == CANCELLATION_FREE) return "免费取消";
|
|
|
+ if (type == CANCELLATION_NOT_FREE) return "不可免责取消,取消将收取订金";
|
|
|
+ if (type == CANCELLATION_CONDITIONAL) {
|
|
|
+ String line = formatFreeCancellationDeadline(order.getFreeCancellationDeadline());
|
|
|
+ return line != null ? line + ";在上述时间前取消订金可原路返回,之后取消将收取订金" : "分情况是否免责,取消将收取订金";
|
|
|
+ }
|
|
|
+ return "取消将收取订金";
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 根据订单状态推导支付状态 0:未支付 1:已支付 2:已退款 */
|
|
|
+ private int derivePaymentStatus(Integer orderStatus) {
|
|
|
+ if (orderStatus == null) return 0;
|
|
|
+ if (orderStatus == 0) return 0;
|
|
|
+ if (orderStatus == 6 || orderStatus == 7) return 2;
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+}
|