-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(mail): change to send mail to members only #753
Changes from 8 commits
8bbb2aa
eb63290
90b1bec
4626bbb
62423b2
d52dee7
81a6306
4aaef87
bede24b
0d9b4e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -449,7 +449,7 @@ class DatabaseInitializer( | |
subject = "[우아한테크코스] 프리코스를 진행하는 목적과 사전 준비", | ||
body = "안녕하세요.", | ||
sender = "[email protected]", | ||
recipients = listOf("[email protected]", "[email protected]", "[email protected]", "[email protected]"), | ||
recipients = listOf(1L, 2L, 3L, 4L), | ||
sentTime = createLocalDateTime(2020, 11, 5, 10) | ||
) | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,6 @@ import org.springframework.core.io.ByteArrayResource | |
import support.views.BindingFormLayout | ||
import support.views.NO_NAME | ||
import support.views.addSortableColumn | ||
import support.views.createEnterBox | ||
import support.views.createErrorSmallButton | ||
import support.views.createNormalButton | ||
import support.views.createUpload | ||
|
@@ -43,6 +42,7 @@ class MailForm( | |
private val mailTargetsGrid: Grid<MailTargetResponse> = createMailTargetsGrid(mailTargets) | ||
private val recipientFilter: Component = createRecipientFilter() | ||
private val fileUpload: Upload = createFileUpload() | ||
private var mailData: MailData? = null | ||
|
||
init { | ||
add(subject, sender, recipientFilter, mailTargetsGrid, body, fileUpload) | ||
|
@@ -60,20 +60,11 @@ class MailForm( | |
|
||
private fun createRecipientFilter(): Component { | ||
return HorizontalLayout( | ||
createTargetEnterBox(), | ||
createIndividualLoadButton(), | ||
createGroupLoadButton() | ||
).apply { defaultVerticalComponentAlignment = FlexComponent.Alignment.END } | ||
} | ||
|
||
private fun createTargetEnterBox(): Component { | ||
return createEnterBox("받는사람") { | ||
if (it.isNotBlank()) { | ||
refreshGrid { mailTargets.add(MailTargetResponse(it, NO_NAME)) } | ||
} | ||
} | ||
} | ||
|
||
private fun createIndividualLoadButton(): Button { | ||
return createNormalButton("개별 불러오기") { | ||
IndividualMailTargetDialog(memberService) { | ||
|
@@ -133,15 +124,16 @@ class MailForm( | |
return null | ||
} | ||
return bindDefaultOrNull()?.apply { | ||
recipients = mailTargets.map { it.email }.toList() | ||
recipients = mailTargets.map { it.id }.toList() | ||
attachments = uploadFile | ||
} | ||
} | ||
|
||
override fun fill(data: MailData) { | ||
mailData = data | ||
fillDefault(data) | ||
toReadOnlyMode() | ||
refreshGrid { mailTargets.addAll(mailTargetService.findAllByEmails(data.recipients)) } | ||
refreshGrid { mailTargets.addAll(mailTargetService.findAllByMemberIds(data.recipients)) } | ||
} | ||
|
||
private fun toReadOnlyMode() { | ||
|
@@ -159,6 +151,8 @@ class MailForm( | |
} | ||
|
||
private fun refreshGridFooter() { | ||
mailTargetsGrid.columns.first().setFooter("받는사람: ${mailTargets.size}명") | ||
mailData?.let { | ||
mailTargetsGrid.columns.first().setFooter("받는사람: ${mailTargets.size}명 (탈퇴 회원 포함 총 ${it.recipients.size}명)") | ||
} ?: mailTargetsGrid.columns.first().setFooter("받는사람: ${mailTargets.size}명") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. r: 탈퇴한 회원을 표시할 방법을 결정하였으므로 더 이상 |
||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. c: 앞으로 다양한
abstract class StringToListConverter<T : Any>(
private val type: KClass<T>,
) : AttributeConverter<List<T>, String> {
override fun convertToDatabaseColumn(attribute: List<T>): String {
return attribute.joinToString(COMMA)
}
override fun convertToEntityAttribute(dbData: String): List<T> {
return dbData.split(COMMA).mapNotNull { type.safeCast(it) }
}
companion object {
private const val COMMA: String = ","
}
}
@Converter
class StringToLongListConverter : StringToListConverter<Long>(Long::class) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아하 사실은 앞으로 사용될 것일지 감이 안잡혀서 일단 기존 컨버터를 삭제하고 새로 만들었었어요. 공유주신 코드 기반으로 작성하면서 String -> 제너릭 타입으로의 변환을 위해 변환 함수를 받도록 변경 했습니다! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package support.domain | ||
|
||
import javax.persistence.AttributeConverter | ||
import javax.persistence.Converter | ||
|
||
@Converter | ||
class StringToLongListConverter : AttributeConverter<List<Long>, String> { | ||
override fun convertToDatabaseColumn(recipients: List<Long>): String { | ||
return recipients.joinToString(COMMA) | ||
} | ||
|
||
override fun convertToEntityAttribute(dbData: String): List<Long> { | ||
return dbData.split(COMMA).map { it.toLong() } | ||
} | ||
|
||
companion object { | ||
private const val COMMA: String = "," | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,14 +7,14 @@ import java.time.LocalDateTime | |
private const val SUBJECT: String = "메일제목" | ||
private const val BODY: String = "메일 본문 입니다." | ||
private const val SENDER: String = "[email protected]" | ||
private val RECIPIENTS: List<String> = listOf("[email protected]", "[email protected]") | ||
private val RECIPIENTS: List<Long> = listOf(1L, 2L) | ||
private val SENT_TIME: LocalDateTime = LocalDateTime.now() | ||
|
||
fun createMailHistory( | ||
subject: String = SUBJECT, | ||
body: String = BODY, | ||
sender: String = SENDER, | ||
recipients: List<String> = RECIPIENTS, | ||
recipients: List<Long> = RECIPIENTS, | ||
sentTime: LocalDateTime = SENT_TIME, | ||
id: Long = 0L | ||
): MailHistory { | ||
|
@@ -25,7 +25,7 @@ fun createMailData( | |
subject: String = SUBJECT, | ||
body: String = BODY, | ||
sender: String = SENDER, | ||
recipients: List<String> = RECIPIENTS, | ||
recipients: List<Long> = RECIPIENTS, | ||
sentTime: LocalDateTime = SENT_TIME, | ||
id: Long = 0L | ||
): MailData { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,6 @@ import apply.domain.evaluationtarget.EvaluationStatus.PENDING | |
import apply.domain.evaluationtarget.EvaluationStatus.WAITING | ||
import apply.domain.evaluationtarget.EvaluationTargetRepository | ||
import apply.domain.member.MemberRepository | ||
import apply.domain.member.findAllByEmailIn | ||
import io.kotest.core.spec.style.BehaviorSpec | ||
import io.kotest.matchers.collections.shouldBeEmpty | ||
import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder | ||
|
@@ -69,7 +68,7 @@ class MailTargetServiceTest : BehaviorSpec({ | |
|
||
Then("평가 대상자의 이름 및 이메일을 확인할 수 있다") { | ||
actual shouldHaveSize 1 | ||
actual[0] shouldBe MailTargetResponse(member.email, member.name) | ||
actual[0] shouldBe MailTargetResponse(member) | ||
} | ||
} | ||
} | ||
|
@@ -88,7 +87,7 @@ class MailTargetServiceTest : BehaviorSpec({ | |
|
||
Then("평가 대상자의 이름 및 이메일을 확인할 수 있다") { | ||
actual shouldHaveSize 1 | ||
actual[0] shouldBe MailTargetResponse(member.email, member.name) | ||
actual[0] shouldBe MailTargetResponse(member) | ||
} | ||
} | ||
} | ||
|
@@ -107,7 +106,7 @@ class MailTargetServiceTest : BehaviorSpec({ | |
|
||
Then("평가 대상자의 이름 및 이메일을 확인할 수 있다") { | ||
actual shouldHaveSize 1 | ||
actual[0] shouldBe MailTargetResponse(member.email, member.name) | ||
actual[0] shouldBe MailTargetResponse(member) | ||
} | ||
} | ||
} | ||
|
@@ -141,16 +140,20 @@ class MailTargetServiceTest : BehaviorSpec({ | |
} | ||
} | ||
|
||
Given("특정 이메일을 가진 회원이 없는 경우") { | ||
val email = "[email protected]" | ||
Given("메일 이력을 통해 회원 id 목록을 확인할 수 있는 경우") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a: 탈퇴한 회원이 구분되지 않아 테스트 코드 수정이 필요해 보이네요. 병합 후 #754 에서 수정하면 될 것 같아요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이후 작업을 놓치지 않게 하기위해 아래 주석을 추가해뒀습니다.
|
||
val members = listOf( | ||
createMember(id = 1L), | ||
createMember(id = 2L), | ||
createMember(id = 3L) | ||
) | ||
|
||
every { memberRepository.findAllByEmailIn(any()) } returns emptyList() | ||
every { memberRepository.findAllById(any()) } returns members | ||
|
||
When("해당 이메일로 이메일 정보를 조회하면") { | ||
val actual = mailTargetService.findAllByEmails(listOf(email)) | ||
When("회원 id를 사용해 메일 수신자 정보를 조회하면") { | ||
val actual = mailTargetService.findAllByMemberIds(listOf(1L, 2L, 3L, 4L)) | ||
|
||
Then("이름이 비어있는 것을 확인할 수 있다") { | ||
actual[0] shouldBe MailTargetResponse(email, null) | ||
Then("현재 회원인 메일 수신자만 확인할 수 있다") { | ||
actual shouldHaveSize 3 | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -121,7 +121,7 @@ class EvaluationTargetRestControllerTest : RestControllerTest() { | |
@EnumSource(names = ["PASS", "FAIL", "WAITING"]) | ||
@ParameterizedTest | ||
fun `메일 발송 대상(합격자)들의 이메일 정보를 조회한다`(enumStatus: EvaluationStatus) { | ||
val responses = listOf(MailTargetResponse("[email protected]", "김로키")) | ||
val responses = listOf(MailTargetResponse("[email protected]", "김로키", 1L)) | ||
every { mailTargetService.findMailTargets(any(), any()) } returns responses | ||
|
||
mockMvc.get("/api/recruitments/{recruitmentId}/evaluations/{evaluationId}/targets/emails", 1L, 1L) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a: IN 절과 관련하여 재밌는 내용이 있네요.