test #123
@@ -65,6 +65,7 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) {
 | 
			
		||||
            .where(
 | 
			
		||||
                order.createdAt.goe(startDate)
 | 
			
		||||
                    .and(order.createdAt.loe(endDate))
 | 
			
		||||
                    .and(order.isActive.isTrue)
 | 
			
		||||
            )
 | 
			
		||||
            .groupBy(audioContent.id, order.type, orderFormattedDate, order.can)
 | 
			
		||||
            .orderBy(member.id.desc(), orderFormattedDate.desc(), audioContent.id.asc())
 | 
			
		||||
 
 | 
			
		||||
@@ -105,6 +105,7 @@ class AudioContentController(private val service: AudioContentService) {
 | 
			
		||||
    fun getAudioContentList(
 | 
			
		||||
        @RequestParam("creator-id") creatorId: Long,
 | 
			
		||||
        @RequestParam("sort-type", required = false) sortType: SortType = SortType.NEWEST,
 | 
			
		||||
        @RequestParam("category-id", required = false) categoryId: Long? = 0,
 | 
			
		||||
        @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
 | 
			
		||||
        pageable: Pageable
 | 
			
		||||
    ) = run {
 | 
			
		||||
@@ -114,6 +115,7 @@ class AudioContentController(private val service: AudioContentService) {
 | 
			
		||||
            service.getAudioContentList(
 | 
			
		||||
                creatorId = creatorId,
 | 
			
		||||
                sortType = sortType,
 | 
			
		||||
                categoryId = categoryId ?: 0,
 | 
			
		||||
                member = member,
 | 
			
		||||
                offset = pageable.offset,
 | 
			
		||||
                limit = pageable.pageSize.toLong()
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ import com.querydsl.core.types.dsl.Expressions
 | 
			
		||||
import com.querydsl.jpa.impl.JPAQueryFactory
 | 
			
		||||
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
 | 
			
		||||
import kr.co.vividnext.sodalive.content.QBundleAudioContent.bundleAudioContent
 | 
			
		||||
import kr.co.vividnext.sodalive.content.category.QCategoryContent.categoryContent
 | 
			
		||||
import kr.co.vividnext.sodalive.content.comment.QAudioContentComment.audioContentComment
 | 
			
		||||
import kr.co.vividnext.sodalive.content.like.QAudioContentLike.audioContentLike
 | 
			
		||||
import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem
 | 
			
		||||
@@ -37,6 +38,7 @@ interface AudioContentQueryRepository {
 | 
			
		||||
        coverImageHost: String,
 | 
			
		||||
        isAdult: Boolean = false,
 | 
			
		||||
        sortType: SortType = SortType.NEWEST,
 | 
			
		||||
        categoryId: Long = 0,
 | 
			
		||||
        offset: Long = 0,
 | 
			
		||||
        limit: Long = 10
 | 
			
		||||
    ): List<GetAudioContentListItem>
 | 
			
		||||
@@ -144,6 +146,7 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
 | 
			
		||||
        coverImageHost: String,
 | 
			
		||||
        isAdult: Boolean,
 | 
			
		||||
        sortType: SortType,
 | 
			
		||||
        categoryId: Long,
 | 
			
		||||
        offset: Long,
 | 
			
		||||
        limit: Long
 | 
			
		||||
    ): List<GetAudioContentListItem> {
 | 
			
		||||
@@ -163,6 +166,10 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
 | 
			
		||||
            where = where.and(audioContent.isAdult.isFalse)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (categoryId > 0) {
 | 
			
		||||
            where = where.and(categoryContent.category.id.eq(categoryId))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return queryFactory
 | 
			
		||||
            .select(
 | 
			
		||||
                QGetAudioContentListItem(
 | 
			
		||||
@@ -180,6 +187,8 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory)
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            .from(audioContent)
 | 
			
		||||
            .leftJoin(categoryContent)
 | 
			
		||||
            .on(audioContent.id.eq(categoryContent.content.id).and(categoryContent.isActive.ne(false)))
 | 
			
		||||
            .leftJoin(pinContent)
 | 
			
		||||
            .on(audioContent.id.eq(pinContent.content.id).and(pinContent.isActive.ne(false)))
 | 
			
		||||
            .where(where)
 | 
			
		||||
 
 | 
			
		||||
@@ -624,6 +624,7 @@ class AudioContentService(
 | 
			
		||||
        creatorId: Long,
 | 
			
		||||
        sortType: SortType,
 | 
			
		||||
        member: Member,
 | 
			
		||||
        categoryId: Long = 0,
 | 
			
		||||
        offset: Long,
 | 
			
		||||
        limit: Long
 | 
			
		||||
    ): GetAudioContentListResponse {
 | 
			
		||||
@@ -637,6 +638,7 @@ class AudioContentService(
 | 
			
		||||
            coverImageHost = coverImageHost,
 | 
			
		||||
            isAdult = member.auth != null,
 | 
			
		||||
            sortType = sortType,
 | 
			
		||||
            categoryId = categoryId,
 | 
			
		||||
            offset = offset,
 | 
			
		||||
            limit = limit
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,19 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.content.category
 | 
			
		||||
 | 
			
		||||
import kr.co.vividnext.sodalive.common.BaseEntity
 | 
			
		||||
import kr.co.vividnext.sodalive.member.Member
 | 
			
		||||
import javax.persistence.Entity
 | 
			
		||||
import javax.persistence.FetchType
 | 
			
		||||
import javax.persistence.JoinColumn
 | 
			
		||||
import javax.persistence.ManyToOne
 | 
			
		||||
 | 
			
		||||
@Entity
 | 
			
		||||
data class Category(
 | 
			
		||||
    var title: String,
 | 
			
		||||
    var orders: Int = 1,
 | 
			
		||||
    var isActive: Boolean = true
 | 
			
		||||
) : BaseEntity() {
 | 
			
		||||
    @ManyToOne(fetch = FetchType.LAZY)
 | 
			
		||||
    @JoinColumn(name = "member_id", nullable = false)
 | 
			
		||||
    var member: Member? = null
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,22 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.content.category
 | 
			
		||||
 | 
			
		||||
import kr.co.vividnext.sodalive.common.BaseEntity
 | 
			
		||||
import kr.co.vividnext.sodalive.content.AudioContent
 | 
			
		||||
import javax.persistence.Entity
 | 
			
		||||
import javax.persistence.FetchType
 | 
			
		||||
import javax.persistence.JoinColumn
 | 
			
		||||
import javax.persistence.ManyToOne
 | 
			
		||||
 | 
			
		||||
@Entity
 | 
			
		||||
data class CategoryContent(
 | 
			
		||||
    var orders: Int = 1,
 | 
			
		||||
    var isActive: Boolean = true
 | 
			
		||||
) : BaseEntity() {
 | 
			
		||||
    @ManyToOne(fetch = FetchType.LAZY)
 | 
			
		||||
    @JoinColumn(name = "content_id", nullable = false)
 | 
			
		||||
    var content: AudioContent? = null
 | 
			
		||||
 | 
			
		||||
    @ManyToOne(fetch = FetchType.LAZY)
 | 
			
		||||
    @JoinColumn(name = "category_id", nullable = false)
 | 
			
		||||
    var category: Category? = null
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,32 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.content.category
 | 
			
		||||
 | 
			
		||||
import com.querydsl.jpa.impl.JPAQueryFactory
 | 
			
		||||
import kr.co.vividnext.sodalive.content.category.QCategoryContent.categoryContent
 | 
			
		||||
import org.springframework.data.jpa.repository.JpaRepository
 | 
			
		||||
 | 
			
		||||
interface CategoryContentRepository : JpaRepository<CategoryContent, Long>, CategoryContentQueryRepository
 | 
			
		||||
 | 
			
		||||
interface CategoryContentQueryRepository {
 | 
			
		||||
    fun findByContentIdAndCategoryId(contentId: Long, categoryId: Long): CategoryContent?
 | 
			
		||||
    fun deleteByCategoryId(categoryId: Long)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class CategoryContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : CategoryContentQueryRepository {
 | 
			
		||||
    override fun findByContentIdAndCategoryId(contentId: Long, categoryId: Long): CategoryContent? {
 | 
			
		||||
        return queryFactory
 | 
			
		||||
            .selectFrom(categoryContent)
 | 
			
		||||
            .where(
 | 
			
		||||
                categoryContent.content.id.eq(contentId)
 | 
			
		||||
                    .and(categoryContent.category.id.eq(categoryId))
 | 
			
		||||
            )
 | 
			
		||||
            .fetchFirst()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun deleteByCategoryId(categoryId: Long) {
 | 
			
		||||
        queryFactory
 | 
			
		||||
            .update(categoryContent)
 | 
			
		||||
            .set(categoryContent.isActive, false)
 | 
			
		||||
            .where(categoryContent.category.id.eq(categoryId))
 | 
			
		||||
            .execute()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,63 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.content.category
 | 
			
		||||
 | 
			
		||||
import kr.co.vividnext.sodalive.common.ApiResponse
 | 
			
		||||
import kr.co.vividnext.sodalive.common.SodaException
 | 
			
		||||
import kr.co.vividnext.sodalive.member.Member
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize
 | 
			
		||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
 | 
			
		||||
import org.springframework.web.bind.annotation.DeleteMapping
 | 
			
		||||
import org.springframework.web.bind.annotation.GetMapping
 | 
			
		||||
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
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/category")
 | 
			
		||||
class CategoryController(private val service: CategoryService) {
 | 
			
		||||
    @PostMapping
 | 
			
		||||
    @PreAuthorize("hasRole('CREATOR')")
 | 
			
		||||
    fun createCategory(
 | 
			
		||||
        @RequestBody request: CreateCategoryRequest,
 | 
			
		||||
        @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
 | 
			
		||||
    ) = run {
 | 
			
		||||
        if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
 | 
			
		||||
 | 
			
		||||
        ApiResponse.ok(service.createCategory(request = request, member = member))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PutMapping
 | 
			
		||||
    @PreAuthorize("hasRole('CREATOR')")
 | 
			
		||||
    fun modifyCategory(
 | 
			
		||||
        @RequestBody request: ModifyCategoryRequest,
 | 
			
		||||
        @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
 | 
			
		||||
    ) = run {
 | 
			
		||||
        if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
 | 
			
		||||
 | 
			
		||||
        ApiResponse.ok(service.modifyCategory(request = request, member = member))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @DeleteMapping("/{id}")
 | 
			
		||||
    @PreAuthorize("hasRole('CREATOR')")
 | 
			
		||||
    fun deleteCategory(
 | 
			
		||||
        @PathVariable("id") categoryId: Long,
 | 
			
		||||
        @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
 | 
			
		||||
    ) = run {
 | 
			
		||||
        if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
 | 
			
		||||
 | 
			
		||||
        ApiResponse.ok(service.deleteCategory(categoryId = categoryId, member = member))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GetMapping
 | 
			
		||||
    fun getCategoryList(
 | 
			
		||||
        @RequestParam creatorId: Long,
 | 
			
		||||
        @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
 | 
			
		||||
    ) = run {
 | 
			
		||||
        if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
 | 
			
		||||
 | 
			
		||||
        ApiResponse.ok(service.getCategoryList(creatorId = creatorId, memberId = member.id!!))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,45 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.content.category
 | 
			
		||||
 | 
			
		||||
import com.querydsl.jpa.impl.JPAQueryFactory
 | 
			
		||||
import kr.co.vividnext.sodalive.content.category.QCategory.category
 | 
			
		||||
import org.springframework.data.jpa.repository.JpaRepository
 | 
			
		||||
 | 
			
		||||
interface CategoryRepository : JpaRepository<Category, Long>, CategoryQueryRepository
 | 
			
		||||
 | 
			
		||||
interface CategoryQueryRepository {
 | 
			
		||||
    fun findByTitleAndMemberId(title: String, memberId: Long): Category?
 | 
			
		||||
 | 
			
		||||
    fun findByIdAndMemberId(categoryId: Long, memberId: Long): Category?
 | 
			
		||||
 | 
			
		||||
    fun findByCreatorId(creatorId: Long): List<GetCategoryListResponse>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class CategoryQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : CategoryQueryRepository {
 | 
			
		||||
    override fun findByTitleAndMemberId(title: String, memberId: Long): Category? {
 | 
			
		||||
        return queryFactory
 | 
			
		||||
            .selectFrom(category)
 | 
			
		||||
            .where(
 | 
			
		||||
                category.title.eq(title)
 | 
			
		||||
                    .and(category.member.id.eq(memberId))
 | 
			
		||||
            )
 | 
			
		||||
            .fetchFirst()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun findByIdAndMemberId(categoryId: Long, memberId: Long): Category? {
 | 
			
		||||
        return queryFactory
 | 
			
		||||
            .selectFrom(category)
 | 
			
		||||
            .where(
 | 
			
		||||
                category.id.eq(categoryId)
 | 
			
		||||
                    .and(category.member.id.eq(memberId))
 | 
			
		||||
            )
 | 
			
		||||
            .fetchFirst()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun findByCreatorId(creatorId: Long): List<GetCategoryListResponse> {
 | 
			
		||||
        return queryFactory
 | 
			
		||||
            .select(QGetCategoryListResponse(category.id, category.title))
 | 
			
		||||
            .from(category)
 | 
			
		||||
            .where(category.member.id.eq(creatorId))
 | 
			
		||||
            .fetch()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,99 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.content.category
 | 
			
		||||
 | 
			
		||||
import kr.co.vividnext.sodalive.common.SodaException
 | 
			
		||||
import kr.co.vividnext.sodalive.content.AudioContentRepository
 | 
			
		||||
import kr.co.vividnext.sodalive.member.Member
 | 
			
		||||
import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
 | 
			
		||||
import org.springframework.stereotype.Service
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional
 | 
			
		||||
 | 
			
		||||
@Service
 | 
			
		||||
class CategoryService(
 | 
			
		||||
    private val repository: CategoryRepository,
 | 
			
		||||
    private val contentRepository: AudioContentRepository,
 | 
			
		||||
    private val blockMemberRepository: BlockMemberRepository,
 | 
			
		||||
    private val categoryContentRepository: CategoryContentRepository
 | 
			
		||||
) {
 | 
			
		||||
    @Transactional
 | 
			
		||||
    fun createCategory(request: CreateCategoryRequest, member: Member) {
 | 
			
		||||
        validateTitle(title = request.title)
 | 
			
		||||
        val category = repository.findByTitleAndMemberId(title = request.title, memberId = member.id!!)
 | 
			
		||||
            ?: repository.save(
 | 
			
		||||
                Category(title = request.title).apply {
 | 
			
		||||
                    this.member = member
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
        category.isActive = true
 | 
			
		||||
 | 
			
		||||
        for (contentId in request.contentIdList) {
 | 
			
		||||
            val content = contentRepository.findByIdAndActive(contentId = contentId)
 | 
			
		||||
                ?: continue
 | 
			
		||||
 | 
			
		||||
            val categoryContent = categoryContentRepository.findByContentIdAndCategoryId(
 | 
			
		||||
                contentId = contentId,
 | 
			
		||||
                categoryId = category.id!!
 | 
			
		||||
            ) ?: categoryContentRepository.save(
 | 
			
		||||
                CategoryContent().apply {
 | 
			
		||||
                    this.content = content
 | 
			
		||||
                    this.category = category
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
            categoryContent.isActive = true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Transactional
 | 
			
		||||
    fun modifyCategory(request: ModifyCategoryRequest, member: Member) {
 | 
			
		||||
        val category = repository.findByIdAndMemberId(categoryId = request.categoryId, memberId = member.id!!)
 | 
			
		||||
            ?: throw SodaException("잘못된 요청입니다.")
 | 
			
		||||
 | 
			
		||||
        if (!request.title.isNullOrBlank()) {
 | 
			
		||||
            validateTitle(title = request.title)
 | 
			
		||||
            category.title = request.title
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (contentId in request.addContentIdList) {
 | 
			
		||||
            val content = contentRepository.findByIdAndActive(contentId = contentId)
 | 
			
		||||
                ?: continue
 | 
			
		||||
 | 
			
		||||
            val categoryContent = categoryContentRepository.findByContentIdAndCategoryId(
 | 
			
		||||
                contentId = contentId,
 | 
			
		||||
                categoryId = category.id!!
 | 
			
		||||
            ) ?: categoryContentRepository.save(
 | 
			
		||||
                CategoryContent().apply {
 | 
			
		||||
                    this.content = content
 | 
			
		||||
                    this.category = category
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
            categoryContent.isActive = true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (contentId in request.removeContentIdList) {
 | 
			
		||||
            val categoryContent = categoryContentRepository.findByContentIdAndCategoryId(
 | 
			
		||||
                contentId = contentId,
 | 
			
		||||
                categoryId = category.id!!
 | 
			
		||||
            ) ?: continue
 | 
			
		||||
            categoryContent.isActive = false
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Transactional
 | 
			
		||||
    fun deleteCategory(categoryId: Long, member: Member) {
 | 
			
		||||
        val category = repository.findByIdAndMemberId(categoryId = categoryId, memberId = member.id!!)
 | 
			
		||||
            ?: throw SodaException("잘못된 요청입니다.")
 | 
			
		||||
        category.isActive = false
 | 
			
		||||
 | 
			
		||||
        categoryContentRepository.deleteByCategoryId(categoryId = categoryId)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getCategoryList(creatorId: Long, memberId: Long): List<GetCategoryListResponse> {
 | 
			
		||||
        val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId)
 | 
			
		||||
        if (isBlocked) throw SodaException("잘못된 접근입니다.")
 | 
			
		||||
 | 
			
		||||
        return repository.findByCreatorId(creatorId = creatorId)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun validateTitle(title: String) {
 | 
			
		||||
        if (title.length < 2) throw SodaException("카테고리명은 2글자 이상 입력하세요")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.content.category
 | 
			
		||||
 | 
			
		||||
data class CreateCategoryRequest(
 | 
			
		||||
    val title: String,
 | 
			
		||||
    val contentIdList: List<Long>
 | 
			
		||||
)
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.content.category
 | 
			
		||||
 | 
			
		||||
import com.querydsl.core.annotations.QueryProjection
 | 
			
		||||
 | 
			
		||||
data class GetCategoryListResponse @QueryProjection constructor(
 | 
			
		||||
    val categoryId: Long,
 | 
			
		||||
    val category: String
 | 
			
		||||
)
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
package kr.co.vividnext.sodalive.content.category
 | 
			
		||||
 | 
			
		||||
data class ModifyCategoryRequest(
 | 
			
		||||
    val categoryId: Long,
 | 
			
		||||
    val title: String?,
 | 
			
		||||
    val addContentIdList: List<Long>,
 | 
			
		||||
    val removeContentIdList: List<Long>
 | 
			
		||||
)
 | 
			
		||||
@@ -116,16 +116,14 @@ class CreatorAdminCalculateQueryRepository(private val queryFactory: JPAQueryFac
 | 
			
		||||
                    order.can.sum()
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            .from(useCanCalculate)
 | 
			
		||||
            .innerJoin(useCanCalculate.useCan, useCan)
 | 
			
		||||
            .innerJoin(useCan.order, order)
 | 
			
		||||
            .from(order)
 | 
			
		||||
            .innerJoin(order.audioContent, audioContent)
 | 
			
		||||
            .innerJoin(audioContent.member, member)
 | 
			
		||||
            .where(
 | 
			
		||||
                useCanCalculate.status.eq(UseCanCalculateStatus.RECEIVED)
 | 
			
		||||
                    .and(useCanCalculate.recipientCreatorId.eq(memberId))
 | 
			
		||||
                    .and(order.createdAt.goe(startDate))
 | 
			
		||||
                order.createdAt.goe(startDate)
 | 
			
		||||
                    .and(order.createdAt.loe(endDate))
 | 
			
		||||
                    .and(order.isActive.isTrue)
 | 
			
		||||
                    .and(order.creator.id.eq(memberId))
 | 
			
		||||
            )
 | 
			
		||||
            .groupBy(audioContent.id, order.type, orderFormattedDate, order.can)
 | 
			
		||||
            .offset(offset)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user