diff --git a/photo-service/src/main/java/kr/mafoo/photo/api/AlbumAdminApi.java b/photo-service/src/main/java/kr/mafoo/photo/api/AlbumAdminApi.java new file mode 100644 index 0000000..0c3511a --- /dev/null +++ b/photo-service/src/main/java/kr/mafoo/photo/api/AlbumAdminApi.java @@ -0,0 +1,80 @@ +package kr.mafoo.photo.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import kr.mafoo.photo.annotation.RequestMemberId; +import kr.mafoo.photo.annotation.ULID; +import kr.mafoo.photo.controller.dto.request.AlbumCreateRequest; +import kr.mafoo.photo.controller.dto.request.AlbumUpdateDisplayIndexRequest; +import kr.mafoo.photo.controller.dto.request.AlbumUpdateRequest; +import kr.mafoo.photo.controller.dto.response.AlbumRawResponse; +import kr.mafoo.photo.controller.dto.response.AlbumResponse; +import kr.mafoo.photo.controller.dto.response.PageResponse; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Validated +@Tag(name = "앨범 어드민 관련 API", description = "앨범 조회, 생성, 수정, 삭제 등 API") +@RequestMapping("/v1/admin/albums") +public interface AlbumAdminApi { + @Operation(summary = "앨범 n건 조회", description = "앨범 목록을 조회합니다.") + @GetMapping + Mono> queryAlbums( + @Parameter(description = "페이지 번호", example = "1") + @RequestParam(defaultValue = "1") + int page, + + @Parameter(description = "페이지 크기", example = "10") + @RequestParam(defaultValue = "10") + int size, + + @RequestParam(required = false) + String name, + + @RequestParam(required = false) + String type, + + @RequestParam(required = false) + String ownerMemberId + ); + +// @Operation(summary = "앨범 생성", description = "앨범을 생성합니다.") +// @PostMapping +// Mono createAlbum( +// @Valid +// @RequestBody +// AlbumCreateRequest request +// ); +// +// @Operation(summary = "앨범 변경", description = "앨범의 속성을 변경합니다.") +// @PutMapping("/{albumId}") +// Mono updateAlbum( +// @RequestMemberId +// String memberId, +// +// @ULID +// @Parameter(description = "앨범 ID", example = "test_album_id") +// @PathVariable +// String albumId, +// +// @Valid +// @RequestBody +// AlbumUpdateRequest request +// ); +// +// @Operation(summary = "앨범 삭제", description = "앨범을 삭제합니다.") +// @DeleteMapping("/{albumId}") +// Mono deleteAlbum( +// @RequestMemberId +// String memberId, +// +// @ULID +// @Parameter(description = "앨범 ID", example = "test_album_id") +// @PathVariable +// String albumId +// ); +} diff --git a/photo-service/src/main/java/kr/mafoo/photo/controller/AlbumAdminController.java b/photo-service/src/main/java/kr/mafoo/photo/controller/AlbumAdminController.java new file mode 100644 index 0000000..3a3e326 --- /dev/null +++ b/photo-service/src/main/java/kr/mafoo/photo/controller/AlbumAdminController.java @@ -0,0 +1,22 @@ +package kr.mafoo.photo.controller; + +import kr.mafoo.photo.api.AlbumAdminApi; +import kr.mafoo.photo.controller.dto.response.AlbumRawResponse; +import kr.mafoo.photo.controller.dto.response.PageResponse; +import kr.mafoo.photo.service.AlbumAdminService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +@RequiredArgsConstructor +@RestController +public class AlbumAdminController implements AlbumAdminApi { + private final AlbumAdminService albumAdminService; + + @Override + public Mono> queryAlbums(int page, int size, String name, String type, String ownerMemberId) { + return albumAdminService + .queryAlbums(page, size, name, type, ownerMemberId) + .map(pageResponse -> pageResponse.map(AlbumRawResponse::fromEntity)); + } +} diff --git a/photo-service/src/main/java/kr/mafoo/photo/controller/dto/response/AlbumRawResponse.java b/photo-service/src/main/java/kr/mafoo/photo/controller/dto/response/AlbumRawResponse.java new file mode 100644 index 0000000..20bd743 --- /dev/null +++ b/photo-service/src/main/java/kr/mafoo/photo/controller/dto/response/AlbumRawResponse.java @@ -0,0 +1,41 @@ +package kr.mafoo.photo.controller.dto.response; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import kr.mafoo.photo.domain.AlbumEntity; +import kr.mafoo.photo.domain.AlbumType; + +import java.time.LocalDateTime; + +@Schema(description = "앨범 응답") +public record AlbumRawResponse( + @Schema(description = "앨범 ID", example = "test_album_id") + String albumId, + + @Schema(description = "앨범 이름", example = "야뿌들") + String name, + + @Schema(description = "앨범 종류", example = "TYPE_B") + AlbumType type, + + @Schema(description = "앨범 내 사진 수", example = "6") + String photoCount, + + @Schema(description = "앨범 주인 ID", example = "6") + String ownerMemberId, + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") + @Schema(description = "생성 시간", example = "2021-08-01 00:00:00") + LocalDateTime createdAt +) { + public static AlbumRawResponse fromEntity(AlbumEntity entity) { + return new AlbumRawResponse( + entity.getAlbumId(), + entity.getName(), + entity.getType(), + entity.getPhotoCount().toString(), + entity.getOwnerMemberId(), + entity.getCreatedAt() + ); + } +} diff --git a/photo-service/src/main/java/kr/mafoo/photo/controller/dto/response/PageResponse.java b/photo-service/src/main/java/kr/mafoo/photo/controller/dto/response/PageResponse.java new file mode 100644 index 0000000..0532118 --- /dev/null +++ b/photo-service/src/main/java/kr/mafoo/photo/controller/dto/response/PageResponse.java @@ -0,0 +1,20 @@ +package kr.mafoo.photo.controller.dto.response; + +import java.util.Collection; +import java.util.function.Function; + +public record PageResponse( + Collection results, + Integer page, + Integer size, + Integer totalElement +) { + public PageResponse map(Function mapper) { + return new PageResponse<>( + results.stream().map(mapper).toList(), + page, + size, + totalElement + ); + } +} diff --git a/photo-service/src/main/java/kr/mafoo/photo/repository/AlbumRepository.java b/photo-service/src/main/java/kr/mafoo/photo/repository/AlbumRepository.java index bc7d9ab..63420cf 100644 --- a/photo-service/src/main/java/kr/mafoo/photo/repository/AlbumRepository.java +++ b/photo-service/src/main/java/kr/mafoo/photo/repository/AlbumRepository.java @@ -1,6 +1,8 @@ package kr.mafoo.photo.repository; import kr.mafoo.photo.domain.AlbumEntity; +import kr.mafoo.photo.domain.AlbumType; +import org.springframework.data.domain.Pageable; import org.springframework.data.r2dbc.repository.Modifying; import org.springframework.data.r2dbc.repository.Query; import org.springframework.data.r2dbc.repository.R2dbcRepository; @@ -23,4 +25,11 @@ public interface AlbumRepository extends R2dbcRepository { @Query("UPDATE album SET display_index = display_index -1 WHERE owner_member_id = :ownerMemberId " + "AND display_index BETWEEN :startIndex AND :lastIndex") Mono popDisplayIndexBetween(String ownerMemberId, Integer startIndex, Integer lastIndex); + + Flux findAllByOrderByAlbumIdDesc(Pageable pageable); + + Flux findAllByNameOrderByAlbumIdDesc(String name, Pageable pageable); + Flux findAllByTypeOrderByAlbumIdDesc(AlbumType type, Pageable pageable); + + Flux findAllByOwnerMemberIdOrderByAlbumIdDesc(String ownerMemberId, Pageable pageable); } diff --git a/photo-service/src/main/java/kr/mafoo/photo/service/AlbumAdminService.java b/photo-service/src/main/java/kr/mafoo/photo/service/AlbumAdminService.java new file mode 100644 index 0000000..c311dd4 --- /dev/null +++ b/photo-service/src/main/java/kr/mafoo/photo/service/AlbumAdminService.java @@ -0,0 +1,40 @@ +package kr.mafoo.photo.service; + +import kr.mafoo.photo.controller.dto.response.PageResponse; +import kr.mafoo.photo.domain.AlbumEntity; +import kr.mafoo.photo.domain.AlbumType; +import kr.mafoo.photo.repository.AlbumRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@RequiredArgsConstructor +@Service +public class AlbumAdminService { + private final AlbumRepository albumRepository; + + public Mono> queryAlbums(int page, int size, String name, String type, String ownerMemberId) { + Flux publisher; + if(name != null) { + publisher = albumRepository.findAllByNameOrderByAlbumIdDesc(name, PageRequest.of(page, size)); + } else if(type != null) { + AlbumType albumType; + try { + albumType = AlbumType.valueOf(type); + publisher = albumRepository.findAllByTypeOrderByAlbumIdDesc(albumType, PageRequest.of(page, size)); + } catch (IllegalArgumentException e) { + publisher = albumRepository.findAllByOrderByAlbumIdDesc(PageRequest.of(page, size)); + } + } else if(ownerMemberId != null) { + publisher = albumRepository.findAllByOwnerMemberIdOrderByAlbumIdDesc(ownerMemberId, PageRequest.of(page, size)); + } else { + publisher = albumRepository.findAllByOrderByAlbumIdDesc(PageRequest.of(page, size)); + } + return publisher + .collectList() + .zipWith(albumRepository.count()) + .map(tuple -> new PageResponse<>(tuple.getT1(), page, size, tuple.getT2().intValue())); + } +}