!theme mono title MySubscription Service - Clean Architecture Class Diagram ' BIZ Layer package "com.unicorn.lifesub.mysub.biz" { package "usecase" { package "in" { interface TotalFeeUseCase { +getTotalFee(userId: String): TotalFeeResponse } interface MySubscriptionsUseCase { +getMySubscriptions(userId: String): List } interface SubscriptionDetailUseCase { +getSubscriptionDetail(subscriptionId: Long): SubDetailResponse } interface SubscribeUseCase { +subscribe(subscriptionId: Long, userId: String): void } interface CancelSubscriptionUseCase { +cancel(subscriptionId: Long): void } interface CategoryUseCase { +getAllCategories(): List +getServicesByCategory(categoryId: String): List } } package "out" { interface MySubscriptionReader { +findByUserId(userId: String): List +findById(id: Long): Optional } interface MySubscriptionWriter { +save(userId: String, subscriptionId: Long): MySubscription +delete(id: Long): void } interface SubscriptionReader { +findById(id: Long): Optional +findByCategory(category: String): List +findAllCategories(): List } } } package "domain" { class MySubscription { -id: Long -userId: String -subscription: Subscription +getPrice(): int } class Subscription { -id: Long -name: String -description: String -category: String -price: int -maxSharedUsers: int -logoUrl: String } class Category { -categoryId: String -name: String } } package "service" { class MySubscriptionService { -mySubscriptionReader: MySubscriptionReader -mySubscriptionWriter: MySubscriptionWriter -subscriptionReader: SubscriptionReader -collectorThreshold: long -addictThreshold: long +getTotalFee(userId: String): TotalFeeResponse +getMySubscriptions(userId: String): List +getSubscriptionDetail(subscriptionId: Long): SubDetailResponse +subscribe(subscriptionId: Long, userId: String): void +cancel(subscriptionId: Long): void +getAllCategories(): List +getServicesByCategory(categoryId: String): List -calculateFeeLevel(totalFee: long): String } enum FeeLevel { LIKFER COLLECTOR ADDICT } } package "dto" { class TotalFeeResponse { -totalFee: Long -feeLevel: String } class MySubResponse { -id: Long -serviceName: String -logoUrl: String } class SubDetailResponse { -serviceName: String -logoUrl: String -category: String -description: String -price: int -maxSharedUsers: int } class CategoryResponse { -categoryId: String -categoryName: String } class ServiceListResponse { -serviceId: String -serviceName: String -description: String -price: int -logoUrl: String } } } ' INFRA Layer package "com.unicorn.lifesub.mysub.infra" { package "controller" { class MySubController { -totalFeeUseCase: TotalFeeUseCase -mySubscriptionsUseCase: MySubscriptionsUseCase +getTotalFee(userId: String): ResponseEntity> +getMySubscriptions(userId: String): ResponseEntity>> } class ServiceController { -subscriptionDetailUseCase: SubscriptionDetailUseCase -subscribeUseCase: SubscribeUseCase -cancelSubscriptionUseCase: CancelSubscriptionUseCase +getSubscriptionDetail(subscriptionId: Long): ResponseEntity> +subscribe(subscriptionId: Long, userId: String): ResponseEntity> +cancel(subscriptionId: Long): ResponseEntity> } class CategoryController { -categoryUseCase: CategoryUseCase +getAllCategories(): ResponseEntity>> +getServicesByCategory(categoryId: String): ResponseEntity>> } } package "gateway" { class MySubscriptionGateway implements MySubscriptionReader, MySubscriptionWriter { -mySubscriptionRepository: MySubscriptionJpaRepository -subscriptionRepository: SubscriptionJpaRepository } class SubscriptionGateway implements SubscriptionReader { -subscriptionRepository: SubscriptionJpaRepository -categoryRepository: CategoryJpaRepository } package "repository" { interface MySubscriptionJpaRepository { +findByUserId(userId: String): List +findBySubscription_Id(subscriptionId: Long): Optional } interface SubscriptionJpaRepository { +findById(id: Long): Optional +findByCategory(category: String): List } interface CategoryJpaRepository { +findAll(): List } } package "entity" { class MySubscriptionEntity { -id: Long -userId: String -subscription: SubscriptionEntity +toDomain(): MySubscription } class SubscriptionEntity { -id: Long -name: String -description: String -category: String -price: int -maxSharedUsers: int -logoUrl: String +toDomain(): Subscription } class CategoryEntity { -categoryId: String -name: String +toDomain(): Category } } } package "config" { class SecurityConfig { -jwtTokenProvider: JwtTokenProvider +securityFilterChain(http: HttpSecurity): SecurityFilterChain +corsConfigurationSource(): CorsConfigurationSource } class SwaggerConfig { +openAPI(): OpenAPI } class DataLoader { -categoryRepository: CategoryJpaRepository -subscriptionRepository: SubscriptionJpaRepository +run(): void } } } ' Relationships MySubscriptionService ..|> TotalFeeUseCase MySubscriptionService ..|> MySubscriptionsUseCase MySubscriptionService ..|> SubscriptionDetailUseCase MySubscriptionService ..|> SubscribeUseCase MySubscriptionService ..|> CancelSubscriptionUseCase MySubscriptionService ..|> CategoryUseCase MySubController --> TotalFeeUseCase MySubController --> MySubscriptionsUseCase ServiceController --> SubscriptionDetailUseCase ServiceController --> SubscribeUseCase ServiceController --> CancelSubscriptionUseCase CategoryController --> CategoryUseCase MySubscriptionGateway --> MySubscriptionJpaRepository MySubscriptionGateway --> SubscriptionJpaRepository SubscriptionGateway --> SubscriptionJpaRepository SubscriptionGateway --> CategoryJpaRepository MySubscriptionEntity ..> MySubscription : converts to SubscriptionEntity ..> Subscription : converts to CategoryEntity ..> Category : converts to MySubscription --> Subscription