Parcourir la source

feat:房间管理API变更

yangyi il y a 4 mois
Parent
commit
443935a601
22 fichiers modifiés avec 405 ajouts et 92 suppressions
  1. 49 0
      src/main/java/space/anyi/petServiceManagementSystem/server/controller/admin/AdminBoardingRoomController.java
  2. 23 0
      src/main/java/space/anyi/petServiceManagementSystem/server/dto/room/BatchRoomStatusDto.java
  3. 30 0
      src/main/java/space/anyi/petServiceManagementSystem/server/dto/room/BoardingRoomCreateDto.java
  4. 17 17
      src/main/java/space/anyi/petServiceManagementSystem/server/entity/Appointment.java
  5. 9 9
      src/main/java/space/anyi/petServiceManagementSystem/server/entity/BoardingRoom.java
  6. 6 6
      src/main/java/space/anyi/petServiceManagementSystem/server/entity/BoardingRoomStatus.java
  7. 8 8
      src/main/java/space/anyi/petServiceManagementSystem/server/entity/DewormingRecord.java
  8. 12 12
      src/main/java/space/anyi/petServiceManagementSystem/server/entity/Pet.java
  9. 6 6
      src/main/java/space/anyi/petServiceManagementSystem/server/entity/Schedule.java
  10. 9 9
      src/main/java/space/anyi/petServiceManagementSystem/server/entity/ServicePackage.java
  11. 11 11
      src/main/java/space/anyi/petServiceManagementSystem/server/entity/User.java
  12. 8 8
      src/main/java/space/anyi/petServiceManagementSystem/server/entity/VaccinationRecord.java
  13. 2 0
      src/main/java/space/anyi/petServiceManagementSystem/server/mapper/BoardingRoomMapper.java
  14. 1 0
      src/main/java/space/anyi/petServiceManagementSystem/server/mapper/BoardingRoomStatusMapper.java
  15. 9 0
      src/main/java/space/anyi/petServiceManagementSystem/server/service/BoardingRoomService.java
  16. 11 1
      src/main/java/space/anyi/petServiceManagementSystem/server/service/impl/AppointmentServiceImpl.java
  17. 145 4
      src/main/java/space/anyi/petServiceManagementSystem/server/service/impl/BoardingRoomServiceImpl.java
  18. 14 0
      src/main/java/space/anyi/petServiceManagementSystem/server/vo/room/TodayGuestVo.java
  19. 22 0
      src/main/java/space/anyi/petServiceManagementSystem/server/vo/room/TodayStatusVo.java
  20. 1 1
      src/main/resources/mapper/AppointmentMapper.xml
  21. 8 0
      src/main/resources/mapper/BoardingRoomMapper.xml
  22. 4 0
      src/main/resources/mapper/BoardingRoomStatusMapper.xml

+ 49 - 0
src/main/java/space/anyi/petServiceManagementSystem/server/controller/admin/AdminBoardingRoomController.java

@@ -5,8 +5,15 @@ import jakarta.validation.Valid;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 import space.anyi.petServiceManagementSystem.server.common.R;
 import space.anyi.petServiceManagementSystem.server.common.R;
+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.dto.room.RoomStatusDto;
 import space.anyi.petServiceManagementSystem.server.service.BoardingRoomService;
 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.TodayStatusVo;
+
+import java.util.List;
 
 
 @RestController
 @RestController
 @RequestMapping("/admin/boarding-rooms")
 @RequestMapping("/admin/boarding-rooms")
@@ -15,9 +22,51 @@ public class AdminBoardingRoomController {
     @Autowired
     @Autowired
     private BoardingRoomService boardingRoomService;
     private BoardingRoomService boardingRoomService;
 
 
+    @GetMapping
+    @Operation(summary = "获取所有房型(含已禁用)")
+    public R<List<BoardingRoomVo>> listAll() {
+        return R.ok(boardingRoomService.listAllRooms());
+    }
+
+    @PostMapping
+    @Operation(summary = "新增房型")
+    public R<BoardingRoomVo> create(@Valid @RequestBody BoardingRoomCreateDto dto) {
+        return R.ok(boardingRoomService.createRoom(dto));
+    }
+
+    @PutMapping("/{id}")
+    @Operation(summary = "修改房型信息")
+    public R<Boolean> update(@PathVariable Long id, @Valid @RequestBody BoardingRoomCreateDto dto) {
+        return R.ok(boardingRoomService.updateRoom(id, dto));
+    }
+
+    @DeleteMapping("/{id}")
+    @Operation(summary = "删除房型(逻辑删除)")
+    public R<Boolean> delete(@PathVariable Long id) {
+        return R.ok(boardingRoomService.deleteRoom(id));
+    }
+
+    @GetMapping("/{id}/status")
+    @Operation(summary = "获取房型某月状态(管理员)")
+    public R<List<RoomStatusVo>> getStatus(@PathVariable Long id, @RequestParam String month) {
+        return R.ok(boardingRoomService.getStatus(id, month));
+    }
+
     @PutMapping("/{roomId}/status")
     @PutMapping("/{roomId}/status")
     @Operation(summary = "手动修改某日房态")
     @Operation(summary = "手动修改某日房态")
     public R<Boolean> updateStatus(@PathVariable Long roomId, @Valid @RequestBody RoomStatusDto dto) {
     public R<Boolean> updateStatus(@PathVariable Long roomId, @Valid @RequestBody RoomStatusDto dto) {
         return R.ok(boardingRoomService.updateStatus(roomId, dto));
         return R.ok(boardingRoomService.updateStatus(roomId, dto));
     }
     }
+
+    @PutMapping("/{roomId}/status/batch")
+    @Operation(summary = "批量修改日期范围房态")
+    public R<Boolean> batchUpdateStatus(@PathVariable Long roomId, @Valid @RequestBody BatchRoomStatusDto dto) {
+        return R.ok(boardingRoomService.batchUpdateStatus(roomId, dto));
+    }
+
+    @GetMapping("/today-status")
+    @Operation(summary = "今日所有房型入住概览")
+    public R<TodayStatusVo> getTodayStatus() {
+        return R.ok(boardingRoomService.getTodayStatus());
+    }
 }
 }

+ 23 - 0
src/main/java/space/anyi/petServiceManagementSystem/server/dto/room/BatchRoomStatusDto.java

@@ -0,0 +1,23 @@
+package space.anyi.petServiceManagementSystem.server.dto.room;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.time.LocalDate;
+
+public class BatchRoomStatusDto {
+    @NotNull(message = "开始日期不能为空")
+    private LocalDate startDate;
+
+    @NotNull(message = "结束日期不能为空")
+    private LocalDate endDate;
+
+    @NotBlank(message = "状态不能为空")
+    private String status;
+
+    public LocalDate getStartDate() { return startDate; }
+    public void setStartDate(LocalDate startDate) { this.startDate = startDate; }
+    public LocalDate getEndDate() { return endDate; }
+    public void setEndDate(LocalDate endDate) { this.endDate = endDate; }
+    public String getStatus() { return status; }
+    public void setStatus(String status) { this.status = status; }
+}

+ 30 - 0
src/main/java/space/anyi/petServiceManagementSystem/server/dto/room/BoardingRoomCreateDto.java

@@ -0,0 +1,30 @@
+package space.anyi.petServiceManagementSystem.server.dto.room;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+
+public class BoardingRoomCreateDto {
+    @NotBlank(message = "房型名称不能为空")
+    private String roomName;
+
+    private String roomType;
+
+    private Integer capacity;
+
+    @NotNull(message = "每晚价格不能为空")
+    private BigDecimal pricePerDay;
+
+    private String description;
+
+    public String getRoomName() { return roomName; }
+    public void setRoomName(String roomName) { this.roomName = roomName; }
+    public String getRoomType() { return roomType; }
+    public void setRoomType(String roomType) { this.roomType = roomType; }
+    public Integer getCapacity() { return capacity; }
+    public void setCapacity(Integer capacity) { this.capacity = capacity; }
+    public BigDecimal getPricePerDay() { return pricePerDay; }
+    public void setPricePerDay(BigDecimal pricePerDay) { this.pricePerDay = pricePerDay; }
+    public String getDescription() { return description; }
+    public void setDescription(String description) { this.description = description; }
+}

+ 17 - 17
src/main/java/space/anyi/petServiceManagementSystem/server/entity/Appointment.java

@@ -5,23 +5,23 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 
 
 public class Appointment {
 public class Appointment {
-    private Long id;
-    private Long userId;
-    private Long petId;
-    private Long packageId;
-    private Long roomId;
-    private String type;
-    private String status;
-    private LocalDate startDate;
-    private LocalDate endDate;
-    private BigDecimal totalPrice;
-    private BigDecimal deposit;
-    private Boolean depositPaid;
-    private String cancelReason;
-    private String rejectReason;
-    private String remark;
-    private LocalDateTime createdAt;
-    private LocalDateTime updatedAt;
+    private Long id; // 主键
+    private Long userId; // 用户ID(下单用户)
+    private Long petId; // 宠物ID
+    private Long packageId; // 套餐ID
+    private Long roomId; // 寄养房型ID(寄养必填)
+    private String type; // 预约类型 BOARDING|GROOMING
+    private String status; // 状态 PENDING|CONFIRMED|CANCELLED|CANCEL_REQUESTED
+    private LocalDate startDate; // 寄养开始/洗护预约日
+    private LocalDate endDate; // 寄养结束日期
+    private BigDecimal totalPrice; // 总价
+    private BigDecimal deposit; // 定金=总价*30%
+    private Boolean depositPaid; // 定金是否已支付 0未支付 1已支付
+    private String cancelReason; // 取消原因
+    private String rejectReason; // 拒绝原因
+    private String remark; // 备注
+    private LocalDateTime createdAt; // 创建时间
+    private LocalDateTime updatedAt; // 更新时间
 
 
     public Long getId() { return id; }
     public Long getId() { return id; }
     public void setId(Long id) { this.id = id; }
     public void setId(Long id) { this.id = id; }

+ 9 - 9
src/main/java/space/anyi/petServiceManagementSystem/server/entity/BoardingRoom.java

@@ -4,15 +4,15 @@ import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 
 
 public class BoardingRoom {
 public class BoardingRoom {
-    private Long id;
-    private String roomName;
-    private String roomType;
-    private Integer capacity;
-    private BigDecimal pricePerDay;
-    private Integer isActive;
-    private String description;
-    private LocalDateTime createdAt;
-    private LocalDateTime updatedAt;
+    private Long id; // 主键
+    private String roomName; // 房型名称
+    private String roomType; // 房型分类 STANDARD|VIP|DELUXE
+    private Integer capacity; // 可容纳宠物数
+    private BigDecimal pricePerDay; // 每晚价格
+    private Integer isActive; // 状态 0禁用 1启用
+    private String description; // 房型描述
+    private LocalDateTime createdAt; // 创建时间
+    private LocalDateTime updatedAt; // 更新时间
 
 
     public Long getId() { return id; }
     public Long getId() { return id; }
     public void setId(Long id) { this.id = id; }
     public void setId(Long id) { this.id = id; }

+ 6 - 6
src/main/java/space/anyi/petServiceManagementSystem/server/entity/BoardingRoomStatus.java

@@ -4,12 +4,12 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 
 
 public class BoardingRoomStatus {
 public class BoardingRoomStatus {
-    private Long id;
-    private Long roomId;
-    private LocalDate date;
-    private String status;
-    private Long appointmentId;
-    private LocalDateTime createdAt;
+    private Long id; // 主键
+    private Long roomId; // 关联房型ID
+    private LocalDate date; // 日期
+    private String status; // 房态 AVAILABLE|OCCUPIED|MAINTENANCE
+    private Long appointmentId; // 关联预约ID(系统写入,手动修改时清空)
+    private LocalDateTime createdAt; // 创建时间
 
 
     public Long getId() { return id; }
     public Long getId() { return id; }
     public void setId(Long id) { this.id = id; }
     public void setId(Long id) { this.id = id; }

+ 8 - 8
src/main/java/space/anyi/petServiceManagementSystem/server/entity/DewormingRecord.java

@@ -4,14 +4,14 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 
 
 public class DewormingRecord {
 public class DewormingRecord {
-    private Long id;
-    private Long petId;
-    private String dewormingName;
-    private LocalDate dewormingDate;
-    private String hospital;
-    private String doctor;
-    private String remark;
-    private LocalDateTime createdAt;
+    private Long id; // 主键
+    private Long petId; // 关联宠物ID
+    private String dewormingName; // 驱虫药名称
+    private LocalDate dewormingDate; // 驱虫日期
+    private String hospital; // 驱虫机构
+    private String doctor; // 驱虫兽医
+    private String remark; // 备注
+    private LocalDateTime createdAt; // 创建时间
 
 
     public Long getId() { return id; }
     public Long getId() { return id; }
     public void setId(Long id) { this.id = id; }
     public void setId(Long id) { this.id = id; }

+ 12 - 12
src/main/java/space/anyi/petServiceManagementSystem/server/entity/Pet.java

@@ -4,18 +4,18 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 
 
 public class Pet {
 public class Pet {
-    private Long id;
-    private Long userId;
-    private String name;
-    private String species;
-    private String breed;
-    private String gender;
-    private LocalDate birthDate;
-    private Double weight;
-    private String avatar;
-    private String remark;
-    private LocalDateTime createdAt;
-    private LocalDateTime updatedAt;
+    private Long id; // 主键
+    private Long userId; // 所属用户ID
+    private String name; // 宠物名称
+    private String species; // 物种 DOG|CAT|OTHER
+    private String breed; // 品种
+    private String gender; // 性别 MALE|FEMALE
+    private LocalDate birthDate; // 出生日期
+    private Double weight; // 体重(kg)
+    private String avatar; // 头像URL
+    private String remark; // 备注
+    private LocalDateTime createdAt; // 创建时间
+    private LocalDateTime updatedAt; // 更新时间
 
 
     public Long getId() { return id; }
     public Long getId() { return id; }
     public void setId(Long id) { this.id = id; }
     public void setId(Long id) { this.id = id; }

+ 6 - 6
src/main/java/space/anyi/petServiceManagementSystem/server/entity/Schedule.java

@@ -4,12 +4,12 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 
 
 public class Schedule {
 public class Schedule {
-    private Long id;
-    private String employeeName;
-    private LocalDate workDate;
-    private String timeSlot;
-    private String remark;
-    private LocalDateTime createdAt;
+    private Long id; // 主键
+    private String employeeName; // 员工姓名
+    private LocalDate workDate; // 排班日期
+    private String timeSlot; // 时段 MORNING|AFTERNOON|FULL_DAY
+    private String remark; // 备注
+    private LocalDateTime createdAt; // 创建时间
 
 
     public Long getId() { return id; }
     public Long getId() { return id; }
     public void setId(Long id) { this.id = id; }
     public void setId(Long id) { this.id = id; }

+ 9 - 9
src/main/java/space/anyi/petServiceManagementSystem/server/entity/ServicePackage.java

@@ -4,15 +4,15 @@ import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 
 
 public class ServicePackage {
 public class ServicePackage {
-    private Long id;
-    private String name;
-    private String type;
-    private BigDecimal price;
-    private Integer duration;
-    private String description;
-    private Integer isActive;
-    private LocalDateTime createdAt;
-    private LocalDateTime updatedAt;
+    private Long id; // 主键
+    private String name; // 套餐名称
+    private String type; // 套餐类型 BOARDING|GROOMING
+    private BigDecimal price; // 价格
+    private Integer duration; // 寄养天数(仅寄养套餐)
+    private String description; // 套餐描述
+    private Integer isActive; // 状态 0禁用 1启用
+    private LocalDateTime createdAt; // 创建时间
+    private LocalDateTime updatedAt; // 更新时间
 
 
     public Long getId() { return id; }
     public Long getId() { return id; }
     public void setId(Long id) { this.id = id; }
     public void setId(Long id) { this.id = id; }

+ 11 - 11
src/main/java/space/anyi/petServiceManagementSystem/server/entity/User.java

@@ -3,17 +3,17 @@ package space.anyi.petServiceManagementSystem.server.entity;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 
 
 public class User {
 public class User {
-    private Long id;
-    private String account;
-    private String username;
-    private String password;
-    private String email;
-    private String phone;
-    private String avatar;
-    private String role;
-    private Integer enable;
-    private LocalDateTime createdAt;
-    private LocalDateTime updatedAt;
+    private Long id; // 主键
+    private String account; // 登录账号(唯一)
+    private String username; // 用户名
+    private String password; // MD5+SALT 加密后的密码
+    private String email; // 邮箱
+    private String phone; // 手机号
+    private String avatar; // 头像URL
+    private String role; // 角色 user|admin
+    private Integer enable; // 状态 0禁用 1启用
+    private LocalDateTime createdAt; // 创建时间
+    private LocalDateTime updatedAt; // 更新时间
 
 
     public Long getId() { return id; }
     public Long getId() { return id; }
     public void setId(Long id) { this.id = id; }
     public void setId(Long id) { this.id = id; }

+ 8 - 8
src/main/java/space/anyi/petServiceManagementSystem/server/entity/VaccinationRecord.java

@@ -4,14 +4,14 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 
 
 public class VaccinationRecord {
 public class VaccinationRecord {
-    private Long id;
-    private Long petId;
-    private String vaccineName;
-    private LocalDate vaccineDate;
-    private String hospital;
-    private String doctor;
-    private String remark;
-    private LocalDateTime createdAt;
+    private Long id; // 主键
+    private Long petId; // 关联宠物ID
+    private String vaccineName; // 疫苗名称
+    private LocalDate vaccineDate; // 接种日期
+    private String hospital; // 接种机构
+    private String doctor; // 接种兽医
+    private String remark; // 备注
+    private LocalDateTime createdAt; // 创建时间
 
 
     public Long getId() { return id; }
     public Long getId() { return id; }
     public void setId(Long id) { this.id = id; }
     public void setId(Long id) { this.id = id; }

+ 2 - 0
src/main/java/space/anyi/petServiceManagementSystem/server/mapper/BoardingRoomMapper.java

@@ -10,5 +10,7 @@ public interface BoardingRoomMapper {
     int insert(BoardingRoom room);
     int insert(BoardingRoom room);
     BoardingRoom selectById(Long id);
     BoardingRoom selectById(Long id);
     List<BoardingRoom> selectActive();
     List<BoardingRoom> selectActive();
+    List<BoardingRoom> selectAll();
     int update(BoardingRoom room);
     int update(BoardingRoom room);
+    int deleteById(Long id);
 }
 }

+ 1 - 0
src/main/java/space/anyi/petServiceManagementSystem/server/mapper/BoardingRoomStatusMapper.java

@@ -13,6 +13,7 @@ public interface BoardingRoomStatusMapper {
     List<BoardingRoomStatus> selectByRoomAndDateRange(@Param("roomId") Long roomId,
     List<BoardingRoomStatus> selectByRoomAndDateRange(@Param("roomId") Long roomId,
                                                        @Param("startDate") LocalDate startDate,
                                                        @Param("startDate") LocalDate startDate,
                                                        @Param("endDate") LocalDate endDate);
                                                        @Param("endDate") LocalDate endDate);
+    List<BoardingRoomStatus> selectByDate(@Param("date") LocalDate date);
     int deleteByAppointmentId(Long appointmentId);
     int deleteByAppointmentId(Long appointmentId);
     int insertBatch(@Param("list") List<BoardingRoomStatus> list);
     int insertBatch(@Param("list") List<BoardingRoomStatus> list);
 }
 }

+ 9 - 0
src/main/java/space/anyi/petServiceManagementSystem/server/service/BoardingRoomService.java

@@ -1,13 +1,22 @@
 package space.anyi.petServiceManagementSystem.server.service;
 package space.anyi.petServiceManagementSystem.server.service;
 
 
+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.dto.room.RoomStatusDto;
 import space.anyi.petServiceManagementSystem.server.vo.room.BoardingRoomVo;
 import space.anyi.petServiceManagementSystem.server.vo.room.BoardingRoomVo;
 import space.anyi.petServiceManagementSystem.server.vo.room.RoomStatusVo;
 import space.anyi.petServiceManagementSystem.server.vo.room.RoomStatusVo;
+import space.anyi.petServiceManagementSystem.server.vo.room.TodayStatusVo;
 
 
 import java.util.List;
 import java.util.List;
 
 
 public interface BoardingRoomService {
 public interface BoardingRoomService {
     List<BoardingRoomVo> listRooms();
     List<BoardingRoomVo> listRooms();
+    List<BoardingRoomVo> listAllRooms();
+    BoardingRoomVo createRoom(BoardingRoomCreateDto dto);
+    Boolean updateRoom(Long id, BoardingRoomCreateDto dto);
+    Boolean deleteRoom(Long id);
     List<RoomStatusVo> getStatus(Long roomId, String month);
     List<RoomStatusVo> getStatus(Long roomId, String month);
     Boolean updateStatus(Long roomId, RoomStatusDto dto);
     Boolean updateStatus(Long roomId, RoomStatusDto dto);
+    Boolean batchUpdateStatus(Long roomId, BatchRoomStatusDto dto);
+    TodayStatusVo getTodayStatus();
 }
 }

+ 11 - 1
src/main/java/space/anyi/petServiceManagementSystem/server/service/impl/AppointmentServiceImpl.java

@@ -125,7 +125,17 @@ public class AppointmentServiceImpl implements AppointmentService {
         if (!"PENDING".equals(appointment.getStatus()) && !"CONFIRMED".equals(appointment.getStatus())) {
         if (!"PENDING".equals(appointment.getStatus()) && !"CONFIRMED".equals(appointment.getStatus())) {
             throw new BusinessException("当前订单状态不允许取消");
             throw new BusinessException("当前订单状态不允许取消");
         }
         }
-        appointmentMapper.updateCancelReason(id, reason != null ? reason : "用户取消");
+
+        String cancelReason = reason != null ? reason : "用户取消";
+        if ("PENDING".equals(appointment.getStatus())) {
+            // PENDING → CANCELLED:直接取消,房间从未锁定无需释放
+            appointmentMapper.updateStatus(id, "CANCELLED");
+            appointmentMapper.updateCancelReason(id, cancelReason);
+        } else {
+            // CONFIRMED → CANCEL_REQUESTED:等待商家审核处理
+            appointmentMapper.updateStatus(id, "CANCEL_REQUESTED");
+            appointmentMapper.updateCancelReason(id, cancelReason);
+        }
         return true;
         return true;
     }
     }
 
 

+ 145 - 4
src/main/java/space/anyi/petServiceManagementSystem/server/service/impl/BoardingRoomServiceImpl.java

@@ -3,17 +3,21 @@ package space.anyi.petServiceManagementSystem.server.service.impl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 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.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.service.BoardingRoomService;
 import space.anyi.petServiceManagementSystem.server.vo.room.BoardingRoomVo;
 import space.anyi.petServiceManagementSystem.server.vo.room.BoardingRoomVo;
 import space.anyi.petServiceManagementSystem.server.vo.room.RoomStatusVo;
 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.LocalDate;
 import java.time.YearMonth;
 import java.time.YearMonth;
+import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
@@ -28,12 +32,62 @@ public class BoardingRoomServiceImpl implements BoardingRoomService {
     @Autowired
     @Autowired
     private BoardingRoomStatusMapper boardingRoomStatusMapper;
     private BoardingRoomStatusMapper boardingRoomStatusMapper;
 
 
+    @Autowired
+    private AppointmentMapper appointmentMapper;
+
+    @Autowired
+    private PetMapper petMapper;
+
+    @Autowired
+    private UserMapper userMapper;
+
     @Override
     @Override
     public List<BoardingRoomVo> listRooms() {
     public List<BoardingRoomVo> listRooms() {
         return boardingRoomMapper.selectActive().stream()
         return boardingRoomMapper.selectActive().stream()
                 .map(this::toBoardingRoomVo).collect(Collectors.toList());
                 .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
     @Override
     public List<RoomStatusVo> getStatus(Long roomId, String month) {
     public List<RoomStatusVo> getStatus(Long roomId, String month) {
         YearMonth yearMonth = YearMonth.parse(month);
         YearMonth yearMonth = YearMonth.parse(month);
@@ -74,6 +128,93 @@ public class BoardingRoomServiceImpl implements BoardingRoomService {
         return boardingRoomStatusMapper.insertOrUpdate(status) > 0;
         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) {
     private BoardingRoomVo toBoardingRoomVo(BoardingRoom room) {
         BoardingRoomVo vo = new BoardingRoomVo();
         BoardingRoomVo vo = new BoardingRoomVo();
         vo.setId(room.getId());
         vo.setId(room.getId());

+ 14 - 0
src/main/java/space/anyi/petServiceManagementSystem/server/vo/room/TodayGuestVo.java

@@ -0,0 +1,14 @@
+package space.anyi.petServiceManagementSystem.server.vo.room;
+
+public class TodayGuestVo {
+    private String roomName;
+    private String petName;
+    private String ownerName;
+
+    public String getRoomName() { return roomName; }
+    public void setRoomName(String roomName) { this.roomName = roomName; }
+    public String getPetName() { return petName; }
+    public void setPetName(String petName) { this.petName = petName; }
+    public String getOwnerName() { return ownerName; }
+    public void setOwnerName(String ownerName) { this.ownerName = ownerName; }
+}

+ 22 - 0
src/main/java/space/anyi/petServiceManagementSystem/server/vo/room/TodayStatusVo.java

@@ -0,0 +1,22 @@
+package space.anyi.petServiceManagementSystem.server.vo.room;
+
+import java.util.List;
+
+public class TodayStatusVo {
+    private int totalRooms;
+    private int availableCount;
+    private int occupiedCount;
+    private int maintenanceCount;
+    private List<TodayGuestVo> todayGuests;
+
+    public int getTotalRooms() { return totalRooms; }
+    public void setTotalRooms(int totalRooms) { this.totalRooms = totalRooms; }
+    public int getAvailableCount() { return availableCount; }
+    public void setAvailableCount(int availableCount) { this.availableCount = availableCount; }
+    public int getOccupiedCount() { return occupiedCount; }
+    public void setOccupiedCount(int occupiedCount) { this.occupiedCount = occupiedCount; }
+    public int getMaintenanceCount() { return maintenanceCount; }
+    public void setMaintenanceCount(int maintenanceCount) { this.maintenanceCount = maintenanceCount; }
+    public List<TodayGuestVo> getTodayGuests() { return todayGuests; }
+    public void setTodayGuests(List<TodayGuestVo> todayGuests) { this.todayGuests = todayGuests; }
+}

+ 1 - 1
src/main/resources/mapper/AppointmentMapper.xml

@@ -54,7 +54,7 @@
     </update>
     </update>
 
 
     <update id="updateCancelReason">
     <update id="updateCancelReason">
-        UPDATE appointment SET cancel_reason = #{cancelReason}, status = 'CANCEL_REQUESTED', updated_at = NOW() WHERE id = #{id}
+        UPDATE appointment SET cancel_reason = #{cancelReason}, updated_at = NOW() WHERE id = #{id}
     </update>
     </update>
 
 
     <update id="update">
     <update id="update">

+ 8 - 0
src/main/resources/mapper/BoardingRoomMapper.xml

@@ -15,6 +15,14 @@
         SELECT * FROM boarding_room WHERE is_active = 1 ORDER BY created_at ASC
         SELECT * FROM boarding_room WHERE is_active = 1 ORDER BY created_at ASC
     </select>
     </select>
 
 
+    <select id="selectAll" resultType="BoardingRoom">
+        SELECT * FROM boarding_room ORDER BY created_at ASC
+    </select>
+
+    <update id="deleteById">
+        UPDATE boarding_room SET is_active = 0, updated_at = NOW() WHERE id = #{id}
+    </update>
+
     <update id="update">
     <update id="update">
         UPDATE boarding_room
         UPDATE boarding_room
         <set>
         <set>

+ 4 - 0
src/main/resources/mapper/BoardingRoomStatusMapper.xml

@@ -15,6 +15,10 @@
         ORDER BY date ASC
         ORDER BY date ASC
     </select>
     </select>
 
 
+    <select id="selectByDate" resultType="BoardingRoomStatus">
+        SELECT * FROM boarding_room_status WHERE date = #{date} ORDER BY room_id ASC
+    </select>
+
     <delete id="deleteByAppointmentId">
     <delete id="deleteByAppointmentId">
         DELETE FROM boarding_room_status WHERE appointment_id = #{appointmentId}
         DELETE FROM boarding_room_status WHERE appointment_id = #{appointmentId}
     </delete>
     </delete>