diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/audition/AuditionApplicant.kt b/src/main/kotlin/kr/co/vividnext/sodalive/audition/AuditionApplicant.kt index e485407..21dc568 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/audition/AuditionApplicant.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/audition/AuditionApplicant.kt @@ -9,8 +9,8 @@ import javax.persistence.ManyToOne @Entity data class AuditionApplicant( - val voicePath: String, val phoneNumber: String, + var voicePath: String? = null, val isActive: Boolean = true ) : BaseEntity() { @ManyToOne(fetch = FetchType.LAZY) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/audition/applicant/ApplyAuditionRoleRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/audition/applicant/ApplyAuditionRoleRequest.kt new file mode 100644 index 0000000..c5b7d4e --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/audition/applicant/ApplyAuditionRoleRequest.kt @@ -0,0 +1,6 @@ +package kr.co.vividnext.sodalive.audition.applicant + +data class ApplyAuditionRoleRequest( + val roleId: Long, + val phoneNumber: String +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/audition/applicant/AuditionApplicantController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/audition/applicant/AuditionApplicantController.kt index ff03e54..9caeb2d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/audition/applicant/AuditionApplicantController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/audition/applicant/AuditionApplicantController.kt @@ -6,9 +6,12 @@ import kr.co.vividnext.sodalive.member.Member import org.springframework.data.domain.Pageable import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RequestPart import org.springframework.web.bind.annotation.RestController +import org.springframework.web.multipart.MultipartFile @RestController @RequestMapping("/audition/applicant") @@ -31,4 +34,22 @@ class AuditionApplicantController(private val service: AuditionApplicantService) ) ) } + + @PostMapping + fun applyAuditionRole( + @RequestPart("contentFile") + contentFile: MultipartFile?, + @RequestPart("request") requestString: String, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.applyAuditionRole( + contentFile = contentFile, + requestString = requestString, + member = member + ) + ) + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/audition/applicant/AuditionApplicantService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/audition/applicant/AuditionApplicantService.kt index edc1c94..d27f7ca 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/audition/applicant/AuditionApplicantService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/audition/applicant/AuditionApplicantService.kt @@ -1,9 +1,30 @@ package kr.co.vividnext.sodalive.audition.applicant +import com.amazonaws.services.s3.model.ObjectMetadata +import com.fasterxml.jackson.databind.ObjectMapper +import kr.co.vividnext.sodalive.audition.AuditionApplicant +import kr.co.vividnext.sodalive.audition.role.AuditionRoleRepository +import kr.co.vividnext.sodalive.aws.s3.S3Uploader +import kr.co.vividnext.sodalive.common.SodaException +import kr.co.vividnext.sodalive.member.Member +import kr.co.vividnext.sodalive.utils.generateFileName +import org.springframework.beans.factory.annotation.Value +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.multipart.MultipartFile @Service -class AuditionApplicantService(private val repository: AuditionApplicantRepository) { +class AuditionApplicantService( + private val repository: AuditionApplicantRepository, + private val roleRepository: AuditionRoleRepository, + + private val s3Uploader: S3Uploader, + private val objectMapper: ObjectMapper, + + @Value("\${cloud.aws.s3.bucket}") + private val bucket: String +) { fun getAuditionApplicantList( auditionRoleId: Long, sortType: AuditionApplicantSortType, @@ -23,4 +44,31 @@ class AuditionApplicantService(private val repository: AuditionApplicantReposito items = items ) } + + @Transactional + fun applyAuditionRole(contentFile: MultipartFile?, requestString: String, member: Member) { + if (contentFile == null) throw SodaException("녹음 파일을 확인해 주세요.") + val request = objectMapper.readValue(requestString, ApplyAuditionRoleRequest::class.java) + + val auditionRole = roleRepository.findByIdOrNull(id = request.roleId) + ?: throw SodaException("잘못된 요청입니다.\n다시 시도해 주세요.") + + val applicant = AuditionApplicant(phoneNumber = request.phoneNumber) + applicant.role = auditionRole + applicant.member = member + repository.save(applicant) + + val contentFileName = generateFileName(prefix = "${applicant.id}-applicant") + + val metadata = ObjectMetadata() + metadata.contentLength = contentFile.size + + val contentPath = s3Uploader.upload( + inputStream = contentFile.inputStream, + bucket = bucket, + filePath = "audition/${applicant.id}/$contentFileName", + metadata = metadata + ) + applicant.voicePath = contentPath + } }