package github.benjamin.equipreservebackend.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import github.benjamin.equipreservebackend.constant.ReservationStatus; import github.benjamin.equipreservebackend.entity.Device; import github.benjamin.equipreservebackend.entity.Reservation; import github.benjamin.equipreservebackend.entity.Role; import github.benjamin.equipreservebackend.entity.User; import github.benjamin.equipreservebackend.exception.ApiException; import github.benjamin.equipreservebackend.mapper.*; import github.benjamin.equipreservebackend.service.ReservationService; import github.benjamin.equipreservebackend.utils.PageUtil; import github.benjamin.equipreservebackend.vo.*; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class ReservationServiceImpl implements ReservationService { private final ReservationMapper reservationMapper; private final DeviceMapper deviceMapper; private final UserMapper userMapper; private final TeamMapper teamMapper; private final RoleMapper roleMapper; /** * 未来days天内有预约的设备显示为“有预约” */ @Value("${equip-reserve.device-days}") private Integer days; @Override public List getApprovedReservationsByDeviceIds(List devicesIds) { LocalDate now = LocalDate.now(); LocalDate endTime = now.plusDays(days); return reservationMapper.selectList(new LambdaQueryWrapper() .in(Reservation::getDeviceId, devicesIds) .in(Reservation::getStatus, List.of(ReservationStatus.APPROVED, ReservationStatus.APPROVED_ASSIST)) .between(Reservation::getStartTime, now, endTime)); } @Override public void addReservation(Reservation reservation) { User user = userMapper.selectById(reservation.getUserId()); Device device = deviceMapper.selectById(reservation.getDeviceId()); reservation.setDeviceAdminId(device.getDeviceAdminId()); reservation.setStatus(String.valueOf(ReservationStatus.PENDING_LEADER)); reservationMapper.insert(reservation); } @Override public Page getUserReservationVO(Long userId, Page pageRequest) { Page reservations = reservationMapper.selectPage(pageRequest, new LambdaQueryWrapper() .eq(Reservation::getUserId, userId) .orderByDesc(Reservation::getCreatedTime)); Page res = PageUtil.copyPage(reservations); if (reservations.getRecords().isEmpty()) { res.setTotal(0); res.setRecords(Collections.EMPTY_LIST); return res; } // 获取设备名称 List deviceIds = reservations.getRecords().stream() .map(Reservation::getDeviceId) .distinct() .toList(); Map deviceNameMap = deviceMapper.selectList(new LambdaQueryWrapper() .in(Device::getId, deviceIds)) .stream() .collect(Collectors.toMap(Device::getId, Function.identity())); List teamIds = deviceNameMap.values().stream().map(Device::getTeamId).toList(); Map teamLeaderMap = userMapper.selectLeaderByTeamIds(teamIds); // 获取设备管理员信息 List deviceAdminIDs = reservations.getRecords().stream() .map(Reservation::getDeviceAdminId) .filter(Objects::nonNull) .distinct() .toList(); List vos; Map deviceAdminMap = userMapper.selectList(new LambdaQueryWrapper() .in(User::getId, deviceAdminIDs)) .stream() .collect(Collectors.toMap(User::getId, Function.identity())); vos = reservations.getRecords().stream() .map(reservation -> new UserReservationVO(reservation, deviceNameMap, deviceAdminMap, teamLeaderMap)) .toList(); res.setRecords(vos); return res; } @Override public List getUnavailableTimes(Long id) { List reservations = reservationMapper.selectList(new LambdaQueryWrapper() .eq(Reservation::getDeviceId, id) .in(Reservation::getStatus, List.of(ReservationStatus.APPROVED, ReservationStatus.APPROVED_ASSIST)) .gt(Reservation::getEndTime, LocalDate.now())); return reservations.stream() .map(r -> new TimeRangeVO(r.getStartTime(), r.getEndTime())) .toList(); } @Override public Page getReservationVO(Long userId, Integer page, Integer size) { User user = userMapper.selectById(userId); List devices = deviceMapper.selectList(new LambdaQueryWrapper() .eq(Device::getTeamId, user.getTeamId()) .select()); if (devices.isEmpty()) { return (Page) PageUtil.EMPTY_PAGE; } List userRole = roleMapper.selectRoleByUserId(userId); ReservationStatus status; if (userRole.stream().anyMatch(r -> r.getCode().equals("LEADER"))) { status = ReservationStatus.PENDING_LEADER; } else if (userRole.stream().anyMatch(r -> r.getCode().equals("DEVICE_ADMIN"))) { status = ReservationStatus.PENDING_DEVICE_ADMIN; } else { throw new ApiException("用户角色不正确,请检查或联系开发人员"); } List deviceIds = devices.stream().map(Device::getId).toList(); Map deviceMap = devices.stream().collect(Collectors.toMap(Device::getId, Function.identity())); Page reservationPage = reservationMapper.selectPage(new Page<>(page, size), new LambdaQueryWrapper() .in(Reservation::getDeviceId, deviceIds) .eq(Reservation::getStatus, status) .orderByDesc(Reservation::getCreatedTime)); Page res = PageUtil.copyPage(reservationPage); res.setRecords(reservationPage.getRecords().stream() .map(r -> new ReservationVO(r, deviceMap.get(r.getDeviceId()))) .toList()); return res; } @Override public List getReservationStats(LocalDate start, LocalDate end) { return reservationMapper.getReservationStats(start, end); } @Override public List getDeviceDetailStats(Long deviceId, LocalDate start, LocalDate end) { return reservationMapper.selectList(new LambdaQueryWrapper() .eq(Reservation::getDeviceId, deviceId) .in(Reservation::getStatus, List.of("APPROVED", "APPROVED_ASSIST")) .ge(Reservation::getStartTime, start) .le(Reservation::getEndTime, end) .orderByAsc(Reservation::getApplicantName, Reservation::getStartTime)).stream().map(DeviceDetailStatsVO::new).toList(); } @Override public void updateEndTime(Long reservationId, LocalDate endTime) { reservationMapper.update(new LambdaUpdateWrapper() .eq(Reservation::getId, reservationId) .set(Reservation::getEndTime, endTime)); } }