diff --git a/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/controller/ShoppingController.java b/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/controller/ShoppingController.java new file mode 100644 index 00000000..fcc0a2a8 --- /dev/null +++ b/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/controller/ShoppingController.java @@ -0,0 +1,57 @@ +package com.namo.spring.application.external.api.shop.controller; + +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.namo.spring.application.external.api.shop.dto.ThemeResponse; +import com.namo.spring.application.external.api.shop.usecase.ShoppingUseCase; +import com.namo.spring.application.external.global.common.security.authentication.SecurityUserDetails; +import com.namo.spring.core.common.response.ResponseDto; +import com.namo.spring.db.mysql.domains.shop.enums.ThemeType; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; + +import lombok.RequiredArgsConstructor; + +@Tag(name = "12. 테마샵", description = "테마샵 쇼핑 관련 API ") +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v2/shop/themes") +public class ShoppingController { + + private final ShoppingUseCase shoppingUseCase; + + @GetMapping("") + @Operation(summary = "판매 중인 테마 조회", description = "판매 중인 테마 목록을 조회합니다.") + public ResponseDto getThemes( + @AuthenticationPrincipal SecurityUserDetails memberInfo, + @Parameter(description = "조회할 테마 타입입니다.", example = "background // profile") + @RequestParam("type") String type, + @Parameter(description = "1 부터 시작하는 페이지 번호입니다 (기본값 1)", example = "1") + @RequestParam(value = "page", defaultValue = "1") int page, + @Parameter(description = "한번에 조회할 테마 갯수 입니다 (기본값 6)", example = "6") + @RequestParam(value = "size", defaultValue = "6") int size) { + + ThemeType themeType = ThemeType.valueOf(type.toUpperCase()); + + return ResponseDto.onSuccess(shoppingUseCase + .getThemesByType(themeType, page, size)); + } + + @GetMapping("{/themeId}") + @Operation(summary = "테마 상세 조회", description = "테마 상세 정보를 조회합니다.") + public ResponseDto getThemeDetail( + @AuthenticationPrincipal SecurityUserDetails memberInfo, + @Parameter(description = "조회할 테마 ID입니다.", example = "1") + @PathVariable("themeId") Long themeId) { + + return ResponseDto.onSuccess(shoppingUseCase + .getThemeDetail(memberInfo.getUserId(), themeId)); + } +} diff --git a/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/converter/ThemeConverter.java b/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/converter/ThemeConverter.java new file mode 100644 index 00000000..d1c9786c --- /dev/null +++ b/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/converter/ThemeConverter.java @@ -0,0 +1,52 @@ +package com.namo.spring.application.external.api.shop.converter; + +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.data.domain.Page; + +import com.namo.spring.application.external.api.shop.dto.ThemeResponse; +import com.namo.spring.db.mysql.domains.shop.entity.Theme; +import com.namo.spring.db.mysql.domains.shop.entity.ThemeDetailImage; + +public class ThemeConverter { + + public static ThemeResponse.ThemeDtoList toThemeDtoList(Page themes) { + List themeDtoList = themes.stream() + .map(ThemeConverter::toThemeResponseDto) + .collect(Collectors.toList()); + + return ThemeResponse.ThemeDtoList.builder() + .themes(themeDtoList) + .totalPages(themes.getTotalPages()) + .currentPage(themes.getNumber() + 1) + .pageSize(themes.getSize()) + .totalItems(themes.getTotalElements()) + .build(); + } + + public static ThemeResponse.ThemePreviewDto toThemeResponseDto(Theme theme) { + return ThemeResponse.ThemePreviewDto.builder() + .id(theme.getId()) + .name(theme.getName()) + .description(theme.getDescription()) + .price(theme.getPrice()) + .previewImageUrl(theme.getPreviewImageUrl()) + .build(); + } + + public static ThemeResponse.ThemeInfoDto toThemeInfoDto(Theme theme) { + List detailImages = theme.getDetailImages().stream() + .map(ThemeDetailImage::getImageUrl) + .toList(); + + return ThemeResponse.ThemeInfoDto.builder() + .id(theme.getId()) + .name(theme.getName()) + .description(theme.getDescription()) + .price(theme.getPrice()) + .detailImages(detailImages) + .isOwned(theme.isOwned()) + .build(); + } +} diff --git a/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/dto/ThemeResponse.java b/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/dto/ThemeResponse.java new file mode 100644 index 00000000..6699f735 --- /dev/null +++ b/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/dto/ThemeResponse.java @@ -0,0 +1,56 @@ +package com.namo.spring.application.external.api.shop.dto; + +import java.util.List; + +import io.swagger.v3.oas.annotations.media.Schema; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class ThemeResponse { + + @Builder + @Getter + @AllArgsConstructor + @NoArgsConstructor + public static class ThemeDtoList { + @Schema(description = "총 페이지 수", example = "5") + private int totalPages; + @Schema(description = "현재 페이지 번호", example = "1") + private int currentPage; + @Schema(description = "한 페이지당 항목 수", example = "20") + private int pageSize; + @Schema(description = "전체 항목 수", example = "100") + private long totalItems; + private List themes; + + } + + @Builder + @Getter + @AllArgsConstructor + @NoArgsConstructor + public static class ThemePreviewDto { + private Long id; + private String name; + private String description; + private Integer price; + private String previewImageUrl; + } + + @Builder + @Getter + @AllArgsConstructor + @NoArgsConstructor + public static class ThemeInfoDto { + private Long id; + private String name; + private String description; + private Integer price; + private String type; + private List detailImages; + private Boolean isOwned; // 테마 보유 여부 + } +} diff --git a/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/service/ThemeManageService.java b/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/service/ThemeManageService.java new file mode 100644 index 00000000..6476c261 --- /dev/null +++ b/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/service/ThemeManageService.java @@ -0,0 +1,51 @@ +package com.namo.spring.application.external.api.shop.service; + + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import com.namo.spring.core.common.code.status.ErrorStatus; +import com.namo.spring.db.mysql.domains.shop.entity.Theme; +import com.namo.spring.db.mysql.domains.shop.enums.ThemeStatus; +import com.namo.spring.db.mysql.domains.shop.enums.ThemeType; +import com.namo.spring.db.mysql.domains.shop.exceptions.ThemeException; +import com.namo.spring.db.mysql.domains.shop.service.MemberThemeService; +import com.namo.spring.db.mysql.domains.shop.service.ThemeService; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class ThemeManageService { + + private final ThemeService themeService; + private final MemberThemeService memberThemeService; + + /** + * 테마 타입에 따른 테마 목록을 반환 합니다. + * @param themeType (프로필, 배경) + * @param page + * @param size + * @return + */ + public Page getSellingThemesByType(ThemeType themeType, int page, int size) { + Pageable pageable = PageRequest.of(page - 1, size); + return themeService.findByTypeAndStatus(themeType, pageable, ThemeStatus.SELLING); + } + + /** + * 테마 정보와 소유 여부를 반환 합니다. + * @param memberId + * @param themeId + * @return + */ + public Theme getThemeByIdWithOwnership(Long memberId, Long themeId) { + Theme theme = themeService.findByIdAndStatus(themeId, ThemeStatus.SELLING) + .orElseThrow(() -> new ThemeException(ErrorStatus.NOT_FOUND_THEME)); + boolean isOwned = memberThemeService.purchaseInfo(memberId, themeId); + theme.setOwned(isOwned); + return theme; + } +} diff --git a/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/usecase/ShoppingUseCase.java b/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/usecase/ShoppingUseCase.java new file mode 100644 index 00000000..0d14215f --- /dev/null +++ b/application/external-api-v2/src/main/java/com/namo/spring/application/external/api/shop/usecase/ShoppingUseCase.java @@ -0,0 +1,32 @@ +package com.namo.spring.application.external.api.shop.usecase; + +import org.springframework.data.domain.Page; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.namo.spring.application.external.api.shop.converter.ThemeConverter; +import com.namo.spring.application.external.api.shop.dto.ThemeResponse; +import com.namo.spring.application.external.api.shop.service.ThemeManageService; +import com.namo.spring.db.mysql.domains.shop.entity.Theme; +import com.namo.spring.db.mysql.domains.shop.enums.ThemeType; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class ShoppingUseCase { + + private final ThemeManageService themeManageService; + + @Transactional(readOnly = true) + public ThemeResponse.ThemeDtoList getThemesByType(ThemeType themeType, int page, int size) { + Page themes = themeManageService.getSellingThemesByType(themeType, page, size); + return ThemeConverter.toThemeDtoList(themes); + } + + @Transactional(readOnly = true) + public ThemeResponse.ThemeInfoDto getThemeDetail(Long memberId, Long themeId) { + Theme theme = themeManageService.getThemeByIdWithOwnership(memberId, themeId); + return ThemeConverter.toThemeInfoDto(theme); + } +} diff --git a/core/core-common/src/main/java/com/namo/spring/core/common/code/status/ErrorStatus.java b/core/core-common/src/main/java/com/namo/spring/core/common/code/status/ErrorStatus.java index 6294e4ab..f670f40d 100644 --- a/core/core-common/src/main/java/com/namo/spring/core/common/code/status/ErrorStatus.java +++ b/core/core-common/src/main/java/com/namo/spring/core/common/code/status/ErrorStatus.java @@ -156,6 +156,8 @@ public enum ErrorStatus implements BaseErrorCode { NOT_FOUND_FRIENDSHIP_REQUEST(NOT_FOUND, "친구 요청을 찾을 수 없습니다."), NOT_FOUND_POINT_REQUEST(NOT_FOUND, "대기중인 포인트 입금 요청을 찾을 수 없습니다."), + NOT_FOUND_THEME(NOT_FOUND, "테마를 찾을 수 없습니다."), + /** * 404 : 예외 상황 에러 */ diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/entity/MemberTheme.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/entity/MemberTheme.java new file mode 100644 index 00000000..b4e676d3 --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/entity/MemberTheme.java @@ -0,0 +1,53 @@ +package com.namo.spring.db.mysql.domains.shop.entity; + +import java.time.LocalDateTime; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; + +import org.hibernate.annotations.DynamicInsert; + +import com.namo.spring.db.mysql.common.model.BaseTimeEntity; +import com.namo.spring.db.mysql.domains.user.entity.Member; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@DynamicInsert +public class MemberTheme extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + private Member member; // 사용자 + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + private Theme theme; // 테마 + + @Column(nullable = false) + private Boolean isActive; // 활성화 여부 + + @Column(nullable = false) + private LocalDateTime purchasedAt; // 구매 시점 + + @Builder + public MemberTheme(Member member, Theme theme, Boolean isActive, LocalDateTime purchasedAt) { + this.member = member; + this.theme = theme; + this.isActive = isActive; + this.purchasedAt = LocalDateTime.now(); + } + +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/entity/Theme.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/entity/Theme.java new file mode 100644 index 00000000..9c5c4c66 --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/entity/Theme.java @@ -0,0 +1,71 @@ +package com.namo.spring.db.mysql.domains.shop.entity; + +import java.util.ArrayList; +import java.util.List; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Transient; + +import org.hibernate.annotations.DynamicInsert; + +import com.namo.spring.db.mysql.common.model.BaseTimeEntity; +import com.namo.spring.db.mysql.domains.shop.enums.ThemeStatus; +import com.namo.spring.db.mysql.domains.shop.enums.ThemeType; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@DynamicInsert +public class Theme extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String name; // 테마 이름 + + private String description; // 테마 설명 + + @Column(nullable = false) + private Integer price; // 테마 가격 + + private String previewImageUrl; // 미리보기 이미지 URL + + @OneToMany(mappedBy = "theme", cascade = CascadeType.ALL) + private List detailImages; + + @Enumerated(EnumType.STRING) + private ThemeType type; // 테마 유형 (배경 테마, 프로필 테마 등) + + @Enumerated(EnumType.STRING) + private ThemeStatus status; // 테마 판매 상태 + + @Setter + @Transient // DB에 저장되지 않는 필드 + private boolean isOwned; + + @Builder + public Theme(String name, String description, Integer price, String previewImageUrl, ThemeType type) { + this.name = name; + this.description = description; + this.price = price; + this.previewImageUrl = previewImageUrl; + this.type = type; + } + + +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/entity/ThemeDetailImage.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/entity/ThemeDetailImage.java new file mode 100644 index 00000000..8e07a849 --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/entity/ThemeDetailImage.java @@ -0,0 +1,45 @@ +package com.namo.spring.db.mysql.domains.shop.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; + +import org.hibernate.annotations.DynamicInsert; + +import com.namo.spring.db.mysql.common.model.BaseTimeEntity; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@DynamicInsert +public class ThemeDetailImage extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String imageUrl; // 상세 이미지 URL + + private Integer orderIndex; // 이미지 순서 + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + private Theme theme; // 연결된 테마 + + + @Builder + public ThemeDetailImage(String imageUrl, Integer orderIndex, Theme theme) { + this.imageUrl = imageUrl; + this.orderIndex = orderIndex; + this.theme = theme; + } +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/enums/ThemeStatus.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/enums/ThemeStatus.java new file mode 100644 index 00000000..6a808623 --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/enums/ThemeStatus.java @@ -0,0 +1,10 @@ +package com.namo.spring.db.mysql.domains.shop.enums; + +public enum ThemeStatus { + SELLING, // 판매 중 + SOLD_OUT, // 품절 + DISCONTINUED, // 판매 중지 + DELETED, // 삭제 처리 (soft delete) + PENDING, // 판매 대기 + ARCHIVED // 과거 아카이브 상태 (사용자는 볼 수 있지만 판매되지 않음) +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/enums/ThemeType.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/enums/ThemeType.java new file mode 100644 index 00000000..6f01ed64 --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/enums/ThemeType.java @@ -0,0 +1,6 @@ +package com.namo.spring.db.mysql.domains.shop.enums; + +public enum ThemeType { + BACKGROUND, // 배경 테마 + PROFILE // 프로필 테마 +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/exceptions/ThemeException.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/exceptions/ThemeException.java new file mode 100644 index 00000000..d4e31b3d --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/exceptions/ThemeException.java @@ -0,0 +1,10 @@ +package com.namo.spring.db.mysql.domains.shop.exceptions; + +import com.namo.spring.core.common.code.BaseErrorCode; +import com.namo.spring.core.common.exception.GeneralException; + +public class ThemeException extends GeneralException { + public ThemeException(BaseErrorCode code) { + super(code); + } +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/repository/MemberThemeRepository.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/repository/MemberThemeRepository.java new file mode 100644 index 00000000..0c4d23a1 --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/repository/MemberThemeRepository.java @@ -0,0 +1,9 @@ +package com.namo.spring.db.mysql.domains.shop.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.namo.spring.db.mysql.domains.shop.entity.MemberTheme; + +public interface MemberThemeRepository extends JpaRepository { + boolean existsByMemberIdAndThemeId(Long memberId, Long themeId); +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/repository/ThemeDetailImageRepository.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/repository/ThemeDetailImageRepository.java new file mode 100644 index 00000000..139c46a1 --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/repository/ThemeDetailImageRepository.java @@ -0,0 +1,8 @@ +package com.namo.spring.db.mysql.domains.shop.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.namo.spring.db.mysql.domains.shop.entity.ThemeDetailImage; + +public interface ThemeDetailImageRepository extends JpaRepository { +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/repository/ThemeRepository.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/repository/ThemeRepository.java new file mode 100644 index 00000000..9152b6a3 --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/repository/ThemeRepository.java @@ -0,0 +1,18 @@ +package com.namo.spring.db.mysql.domains.shop.repository; + +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +import com.namo.spring.db.mysql.domains.shop.entity.Theme; +import com.namo.spring.db.mysql.domains.shop.enums.ThemeStatus; +import com.namo.spring.db.mysql.domains.shop.enums.ThemeType; + +public interface ThemeRepository extends JpaRepository { + + Page findByTypeAndStatus(ThemeType themeType, Pageable pageable, ThemeStatus themeStatus); + + Optional findByIdAndStatus(Long id, ThemeStatus themeStatus); +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/service/MemberThemeService.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/service/MemberThemeService.java new file mode 100644 index 00000000..eeef0131 --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/service/MemberThemeService.java @@ -0,0 +1,17 @@ +package com.namo.spring.db.mysql.domains.shop.service; + +import com.namo.spring.core.common.annotation.DomainService; +import com.namo.spring.db.mysql.domains.shop.repository.MemberThemeRepository; + +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class MemberThemeService { + + private final MemberThemeRepository memberThemeRepository; + + public boolean purchaseInfo(Long memberId, Long themeId) { + return memberThemeRepository.existsByMemberIdAndThemeId(memberId, themeId); + } +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/service/ThemeDetailImageService.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/service/ThemeDetailImageService.java new file mode 100644 index 00000000..9885f744 --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/service/ThemeDetailImageService.java @@ -0,0 +1,14 @@ +package com.namo.spring.db.mysql.domains.shop.service; + +import com.namo.spring.core.common.annotation.DomainService; +import com.namo.spring.db.mysql.domains.shop.repository.ThemeDetailImageRepository; + +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class ThemeDetailImageService { + + private final ThemeDetailImageRepository themeDetailImageRepository; + +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/service/ThemeService.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/service/ThemeService.java new file mode 100644 index 00000000..cc5201e5 --- /dev/null +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/shop/service/ThemeService.java @@ -0,0 +1,29 @@ +package com.namo.spring.db.mysql.domains.shop.service; + +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import com.namo.spring.core.common.annotation.DomainService; +import com.namo.spring.db.mysql.domains.shop.entity.Theme; +import com.namo.spring.db.mysql.domains.shop.enums.ThemeStatus; +import com.namo.spring.db.mysql.domains.shop.enums.ThemeType; +import com.namo.spring.db.mysql.domains.shop.repository.ThemeRepository; + +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class ThemeService { + + private final ThemeRepository themeRepository; + + public Optional findByIdAndStatus(Long id, ThemeStatus themeStatus) { + return themeRepository.findByIdAndStatus(id, ThemeStatus.SELLING); + } + + public Page findByTypeAndStatus(ThemeType themeType, Pageable pageable, ThemeStatus themeStatus) { + return themeRepository.findByTypeAndStatus(themeType, pageable, themeStatus); + } +} diff --git a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/user/entity/Member.java b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/user/entity/Member.java index 6d9c2313..51c6a727 100644 --- a/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/user/entity/Member.java +++ b/storage/db-mysql-v2/src/main/java/com/namo/spring/db/mysql/domains/user/entity/Member.java @@ -36,6 +36,7 @@ import com.namo.spring.db.mysql.domains.notification.entity.Device; import com.namo.spring.db.mysql.domains.point.entity.Point; import com.namo.spring.db.mysql.domains.schedule.entity.Participant; +import com.namo.spring.db.mysql.domains.shop.entity.MemberTheme; import com.namo.spring.db.mysql.domains.user.type.MemberRole; import com.namo.spring.db.mysql.domains.user.type.MemberStatus; import com.namo.spring.db.mysql.domains.user.type.SocialType; @@ -133,6 +134,9 @@ public class Member extends BaseTimeEntity implements User { @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) private List participants; + @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) + private List ownedThemes; + @Builder public Member(String name, String tag, LocalDate birthday, String authId, String email, SocialType socialType, String socialRefreshToken) {