diff --git a/src/main/java/Ness/Backend/domain/auth/jwt/JwtAuthenticationFilter.java b/src/main/java/Ness/Backend/domain/auth/jwt/JwtAuthenticationFilter.java index 436802e..c96ec24 100644 --- a/src/main/java/Ness/Backend/domain/auth/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/Ness/Backend/domain/auth/jwt/JwtAuthenticationFilter.java @@ -17,7 +17,6 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.stereotype.Component; import java.io.IOException; diff --git a/src/main/java/Ness/Backend/domain/auth/jwt/JwtAuthorizationFilter.java b/src/main/java/Ness/Backend/domain/auth/jwt/JwtAuthorizationFilter.java index 995d495..17e152d 100644 --- a/src/main/java/Ness/Backend/domain/auth/jwt/JwtAuthorizationFilter.java +++ b/src/main/java/Ness/Backend/domain/auth/jwt/JwtAuthorizationFilter.java @@ -4,8 +4,6 @@ import Ness.Backend.domain.auth.security.AuthDetails; import Ness.Backend.domain.member.entity.Member; import Ness.Backend.global.error.ErrorCode; -import static Ness.Backend.global.error.FilterExceptionHandler.setResponse; - import com.auth0.jwt.exceptions.SignatureVerificationException; import com.auth0.jwt.exceptions.TokenExpiredException; import jakarta.servlet.FilterChain; @@ -19,11 +17,12 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; -import org.springframework.stereotype.Component; import java.io.IOException; import java.util.Collections; +import static Ness.Backend.global.error.FilterExceptionHandler.setResponse; + /* 사용자의 권한 부여 * 요청에 포함된 JWT 토큰을 검증하고, 토큰에서 추출한 권한 정보를 기반으로 사용자에 대한 권한을 확인 * 모든 사용자가 모든 리소스에 대한 권한을 가지는 것은 아님-특정 리소스에 대한 권한만 가지도록 해야 함*/ diff --git a/src/main/java/Ness/Backend/domain/auth/jwt/JwtTokenProvider.java b/src/main/java/Ness/Backend/domain/auth/jwt/JwtTokenProvider.java index 047cb71..9faef0b 100644 --- a/src/main/java/Ness/Backend/domain/auth/jwt/JwtTokenProvider.java +++ b/src/main/java/Ness/Backend/domain/auth/jwt/JwtTokenProvider.java @@ -9,7 +9,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; import org.springframework.web.client.HttpServerErrorException; import java.time.LocalDateTime; diff --git a/src/main/java/Ness/Backend/domain/auth/oAuth/OAuth2Controller.java b/src/main/java/Ness/Backend/domain/auth/oAuth/OAuth2Controller.java index cbcfe39..b0c5179 100644 --- a/src/main/java/Ness/Backend/domain/auth/oAuth/OAuth2Controller.java +++ b/src/main/java/Ness/Backend/domain/auth/oAuth/OAuth2Controller.java @@ -7,8 +7,6 @@ import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import org.springframework.http.HttpStatusCode; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @RestController diff --git a/src/main/java/Ness/Backend/domain/auth/security/AuthDetails.java b/src/main/java/Ness/Backend/domain/auth/security/AuthDetails.java index e08378d..3b45c7f 100644 --- a/src/main/java/Ness/Backend/domain/auth/security/AuthDetails.java +++ b/src/main/java/Ness/Backend/domain/auth/security/AuthDetails.java @@ -2,7 +2,6 @@ import Ness.Backend.domain.member.entity.Member; import lombok.Data; -import lombok.RequiredArgsConstructor; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; diff --git a/src/main/java/Ness/Backend/domain/auth/security/SecurityConfig.java b/src/main/java/Ness/Backend/domain/auth/security/SecurityConfig.java index 1964eb9..4e174d0 100644 --- a/src/main/java/Ness/Backend/domain/auth/security/SecurityConfig.java +++ b/src/main/java/Ness/Backend/domain/auth/security/SecurityConfig.java @@ -16,7 +16,6 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; diff --git a/src/main/java/Ness/Backend/domain/category/CategoryController.java b/src/main/java/Ness/Backend/domain/category/CategoryController.java index c4e0637..71d4ea6 100644 --- a/src/main/java/Ness/Backend/domain/category/CategoryController.java +++ b/src/main/java/Ness/Backend/domain/category/CategoryController.java @@ -38,4 +38,11 @@ public ResponseEntity putUserCategory(@AuthUser Member member, @RequestBody P categoryService.putUserCategory(member.getId(), putCategoryDto); return new ResponseEntity<>(HttpStatusCode.valueOf(200)); } + + @DeleteMapping("") + @Operation(summary = "사용자가 만든 카테고리 삭제", description = "사용자가 만든 카테고리를 삭제합니다.") + public ResponseEntity putUserCategory(@AuthUser Member member, @RequestParam Long categoryId){ + categoryService.deleteUserCategory(member.getId(), categoryId); + return new ResponseEntity<>(HttpStatusCode.valueOf(200)); + } } diff --git a/src/main/java/Ness/Backend/domain/category/CategoryRepository.java b/src/main/java/Ness/Backend/domain/category/CategoryRepository.java index a5fc58d..a1c7f63 100644 --- a/src/main/java/Ness/Backend/domain/category/CategoryRepository.java +++ b/src/main/java/Ness/Backend/domain/category/CategoryRepository.java @@ -3,6 +3,7 @@ import Ness.Backend.domain.category.entity.Category; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; @@ -21,4 +22,12 @@ public interface CategoryRepository extends JpaRepository { List findCategoriesByMember_idAndNameExcludeId(Long memberId, String name, Long categoryId); List findCategoriesByMember_idAndName(Long memberId, String name); + + @Query(value = "SELECT * FROM category " + + "WHERE member_id = :memberId " + + "AND is_default_none = :isDefaultNone " + + "LIMIT 1", + nativeQuery = true) + Category findCategoryByMember_idAndIsDefaultNone(@Param("memberId") Long memberId, + @Param("isDefaultNone") boolean isDefaultNone); } diff --git a/src/main/java/Ness/Backend/domain/category/CategoryService.java b/src/main/java/Ness/Backend/domain/category/CategoryService.java index 590b0b2..a6843a2 100644 --- a/src/main/java/Ness/Backend/domain/category/CategoryService.java +++ b/src/main/java/Ness/Backend/domain/category/CategoryService.java @@ -7,22 +7,29 @@ import Ness.Backend.domain.category.entity.Category; import Ness.Backend.domain.member.MemberRepository; import Ness.Backend.domain.member.entity.Member; +import Ness.Backend.domain.schedule.ScheduleRepository; +import Ness.Backend.domain.schedule.entity.Schedule; +import Ness.Backend.global.error.exception.DefaultCategoryException; import Ness.Backend.global.error.exception.DuplicateCategoryException; +import Ness.Backend.global.error.exception.UnauthorizedAccessException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Objects; @Service @RequiredArgsConstructor @Slf4j -@Transactional(readOnly = true) +@Transactional public class CategoryService { private final CategoryRepository categoryRepository; private final MemberRepository memberRepository; + private final ScheduleRepository scheduleRepository; /* 특정 유저의 카테고리 전부 가져오기 */ + @Transactional(readOnly = true) public GetCategoryListDto getUserCategory(Long memberId) { List categoryList = categoryRepository.findCategoriesByMember_id(memberId); @@ -37,7 +44,6 @@ public GetCategoryListDto getUserCategory(Long memberId) { } /* 카테고리 새롭게 만들기(유저에 의해서만 직접 생성) */ - @Transactional public void postUserCategory(Long memberId, PostCategoryDto postCategoryDto){ List categoryList = categoryRepository.findCategoriesByMember_idAndName(memberId, postCategoryDto.getName()); if(categoryList.isEmpty()){ @@ -58,17 +64,51 @@ public void postUserCategory(Long memberId, PostCategoryDto postCategoryDto){ } /* 카테고리 수정하기 */ - @Transactional public void putUserCategory(Long memberId, PutCategoryDto putCategoryDto){ + Category changeCategory = categoryRepository.findCategoryById(putCategoryDto.getId()); + checkCategoryAuth(memberId, changeCategory); + List categoryList = categoryRepository.findCategoriesByMember_idAndNameExcludeId(memberId, putCategoryDto.getName(), putCategoryDto.getId()); if(categoryList.isEmpty()){ //중복되지 않은 카테고리일 경우는 변경사항 저장 가능 - Category category = categoryRepository.findCategoryById(putCategoryDto.getId()); - category.changeCategory(putCategoryDto.getName(), putCategoryDto.getColor()); + log.info(putCategoryDto.getId() + "번 카테고리 " + changeCategory.getName() + " 수정"); + changeCategory.changeCategory(putCategoryDto.getName(), putCategoryDto.getColor()); } else { throw new DuplicateCategoryException(); } } + + /* 카테고리 삭제하기 */ + @Transactional + public void deleteUserCategory(Long memberId, Long categoryId){ + Category deleteCategory = categoryRepository.findCategoryById(categoryId); + checkCategoryAuth(memberId,deleteCategory); + + if(deleteCategory.isDefaultNone()){ + //디폴트 미분류 카테고리는 삭제 불가 + throw new DefaultCategoryException(); + } else{ + //디폴트 카테고리 찾기 + Category defaultCategory = categoryRepository.findCategoryByMember_idAndIsDefaultNone(memberId, true); + + //삭제할 카테고리의 일정은 모두 디폴트로 옮기기 + List changeScheduleList = scheduleRepository.findSchedulesByCategory_Id(categoryId); + + changeScheduleList.forEach( + schedule -> schedule.changeCategory(defaultCategory)); + + //해당 카테고리 삭제 + log.info(categoryId + "번 카테고리 " + deleteCategory.getName() + " 삭제"); + categoryRepository.delete(deleteCategory); + } + } + + //자기 자신의 리소스를 접근하고 있는지 확인 + private void checkCategoryAuth(Long memberId, Category category){ + if(!Objects.equals(memberId, category.getMember().getId())){ + throw new UnauthorizedAccessException("권한이 없습니다. 해당 카테고리는 다른 유저가 권한을 가지고 있습니다."); + } + } } diff --git a/src/main/java/Ness/Backend/domain/category/entity/Category.java b/src/main/java/Ness/Backend/domain/category/entity/Category.java index c5622ae..cfaf52d 100644 --- a/src/main/java/Ness/Backend/domain/category/entity/Category.java +++ b/src/main/java/Ness/Backend/domain/category/entity/Category.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; @Entity @Getter @@ -24,6 +25,9 @@ public class Category { //카테고리별 색상 private String color; + //디폴트로는 false + private boolean isDefaultNone; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id", nullable = false) private Member member; @@ -37,9 +41,10 @@ public void changeCategory(String name, String color){ } @Builder - public Category(Member member, String name, String color){ + public Category(Member member, String name, String color, boolean isDefaultNone){ this.member = member; this.name = name; this.color = color; + this.isDefaultNone = Objects.requireNonNullElse(isDefaultNone, false); } } diff --git a/src/main/java/Ness/Backend/domain/member/MemberService.java b/src/main/java/Ness/Backend/domain/member/MemberService.java index 0569b14..3b74e04 100644 --- a/src/main/java/Ness/Backend/domain/member/MemberService.java +++ b/src/main/java/Ness/Backend/domain/member/MemberService.java @@ -42,14 +42,48 @@ public Member createMember(String email, String password, String picture, String .build(); //디폴트 미분류 카테고리가 있어야 함, 맴버 생성시 자동 만들어주기 - Category category = Category.builder() + //회색 + Category noneCategory = Category.builder() .member(member) .name("\uD83C\uDF40미분류") .color("#D9D9D9") + .isDefaultNone(true) + .build(); + + //초록 + Category studyCategory = Category.builder() + .member(member) + .name("\uD83D\uDCD6공부") + .color("#00C09E") + .build(); + + //하늘 + Category workoutCategory = Category.builder() + .member(member) + .name("\uD83C\uDFC3\u200D♀\uFE0F운동") + .color("#759CFF") + .build(); + + //핑크 + Category restCategory = Category.builder() + .member(member) + .name("\uD83D\uDEDF여가") + .color("#FF75C8") + .build(); + + //주황 + Category meetingCategory = Category.builder() + .member(member) + .name("\uD83D\uDC65약속") + .color("#FFB775") .build(); profileRepository.save(profile); - categoryRepository.save(category); + categoryRepository.save(noneCategory); + categoryRepository.save(studyCategory); + categoryRepository.save(workoutCategory); + categoryRepository.save(restCategory); + categoryRepository.save(meetingCategory); return memberRepository.save(member); } } diff --git a/src/main/java/Ness/Backend/domain/profile/ProfileController.java b/src/main/java/Ness/Backend/domain/profile/ProfileController.java index ee127ea..0ba68e6 100644 --- a/src/main/java/Ness/Backend/domain/profile/ProfileController.java +++ b/src/main/java/Ness/Backend/domain/profile/ProfileController.java @@ -2,8 +2,8 @@ import Ness.Backend.domain.member.entity.Member; -import Ness.Backend.domain.profile.dto.request.PutProfileDto; import Ness.Backend.domain.profile.dto.request.PatchPersonaDto; +import Ness.Backend.domain.profile.dto.request.PutProfileDto; import Ness.Backend.domain.profile.dto.response.GetProfileDto; import Ness.Backend.global.auth.AuthUser; import io.swagger.v3.oas.annotations.Operation; diff --git a/src/main/java/Ness/Backend/domain/report/ReportActivityRepository.java b/src/main/java/Ness/Backend/domain/report/ReportActivityRepository.java index e2f84e7..e4f9cb6 100644 --- a/src/main/java/Ness/Backend/domain/report/ReportActivityRepository.java +++ b/src/main/java/Ness/Backend/domain/report/ReportActivityRepository.java @@ -11,7 +11,7 @@ public interface ReportActivityRepository extends JpaRepository findTodayReportActivityByMember_Id( diff --git a/src/main/java/Ness/Backend/domain/report/ReportMemoryRepository.java b/src/main/java/Ness/Backend/domain/report/ReportMemoryRepository.java index 9dde89c..7080734 100644 --- a/src/main/java/Ness/Backend/domain/report/ReportMemoryRepository.java +++ b/src/main/java/Ness/Backend/domain/report/ReportMemoryRepository.java @@ -12,7 +12,7 @@ public interface ReportMemoryRepository extends JpaRepository { // 특정 맴버의 오늘 하루 생성된 한줄 추천 데이터만 반환 @Query( value = "SELECT * FROM report_recommend " + "WHERE member_id = :memberId " + - "AND DATE(created_date) = CURDATE() " + + "AND DATE(CONVERT_TZ(created_date, '+00:00', '+09:00')) = CURDATE() " + "ORDER BY created_date ASC", nativeQuery = true) - ReportRecommend findTodayReportRecommendByMember_Id( + List findTodayReportRecommendByMember_Id( @Param("memberId") Long memberId); } diff --git a/src/main/java/Ness/Backend/domain/report/ReportService.java b/src/main/java/Ness/Backend/domain/report/ReportService.java index 02ee477..8d62399 100644 --- a/src/main/java/Ness/Backend/domain/report/ReportService.java +++ b/src/main/java/Ness/Backend/domain/report/ReportService.java @@ -10,6 +10,8 @@ import Ness.Backend.domain.report.entity.ReportMemory; import Ness.Backend.domain.report.entity.ReportRecommend; import Ness.Backend.domain.report.entity.ReportTag; +import Ness.Backend.global.error.ErrorCode; +import Ness.Backend.global.error.exception.NotFoundException; import Ness.Backend.global.fastApi.FastApiMemoryApi; import Ness.Backend.global.fastApi.FastApiRecommendApi; import Ness.Backend.global.fastApi.FastApiTagApi; @@ -148,9 +150,9 @@ public PostFastApiAiTagListDto postNewAiTag(Long id, ZonedDateTime today){ public PostFastApiAiRecommendActivityDto getRecommendActivity(Long memberId){ // 오늘 날짜 가져오기 ZonedDateTime now = getToday(); - ReportRecommend reportRecommend = reportRecommendRepository.findTodayReportRecommendByMember_Id(memberId); + List reportRecommends = reportRecommendRepository.findTodayReportRecommendByMember_Id(memberId); - if(reportRecommend == null){ + if(reportRecommends.isEmpty()){ //새로운 한 줄 추천 및 엑티비티 생성하기 PostFastApiAiRecommendActivityDto aiDto = postNewAiRecommend(memberId, now); aiDto.setAnswer(parseAiRecommend(aiDto.getAnswer())); @@ -177,9 +179,14 @@ public PostFastApiAiRecommendActivityDto getRecommendActivity(Long memberId){ } return aiDto; } else{ + ReportRecommend reportRecommend = reportRecommends.stream() + .findFirst() + .orElseThrow(() -> new NotFoundException(ErrorCode.MISMATCH_REPORT_RECOMMEND.getMessage())); + List reportActivities = reportActivityRepository.findTodayReportActivityByMember_Id(memberId); List postFastApiAiActivityDtos = reportActivities.stream() + .limit(3) // 처음 세 개의 원소만 선택 .map(activity -> PostFastApiAiActivityDto.builder() .activity(activity.getActivityText()) .imageTag(activity.getImageTag()) diff --git a/src/main/java/Ness/Backend/domain/report/ReportTagRepository.java b/src/main/java/Ness/Backend/domain/report/ReportTagRepository.java index fe13392..dfd221c 100644 --- a/src/main/java/Ness/Backend/domain/report/ReportTagRepository.java +++ b/src/main/java/Ness/Backend/domain/report/ReportTagRepository.java @@ -11,8 +11,8 @@ public interface ReportTagRepository extends JpaRepository { //매 월 1일마다 특정 멤버가 생성한 보고서 태그 데이터를 가져오는 역할 @Query( value = "SELECT * FROM report_tag " + "WHERE member_id = :memberId " + - "AND EXTRACT(YEAR_MONTH FROM CONVERT_TZ(created_date, 'UTC', 'Asia/Seoul')) = EXTRACT(YEAR_MONTH FROM NOW()) " + - "AND EXTRACT(DAY FROM CONVERT_TZ(created_date, 'UTC', 'Asia/Seoul')) = 1;", + "AND EXTRACT(YEAR_MONTH FROM CONVERT_TZ(created_date, '+00:00', '+09:00')) = EXTRACT(YEAR_MONTH FROM NOW()) " + + "AND EXTRACT(DAY FROM CONVERT_TZ(created_date, '+00:00', '+09:00')) = 1;", nativeQuery = true) List findLastMonthReportTagByMember_Id( @Param("memberId") Long memberId); diff --git a/src/main/java/Ness/Backend/domain/schedule/ScheduleRepository.java b/src/main/java/Ness/Backend/domain/schedule/ScheduleRepository.java index e423bbe..e3139e8 100644 --- a/src/main/java/Ness/Backend/domain/schedule/ScheduleRepository.java +++ b/src/main/java/Ness/Backend/domain/schedule/ScheduleRepository.java @@ -36,4 +36,6 @@ List findOneDaySchedulesByMember_Id( //스케쥴 ID로 특정 스케쥴 찾아주기 Schedule findScheduleById(Long scheduleId); + + List findSchedulesByCategory_Id(Long categoryId); } diff --git a/src/main/java/Ness/Backend/domain/schedule/ScheduleService.java b/src/main/java/Ness/Backend/domain/schedule/ScheduleService.java index f3d8e72..252be58 100644 --- a/src/main/java/Ness/Backend/domain/schedule/ScheduleService.java +++ b/src/main/java/Ness/Backend/domain/schedule/ScheduleService.java @@ -10,9 +10,9 @@ import Ness.Backend.domain.member.MemberRepository; import Ness.Backend.domain.member.entity.Member; import Ness.Backend.domain.schedule.dto.request.*; -import Ness.Backend.domain.schedule.dto.response.GetScheduleListDto; import Ness.Backend.domain.schedule.dto.response.GetScheduleDetailDto; import Ness.Backend.domain.schedule.dto.response.GetScheduleDto; +import Ness.Backend.domain.schedule.dto.response.GetScheduleListDto; import Ness.Backend.domain.schedule.entity.Schedule; import Ness.Backend.global.fastApi.FastApiDeleteScheduleApi; import Ness.Backend.global.fastApi.FastApiPostScheduleApi; @@ -236,6 +236,7 @@ public GetScheduleListDto makeScheduleListDto(List scheduleList){ .id(schedule.getId()) .category(schedule.getCategory().getName()) .categoryNum(schedule.getCategory().getId()) + .categoryColor(schedule.getCategory().getColor()) .info(schedule.getInfo()) .startTime(schedule.getStartTime()) .endTime(schedule.getEndTime()) diff --git a/src/main/java/Ness/Backend/domain/schedule/dto/request/PutFastApiScheduleDto.java b/src/main/java/Ness/Backend/domain/schedule/dto/request/PutFastApiScheduleDto.java index 03e7058..4872afd 100644 --- a/src/main/java/Ness/Backend/domain/schedule/dto/request/PutFastApiScheduleDto.java +++ b/src/main/java/Ness/Backend/domain/schedule/dto/request/PutFastApiScheduleDto.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/src/main/java/Ness/Backend/domain/schedule/dto/request/PutScheduleDto.java b/src/main/java/Ness/Backend/domain/schedule/dto/request/PutScheduleDto.java index 93226c4..8faf52c 100644 --- a/src/main/java/Ness/Backend/domain/schedule/dto/request/PutScheduleDto.java +++ b/src/main/java/Ness/Backend/domain/schedule/dto/request/PutScheduleDto.java @@ -1,7 +1,6 @@ package Ness.Backend.domain.schedule.dto.request; -import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; diff --git a/src/main/java/Ness/Backend/domain/schedule/dto/response/GetScheduleDto.java b/src/main/java/Ness/Backend/domain/schedule/dto/response/GetScheduleDto.java index 8a47e29..0f5a0b8 100644 --- a/src/main/java/Ness/Backend/domain/schedule/dto/response/GetScheduleDto.java +++ b/src/main/java/Ness/Backend/domain/schedule/dto/response/GetScheduleDto.java @@ -34,17 +34,22 @@ public class GetScheduleDto { @JsonProperty("categoryNum") private Long categoryNum; + @Schema(description = "스케줄 카테고리 색상", example = "#FFFFFF") + @JsonProperty("categoryColor") + private String categoryColor; + @Schema(description = "스케줄 디테일", example = "위치, 사람, id 등") @JsonProperty("details") private GetScheduleDetailDto details; @Builder - public GetScheduleDto(Long id, String category, Long categoryNum, + public GetScheduleDto(Long id, String category, Long categoryNum, String categoryColor, String info, ZonedDateTime startTime, ZonedDateTime endTime, GetScheduleDetailDto details){ this.id = id; this.category = category; this.categoryNum = categoryNum; + this.categoryColor = categoryColor; this.info = info; this.startTime = startTime; this.endTime = endTime; diff --git a/src/main/java/Ness/Backend/domain/schedule/entity/Schedule.java b/src/main/java/Ness/Backend/domain/schedule/entity/Schedule.java index 4a75963..f4dafae 100644 --- a/src/main/java/Ness/Backend/domain/schedule/entity/Schedule.java +++ b/src/main/java/Ness/Backend/domain/schedule/entity/Schedule.java @@ -63,4 +63,8 @@ public void changeSchedule(String info, String location, String person, ZonedDat this.endTime = endTime; this.category = category; } + + public void changeCategory(Category category){ + this.category = category; + } } diff --git a/src/main/java/Ness/Backend/global/error/ErrorCode.java b/src/main/java/Ness/Backend/global/error/ErrorCode.java index 1b441c0..cbaa3e9 100644 --- a/src/main/java/Ness/Backend/global/error/ErrorCode.java +++ b/src/main/java/Ness/Backend/global/error/ErrorCode.java @@ -32,7 +32,11 @@ public enum ErrorCode { INVALID_PRINCIPAL(BAD_REQUEST, "AUTH012", "인증정보가 존재하지 않습니다."), /* 카테고리 관련 */ - INVALID_CATEGORY_NAME(CONFLICT, "CATE001", "해당 카테고리명이 이미 존재합니다. 카테고리명은 중복될 수 없습니다."); + INVALID_CATEGORY_NAME(CONFLICT, "CATE001", "해당 카테고리명이 이미 존재합니다. 카테고리명은 중복될 수 없습니다."), + INVALID_CATEGORY_DELETE(BAD_REQUEST, "CATE002", "미분류 카테고리는 삭제 불가능합니다."), + + /* 리포트 관련 */ + MISMATCH_REPORT_RECOMMEND(BAD_REQUEST, "RPT001", "한 줄 추천이 존재하지 않습니다."); private final HttpStatus httpStatus; private final String code; diff --git a/src/main/java/Ness/Backend/global/error/ErrorResponse.java b/src/main/java/Ness/Backend/global/error/ErrorResponse.java index 3f3cf1b..8abb503 100644 --- a/src/main/java/Ness/Backend/global/error/ErrorResponse.java +++ b/src/main/java/Ness/Backend/global/error/ErrorResponse.java @@ -44,4 +44,12 @@ public static ErrorResponse onFailure(ErrorCode errorCode) { .message(errorCode.getMessage()) .build(); } + + public static ErrorResponse onFailure(ErrorCode errorCode, String message) { + return ErrorResponse.builder() + .status(errorCode.getHttpStatus().value()) + .code(errorCode.getCode()) + .message(message) + .build(); + } } diff --git a/src/main/java/Ness/Backend/global/error/FilterExceptionHandler.java b/src/main/java/Ness/Backend/global/error/FilterExceptionHandler.java index e9c1fa3..0263d51 100644 --- a/src/main/java/Ness/Backend/global/error/FilterExceptionHandler.java +++ b/src/main/java/Ness/Backend/global/error/FilterExceptionHandler.java @@ -1,7 +1,7 @@ package Ness.Backend.global.error; -import Ness.Backend.global.response.ApiResponse; import jakarta.servlet.http.HttpServletResponse; + import java.io.IOException; public class FilterExceptionHandler { diff --git a/src/main/java/Ness/Backend/global/error/GlobalExceptionHandler.java b/src/main/java/Ness/Backend/global/error/GlobalExceptionHandler.java index c50ebec..2477c71 100644 --- a/src/main/java/Ness/Backend/global/error/GlobalExceptionHandler.java +++ b/src/main/java/Ness/Backend/global/error/GlobalExceptionHandler.java @@ -16,6 +16,6 @@ public class GlobalExceptionHandler { protected ResponseEntity handleBusinessException(final BaseException baseException, HttpServletRequest httpServletRequest) { log.error("handleBusinessException", baseException); final ContentCachingRequestWrapper contentCachingRequestWrapper = new ContentCachingRequestWrapper(httpServletRequest); - return new ResponseEntity<>(ErrorResponse.onFailure(baseException.getErrorCode()),null, baseException.getErrorCode().getHttpStatus()); + return new ResponseEntity<>(ErrorResponse.onFailure(baseException.getErrorCode(), baseException.getMessage()),null, baseException.getErrorCode().getHttpStatus()); } } diff --git a/src/main/java/Ness/Backend/global/error/exception/DefaultCategoryException.java b/src/main/java/Ness/Backend/global/error/exception/DefaultCategoryException.java new file mode 100644 index 0000000..9de5530 --- /dev/null +++ b/src/main/java/Ness/Backend/global/error/exception/DefaultCategoryException.java @@ -0,0 +1,16 @@ +package Ness.Backend.global.error.exception; + +import Ness.Backend.global.error.ErrorCode; +import lombok.Getter; +@Getter +public class DefaultCategoryException extends BaseException { + public DefaultCategoryException() { + super(ErrorCode.INVALID_CATEGORY_DELETE, ErrorCode.INVALID_CATEGORY_DELETE.getMessage()); + } + public DefaultCategoryException(String message) { + super(ErrorCode.INVALID_CATEGORY_DELETE, message); + } + public DefaultCategoryException(ErrorCode errorCode) { + super(errorCode, errorCode.getMessage()); + } +} diff --git a/src/main/java/Ness/Backend/global/error/exception/NotFoundException.java b/src/main/java/Ness/Backend/global/error/exception/NotFoundException.java new file mode 100644 index 0000000..4dc420a --- /dev/null +++ b/src/main/java/Ness/Backend/global/error/exception/NotFoundException.java @@ -0,0 +1,17 @@ +package Ness.Backend.global.error.exception; + +import Ness.Backend.global.error.ErrorCode; +import lombok.Getter; + +@Getter +public class NotFoundException extends BaseException { + public NotFoundException() { + super(ErrorCode._BAD_REQUEST, ErrorCode._BAD_REQUEST.getMessage()); + } + public NotFoundException(String message) { + super(ErrorCode._BAD_REQUEST, message); + } + public NotFoundException(ErrorCode errorCode) { + super(errorCode, errorCode.getMessage()); + } +} diff --git a/src/main/java/Ness/Backend/global/fastApi/FastApiChatApi.java b/src/main/java/Ness/Backend/global/fastApi/FastApiChatApi.java index 495e171..1998d70 100644 --- a/src/main/java/Ness/Backend/global/fastApi/FastApiChatApi.java +++ b/src/main/java/Ness/Backend/global/fastApi/FastApiChatApi.java @@ -2,9 +2,7 @@ import Ness.Backend.domain.chat.dto.request.PostFastApiUserChatDto; import Ness.Backend.domain.chat.dto.response.PostFastApiAiChatDto; -import com.fasterxml.jackson.databind.JsonNode; import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; @FeignClient( name = "FastApiChat", diff --git a/src/main/java/Ness/Backend/global/response/ApiResponse.java b/src/main/java/Ness/Backend/global/response/ApiResponse.java index e708b04..cdfcf24 100644 --- a/src/main/java/Ness/Backend/global/response/ApiResponse.java +++ b/src/main/java/Ness/Backend/global/response/ApiResponse.java @@ -4,10 +4,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Builder; -import net.minidev.json.JSONObject; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; public class ApiResponse { @JsonProperty("status")