|
|
@@ -3,17 +3,21 @@ package space.anyi.petServiceManagementSystem.server.service.impl;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
+import space.anyi.petServiceManagementSystem.server.common.BusinessException;
|
|
|
+import space.anyi.petServiceManagementSystem.server.dto.room.BatchRoomStatusDto;
|
|
|
+import space.anyi.petServiceManagementSystem.server.dto.room.BoardingRoomCreateDto;
|
|
|
import space.anyi.petServiceManagementSystem.server.dto.room.RoomStatusDto;
|
|
|
-import space.anyi.petServiceManagementSystem.server.entity.BoardingRoom;
|
|
|
-import space.anyi.petServiceManagementSystem.server.entity.BoardingRoomStatus;
|
|
|
-import space.anyi.petServiceManagementSystem.server.mapper.BoardingRoomMapper;
|
|
|
-import space.anyi.petServiceManagementSystem.server.mapper.BoardingRoomStatusMapper;
|
|
|
+import space.anyi.petServiceManagementSystem.server.entity.*;
|
|
|
+import space.anyi.petServiceManagementSystem.server.mapper.*;
|
|
|
import space.anyi.petServiceManagementSystem.server.service.BoardingRoomService;
|
|
|
import space.anyi.petServiceManagementSystem.server.vo.room.BoardingRoomVo;
|
|
|
import space.anyi.petServiceManagementSystem.server.vo.room.RoomStatusVo;
|
|
|
+import space.anyi.petServiceManagementSystem.server.vo.room.TodayGuestVo;
|
|
|
+import space.anyi.petServiceManagementSystem.server.vo.room.TodayStatusVo;
|
|
|
|
|
|
import java.time.LocalDate;
|
|
|
import java.time.YearMonth;
|
|
|
+import java.time.temporal.ChronoUnit;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
@@ -28,12 +32,62 @@ public class BoardingRoomServiceImpl implements BoardingRoomService {
|
|
|
@Autowired
|
|
|
private BoardingRoomStatusMapper boardingRoomStatusMapper;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private AppointmentMapper appointmentMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private PetMapper petMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private UserMapper userMapper;
|
|
|
+
|
|
|
@Override
|
|
|
public List<BoardingRoomVo> listRooms() {
|
|
|
return boardingRoomMapper.selectActive().stream()
|
|
|
.map(this::toBoardingRoomVo).collect(Collectors.toList());
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public List<BoardingRoomVo> listAllRooms() {
|
|
|
+ return boardingRoomMapper.selectAll().stream()
|
|
|
+ .map(this::toBoardingRoomVo).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public BoardingRoomVo createRoom(BoardingRoomCreateDto dto) {
|
|
|
+ BoardingRoom room = new BoardingRoom();
|
|
|
+ room.setRoomName(dto.getRoomName());
|
|
|
+ room.setRoomType(dto.getRoomType());
|
|
|
+ room.setCapacity(dto.getCapacity());
|
|
|
+ room.setPricePerDay(dto.getPricePerDay());
|
|
|
+ room.setDescription(dto.getDescription());
|
|
|
+ room.setIsActive(1);
|
|
|
+ boardingRoomMapper.insert(room);
|
|
|
+ return toBoardingRoomVo(room);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Boolean updateRoom(Long id, BoardingRoomCreateDto dto) {
|
|
|
+ BoardingRoom room = boardingRoomMapper.selectById(id);
|
|
|
+ if (room == null) {
|
|
|
+ throw new BusinessException("房型不存在");
|
|
|
+ }
|
|
|
+ room.setRoomName(dto.getRoomName());
|
|
|
+ room.setRoomType(dto.getRoomType());
|
|
|
+ room.setCapacity(dto.getCapacity());
|
|
|
+ room.setPricePerDay(dto.getPricePerDay());
|
|
|
+ room.setDescription(dto.getDescription());
|
|
|
+ return boardingRoomMapper.update(room) > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Boolean deleteRoom(Long id) {
|
|
|
+ return boardingRoomMapper.deleteById(id) > 0;
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public List<RoomStatusVo> getStatus(Long roomId, String month) {
|
|
|
YearMonth yearMonth = YearMonth.parse(month);
|
|
|
@@ -74,6 +128,93 @@ public class BoardingRoomServiceImpl implements BoardingRoomService {
|
|
|
return boardingRoomStatusMapper.insertOrUpdate(status) > 0;
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Boolean batchUpdateStatus(Long roomId, BatchRoomStatusDto dto) {
|
|
|
+ // 校验日期范围不超过31天
|
|
|
+ long daysBetween = ChronoUnit.DAYS.between(dto.getStartDate(), dto.getEndDate());
|
|
|
+ if (daysBetween < 0) {
|
|
|
+ throw new BusinessException("结束日期必须大于或等于开始日期");
|
|
|
+ }
|
|
|
+ if (daysBetween > 31) {
|
|
|
+ throw new BusinessException("批量修改日期范围不能超过31天");
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i <= daysBetween; i++) {
|
|
|
+ BoardingRoomStatus status = new BoardingRoomStatus();
|
|
|
+ status.setRoomId(roomId);
|
|
|
+ status.setDate(dto.getStartDate().plusDays(i));
|
|
|
+ status.setStatus(dto.getStatus());
|
|
|
+ // 手动修改时,如果原来有关联预约,自动清除(由 ON DUPLICATE KEY UPDATE 的 appointment_id=null 处理)
|
|
|
+ boardingRoomStatusMapper.insertOrUpdate(status);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public TodayStatusVo getTodayStatus() {
|
|
|
+ LocalDate today = LocalDate.now();
|
|
|
+
|
|
|
+ // 获取所有启用房型
|
|
|
+ List<BoardingRoom> rooms = boardingRoomMapper.selectActive();
|
|
|
+
|
|
|
+ // 获取今日所有房态记录
|
|
|
+ List<BoardingRoomStatus> todayStatuses = boardingRoomStatusMapper.selectByDate(today);
|
|
|
+
|
|
|
+ // 构建 roomId → status 的映射
|
|
|
+ Map<Long, BoardingRoomStatus> statusMap = todayStatuses.stream()
|
|
|
+ .collect(Collectors.toMap(BoardingRoomStatus::getRoomId, s -> s));
|
|
|
+
|
|
|
+ int availableCount = 0;
|
|
|
+ int occupiedCount = 0;
|
|
|
+ int maintenanceCount = 0;
|
|
|
+ List<TodayGuestVo> todayGuests = new ArrayList<>();
|
|
|
+
|
|
|
+ for (BoardingRoom room : rooms) {
|
|
|
+ BoardingRoomStatus s = statusMap.get(room.getId());
|
|
|
+ String status = (s != null) ? s.getStatus() : "AVAILABLE";
|
|
|
+ switch (status) {
|
|
|
+ case "OCCUPIED":
|
|
|
+ occupiedCount++;
|
|
|
+ if (s.getAppointmentId() != null) {
|
|
|
+ TodayGuestVo guest = buildTodayGuest(room, s.getAppointmentId());
|
|
|
+ if (guest != null) {
|
|
|
+ todayGuests.add(guest);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case "MAINTENANCE":
|
|
|
+ maintenanceCount++;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ availableCount++;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ TodayStatusVo vo = new TodayStatusVo();
|
|
|
+ vo.setTotalRooms(rooms.size());
|
|
|
+ vo.setAvailableCount(availableCount);
|
|
|
+ vo.setOccupiedCount(occupiedCount);
|
|
|
+ vo.setMaintenanceCount(maintenanceCount);
|
|
|
+ vo.setTodayGuests(todayGuests);
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ private TodayGuestVo buildTodayGuest(BoardingRoom room, Long appointmentId) {
|
|
|
+ Appointment appointment = appointmentMapper.selectById(appointmentId);
|
|
|
+ if (appointment == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Pet pet = petMapper.selectById(appointment.getPetId());
|
|
|
+ User user = userMapper.selectById(appointment.getUserId());
|
|
|
+ TodayGuestVo guest = new TodayGuestVo();
|
|
|
+ guest.setRoomName(room.getRoomName());
|
|
|
+ guest.setPetName(pet != null ? pet.getName() : "未知");
|
|
|
+ guest.setOwnerName(user != null ? user.getUsername() : "未知");
|
|
|
+ return guest;
|
|
|
+ }
|
|
|
+
|
|
|
private BoardingRoomVo toBoardingRoomVo(BoardingRoom room) {
|
|
|
BoardingRoomVo vo = new BoardingRoomVo();
|
|
|
vo.setId(room.getId());
|