diff --git a/src/main/kotlin/com/wafflestudio/csereal/common/controller/ImageContentEntityType.kt b/src/main/kotlin/com/wafflestudio/csereal/common/controller/MainImageContentEntityType.kt similarity index 82% rename from src/main/kotlin/com/wafflestudio/csereal/common/controller/ImageContentEntityType.kt rename to src/main/kotlin/com/wafflestudio/csereal/common/controller/MainImageContentEntityType.kt index 8f58c860..eae7403c 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/common/controller/ImageContentEntityType.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/common/controller/MainImageContentEntityType.kt @@ -2,6 +2,6 @@ package com.wafflestudio.csereal.common.controller import com.wafflestudio.csereal.core.resource.mainImage.database.MainImageEntity -interface ImageContentEntityType { +interface MainImageContentEntityType { fun bringMainImage(): MainImageEntity? } \ No newline at end of file diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/about/database/AboutEntity.kt b/src/main/kotlin/com/wafflestudio/csereal/core/about/database/AboutEntity.kt index 8dd8b967..a77058a7 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/about/database/AboutEntity.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/about/database/AboutEntity.kt @@ -2,7 +2,7 @@ package com.wafflestudio.csereal.core.about.database import com.wafflestudio.csereal.common.config.BaseTimeEntity import com.wafflestudio.csereal.common.controller.AttachmentContentEntityType -import com.wafflestudio.csereal.common.controller.ImageContentEntityType +import com.wafflestudio.csereal.common.controller.MainImageContentEntityType import com.wafflestudio.csereal.core.about.dto.AboutDto import com.wafflestudio.csereal.core.resource.attachment.database.AttachmentEntity import com.wafflestudio.csereal.core.resource.mainImage.database.MainImageEntity @@ -26,7 +26,7 @@ class AboutEntity( @OneToOne var mainImage: MainImageEntity? = null, - ) : BaseTimeEntity(), ImageContentEntityType, AttachmentContentEntityType { + ) : BaseTimeEntity(), MainImageContentEntityType, AttachmentContentEntityType { override fun bringMainImage(): MainImageEntity? = mainImage override fun bringAttachments(): List = attachments diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/member/database/ProfessorEntity.kt b/src/main/kotlin/com/wafflestudio/csereal/core/member/database/ProfessorEntity.kt index 1414a0ae..4036a9dd 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/member/database/ProfessorEntity.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/member/database/ProfessorEntity.kt @@ -1,7 +1,7 @@ package com.wafflestudio.csereal.core.member.database import com.wafflestudio.csereal.common.config.BaseTimeEntity -import com.wafflestudio.csereal.common.controller.ImageContentEntityType +import com.wafflestudio.csereal.common.controller.MainImageContentEntityType import com.wafflestudio.csereal.core.member.dto.ProfessorDto import com.wafflestudio.csereal.core.research.database.LabEntity import com.wafflestudio.csereal.core.resource.mainImage.database.MainImageEntity @@ -44,7 +44,7 @@ class ProfessorEntity( @OneToOne var mainImage: MainImageEntity? = null, -) : BaseTimeEntity(), ImageContentEntityType { +) : BaseTimeEntity(), MainImageContentEntityType { override fun bringMainImage(): MainImageEntity? = mainImage companion object { diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/member/database/StaffEntity.kt b/src/main/kotlin/com/wafflestudio/csereal/core/member/database/StaffEntity.kt index d4e5ec3a..355d4125 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/member/database/StaffEntity.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/member/database/StaffEntity.kt @@ -1,7 +1,7 @@ package com.wafflestudio.csereal.core.member.database import com.wafflestudio.csereal.common.config.BaseTimeEntity -import com.wafflestudio.csereal.common.controller.ImageContentEntityType +import com.wafflestudio.csereal.common.controller.MainImageContentEntityType import com.wafflestudio.csereal.core.member.dto.StaffDto import com.wafflestudio.csereal.core.resource.mainImage.database.MainImageEntity import jakarta.persistence.CascadeType @@ -24,7 +24,7 @@ class StaffEntity( @OneToOne var mainImage: MainImageEntity? = null, - ) : BaseTimeEntity(), ImageContentEntityType { + ) : BaseTimeEntity(), MainImageContentEntityType { override fun bringMainImage(): MainImageEntity? = mainImage companion object { diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/news/database/NewsEntity.kt b/src/main/kotlin/com/wafflestudio/csereal/core/news/database/NewsEntity.kt index 8349a433..327ebcd3 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/news/database/NewsEntity.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/news/database/NewsEntity.kt @@ -2,7 +2,7 @@ package com.wafflestudio.csereal.core.news.database import com.wafflestudio.csereal.common.config.BaseTimeEntity import com.wafflestudio.csereal.common.controller.AttachmentContentEntityType -import com.wafflestudio.csereal.common.controller.ImageContentEntityType +import com.wafflestudio.csereal.common.controller.MainImageContentEntityType import com.wafflestudio.csereal.core.news.dto.NewsDto import com.wafflestudio.csereal.core.resource.attachment.database.AttachmentEntity import com.wafflestudio.csereal.core.resource.mainImage.database.MainImageEntity @@ -30,7 +30,7 @@ class NewsEntity( @OneToMany(mappedBy = "news", cascade = [CascadeType.ALL]) var newsTags: MutableSet = mutableSetOf() -): BaseTimeEntity(), ImageContentEntityType, AttachmentContentEntityType { +): BaseTimeEntity(), MainImageContentEntityType, AttachmentContentEntityType { override fun bringMainImage() = mainImage override fun bringAttachments() = attachments diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/research/api/ResearchController.kt b/src/main/kotlin/com/wafflestudio/csereal/core/research/api/ResearchController.kt index 08d9cd16..af093051 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/research/api/ResearchController.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/research/api/ResearchController.kt @@ -16,46 +16,50 @@ class ResearchController( ) { @PostMapping fun createResearchDetail( - @Valid @RequestBody request: ResearchDto - ) : ResponseEntity { - return ResponseEntity.ok(researchService.createResearchDetail(request)) + @Valid @RequestPart("request") request: ResearchDto, + @RequestPart("mainImage") mainImage: MultipartFile?, + @RequestPart("attachments") attachments: List? + ): ResponseEntity { + return ResponseEntity.ok(researchService.createResearchDetail(request, mainImage, attachments)) } @GetMapping("/groups") - fun readAllResearchGroups() : ResponseEntity { + fun readAllResearchGroups(): ResponseEntity { return ResponseEntity.ok(researchService.readAllResearchGroups()) } @GetMapping("/centers") - fun readAllResearchCenters() : ResponseEntity> { + fun readAllResearchCenters(): ResponseEntity> { return ResponseEntity.ok(researchService.readAllResearchCenters()) } @PatchMapping("/{researchId}") fun updateResearchDetail( @PathVariable researchId: Long, - @Valid @RequestBody request: ResearchDto - ) : ResponseEntity { - return ResponseEntity.ok(researchService.updateResearchDetail(researchId, request)) + @Valid @RequestPart("request") request: ResearchDto, + @RequestPart("mainImage") mainImage: MultipartFile?, + @RequestPart("attachments") attachments: List? + ): ResponseEntity { + return ResponseEntity.ok(researchService.updateResearchDetail(researchId, request, mainImage, attachments)) } @PostMapping("/lab") fun createLab( @Valid @RequestPart("request") request: LabDto, @RequestPart("pdf") pdf: MultipartFile? - ) : ResponseEntity { + ): ResponseEntity { return ResponseEntity.ok(researchService.createLab(request, pdf)) } @GetMapping("/labs") - fun readAllLabs() : ResponseEntity> { + fun readAllLabs(): ResponseEntity> { return ResponseEntity.ok(researchService.readAllLabs()) } @GetMapping("/lab/{labId}") fun readLab( @PathVariable labId: Long, - ) : ResponseEntity { + ): ResponseEntity { return ResponseEntity.ok(researchService.readLab(labId)) } } \ No newline at end of file diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/research/database/ResearchEntity.kt b/src/main/kotlin/com/wafflestudio/csereal/core/research/database/ResearchEntity.kt index c6c2b282..70cbca2b 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/research/database/ResearchEntity.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/research/database/ResearchEntity.kt @@ -1,7 +1,11 @@ package com.wafflestudio.csereal.core.research.database import com.wafflestudio.csereal.common.config.BaseTimeEntity +import com.wafflestudio.csereal.common.controller.AttachmentContentEntityType +import com.wafflestudio.csereal.common.controller.MainImageContentEntityType import com.wafflestudio.csereal.core.research.dto.ResearchDto +import com.wafflestudio.csereal.core.resource.attachment.database.AttachmentEntity +import com.wafflestudio.csereal.core.resource.mainImage.database.MainImageEntity import jakarta.persistence.* @Entity(name = "research") @@ -11,18 +15,26 @@ class ResearchEntity( var name: String, var description: String?, - var websiteURL: String?, @OneToMany(mappedBy = "research", cascade = [CascadeType.ALL], orphanRemoval = true) - var labs: MutableList = mutableListOf() -): BaseTimeEntity() { + var labs: MutableList = mutableListOf(), + + @OneToOne + var mainImage: MainImageEntity? = null, + + @OneToMany(mappedBy = "research", cascade = [CascadeType.ALL], orphanRemoval = true) + var attachments: MutableList = mutableListOf(), + + ) : BaseTimeEntity(), MainImageContentEntityType, AttachmentContentEntityType { + override fun bringMainImage() = mainImage + override fun bringAttachments() = attachments + companion object { - fun of(researchDto: ResearchDto) : ResearchEntity { + fun of(researchDto: ResearchDto): ResearchEntity { return ResearchEntity( postType = researchDto.postType, name = researchDto.name, description = researchDto.description, - websiteURL = researchDto.websiteURL, ) } } diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/research/dto/ResearchDto.kt b/src/main/kotlin/com/wafflestudio/csereal/core/research/dto/ResearchDto.kt index 51acfef9..0f694e81 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/research/dto/ResearchDto.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/research/dto/ResearchDto.kt @@ -2,6 +2,7 @@ package com.wafflestudio.csereal.core.research.dto import com.wafflestudio.csereal.core.research.database.ResearchEntity import com.wafflestudio.csereal.core.research.database.ResearchPostType +import com.wafflestudio.csereal.core.resource.attachment.dto.AttachmentResponse import java.time.LocalDateTime data class ResearchDto( @@ -9,22 +10,24 @@ data class ResearchDto( val postType: ResearchPostType, val name: String, val description: String?, - val websiteURL: String?, val createdAt: LocalDateTime?, val modifiedAt: LocalDateTime?, - val labs: List? + val labs: List?, + val imageURL: String?, + val attachments: List?, ) { companion object { - fun of(entity: ResearchEntity) = entity.run { + fun of(entity: ResearchEntity, imageURL: String?, attachmentResponse: List) = entity.run { ResearchDto( id = this.id, postType = this.postType, name = this.name, description = this.description, - websiteURL = this.websiteURL, createdAt = this.createdAt, modifiedAt = this.modifiedAt, - labs = this.labs.map { ResearchLabResponse(id = it.id, name = it.name) } + labs = this.labs.map { ResearchLabResponse(id = it.id, name = it.name) }, + imageURL = imageURL, + attachments = attachmentResponse ) } } diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/research/service/ResearchService.kt b/src/main/kotlin/com/wafflestudio/csereal/core/research/service/ResearchService.kt index d41d9a8c..27f31f4c 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/research/service/ResearchService.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/research/service/ResearchService.kt @@ -6,16 +6,17 @@ import com.wafflestudio.csereal.core.research.database.* import com.wafflestudio.csereal.core.research.dto.* import com.wafflestudio.csereal.core.resource.attachment.database.AttachmentEntity import com.wafflestudio.csereal.core.resource.attachment.service.AttachmentService +import com.wafflestudio.csereal.core.resource.mainImage.service.MainImageService import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import org.springframework.web.multipart.MultipartFile interface ResearchService { - fun createResearchDetail(request: ResearchDto): ResearchDto + fun createResearchDetail(request: ResearchDto, mainImage: MultipartFile?, attachments: List?): ResearchDto fun readAllResearchGroups(): ResearchGroupResponse fun readAllResearchCenters(): List - fun updateResearchDetail(researchId: Long, request: ResearchDto): ResearchDto + fun updateResearchDetail(researchId: Long, request: ResearchDto, mainImage: MultipartFile?, attachments: List?): ResearchDto fun createLab(request: LabDto, pdf: MultipartFile?): LabDto fun readAllLabs(): List fun readLab(labId: Long): LabDto @@ -26,11 +27,13 @@ class ResearchServiceImpl( private val researchRepository: ResearchRepository, private val labRepository: LabRepository, private val professorRepository: ProfessorRepository, + private val mainImageService: MainImageService, private val attachmentService: AttachmentService, ) : ResearchService { @Transactional - override fun createResearchDetail(request: ResearchDto): ResearchDto { + override fun createResearchDetail(request: ResearchDto, mainImage: MultipartFile?, attachments: List?): ResearchDto { val newResearch = ResearchEntity.of(request) + if(request.labs != null) { for(lab in request.labs) { @@ -41,9 +44,20 @@ class ResearchServiceImpl( } } + if(mainImage != null) { + mainImageService.uploadMainImage(newResearch, mainImage) + } + + if(attachments != null) { + attachmentService.uploadAllAttachments(newResearch, attachments) + } + researchRepository.save(newResearch) - return ResearchDto.of(newResearch) + val imageURL = mainImageService.createImageURL(newResearch.mainImage) + val attachmentResponses = attachmentService.createAttachmentResponses(newResearch.attachments) + + return ResearchDto.of(newResearch, imageURL, attachmentResponses) } @Transactional(readOnly = true) @@ -55,7 +69,10 @@ class ResearchServiceImpl( "오늘도 인류가 꿈꾸는 행복하고 편리한 세상을 위해 변화와 혁신, 연구와 도전을 계속하고 있습니다." val researchGroups = researchRepository.findAllByPostTypeOrderByName(ResearchPostType.GROUPS).map { - ResearchDto.of(it) + val imageURL = mainImageService.createImageURL(it.mainImage) + val attachmentResponses = attachmentService.createAttachmentResponses(it.attachments) + + ResearchDto.of(it, imageURL, attachmentResponses) } return ResearchGroupResponse(description, researchGroups) @@ -64,13 +81,16 @@ class ResearchServiceImpl( @Transactional(readOnly = true) override fun readAllResearchCenters(): List { val researchCenters = researchRepository.findAllByPostTypeOrderByName(ResearchPostType.CENTERS).map { - ResearchDto.of(it) + val imageURL = mainImageService.createImageURL(it.mainImage) + val attachmentResponses = attachmentService.createAttachmentResponses(it.attachments) + + ResearchDto.of(it, imageURL, attachmentResponses) } return researchCenters } @Transactional - override fun updateResearchDetail(researchId: Long, request: ResearchDto): ResearchDto { + override fun updateResearchDetail(researchId: Long, request: ResearchDto, mainImage: MultipartFile?, attachments: List?): ResearchDto { val research = researchRepository.findByIdOrNull(researchId) ?: throw CserealException.Csereal404("해당 게시글을 찾을 수 없습니다.(researchId=$researchId)") @@ -96,7 +116,19 @@ class ResearchServiceImpl( } } - return ResearchDto.of(research) + if(mainImage != null) { + mainImageService.uploadMainImage(research, mainImage) + } + + if(attachments != null) { + attachmentService.uploadAllAttachments(research, attachments) + } + + val imageURL = mainImageService.createImageURL(research.mainImage) + val attachmentResponses = attachmentService.createAttachmentResponses(research.attachments) + + + return ResearchDto.of(research, imageURL, attachmentResponses) } @Transactional diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/resource/attachment/database/AttachmentEntity.kt b/src/main/kotlin/com/wafflestudio/csereal/core/resource/attachment/database/AttachmentEntity.kt index a1e9c8bf..1c79236a 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/resource/attachment/database/AttachmentEntity.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/resource/attachment/database/AttachmentEntity.kt @@ -6,6 +6,7 @@ import com.wafflestudio.csereal.core.academics.database.AcademicsEntity import com.wafflestudio.csereal.core.academics.database.CourseEntity import com.wafflestudio.csereal.core.news.database.NewsEntity import com.wafflestudio.csereal.core.research.database.LabEntity +import com.wafflestudio.csereal.core.research.database.ResearchEntity import com.wafflestudio.csereal.core.seminar.database.SeminarEntity import jakarta.persistence.* @@ -42,6 +43,10 @@ class AttachmentEntity( @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "lab_id") var lab: LabEntity? = null, + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "research_id") + var research: ResearchEntity? = null, ) : BaseTimeEntity() { } \ No newline at end of file diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/resource/attachment/service/AttachmentService.kt b/src/main/kotlin/com/wafflestudio/csereal/core/resource/attachment/service/AttachmentService.kt index 30dd1a77..024fbb78 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/resource/attachment/service/AttachmentService.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/resource/attachment/service/AttachmentService.kt @@ -6,6 +6,7 @@ import com.wafflestudio.csereal.core.academics.database.AcademicsEntity import com.wafflestudio.csereal.core.academics.database.CourseEntity import com.wafflestudio.csereal.core.news.database.NewsEntity import com.wafflestudio.csereal.core.research.database.LabEntity +import com.wafflestudio.csereal.core.research.database.ResearchEntity import com.wafflestudio.csereal.core.resource.attachment.database.AttachmentEntity import com.wafflestudio.csereal.core.resource.attachment.database.AttachmentRepository import com.wafflestudio.csereal.core.resource.attachment.dto.AttachmentDto @@ -142,6 +143,10 @@ class AttachmentServiceImpl( contentEntity.attachments.add(attachment) attachment.course = contentEntity } + is ResearchEntity -> { + contentEntity.attachments.add(attachment) + attachment.research = contentEntity + } } } } \ No newline at end of file diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/resource/mainImage/service/MainImageService.kt b/src/main/kotlin/com/wafflestudio/csereal/core/resource/mainImage/service/MainImageService.kt index 0a5690f1..9abd6eb3 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/resource/mainImage/service/MainImageService.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/resource/mainImage/service/MainImageService.kt @@ -1,12 +1,13 @@ package com.wafflestudio.csereal.core.resource.mainImage.service import com.wafflestudio.csereal.common.CserealException -import com.wafflestudio.csereal.common.controller.ImageContentEntityType +import com.wafflestudio.csereal.common.controller.MainImageContentEntityType import com.wafflestudio.csereal.common.properties.EndpointProperties import com.wafflestudio.csereal.core.about.database.AboutEntity import com.wafflestudio.csereal.core.member.database.ProfessorEntity import com.wafflestudio.csereal.core.member.database.StaffEntity import com.wafflestudio.csereal.core.news.database.NewsEntity +import com.wafflestudio.csereal.core.research.database.ResearchEntity import com.wafflestudio.csereal.core.resource.mainImage.database.MainImageRepository import com.wafflestudio.csereal.core.resource.mainImage.database.MainImageEntity import com.wafflestudio.csereal.core.resource.mainImage.dto.MainImageDto @@ -25,7 +26,7 @@ import kotlin.io.path.name interface MainImageService { fun uploadMainImage( - contentEntityType: ImageContentEntityType, + contentEntityType: MainImageContentEntityType, requestImage: MultipartFile, ): MainImageDto @@ -42,7 +43,7 @@ class MainImageServiceImpl( @Transactional override fun uploadMainImage( - contentEntityType: ImageContentEntityType, + contentEntityType: MainImageContentEntityType, requestImage: MultipartFile, ): MainImageDto { Files.createDirectories(Paths.get(path)) @@ -94,7 +95,7 @@ class MainImageServiceImpl( } else null } - private fun connectMainImageToEntity(contentEntity: ImageContentEntityType, mainImage: MainImageEntity) { + private fun connectMainImageToEntity(contentEntity: MainImageContentEntityType, mainImage: MainImageEntity) { when (contentEntity) { is NewsEntity -> { contentEntity.mainImage = mainImage @@ -116,6 +117,9 @@ class MainImageServiceImpl( contentEntity.mainImage = mainImage } + is ResearchEntity -> { + contentEntity.mainImage = mainImage + } else -> { throw WrongMethodTypeException("해당하는 엔티티가 없습니다") } diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/seminar/database/SeminarEntity.kt b/src/main/kotlin/com/wafflestudio/csereal/core/seminar/database/SeminarEntity.kt index 04c6359d..9e2ba977 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/seminar/database/SeminarEntity.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/seminar/database/SeminarEntity.kt @@ -2,7 +2,7 @@ package com.wafflestudio.csereal.core.seminar.database import com.wafflestudio.csereal.common.config.BaseTimeEntity import com.wafflestudio.csereal.common.controller.AttachmentContentEntityType -import com.wafflestudio.csereal.common.controller.ImageContentEntityType +import com.wafflestudio.csereal.common.controller.MainImageContentEntityType import com.wafflestudio.csereal.core.resource.attachment.database.AttachmentEntity import com.wafflestudio.csereal.core.resource.mainImage.database.MainImageEntity import com.wafflestudio.csereal.core.seminar.dto.SeminarDto @@ -47,7 +47,7 @@ class SeminarEntity( @OneToMany(mappedBy = "seminar", cascade = [CascadeType.ALL], orphanRemoval = true) var attachments: MutableList = mutableListOf(), - ): BaseTimeEntity(), ImageContentEntityType, AttachmentContentEntityType { + ): BaseTimeEntity(), MainImageContentEntityType, AttachmentContentEntityType { override fun bringMainImage(): MainImageEntity? = mainImage override fun bringAttachments() = attachments diff --git a/src/main/kotlin/com/wafflestudio/csereal/core/seminar/service/SeminarService.kt b/src/main/kotlin/com/wafflestudio/csereal/core/seminar/service/SeminarService.kt index 1ddd8287..ebba6b47 100644 --- a/src/main/kotlin/com/wafflestudio/csereal/core/seminar/service/SeminarService.kt +++ b/src/main/kotlin/com/wafflestudio/csereal/core/seminar/service/SeminarService.kt @@ -84,8 +84,7 @@ class SeminarServiceImpl( val imageURL = mainImageService.createImageURL(seminar.mainImage) val attachmentResponses = attachmentService.createAttachmentResponses(seminar.attachments) - - + return SeminarDto.of(seminar, imageURL, attachmentResponses, null) } @Transactional