From 17ee380f2c5ae4c6c3be334b17d884df52283e20 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 8 Jul 2024 12:22:08 +0900 Subject: [PATCH] =?UTF-8?q?[Feat/#131]=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EA=B5=AC=EB=8F=85=20=EB=82=B4=EC=9A=A9=20=EC=B1=84=EC=9B=8C?= =?UTF-8?q?=EC=84=9C=20=EA=B5=AC=ED=98=84=20(#156)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: SendArticleEmailArgs의 content 재정의 * feat: BatchCategoryType, BatchMemberType 추가 * refactor: WorkBookSubscriberWriter 수정 * test: SendArticleEmailArgs의 content 재정의 반영 * refactor: 유료 계정 전환으로 인한 이메일 테스트 Disabled 처리 * fix: 요일이 영어로 내려가는 문제 해결 * refactor: articleLink 변경 사항 반영 * test: b00b1fede169ef0da21bd53d932515a9e34585a1 반영 * refactor: 인터페이스를 사용하여 상속 대신하고 data 클래스로 변경 * refactor: article 이메일 템플릿 변경 반영 * fix: 수신 거부 링크 오타 수정 --- .../data/common/code/BatchCategoryType.kt | 27 ++ .../batch/data/common/code/BatchMemberType.kt | 17 ++ .../writer/WorkBookSubscriberWriter.kt | 80 ++++- .../writer/WorkBookSubscriberWriterTest.kt | 24 +- .../WorkBookSubscriberWriterTestSetHelper.kt | 72 ++++- .../com/few/data/common/code/CategoryType.kt | 3 + .../com/few/data/common/code/MemberType.kt | 3 + .../com/few/email/sender/dto/SendMailArgs.kt | 36 +-- .../article/SendArticleEmailService.kt | 21 +- .../article/dto/SendArticleEmailArgs.kt | 27 +- .../src/main/resources/templates/article.html | 283 +++++++++++------- .../article/SendArticleEmailServiceTest.kt | 21 +- 12 files changed, 424 insertions(+), 190 deletions(-) create mode 100644 batch/src/main/kotlin/com/few/batch/data/common/code/BatchCategoryType.kt create mode 100644 batch/src/main/kotlin/com/few/batch/data/common/code/BatchMemberType.kt diff --git a/batch/src/main/kotlin/com/few/batch/data/common/code/BatchCategoryType.kt b/batch/src/main/kotlin/com/few/batch/data/common/code/BatchCategoryType.kt new file mode 100644 index 000000000..e9c86b6ff --- /dev/null +++ b/batch/src/main/kotlin/com/few/batch/data/common/code/BatchCategoryType.kt @@ -0,0 +1,27 @@ +package com.few.batch.data.common.code + +/** + * BatchCategoryType is origin from CategoryType in few-data module. + * @see com.few.data.common.code.CategoryType + */ +enum class BatchCategoryType(val code: Byte, val displayName: String) { + ECONOMY(0, "경제"), + IT(10, "IT"), + MARKETING(20, "마케팅"), + CULTURE(30, "교양"), + SCIENCE(40, "과학"); + + companion object { + fun fromCode(code: Byte): BatchCategoryType? { + return entries.find { it.code == code } + } + + fun convertToCode(displayName: String): Byte { + return entries.find { it.name == displayName }?.code ?: throw IllegalArgumentException("Invalid category name") + } + + fun convertToDisplayName(code: Byte): String { + return entries.find { it.code == code }?.displayName ?: throw IllegalArgumentException("Invalid category code") + } + } +} \ No newline at end of file diff --git a/batch/src/main/kotlin/com/few/batch/data/common/code/BatchMemberType.kt b/batch/src/main/kotlin/com/few/batch/data/common/code/BatchMemberType.kt new file mode 100644 index 000000000..a32e54c00 --- /dev/null +++ b/batch/src/main/kotlin/com/few/batch/data/common/code/BatchMemberType.kt @@ -0,0 +1,17 @@ +package com.few.batch.data.common.code + +/** + * BatchMemberType is origin from MemberType in few-data module. + * @see com.few.data.common.code.MemberType + */ +enum class BatchMemberType(val code: Byte, val displayName: String) { + NORMAL(60, "일반멤버"), + ADMIN(0, "어드민멤버"), + WRITER(120, "작가멤버"); + + companion object { + fun fromCode(code: Byte): BatchMemberType? { + return values().find { it.code == code } + } + } +} \ No newline at end of file diff --git a/batch/src/main/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriter.kt b/batch/src/main/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriter.kt index 140924024..4e3914329 100644 --- a/batch/src/main/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriter.kt +++ b/batch/src/main/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriter.kt @@ -1,19 +1,20 @@ package com.few.batch.service.article.writer +import com.few.batch.data.common.code.BatchCategoryType +import com.few.batch.data.common.code.BatchMemberType import com.few.batch.service.article.dto.WorkBookSubscriberItem import com.few.batch.service.article.dto.toMemberIds import com.few.batch.service.article.dto.toTargetWorkBookIds import com.few.batch.service.article.dto.toTargetWorkBookProgress import com.few.email.service.article.SendArticleEmailService +import com.few.email.service.article.dto.Content import com.few.email.service.article.dto.SendArticleEmailArgs -import jooq.jooq_dsl.tables.ArticleIfo -import jooq.jooq_dsl.tables.MappingWorkbookArticle -import jooq.jooq_dsl.tables.Member -import jooq.jooq_dsl.tables.Subscription +import jooq.jooq_dsl.tables.* import org.jooq.DSLContext import org.jooq.impl.DSL import org.springframework.stereotype.Component import org.springframework.transaction.annotation.Transactional +import java.net.URL import java.time.LocalDate import java.time.LocalDateTime @@ -39,23 +40,40 @@ data class MemberReceiveArticles( } } +data class ArticleContent( + val id: Long, + val category: String, // todo fix + val articleTitle: String, + val articleContent: String, + val writerName: String, + val writerLink: URL +) + +fun List.peek(articleId: Long): ArticleContent { + return this.find { + it.id == articleId + } ?: throw IllegalArgumentException("article not found") +} + @Component class WorkBookSubscriberWriter( private val dslContext: DSLContext, private val sendArticleEmailService: SendArticleEmailService ) { + companion object { + private const val ARTICLE_SUBJECT_TEMPLATE = "Day%d %s" + private const val ARTICLE_TEMPLATE = "article" + } + @Transactional fun execute(items: List): Map { val memberT = Member.MEMBER val mappingWorkbookArticleT = MappingWorkbookArticle.MAPPING_WORKBOOK_ARTICLE val articleIfoT = ArticleIfo.ARTICLE_IFO + val articleMstT = ArticleMst.ARTICLE_MST val subscriptionT = Subscription.SUBSCRIPTION - val ARTICLE_SUBJECT = "${LocalDate.now()} 일자 학습 아티클" - val ARTICLE_TEMPLATE = "article" // todo fix - val ARTICLE_STYLE = "style" // todo fix - val memberIds = items.toMemberIds() val targetWorkBookIds = items.toTargetWorkBookIds() val targetWorkBookProgress = items.toTargetWorkBookProgress() @@ -90,25 +108,55 @@ class WorkBookSubscriberWriter( MemberReceiveArticles(it) } - /** 구독자들이 받을 학습지 정보를 기준으로 학습지의 내용을 조회한다.*/ - val articleContentsMap = dslContext.select( - articleIfoT.ARTICLE_MST_ID, - articleIfoT.CONTENT + /** 구독자들이 받을 학습지 정보를 기준으로 학습지 관련 정보를 조회한다.*/ + val articleContents = dslContext.select( + articleIfoT.ARTICLE_MST_ID.`as`(ArticleContent::id.name), + articleIfoT.CONTENT.`as`(ArticleContent::articleContent.name), + articleMstT.TITLE.`as`(ArticleContent::articleTitle.name), + articleMstT.CATEGORY_CD.`as`(ArticleContent::category.name), + DSL.jsonGetAttributeAsText(memberT.DESCRIPTION, "name").`as`(ArticleContent::writerName.name), + DSL.jsonGetAttribute(memberT.DESCRIPTION, "url").`as`(ArticleContent::writerLink.name) ) .from(articleIfoT) + .join(articleMstT) + .on(articleIfoT.ARTICLE_MST_ID.eq(articleMstT.ID)) + .join(memberT) + .on( + articleMstT.MEMBER_ID.eq(memberT.ID) + .and(memberT.TYPE_CD.eq(BatchMemberType.WRITER.code)) + ) .where(articleIfoT.ARTICLE_MST_ID.`in`(memberReceiveArticles.getArticleIds())) .and(articleIfoT.DELETED_AT.isNull) - .fetch() - .intoMap(articleIfoT.ARTICLE_MST_ID, articleIfoT.CONTENT) + .fetchInto(ArticleContent::class.java) val memberSuccessRecords = memberIds.associateWith { true }.toMutableMap() val failRecords = mutableMapOf>>() // todo check !! target is not null + val date = LocalDate.now() val emailServiceArgs = items.map { val toEmail = memberEmailRecords[it.memberId]!! val memberArticle = memberReceiveArticles.getByWorkBookIdAndDayCol(it.targetWorkBookId, it.progress + 1) - val articleContent = articleContentsMap[memberArticle.articleId]!! - return@map it.memberId to SendArticleEmailArgs(toEmail, ARTICLE_SUBJECT, ARTICLE_TEMPLATE, articleContent, ARTICLE_STYLE) + val articleContent = articleContents.peek(memberArticle.articleId).let { article -> + Content( + articleLink = URL("https://www.fewletter.com/article/${memberArticle.articleId}"), + currentDate = date, + category = BatchCategoryType.convertToDisplayName(article.category.toByte()), + articleDay = memberArticle.dayCol.toInt(), + articleTitle = article.articleTitle, + writerName = article.writerName, + writerLink = article.writerLink, + articleContent = article.articleContent, + problemLink = URL("https://www.fewletter.com/problem?articleId=${memberArticle.articleId}"), + unsubscribeLink = URL("https://www.fewletter.com/unsubscribe?user=${memberEmailRecords[it.memberId]}&workbookId=${it.targetWorkBookId}&articleId=${memberArticle.articleId}") + ) + } + return@map it.memberId to + SendArticleEmailArgs( + toEmail, + ARTICLE_SUBJECT_TEMPLATE.format(memberArticle.dayCol, articleContent.articleTitle), + ARTICLE_TEMPLATE, + articleContent + ) } // todo refactoring to send email in parallel or batch diff --git a/batch/src/test/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriterTest.kt b/batch/src/test/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriterTest.kt index c8eb8859a..f43cd1a92 100644 --- a/batch/src/test/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriterTest.kt +++ b/batch/src/test/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriterTest.kt @@ -7,6 +7,7 @@ import jooq.jooq_dsl.tables.ArticleIfo import jooq.jooq_dsl.tables.MappingWorkbookArticle import jooq.jooq_dsl.tables.Member import jooq.jooq_dsl.tables.Subscription +import org.jboss.logging.MDC import org.jooq.DSLContext import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach @@ -14,7 +15,6 @@ import org.junit.jupiter.api.Test import org.mockito.Mockito.* import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.mock.mockito.MockBean -import java.time.LocalDate import kotlin.random.Random class WorkBookSubscriberWriterTest : BatchTestSpec() { @@ -40,11 +40,15 @@ class WorkBookSubscriberWriterTest : BatchTestSpec() { // setup member helper.setUpMembers(10) + helper.setUpWriter(11) // setup subscription helper.setUpSubscriptions(start = 1, count = 5, workbookId = 1) helper.setUpSubscriptions(start = 6, count = 10, workbookId = 2) + // setup article mst + helper.setUpArticleMst(start = 1, count = 10, writerId = 11) + // setup mapping workbook article helper.setUpMappingWorkbookArticle(start = 1, count = 5, workbookId = 1) helper.setUpMappingWorkbookArticle(start = 6, count = 10, workbookId = 2, dayCorrection = 5) @@ -79,16 +83,16 @@ class WorkBookSubscriberWriterTest : BatchTestSpec() { // given val items = helper.browseItems(listOf(1, 2)) val failItem = items[Random.nextInt(6, items.size - 1)] + val failArgs = SendArticleEmailArgs( + "member${failItem.memberId}@gmail.com", + "Day${failItem.content.articleDay} ${failItem.content.articleTitle}", + "article", + failItem.content, + "" + ) + MDC.put("test", failArgs) `when`( - sendArticleEmailService.send( - SendArticleEmailArgs( - "member${failItem.memberId}@gmail.com", - "${LocalDate.now()} 일자 학습 아티클", - "article", - failItem.content, - "style" - ) - ) + sendArticleEmailService.send(failArgs) ).thenThrow(RuntimeException("send email error")) // when diff --git a/batch/src/test/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriterTestSetHelper.kt b/batch/src/test/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriterTestSetHelper.kt index cf9c48d8a..4e5a3a822 100644 --- a/batch/src/test/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriterTestSetHelper.kt +++ b/batch/src/test/kotlin/com/few/batch/service/article/writer/WorkBookSubscriberWriterTestSetHelper.kt @@ -1,12 +1,15 @@ package com.few.batch.service.article.writer +import com.few.batch.data.common.code.BatchCategoryType +import com.few.batch.data.common.code.BatchMemberType import com.few.batch.service.article.dto.WorkBookSubscriberItem -import jooq.jooq_dsl.tables.ArticleIfo -import jooq.jooq_dsl.tables.MappingWorkbookArticle -import jooq.jooq_dsl.tables.Member -import jooq.jooq_dsl.tables.Subscription +import com.few.email.service.article.dto.Content +import jooq.jooq_dsl.tables.* import org.jooq.DSLContext +import org.jooq.JSON import org.springframework.boot.test.context.TestComponent +import java.net.URL +import java.time.LocalDate import kotlin.random.Random fun List.toServiceDto(): List { @@ -23,7 +26,14 @@ data class TestWorkBookSubscriberDto( val memberId: Long, val targetWorkBookId: Long, val progress: Long, - val content: String + val content: Content +) + +data class ArticleDto( + val articleId: Long, + val dayCol: Int, + val content: String, + val title: String ) @TestComponent @@ -36,11 +46,20 @@ class WorkBookSubscriberWriterTestSetHelper( dslContext.insertInto(Member.MEMBER) .set(Member.MEMBER.ID, i.toLong()) .set(Member.MEMBER.EMAIL, "member$i@gmail.com") - .set(Member.MEMBER.TYPE_CD, 0) // todo fix + .set(Member.MEMBER.TYPE_CD, BatchMemberType.NORMAL.code) .execute() } } + fun setUpWriter(id: Long) { + dslContext.insertInto(Member.MEMBER) + .set(Member.MEMBER.ID, id) + .set(Member.MEMBER.EMAIL, "writer@gmail.com") + .set(Member.MEMBER.TYPE_CD, BatchMemberType.WRITER.code) + .set(Member.MEMBER.DESCRIPTION, JSON.valueOf("{\"url\": \"http://localhost:8080\", \"name\": \"writer\"}")) + .execute() + } + fun setUpSubscriptions(start: Int = 1, count: Int, workbookId: Long = 1) { for (i in start..count) { dslContext.insertInto(Subscription.SUBSCRIPTION) @@ -51,7 +70,7 @@ class WorkBookSubscriberWriterTestSetHelper( } } - fun setUpMappingWorkbookArticle(start: Int = 1, count: Int, workbookId: Long = 1, dayCorrection: Int = 0) { + fun setUpMappingWorkbookArticle(start: Int = 1, count: Int, workbookId: Long = 1, dayCorrection: Int = 1) { for (i in start..count) { dslContext.insertInto(MappingWorkbookArticle.MAPPING_WORKBOOK_ARTICLE) .set(MappingWorkbookArticle.MAPPING_WORKBOOK_ARTICLE.WORKBOOK_ID, workbookId) @@ -61,6 +80,18 @@ class WorkBookSubscriberWriterTestSetHelper( } } + fun setUpArticleMst(start: Int = 1, count: Int, writerId: Long) { + for (i in start..count) { + dslContext.insertInto(ArticleMst.ARTICLE_MST) + .set(ArticleMst.ARTICLE_MST.ID, i.toLong()) + .set(ArticleMst.ARTICLE_MST.TITLE, "title$i") + .set(ArticleMst.ARTICLE_MST.MEMBER_ID, writerId) + .set(ArticleMst.ARTICLE_MST.CATEGORY_CD, BatchCategoryType.fromCode(0)!!.code) + .set(ArticleMst.ARTICLE_MST.MAIN_IMAGE_URL, "http://localhost:8080") + .execute() + } + } + fun setUpArticleIfo(start: Int = 1, count: Int) { for (i in start..count) { dslContext.insertInto(ArticleIfo.ARTICLE_IFO) @@ -92,11 +123,36 @@ class WorkBookSubscriberWriterTestSetHelper( .and(MappingWorkbookArticle.MAPPING_WORKBOOK_ARTICLE.DELETED_AT.isNull) .fetchOneInto(String::class.java) + val articleDto = dslContext.select( + MappingWorkbookArticle.MAPPING_WORKBOOK_ARTICLE.ARTICLE_ID, + MappingWorkbookArticle.MAPPING_WORKBOOK_ARTICLE.DAY_COL, + ArticleIfo.ARTICLE_IFO.CONTENT, + ArticleMst.ARTICLE_MST.TITLE + ).from(MappingWorkbookArticle.MAPPING_WORKBOOK_ARTICLE) + .join(ArticleIfo.ARTICLE_IFO) + .on(MappingWorkbookArticle.MAPPING_WORKBOOK_ARTICLE.ARTICLE_ID.eq(ArticleIfo.ARTICLE_IFO.ARTICLE_MST_ID)) + .join(ArticleMst.ARTICLE_MST) + .on(ArticleIfo.ARTICLE_IFO.ARTICLE_MST_ID.eq(ArticleMst.ARTICLE_MST.ID)) + .where(MappingWorkbookArticle.MAPPING_WORKBOOK_ARTICLE.WORKBOOK_ID.eq(workbookId)) + .and(MappingWorkbookArticle.MAPPING_WORKBOOK_ARTICLE.DAY_COL.eq(it[Subscription.SUBSCRIPTION.PROGRESS].toInt() + 1)) + .fetchOneInto(ArticleDto::class.java) + val dto = TestWorkBookSubscriberDto( memberId = it[Subscription.SUBSCRIPTION.MEMBER_ID], targetWorkBookId = workbookId, progress = it[Subscription.SUBSCRIPTION.PROGRESS], - content = content!! + content = Content( + articleLink = URL("https://www.fewletter.com/article/${articleDto!!.articleId}"), + currentDate = LocalDate.now(), + category = BatchCategoryType.fromCode(0)!!.displayName, + articleDay = articleDto.dayCol, + articleTitle = articleDto.title, + writerName = "writer", + writerLink = URL("http://localhost:8080"), + articleContent = articleDto.content, + problemLink = URL("https://www.fewletter.com/problem?articleId=${articleDto.articleId}"), + unsubscribeLink = URL("https://www.fewletter.com/unsbuscribe?user=member${it[Subscription.SUBSCRIPTION.MEMBER_ID]}@gmail.com&workbookId=$workbookId&articleId=${articleDto.articleId}") + ) ) items.add(dto) } diff --git a/data/src/main/kotlin/com/few/data/common/code/CategoryType.kt b/data/src/main/kotlin/com/few/data/common/code/CategoryType.kt index e9b029b46..3e2286ef1 100644 --- a/data/src/main/kotlin/com/few/data/common/code/CategoryType.kt +++ b/data/src/main/kotlin/com/few/data/common/code/CategoryType.kt @@ -1,5 +1,8 @@ package com.few.data.common.code +/** + * @see com.few.batch.data.common.code.BatchCategoryType + */ enum class CategoryType(val code: Byte, val displayName: String) { POLITICS(0, "정치"), ECONOMY(10, "경제"), diff --git a/data/src/main/kotlin/com/few/data/common/code/MemberType.kt b/data/src/main/kotlin/com/few/data/common/code/MemberType.kt index b58bd37a5..c9fe60031 100644 --- a/data/src/main/kotlin/com/few/data/common/code/MemberType.kt +++ b/data/src/main/kotlin/com/few/data/common/code/MemberType.kt @@ -1,5 +1,8 @@ package com.few.data.common.code +/** + * @see com.few.batch.data.common.code.BatchMemberType + */ enum class MemberType(val code: Byte, val displayName: String) { NORMAL(60, "일반멤버"), ADMIN(0, "어드민멤버"), diff --git a/email/src/main/kotlin/com/few/email/sender/dto/SendMailArgs.kt b/email/src/main/kotlin/com/few/email/sender/dto/SendMailArgs.kt index 003760647..fb46f2513 100644 --- a/email/src/main/kotlin/com/few/email/sender/dto/SendMailArgs.kt +++ b/email/src/main/kotlin/com/few/email/sender/dto/SendMailArgs.kt @@ -1,33 +1,9 @@ package com.few.email.sender.dto -abstract class SendMailArgs( - val to: String, - val subject: String, - val template: String, - private val content: C, - private val properties: P -) { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as SendMailArgs<*, *> - - if (to != other.to) return false - if (subject != other.subject) return false - if (template != other.template) return false - if (content != other.content) return false - if (properties != other.properties) return false - - return true - } - - override fun hashCode(): Int { - var result = to.hashCode() - result = 31 * result + subject.hashCode() - result = 31 * result + template.hashCode() - result = 31 * result + (content?.hashCode() ?: 0) - result = 31 * result + (properties?.hashCode() ?: 0) - return result - } +interface SendMailArgs { + val to: String + val subject: String + val template: String + val content: C + val properties: P } \ No newline at end of file diff --git a/email/src/main/kotlin/com/few/email/service/article/SendArticleEmailService.kt b/email/src/main/kotlin/com/few/email/service/article/SendArticleEmailService.kt index ff726a086..bbbf6dd62 100644 --- a/email/src/main/kotlin/com/few/email/service/article/SendArticleEmailService.kt +++ b/email/src/main/kotlin/com/few/email/service/article/SendArticleEmailService.kt @@ -7,6 +7,8 @@ import org.springframework.mail.javamail.JavaMailSender import org.springframework.stereotype.Component import org.thymeleaf.TemplateEngine import org.thymeleaf.context.Context +import java.time.format.DateTimeFormatter +import java.util.* @Component class SendArticleEmailService( @@ -17,8 +19,23 @@ class SendArticleEmailService( override fun getHtml(args: SendArticleEmailArgs): String { val context = Context() - context.setVariable("content", args.articleContent) - context.setVariable("style", args.style) + context.setVariable("articleLink", args.content.articleLink.toString() + "?fromEmail=true") + context.setVariable( + "currentDate", + args.content.currentDate.format( + DateTimeFormatter.ofPattern("yyyy/MM/dd EEEE").withLocale( + Locale.KOREA + ) + ) + ) + context.setVariable("category", args.content.category) + context.setVariable("articleDay", "Day" + args.content.articleDay) + context.setVariable("articleTitle", args.content.articleTitle) + context.setVariable("writerName", args.content.writerName) + context.setVariable("writerLink", args.content.writerLink) + context.setVariable("articleContent", args.content.articleContent) + context.setVariable("problemLink", args.content.problemLink) + context.setVariable("unsubscribeLink", args.content.unsubscribeLink) return templateEngine.process(args.template, context) } } \ No newline at end of file diff --git a/email/src/main/kotlin/com/few/email/service/article/dto/SendArticleEmailArgs.kt b/email/src/main/kotlin/com/few/email/service/article/dto/SendArticleEmailArgs.kt index 4cb1e4c46..2c5d18c5f 100644 --- a/email/src/main/kotlin/com/few/email/service/article/dto/SendArticleEmailArgs.kt +++ b/email/src/main/kotlin/com/few/email/service/article/dto/SendArticleEmailArgs.kt @@ -1,11 +1,26 @@ package com.few.email.service.article.dto import com.few.email.sender.dto.SendMailArgs +import java.net.URL +import java.time.LocalDate -class SendArticleEmailArgs( - to: String, - subject: String, - template: String, +data class SendArticleEmailArgs( + override val to: String, + override val subject: String, + override val template: String, + override val content: Content, + override val properties: String = "" +) : SendMailArgs + +data class Content( + val articleLink: URL, + val currentDate: LocalDate, + val category: String, + val articleDay: Int, + val articleTitle: String, + val writerName: String, + val writerLink: URL, val articleContent: String, - val style: String -) : SendMailArgs(to, subject, template, articleContent, style) \ No newline at end of file + val problemLink: URL, + val unsubscribeLink: URL +) \ No newline at end of file diff --git a/email/src/main/resources/templates/article.html b/email/src/main/resources/templates/article.html index 7d8c63623..5e1404a96 100644 --- a/email/src/main/resources/templates/article.html +++ b/email/src/main/resources/templates/article.html @@ -1,126 +1,179 @@ - + - - - - - + + + FEW - - - - -