diff --git a/src/main/java/com/adoonge/seedzip/seed/controller/SeedController.java b/src/main/java/com/adoonge/seedzip/seed/controller/SeedController.java index 17fbc49..43f3d94 100644 --- a/src/main/java/com/adoonge/seedzip/seed/controller/SeedController.java +++ b/src/main/java/com/adoonge/seedzip/seed/controller/SeedController.java @@ -1,8 +1,8 @@ package com.adoonge.seedzip.seed.controller; -import com.adoonge.seedzip.seed.dto.request.SeedDeleteListRequest; import com.adoonge.seedzip.seed.dto.request.SeedFilteringRequest; import com.adoonge.seedzip.seed.dto.request.SeedUpdateRequest; +import com.adoonge.seedzip.seed.dto.request.SeedUpdateRequestForApp; import com.adoonge.seedzip.seed.dto.response.SeedResponse.GetFilteredSeeds; import java.util.List; @@ -29,6 +29,7 @@ import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -255,6 +256,22 @@ public ApiResponse modifySeed( return new ApiResponse<>(seedInfoSimple); } + @PatchMapping("/app/{seedId}") + @Operation(summary = "앱용 씨드 수정 API", description = "앱용 씨드 내용을 수정하는 API입니다.") + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "성공적으로 업로드됨", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = SeedResponse.SeedInfoSimple.class))), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "500", description = "서버 오류") + }) + public ApiResponse modifySeedForApp( + @PathVariable("seedId") Long seedId, + @RequestBody @Valid SeedUpdateRequestForApp request, + @AuthenticationPrincipal CustomUserDetails customUserDetails) { + Member member = customUserDetails.getMember(); + return new ApiResponse<>(seedService.updateSeedForApp(request, seedId, member)); + } + @GetMapping(value = "/popular") @Operation(summary = "많이 찾는 씨드 조회", description = "많이 찾는 씨드 목록을 조회하는 API입니다." + "조회수가 3회 이상인 씨드 중 조회수가 높은순으로 30개를 반환합니다.") diff --git a/src/main/java/com/adoonge/seedzip/seed/dto/request/SeedUpdateRequestForApp.java b/src/main/java/com/adoonge/seedzip/seed/dto/request/SeedUpdateRequestForApp.java new file mode 100644 index 0000000..fb482aa --- /dev/null +++ b/src/main/java/com/adoonge/seedzip/seed/dto/request/SeedUpdateRequestForApp.java @@ -0,0 +1,20 @@ +package com.adoonge.seedzip.seed.dto.request; + +import java.time.LocalDate; +import com.adoonge.seedzip.seed.domain.SeedType; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +/** + * 앱 전용 씨드 수정 요청 DTO + * - 파일(이미지, 링크)은 수정 불가 + * - 제목/내용/태그/카테고리 등만 수정 가능 + */ +public record SeedUpdateRequestForApp( + @NotNull SeedType seedType, + String seedName, // 제목 (없으면 null) + @NotNull String[] categoryName, // 카테고리 (없으면 null) + @NotNull @Size(min = 2, message = "태그는 최소 2개 이상 입력해야 합니다.") String[] tagName, + LocalDate dDay, // 없으면 null + String seedDetail // 없으면 null +) {} diff --git a/src/main/java/com/adoonge/seedzip/seed/service/SeedService.java b/src/main/java/com/adoonge/seedzip/seed/service/SeedService.java index 9ed847d..edc6b51 100644 --- a/src/main/java/com/adoonge/seedzip/seed/service/SeedService.java +++ b/src/main/java/com/adoonge/seedzip/seed/service/SeedService.java @@ -22,6 +22,7 @@ import com.adoonge.seedzip.seed.dto.request.SeedFilteringRequest; import com.adoonge.seedzip.seed.dto.request.SeedRequest; import com.adoonge.seedzip.seed.dto.request.SeedUpdateRequest; +import com.adoonge.seedzip.seed.dto.request.SeedUpdateRequestForApp; import com.adoonge.seedzip.seed.dto.response.SeedResponse; import com.adoonge.seedzip.seed.repository.CategorySeedRepository; import com.adoonge.seedzip.seed.repository.FileRepository; @@ -418,6 +419,47 @@ public SeedResponse.SeedInfoSimple updateSeed(SeedUpdateRequest request, .build(); } + @Transactional + public SeedResponse.SeedInfoSimple updateSeedForApp(SeedUpdateRequestForApp request, + Long seedId, Member member) { + Seed seed = getSeedOrThrow(seedId); + + if (!seed.getMember().getId().equals(member.getId())) { + throw SeedzipException.from(ErrorCode.MEMBER_NOT_OWNER); + } + + if (!request.seedType().equals(seed.getSeedType())) { + throw SeedzipException.from(ErrorCode.SEED_TYPE_NOT_SUPPORTED); + } + + // 기본 필드 수정 + if (!Objects.equals(seed.getSeedName(), request.seedName())) { + seed.updateSeedName(request.seedName()); + } + if (!Objects.equals(seed.getDDay(), request.dDay())) { + seed.updateDDay(request.dDay()); + } + if (!Objects.equals(seed.getSeedDetail(), request.seedDetail())) { + seed.updateSeedDetail(request.seedDetail()); + } + + // 태그, 카테고리 갱신 + seedTagRepository.deleteAllBySeedId(seedId); + saveSeedTags(request.tagName(), member, seed); + + categorySeedRepository.deleteAllBySeedId(seedId); + saveSeedCategories(request.categoryName(), member, seed); + + // 🚫 파일 삭제나 링크 수정 없음 + + Seed updatedSeed = seedRepository.save(seed); + return SeedResponse.SeedInfoSimple.builder() + .seedId(updatedSeed.getId()) + .seedName(updatedSeed.getSeedName()) + .build(); + } + + //북마크된 씨드 조회 @Transactional public SeedResponse.GetAllSeeds getBookmarkedSeeds(Member member, int page, int size, String sortBy, boolean isAsc,