BookReservationServiceImpl.java

package org.darkroomlibrary.service.impl;

import org.darkroomlibrary.context.CurrentUserContext;
import org.darkroomlibrary.mapper.BookMapper;
import org.darkroomlibrary.mapper.BookReservationMapper;
import org.darkroomlibrary.mapper.BorrowRecordMapper;
import org.darkroomlibrary.mapper.UserMapper;
import org.darkroomlibrary.web.response.ApiResponse;
import org.darkroomlibrary.web.response.PageResponse;
import org.darkroomlibrary.web.dto.query.BookReservationPageQuery;
import org.darkroomlibrary.domain.type.AccountStatus;
import org.darkroomlibrary.domain.type.UserRole;
import org.darkroomlibrary.domain.model.Book;
import org.darkroomlibrary.domain.model.BookReservation;
import org.darkroomlibrary.domain.model.User;
import org.darkroomlibrary.web.view.BookReservationView;
import org.darkroomlibrary.service.BookReservationService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 图书预约服务实现
 */
@Service
public class BookReservationServiceImpl implements BookReservationService {

    @Resource
    private BookReservationMapper bookReservationMapper;

    @Resource
    private BookMapper bookMapper;

    @Resource
    private BorrowRecordMapper borrowRecordMapper;

    @Resource
    private UserMapper userMapper;

    @Value("${reservation.max-count:3}")
    private int maxReservationCount;

    @Override
    @Transactional
    public ApiResponse<Void> reserve(Integer bookId) {
        Integer userId = CurrentUserContext.userId();
        if (userId == null) {
            return ApiResponse.error("身份认证失败,请先登录");
        }
        if (bookId == null) {
            return ApiResponse.error("图书编号不能为空");
        }
        User user = userMapper.findByIdForUpdate(userId);
        if (user == null) {
            return ApiResponse.error("当前用户不存在或已被删除");
        }
        if (!java.util.Objects.equals(user.getAccountStatus(), AccountStatus.NORMAL.code())
                || Boolean.TRUE.equals(user.getIsLogin())
                || !java.util.Objects.equals(user.getUserRole(), CurrentUserContext.roleCode())
                || !java.util.Objects.equals(user.getUserRole(), UserRole.READER.code())) {
            return ApiResponse.error("当前账号状态不允许预约");
        }
        int activeCount = bookReservationMapper.countActiveByUserId(userId);
        if (activeCount >= maxReservationCount) {
            return ApiResponse.error("预约数量已达上限(" + maxReservationCount + "本),请先取消其他预约");
        }
        Book book = bookMapper.findByIdForUpdate(bookId);
        if (book == null || Boolean.TRUE.equals(book.getIsDeleted())) {
            return ApiResponse.error("图书不存在");
        }
        if (borrowRecordMapper.countActiveByUserIdAndBookId(userId, bookId) > 0) {
            return ApiResponse.error("您正在借阅该图书,无需重复预约");
        }
        if (book.getAvailableCount() != null && book.getAvailableCount() > 0) {
            return ApiResponse.error("图书还有库存,可直接借阅,无需预约");
        }
        BookReservation reservation = BookReservation.builder()
                .userId(userId)
                .bookId(bookId)
                .reserveTime(LocalDateTime.now())
                .status(0)
                .build();
        try {
            int inserted = bookReservationMapper.insertIfNoActiveReservation(reservation);
            if (inserted == 0) {
                return ApiResponse.error("您已预约过该图书,请勿重复预约");
            }
        } catch (DuplicateKeyException e) {
            return ApiResponse.error("您已预约过该图书,请勿重复预约");
        }
        return ApiResponse.success("预约成功,图书到货后会通知您");
    }

    @Override
    @Transactional
    public ApiResponse<Void> cancel(Integer reservationId) {
        Integer userId = CurrentUserContext.userId();
        BookReservation reservation = bookReservationMapper.getById(reservationId);
        if (reservation == null) {
            return ApiResponse.error("预约记录不存在");
        }
        if (!reservation.getUserId().equals(userId)) {
            return ApiResponse.error("该预约记录不属于当前用户");
        }
        if (reservation.getStatus() != 0) {
            return ApiResponse.error("该预约已处理,无法取消");
        }
        if (bookReservationMapper.cancelWaiting(reservationId, userId) == 0) {
            return ApiResponse.error("该预约状态已变化,请刷新后重试");
        }
        return ApiResponse.success("取消预约成功");
    }

    @Override
    public ApiResponse<List<BookReservationView>> query(BookReservationPageQuery dto) {
        if (dto == null) {
            dto = new BookReservationPageQuery();
        }
        if (!CurrentUserContext.isAdministrator()) {
            dto.setUserId(CurrentUserContext.userId());
        }
        List<BookReservationView> list = bookReservationMapper.query(dto);
        Integer total = bookReservationMapper.queryCount(dto);
        return PageResponse.success(list, total);
    }

}