diff --git a/src/main/java/com/cozymate/cozymate_server/domain/role/RoleRepository.java b/src/main/java/com/cozymate/cozymate_server/domain/role/RoleRepository.java deleted file mode 100644 index 213497f2..00000000 --- a/src/main/java/com/cozymate/cozymate_server/domain/role/RoleRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.cozymate.cozymate_server.domain.role; - -import org.springframework.data.jpa.repository.JpaRepository; - -public interface RoleRepository extends JpaRepository { - void deleteByMateId(Long mateId); - -} diff --git a/src/main/java/com/cozymate/cozymate_server/domain/role/controller/RoleController.java b/src/main/java/com/cozymate/cozymate_server/domain/role/controller/RoleController.java new file mode 100644 index 00000000..21d01cd3 --- /dev/null +++ b/src/main/java/com/cozymate/cozymate_server/domain/role/controller/RoleController.java @@ -0,0 +1,72 @@ +package com.cozymate.cozymate_server.domain.role.controller; + +import com.cozymate.cozymate_server.domain.auth.userDetails.MemberDetails; +import com.cozymate.cozymate_server.domain.role.dto.RoleRequestDto.CreateRoleRequestDto; +import com.cozymate.cozymate_server.domain.role.dto.RoleResponseDto.RoleListDetailResponseDto; +import com.cozymate.cozymate_server.domain.role.service.RoleCommandService; +import com.cozymate.cozymate_server.domain.role.service.RoleQueryService; +import com.cozymate.cozymate_server.global.response.ApiResponse; +import com.cozymate.cozymate_server.global.response.code.status.ErrorStatus; +import com.cozymate.cozymate_server.global.utils.SwaggerApiError; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/role") +public class RoleController { + + private final RoleCommandService roleCommandService; + private final RoleQueryService roleQueryService; + + @PostMapping("/{roomId}") + @Operation(summary = "[무빗] 특정 방에 role 생성", description = "본인의 룸메라면 Role을 할당할 수 있습니다.") + @SwaggerApiError({ErrorStatus._MATE_OR_ROOM_NOT_FOUND}) + public ResponseEntity> createRole( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long roomId, + @Valid @RequestBody CreateRoleRequestDto createRoleRequestDto + + ) { + roleCommandService.createRole(memberDetails.getMember(), roomId, createRoleRequestDto); + return ResponseEntity.ok(ApiResponse.onSuccess("Role 생성 완료.")); + } + + @GetMapping("/{roomId}") + @Operation(summary = "[무빗] 특정 방에 role 목록 조회", description = "") + @SwaggerApiError({ErrorStatus._MATE_OR_ROOM_NOT_FOUND}) + public ResponseEntity> getRoleList( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long roomId + ) { + + return ResponseEntity.ok(ApiResponse.onSuccess( + roleQueryService.getRole(roomId, memberDetails.getMember()) + )); + } + + @DeleteMapping("{roomId}") + @Operation(summary = "[무빗] 특정 role 삭제", description = "본인의 룸메라면 Role을 삭제할 수 있습니다.") + @SwaggerApiError({ErrorStatus._MATE_OR_ROOM_NOT_FOUND, ErrorStatus._ROLE_NOT_FOUND, + ErrorStatus._ROLE_MATE_MISMATCH}) + public ResponseEntity> deleteRole( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long roomId, + @RequestParam Long roleId + ) { + roleCommandService.deleteRole(roomId, roleId, memberDetails.getMember()); + return ResponseEntity.ok(ApiResponse.onSuccess("Role 삭제 완료")); + } + +} diff --git a/src/main/java/com/cozymate/cozymate_server/domain/role/converter/RoleConverter.java b/src/main/java/com/cozymate/cozymate_server/domain/role/converter/RoleConverter.java new file mode 100644 index 00000000..cf9e14fa --- /dev/null +++ b/src/main/java/com/cozymate/cozymate_server/domain/role/converter/RoleConverter.java @@ -0,0 +1,67 @@ +package com.cozymate.cozymate_server.domain.role.converter; + +import com.cozymate.cozymate_server.domain.mate.Mate; +import com.cozymate.cozymate_server.domain.role.Role; +import com.cozymate.cozymate_server.domain.role.dto.RoleResponseDto.RoleDetailResponseDto; +import com.cozymate.cozymate_server.domain.role.dto.RoleResponseDto.RoleListDetailResponseDto; +import com.cozymate.cozymate_server.domain.role.enums.DayListBitmask; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class RoleConverter { + + private static final int ALL_DAYS_BITMASK = 127; + + public static Role toEntity(Mate mate, String content, int repeatDays) { + return Role.builder() + .mate(mate) + .content(content) + .repeatDays(repeatDays) + .build(); + } + + // Day List → Bitmask + public static int convertDayListToBitmask(List dayList) { + int bitmask = 0; + for (DayListBitmask dayBitMask : dayList) { + bitmask |= dayBitMask.getValue(); + } + return bitmask; + } + + // Bitmask → Day List + public static List convertBitmaskToDayList(int bitmask) { + List dayList = new ArrayList<>(); + for (DayListBitmask day : DayListBitmask.values()) { + if ((bitmask & day.getValue()) != 0) { + dayList.add(day); + } + } + return dayList; + } + + public static RoleDetailResponseDto toRoleDetailResponseDto(Role role) { + return RoleDetailResponseDto.builder() + .id(role.getId()) + .content(role.getContent()) + .repeatDayList( + convertBitmaskToDayList(role.getRepeatDays()).stream() + .map(DayListBitmask::name) + .toList() + ) + .isAllDays(role.getRepeatDays() == ALL_DAYS_BITMASK) + .build(); + } + + public static RoleListDetailResponseDto toRoleListDetailResponseDto( + List myRoleList, + Map> otherRoleList) { + return RoleListDetailResponseDto.builder() + .myRoleList(myRoleList) + .otherRoleList(otherRoleList) + .build(); + } + + +} diff --git a/src/main/java/com/cozymate/cozymate_server/domain/role/dto/RoleRequestDto.java b/src/main/java/com/cozymate/cozymate_server/domain/role/dto/RoleRequestDto.java new file mode 100644 index 00000000..f78f1ad2 --- /dev/null +++ b/src/main/java/com/cozymate/cozymate_server/domain/role/dto/RoleRequestDto.java @@ -0,0 +1,28 @@ +package com.cozymate.cozymate_server.domain.role.dto; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Size; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.hibernate.validator.constraints.Length; + +public class RoleRequestDto { + + @AllArgsConstructor + @Getter + public static class CreateRoleRequestDto { + + @NotEmpty + private List mateIdList; + + @Length(min = 1, max = 20) + private String title; + + @NotEmpty + @Size(min = 1, max = 7) + private List repeatDayList; + + } + +} diff --git a/src/main/java/com/cozymate/cozymate_server/domain/role/dto/RoleResponseDto.java b/src/main/java/com/cozymate/cozymate_server/domain/role/dto/RoleResponseDto.java new file mode 100644 index 00000000..c53ee59a --- /dev/null +++ b/src/main/java/com/cozymate/cozymate_server/domain/role/dto/RoleResponseDto.java @@ -0,0 +1,40 @@ +package com.cozymate.cozymate_server.domain.role.dto; + +import com.cozymate.cozymate_server.domain.mate.Mate; +import java.util.List; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class RoleResponseDto { + + @Builder + @Getter + @AllArgsConstructor + @NoArgsConstructor + public static class RoleDetailResponseDto { + + private Long id; + + private String content; + + private List repeatDayList; + + private boolean isAllDays; + + } + + @Builder + @Getter + @AllArgsConstructor + @NoArgsConstructor + public static class RoleListDetailResponseDto { + + private List myRoleList; + + private Map> otherRoleList; + } + +} diff --git a/src/main/java/com/cozymate/cozymate_server/domain/role/enums/DayListBitmask.java b/src/main/java/com/cozymate/cozymate_server/domain/role/enums/DayListBitmask.java new file mode 100644 index 00000000..a0e0d095 --- /dev/null +++ b/src/main/java/com/cozymate/cozymate_server/domain/role/enums/DayListBitmask.java @@ -0,0 +1,23 @@ +package com.cozymate.cozymate_server.domain.role.enums; + +import java.util.List; + +public enum DayListBitmask { + 월(1), + 화(2), + 수(4), + 목(8), + 금(16), + 토(32), + 일(64); + + private int value; + + DayListBitmask(int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/com/cozymate/cozymate_server/domain/role/repository/RoleRepository.java b/src/main/java/com/cozymate/cozymate_server/domain/role/repository/RoleRepository.java new file mode 100644 index 00000000..4079576f --- /dev/null +++ b/src/main/java/com/cozymate/cozymate_server/domain/role/repository/RoleRepository.java @@ -0,0 +1,13 @@ +package com.cozymate.cozymate_server.domain.role.repository; + +import com.cozymate.cozymate_server.domain.role.Role; +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RoleRepository extends JpaRepository { + + List findAllByMateRoomId(Long roomId); + + void deleteByMateId(Long mateId); + +} diff --git a/src/main/java/com/cozymate/cozymate_server/domain/role/service/RoleCommandService.java b/src/main/java/com/cozymate/cozymate_server/domain/role/service/RoleCommandService.java new file mode 100644 index 00000000..22640a9b --- /dev/null +++ b/src/main/java/com/cozymate/cozymate_server/domain/role/service/RoleCommandService.java @@ -0,0 +1,63 @@ +package com.cozymate.cozymate_server.domain.role.service; + +import com.cozymate.cozymate_server.domain.mate.Mate; +import com.cozymate.cozymate_server.domain.mate.repository.MateRepository; +import com.cozymate.cozymate_server.domain.member.Member; +import com.cozymate.cozymate_server.domain.role.Role; +import com.cozymate.cozymate_server.domain.role.converter.RoleConverter; +import com.cozymate.cozymate_server.domain.role.dto.RoleRequestDto.CreateRoleRequestDto; +import com.cozymate.cozymate_server.domain.role.enums.DayListBitmask; +import com.cozymate.cozymate_server.domain.role.repository.RoleRepository; +import com.cozymate.cozymate_server.global.response.code.status.ErrorStatus; +import com.cozymate.cozymate_server.global.response.exception.GeneralException; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class RoleCommandService { + + private final RoleRepository roleRepository; + private final MateRepository mateRepository; + + + @Transactional + public void createRole( + Member member, + Long roomId, + CreateRoleRequestDto requestDto + ) { + // 해당 API를 호출한 사람 + Mate mate = mateRepository.findByMemberIdAndRoomId(member.getId(), roomId) + .orElseThrow(() -> new GeneralException(ErrorStatus._MATE_OR_ROOM_NOT_FOUND)); + + List repeatDayList = requestDto.getRepeatDayList().stream() + .map(DayListBitmask::valueOf).toList(); + int repeatDayBitmast = RoleConverter.convertDayListToBitmask(repeatDayList); + + // Role의 대상이 되는 사람 + requestDto.getMateIdList().forEach(mateId -> { + Mate targerMate = mateRepository.findById(mateId) // TODO: mate를 한번에 가져오는 방식으로 변경해야함 + .orElseThrow(() -> new GeneralException(ErrorStatus._MATE_NOT_FOUND)); + Role role = RoleConverter.toEntity(targerMate, requestDto.getTitle(), repeatDayBitmast); + roleRepository.save(role); + }); + } + + public void deleteRole(Long roomId, Long roleId, Member member) { + Mate mate = mateRepository.findByMemberIdAndRoomId(member.getId(), roomId) + .orElseThrow(() -> new GeneralException(ErrorStatus._MATE_OR_ROOM_NOT_FOUND)); + + Role roleToDelete = roleRepository.findById(roleId) + .orElseThrow(() -> new GeneralException(ErrorStatus._ROLE_NOT_FOUND)); + + if (Boolean.FALSE.equals( + member.getId().equals(roleToDelete.getMate().getMember().getId()) + )) { + throw new GeneralException(ErrorStatus._ROLE_MATE_MISMATCH); + } + roleRepository.delete(roleToDelete); + } +} diff --git a/src/main/java/com/cozymate/cozymate_server/domain/role/service/RoleQueryService.java b/src/main/java/com/cozymate/cozymate_server/domain/role/service/RoleQueryService.java new file mode 100644 index 00000000..c8374d98 --- /dev/null +++ b/src/main/java/com/cozymate/cozymate_server/domain/role/service/RoleQueryService.java @@ -0,0 +1,55 @@ +package com.cozymate.cozymate_server.domain.role.service; + +import com.cozymate.cozymate_server.domain.mate.Mate; +import com.cozymate.cozymate_server.domain.mate.repository.MateRepository; +import com.cozymate.cozymate_server.domain.member.Member; +import com.cozymate.cozymate_server.domain.role.Role; +import com.cozymate.cozymate_server.domain.role.converter.RoleConverter; +import com.cozymate.cozymate_server.domain.role.dto.RoleResponseDto.RoleDetailResponseDto; +import com.cozymate.cozymate_server.domain.role.dto.RoleResponseDto.RoleListDetailResponseDto; +import com.cozymate.cozymate_server.domain.role.repository.RoleRepository; +import com.cozymate.cozymate_server.domain.rule.converter.RuleConverter; +import com.cozymate.cozymate_server.domain.rule.dto.RuleResponseDto.RuleDetailResponseDto; +import com.cozymate.cozymate_server.global.response.code.status.ErrorStatus; +import com.cozymate.cozymate_server.global.response.exception.GeneralException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class RoleQueryService { + + private final RoleRepository roleRepository; + private final MateRepository mateRepository; + + public RoleListDetailResponseDto getRole(Long roomId, Member member) { + Mate mate = mateRepository.findByMemberIdAndRoomId(member.getId(), roomId) + .orElseThrow(() -> new GeneralException(ErrorStatus._MATE_OR_ROOM_NOT_FOUND)); + + List roleList = roleRepository.findAllByMateRoomId(mate.getRoom().getId()); + List myRoleListResponseDto = new ArrayList<>(); + Map> mateRoleListResponseDto = new HashMap<>(); + + roleList.forEach(role -> { + if (role.getMate().getId().equals(mate.getId())) { + myRoleListResponseDto.add(RoleConverter.toRoleDetailResponseDto(role)); + } else { + String mateName = role.getMate().getMember().getName(); + RoleDetailResponseDto roleDto = RoleConverter.toRoleDetailResponseDto(role); + mateRoleListResponseDto.computeIfAbsent(mateName, k -> new ArrayList<>()) + .add(roleDto); + } + }); + + return RoleConverter.toRoleListDetailResponseDto( + myRoleListResponseDto, + mateRoleListResponseDto); + + } +} diff --git a/src/main/java/com/cozymate/cozymate_server/domain/room/service/RoomCommandService.java b/src/main/java/com/cozymate/cozymate_server/domain/room/service/RoomCommandService.java index 7468e154..c84ffdcb 100644 --- a/src/main/java/com/cozymate/cozymate_server/domain/room/service/RoomCommandService.java +++ b/src/main/java/com/cozymate/cozymate_server/domain/room/service/RoomCommandService.java @@ -11,7 +11,7 @@ import com.cozymate.cozymate_server.domain.post.repository.PostRepository; import com.cozymate.cozymate_server.domain.postcomment.PostCommentRepository; import com.cozymate.cozymate_server.domain.postimage.PostImageRepository; -import com.cozymate.cozymate_server.domain.role.RoleRepository; +import com.cozymate.cozymate_server.domain.role.repository.RoleRepository; import com.cozymate.cozymate_server.domain.room.Room; import com.cozymate.cozymate_server.domain.room.converter.RoomConverter; import com.cozymate.cozymate_server.domain.room.dto.RoomCreateRequest; diff --git a/src/main/java/com/cozymate/cozymate_server/domain/rule/controller/RuleController.java b/src/main/java/com/cozymate/cozymate_server/domain/rule/controller/RuleController.java index 2d135bd5..45469e3f 100644 --- a/src/main/java/com/cozymate/cozymate_server/domain/rule/controller/RuleController.java +++ b/src/main/java/com/cozymate/cozymate_server/domain/rule/controller/RuleController.java @@ -1,15 +1,19 @@ package com.cozymate.cozymate_server.domain.rule.controller; +import com.cozymate.cozymate_server.domain.auth.userDetails.MemberDetails; import com.cozymate.cozymate_server.domain.rule.dto.RuleRequestDto.CreateRuleRequestDto; import com.cozymate.cozymate_server.domain.rule.dto.RuleResponseDto.RuleDetailResponseDto; import com.cozymate.cozymate_server.domain.rule.service.RuleCommandService; import com.cozymate.cozymate_server.domain.rule.service.RuleQueryService; import com.cozymate.cozymate_server.global.response.ApiResponse; +import com.cozymate.cozymate_server.global.response.code.status.ErrorStatus; +import com.cozymate.cozymate_server.global.utils.SwaggerApiError; import io.swagger.v3.oas.annotations.Operation; import jakarta.validation.Valid; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -31,36 +35,43 @@ public class RuleController { @Operation( summary = "[무빗] 특정 방의 Rule 생성", description = "rule 내용은 필수, memo는 선택입니다.") + @SwaggerApiError({ErrorStatus._MATE_OR_ROOM_NOT_FOUND, ErrorStatus._RULE_OVER_MAX}) public ResponseEntity> createRule( + @AuthenticationPrincipal MemberDetails memberDetails, @PathVariable Long roomId, - @RequestParam Long memberId, @Valid @RequestBody CreateRuleRequestDto createRuleRequestDto ) { - ruleCommandService.createRule(roomId, memberId, createRuleRequestDto); + ruleCommandService.createRule(memberDetails.getMember(), roomId, createRuleRequestDto); return ResponseEntity.ok(ApiResponse.onSuccess("규칙 생성에 성공했습니다.")); } @GetMapping("/{roomId}") @Operation( summary = "[무빗] 특정 방의 Rule 목록 조회", - description = "memo는 null 반환이 가능합니다.") + description = "Rule에서 memo는 null 반환이 가능합니다.") + @SwaggerApiError({ErrorStatus._MATE_OR_ROOM_NOT_FOUND, ErrorStatus._RULE_NOT_FOUND, + ErrorStatus._RULE_MATE_MISMATCH}) public ResponseEntity>> getRuleList( - @PathVariable Long roomId, - @RequestParam Long memberId + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long roomId ) { - return ResponseEntity.ok(ApiResponse.onSuccess(ruleQueryService.getRule(roomId, memberId))); + return ResponseEntity.ok(ApiResponse.onSuccess( + ruleQueryService.getRule(roomId, memberDetails.getMember()) + )); } @DeleteMapping("/{roomId}") @Operation( summary = "[무빗] 특정 방의 특정 Rule 삭제", description = "rule의 고유 번호로 삭제가 가능합니다.") + @SwaggerApiError({ErrorStatus._MATE_OR_ROOM_NOT_FOUND, ErrorStatus._RULE_NOT_FOUND, + ErrorStatus._RULE_MATE_MISMATCH}) public ResponseEntity> deleteRule( + @AuthenticationPrincipal MemberDetails memberDetails, @PathVariable Long roomId, - @RequestParam Long memberId, @RequestParam Long ruleId ) { - ruleCommandService.deleteRule(roomId, memberId, ruleId); + ruleCommandService.deleteRule(memberDetails.getMember(), roomId, ruleId); return ResponseEntity.ok(ApiResponse.onSuccess("삭제되었습니다.")); } diff --git a/src/main/java/com/cozymate/cozymate_server/domain/rule/service/RuleCommandService.java b/src/main/java/com/cozymate/cozymate_server/domain/rule/service/RuleCommandService.java index 962a907c..a7695a3a 100644 --- a/src/main/java/com/cozymate/cozymate_server/domain/rule/service/RuleCommandService.java +++ b/src/main/java/com/cozymate/cozymate_server/domain/rule/service/RuleCommandService.java @@ -2,6 +2,7 @@ import com.cozymate.cozymate_server.domain.mate.Mate; import com.cozymate.cozymate_server.domain.mate.repository.MateRepository; +import com.cozymate.cozymate_server.domain.member.Member; import com.cozymate.cozymate_server.domain.rule.Rule; import com.cozymate.cozymate_server.domain.rule.converter.RuleConverter; import com.cozymate.cozymate_server.domain.rule.dto.RuleRequestDto.CreateRuleRequestDto; @@ -20,8 +21,8 @@ public class RuleCommandService { private static final int MAX_RULE_COUNT = 10; - public void createRule(Long roomId, Long memberId, CreateRuleRequestDto requestDto) { - Mate mate = mateRepository.findByMemberIdAndRoomId(memberId, roomId) + public void createRule(Member member, Long roomId, CreateRuleRequestDto requestDto) { + Mate mate = mateRepository.findByMemberIdAndRoomId(member.getId(), roomId) .orElseThrow(() -> new GeneralException(ErrorStatus._MATE_OR_ROOM_NOT_FOUND)); // rule 최대개수 초과 여부 판단 @@ -35,8 +36,8 @@ public void createRule(Long roomId, Long memberId, CreateRuleRequestDto requestD } - public void deleteRule(Long roomId, Long memberId, Long ruleId) { - Mate mate = mateRepository.findByMemberIdAndRoomId(memberId, roomId) + public void deleteRule(Member member, Long roomId, Long ruleId) { + Mate mate = mateRepository.findByMemberIdAndRoomId(member.getId(), roomId) .orElseThrow(() -> new GeneralException(ErrorStatus._MATE_OR_ROOM_NOT_FOUND)); Rule rule = ruleRepository.findById(ruleId) diff --git a/src/main/java/com/cozymate/cozymate_server/domain/rule/service/RuleQueryService.java b/src/main/java/com/cozymate/cozymate_server/domain/rule/service/RuleQueryService.java index 17fbee06..1af90997 100644 --- a/src/main/java/com/cozymate/cozymate_server/domain/rule/service/RuleQueryService.java +++ b/src/main/java/com/cozymate/cozymate_server/domain/rule/service/RuleQueryService.java @@ -2,6 +2,7 @@ import com.cozymate.cozymate_server.domain.mate.Mate; import com.cozymate.cozymate_server.domain.mate.repository.MateRepository; +import com.cozymate.cozymate_server.domain.member.Member; import com.cozymate.cozymate_server.domain.rule.Rule; import com.cozymate.cozymate_server.domain.rule.converter.RuleConverter; import com.cozymate.cozymate_server.domain.rule.dto.RuleResponseDto.RuleDetailResponseDto; @@ -21,8 +22,8 @@ public class RuleQueryService { private final RuleRepository ruleRepository; private final MateRepository mateRepository; - public List getRule(Long roomId, Long memberId) { - Mate mate = mateRepository.findByMemberIdAndRoomId(memberId, roomId) + public List getRule(Long roomId, Member member) { + Mate mate = mateRepository.findByMemberIdAndRoomId(member.getId(), roomId) .orElseThrow(() -> new GeneralException(ErrorStatus._MATE_OR_ROOM_NOT_FOUND)); List ruleList = ruleRepository.findAllByRoomId(mate.getRoom().getId()); diff --git a/src/main/java/com/cozymate/cozymate_server/domain/todo/controller/TodoController.java b/src/main/java/com/cozymate/cozymate_server/domain/todo/controller/TodoController.java index 24f32f35..7f857685 100644 --- a/src/main/java/com/cozymate/cozymate_server/domain/todo/controller/TodoController.java +++ b/src/main/java/com/cozymate/cozymate_server/domain/todo/controller/TodoController.java @@ -1,6 +1,7 @@ package com.cozymate.cozymate_server.domain.todo.controller; +import com.cozymate.cozymate_server.domain.auth.userDetails.MemberDetails; import com.cozymate.cozymate_server.domain.todo.dto.TodoRequestDto.CreateTodoRequestDto; import com.cozymate.cozymate_server.domain.todo.dto.TodoRequestDto.UpdateTodoCompleteStateRequestDto; import com.cozymate.cozymate_server.domain.todo.dto.TodoResponseDto.TodoListResponseDto; @@ -16,6 +17,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -35,14 +37,13 @@ public class TodoController { @PostMapping("/{roomId}") @Operation(summary = "[무빗] 특정 방에 본인의 Todo 생성", description = "Todo는 본인한테만 할당할 수 있습니다.") - @SwaggerApiError({ErrorStatus._MATE_NOT_FOUND}) + @SwaggerApiError({ErrorStatus._MATE_NOT_FOUND, ErrorStatus._TODO_OVER_MAX}) public ResponseEntity> createTodo( - @Valid @RequestBody CreateTodoRequestDto createTodoRequestDto, + @AuthenticationPrincipal MemberDetails memberDetails, @PathVariable Long roomId, - @RequestParam Long memberId) { - // TODO: 소셜로그인 구현 후 RequestParam의 userId는 JWT를 인증할 때 수정 예정 - - todoCommandService.createTodo(createTodoRequestDto, roomId, memberId); + @Valid @RequestBody CreateTodoRequestDto createTodoRequestDto + ) { + todoCommandService.createTodo(memberDetails.getMember(), roomId, createTodoRequestDto); return ResponseEntity.ok(ApiResponse.onSuccess("Todo를 정상 생성하였습니다.")); } @@ -53,26 +54,28 @@ public ResponseEntity> createTodo( description = "본인이 참가한 방에서만 조회가 가능합니다. | timePoint를 지정하지 않으면 오늘 날짜 기준으로 반환합니다.") @SwaggerApiError({ErrorStatus._MATE_NOT_FOUND}) public ResponseEntity> getTodo( + @AuthenticationPrincipal MemberDetails memberDetails, @PathVariable Long roomId, - @RequestParam Long memberId, @Parameter(example = "2024-08-01") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate timePoint ) { if (timePoint == null) { timePoint = LocalDate.now(); } - return ResponseEntity.ok( - ApiResponse.onSuccess(todoQueryService.getTodo(roomId, memberId, timePoint))); + return ResponseEntity.ok(ApiResponse.onSuccess( + todoQueryService.getTodo(roomId, memberDetails.getMember(), timePoint) + )); } @PatchMapping("/state") @Operation(summary = "[무빗] Todo 완료 여부를 변경", description = "boolean 값을 같이 넘겨받습니다.") - @SwaggerApiError({ErrorStatus._MATE_NOT_FOUND, ErrorStatus._TODO_NOT_VALID, ErrorStatus._TODO_NOT_FOUND}) + @SwaggerApiError({ErrorStatus._TODO_NOT_VALID, ErrorStatus._TODO_NOT_FOUND}) public ResponseEntity> updateTodoCompleteState( - @Valid @RequestBody UpdateTodoCompleteStateRequestDto updateTodoCompleteStateRequestDto, - @RequestParam Long memberId) { - // TODO: 소셜로그인 후... - todoCommandService.updateTodoCompleteState(updateTodoCompleteStateRequestDto, memberId); + @AuthenticationPrincipal MemberDetails memberDetails, + @Valid @RequestBody UpdateTodoCompleteStateRequestDto updateTodoCompleteStateRequestDto + ) { + todoCommandService.updateTodoCompleteState(memberDetails.getMember(), + updateTodoCompleteStateRequestDto); return ResponseEntity.ok(ApiResponse.onSuccess("완료되었습니다.")); } } diff --git a/src/main/java/com/cozymate/cozymate_server/domain/todo/service/TodoCommandService.java b/src/main/java/com/cozymate/cozymate_server/domain/todo/service/TodoCommandService.java index 797d30ab..61b82946 100644 --- a/src/main/java/com/cozymate/cozymate_server/domain/todo/service/TodoCommandService.java +++ b/src/main/java/com/cozymate/cozymate_server/domain/todo/service/TodoCommandService.java @@ -2,6 +2,7 @@ import com.cozymate.cozymate_server.domain.mate.Mate; import com.cozymate.cozymate_server.domain.mate.repository.MateRepository; +import com.cozymate.cozymate_server.domain.member.Member; import com.cozymate.cozymate_server.domain.todo.Todo; import com.cozymate.cozymate_server.domain.todo.dto.TodoRequestDto.CreateTodoRequestDto; import com.cozymate.cozymate_server.domain.todo.dto.TodoRequestDto.UpdateTodoCompleteStateRequestDto; @@ -21,13 +22,17 @@ public class TodoCommandService { private final MateRepository mateRepository; private final TodoRepository todoRepository; - public void createTodo(CreateTodoRequestDto createTodoRequestDto, Long roomId, Long memberId) { + public void createTodo( + Member member, + Long roomId, + CreateTodoRequestDto createTodoRequestDto + ) { - Mate mate = mateRepository.findByMemberIdAndRoomId(memberId, roomId) + Mate mate = mateRepository.findByMemberIdAndRoomId(member.getId(), roomId) .orElseThrow(() -> new GeneralException(ErrorStatus._MATE_NOT_FOUND)); // 최대 투두 생성 개수 초과 여부 판단 - int todoCount = todoRepository.countAllByRoomIdAndMateIdAndTimePoint(roomId, memberId, + int todoCount = todoRepository.countAllByRoomIdAndMateIdAndTimePoint(roomId, member.getId(), createTodoRequestDto.getTimePoint()); if (todoCount >= MAX_TODO_PER_DAY) { throw new GeneralException(ErrorStatus._TODO_OVER_MAX); @@ -40,12 +45,13 @@ public void createTodo(CreateTodoRequestDto createTodoRequestDto, Long roomId, L } public void updateTodoCompleteState( - UpdateTodoCompleteStateRequestDto updateTodoCompleteStateRequestDto, - Long memberId) { + Member member, + UpdateTodoCompleteStateRequestDto updateTodoCompleteStateRequestDto + ) { Todo todo = todoRepository.findById(updateTodoCompleteStateRequestDto.getTodoId()) .orElseThrow(() -> new GeneralException(ErrorStatus._TODO_NOT_FOUND)); - if (!todo.getMate().getMember().getId().equals(memberId)) { + if (Boolean.FALSE.equals(todo.getMate().getMember().getId().equals(member.getId()))) { throw new GeneralException(ErrorStatus._TODO_NOT_VALID); } todo.updateCompleteState(updateTodoCompleteStateRequestDto.getCompleted()); diff --git a/src/main/java/com/cozymate/cozymate_server/domain/todo/service/TodoQueryService.java b/src/main/java/com/cozymate/cozymate_server/domain/todo/service/TodoQueryService.java index 38df12d6..52bae039 100644 --- a/src/main/java/com/cozymate/cozymate_server/domain/todo/service/TodoQueryService.java +++ b/src/main/java/com/cozymate/cozymate_server/domain/todo/service/TodoQueryService.java @@ -2,6 +2,7 @@ import com.cozymate.cozymate_server.domain.mate.Mate; import com.cozymate.cozymate_server.domain.mate.repository.MateRepository; +import com.cozymate.cozymate_server.domain.member.Member; import com.cozymate.cozymate_server.domain.todo.Todo; import com.cozymate.cozymate_server.domain.todo.converter.TodoConverter; import com.cozymate.cozymate_server.domain.todo.dto.TodoResponseDto.TodoDetailResponseDto; @@ -26,9 +27,9 @@ public class TodoQueryService { private final TodoRepository todoRepository; private final MateRepository mateRepository; - public TodoListResponseDto getTodo(Long roomId, Long memberId, LocalDate timePoint) { + public TodoListResponseDto getTodo(Long roomId, Member member, LocalDate timePoint) { - Mate mate = mateRepository.findByMemberIdAndRoomId(memberId, roomId) + Mate mate = mateRepository.findByMemberIdAndRoomId(member.getId(), roomId) .orElseThrow(() -> new GeneralException(ErrorStatus._MATE_NOT_FOUND)); List todoList = todoRepository.findAllByRoomIdAndTimePoint(roomId, timePoint); @@ -41,6 +42,7 @@ public TodoListResponseDto getTodo(Long roomId, Long memberId, LocalDate timePoi } else { String mateName = todo.getMate().getMember().getName(); TodoDetailResponseDto todoDto = TodoConverter.toTodoDetailResponseDto(todo); + // mateTodoListResponseDto에 mateName이 없으면 새로 생성 mateTodoListResponseDto.computeIfAbsent(mateName, k -> new ArrayList<>()) .add(todoDto); } diff --git a/src/main/java/com/cozymate/cozymate_server/global/common/PageResponseDto.java b/src/main/java/com/cozymate/cozymate_server/global/common/PageResponseDto.java index e3d79e0a..317fdd45 100644 --- a/src/main/java/com/cozymate/cozymate_server/global/common/PageResponseDto.java +++ b/src/main/java/com/cozymate/cozymate_server/global/common/PageResponseDto.java @@ -11,5 +11,4 @@ public class PageResponseDto { private boolean hasNext; private T result; - } \ No newline at end of file diff --git a/src/main/java/com/cozymate/cozymate_server/global/response/code/status/ErrorStatus.java b/src/main/java/com/cozymate/cozymate_server/global/response/code/status/ErrorStatus.java index 400eb9ca..f112f84b 100644 --- a/src/main/java/com/cozymate/cozymate_server/global/response/code/status/ErrorStatus.java +++ b/src/main/java/com/cozymate/cozymate_server/global/response/code/status/ErrorStatus.java @@ -18,6 +18,16 @@ public enum ErrorStatus implements BaseErrorCode { _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."), // [도메인] 관련해서 아래에 계속 추가해주시면 됩니다. + + // 소셜 + // 카카오 + _KAKAO_ACCESS_RESPONSE_RECEIVING_FAIL( + HttpStatus.INTERNAL_SERVER_ERROR, "AUTH500", "카카오에서 response를 받지 못했습니다."), + + _KAKAO_RESPONSE_PARSING_FAIL( + HttpStatus.INTERNAL_SERVER_ERROR, "AUTH501", "카카오 response 파싱 실패"), + _KAKAO_ACCESS_TOKEN_PARSING_FAIL( + HttpStatus.INTERNAL_SERVER_ERROR, "AUTH501", "카카오 accessToken 파싱 실패"), // [Member] 관련 에러 _MEMBER_NOT_FOUND(HttpStatus.BAD_REQUEST, "MEMBER400", "멤버를 찾을 수 없습니다."), @@ -86,12 +96,18 @@ public enum ErrorStatus implements BaseErrorCode { _FRIEND_REQUEST_WAITING(HttpStatus.BAD_REQUEST, "FRIEND404", "대기 중인 친구요청입니다."), _FRIEND_REQUEST_EQUAL(HttpStatus.BAD_REQUEST, "FRIEND405", "같은 사람에게 친구요청을 보낼 수 없습니다."), + // Role 관련 + _ROLE_NOT_FOUND(HttpStatus.BAD_REQUEST, "ROLE400", "역할을 찾을 수 없습니다."), + _ROLE_MATE_MISMATCH(HttpStatus.BAD_REQUEST, "ROLE401", "Mate에게 해당 Role을 삭제할 권한이 없습니다."), + // Feed 관련 에러 _FEED_EXISTS(HttpStatus.BAD_REQUEST, "FEED400", "피드 정보가 이미 존재합니다."), _FEED_NOT_EXISTS(HttpStatus.BAD_REQUEST, "FEED401", "피드 정보가 존재하지 않습니다."), + // Post관련 _POST_NOT_FOUND(HttpStatus.BAD_REQUEST, "POST400", "게시물이 존재하지 않습니다."), + // Post Comment _POST_COMMENT_NOT_FOUND(HttpStatus.BAD_REQUEST, "COMMENT400", "댓글이 존재하지 않습니다."), ;