diff --git a/src/main/java/com/ffii/core/utils/LocaleUtils.java b/src/main/java/com/ffii/core/utils/LocaleUtils.java new file mode 100644 index 0000000..93b3383 --- /dev/null +++ b/src/main/java/com/ffii/core/utils/LocaleUtils.java @@ -0,0 +1,42 @@ +package com.ffii.core.utils; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.context.i18n.LocaleContextHolder; + +import java.util.Locale; + +/** this utils follow "-" standard ("zh-TW", no "zh_TW") */ +public abstract class LocaleUtils { + + public static Locale getLocale() { + return LocaleContextHolder.getLocale(); + } + + public static String getLocaleStr() { + return toLocaleStr(LocaleContextHolder.getLocale()); + } + + public static String toLocaleStr(Locale locale) { + String language = locale.getLanguage(); + String country = locale.getCountry(); + + if (StringUtils.isNotBlank(country)) { + return language + "-" + country; + } else { + return language; + } + } + + /** + * @param localeStr + * e.g. zh-TW + */ + public static Locale from(String localeStr) { + String[] localeArr = localeStr.split("-"); + if (localeArr.length == 1) { + return new Locale(localeArr[0]); + } else { + return new Locale(localeArr[0], localeArr[1]); + } + } +} diff --git a/src/main/java/com/ffii/fpsms/modules/common/MailSMTP.kt b/src/main/java/com/ffii/fpsms/modules/common/MailSMTP.kt new file mode 100644 index 0000000..54b0f82 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/common/MailSMTP.kt @@ -0,0 +1,38 @@ +package com.ffii.fpsms.modules.common + +import com.ffii.fpsms.modules.settings.service.SettingsService +import org.apache.commons.lang3.StringUtils + +open class MailSMTP(settingsService: SettingsService) { + + open var host: String? = null + open var port: Int? = null + open var username: String? = null + open var password: String? = null + open var auth: Boolean? = null + + init { + this.host = settingsService.getString(SettingNames.MAIL_SMTP_HOST) + this.port = settingsService.getInt(SettingNames.MAIL_SMTP_PORT) + this.username = settingsService.getString(SettingNames.MAIL_SMTP_USERNAME) + this.password = settingsService.getString(SettingNames.MAIL_SMTP_PASSWORD) + this.auth = settingsService.getBoolean(SettingNames.MAIL_SMTP_AUTH) + } + + final override fun equals(other: Any?): Boolean { + if (other == null || other !is MailSMTP) return false + + val o = other as MailSMTP + if (StringUtils.equals( + this.host, + o.host + ) && this.port == o.port && + StringUtils.equals(this.username, o.username) && + StringUtils.equals(this.password, o.password) + ) { + return true + } + + return false + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/common/SettingNames.java b/src/main/java/com/ffii/fpsms/modules/common/SettingNames.java index 66e7adf..9f2fa21 100644 --- a/src/main/java/com/ffii/fpsms/modules/common/SettingNames.java +++ b/src/main/java/com/ffii/fpsms/modules/common/SettingNames.java @@ -38,6 +38,8 @@ public abstract class SettingNames { public static final String MAIL_SMTP_RECIPIENTS = "MAIL.smtp.recipients"; + public static final String MAIL_SMTP_AUTH = "MAIL.smtp.auth"; + public static final String JS_VERSION = "JS.version"; public static final String REPORT_DAILYMAINT_RECIPIENTS_MECH = "REPORT.dailyMaint.recipients.mech"; diff --git a/src/main/java/com/ffii/fpsms/modules/common/mail/pojo/MailRequest.kt b/src/main/java/com/ffii/fpsms/modules/common/mail/pojo/MailRequest.kt new file mode 100644 index 0000000..4ff9ab9 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/common/mail/pojo/MailRequest.kt @@ -0,0 +1,246 @@ +package com.ffii.fpsms.modules.common.mail.pojo + +import jakarta.mail.internet.InternetAddress + +open class MailRequest() { + + val PRIORITY_HIGHEST: Int = 1 + val PRIORITY_HIGH: Int = 2 + val PRIORITY_NORMAL: Int = 3 + val PRIORITY_LOW: Int = 4 + val PRIORITY_LOWEST: Int = 5 + + open var from: InternetAddress? = null + + open var to: List = mutableListOf() + + open var subject: String? = null + + open var template: String? = null + + open var templateContent: String? = null + + open var args: Map = mapOf() + + open var priority: Int? = null + + open var replyTo: InternetAddress? = null + + open var cc: List = mutableListOf() + + open var bcc: List = mutableListOf() + + open var attachments: Map = mapOf() + + open fun builder(): Builder { + return Builder() + } + + open fun addAttachment(attachmentFilename: String, byteArray: ByteArray) { + this.attachments += Pair(attachmentFilename, byteArray) + } + + open fun addTo(to: InternetAddress) { + this.to += to + } + + open fun addCc(cc: InternetAddress) { + this.cc += cc + } + + open fun addBcc(bcc: InternetAddress) { + this.bcc += bcc + } + + open class Builder() { + open var mailRequest:MailRequest = MailRequest() + + init { + this.mailRequest = MailRequest() + } + + open fun build(): MailRequest { + return this.mailRequest + } + + open fun addAttachment(attachmentFilename: String, byteArray: ByteArray): Builder { + mailRequest.addAttachment(attachmentFilename, byteArray) + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("addToInternetAddress") + open fun addTo(to: InternetAddress): Builder { + mailRequest.addTo(to) + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("addToString") + open fun addTo(to: String): Builder { + mailRequest.addTo(InternetAddress(to)) + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("addToList") + open fun addTo(to: List): Builder { + to.forEach { + if (it.isNotEmpty()) { + mailRequest.addTo(InternetAddress(it)) + } + } + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("addCcInternetAddress") + open fun addCc(cc: InternetAddress): Builder { + mailRequest.addCc(cc) + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("addCcString") + open fun addCc(cc: String): Builder { + mailRequest.addCc(InternetAddress(cc)) + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("addCcStringList") + open fun addCc(cc: List): Builder { + cc.forEach { + if (it.isNotEmpty()) { + mailRequest.addCc(InternetAddress(it)) + } + } + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("addBccInternetAddress") + open fun addBcc(bcc: InternetAddress): Builder { + mailRequest.addBcc(bcc) + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("addBccString") + open fun addBcc(bcc: String): Builder { + mailRequest.addBcc(InternetAddress(bcc)) + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("addBccStringList") + open fun addBcc(bcc: List): Builder { + bcc.forEach { + if (it.isNotEmpty()) { + mailRequest.addBcc(InternetAddress(it)) + } + } + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("fromInternetAddress") + open fun from(from: InternetAddress): Builder { + mailRequest.from = from + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("fromString") + open fun from(from: String): Builder { + mailRequest.from = InternetAddress(from) + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("toListInternetAddress") + open fun to(to: List): Builder { + mailRequest.to = to + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("toListString") + open fun to(to: List): Builder { + mailRequest.to = to.map { InternetAddress(it) } + return this + } + + open fun subject(subject: String?): Builder { + mailRequest.subject = subject + return this + } + + open fun template(template: String?): Builder { + mailRequest.template = template + return this + } + + open fun templateContent(templateContent: String?): Builder { + mailRequest.templateContent = templateContent + return this + } + + open fun args(args: Map): Builder { + mailRequest.args = args + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("replyToInternetAddress") + open fun replyTo(replyTo: InternetAddress?): Builder { + mailRequest.replyTo = replyTo + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("replyToString") + open fun replyTo(replyTo: String?): Builder { + mailRequest.replyTo = InternetAddress(replyTo) + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("ccListInternetAddress") + open fun cc(cc: List): Builder { + mailRequest.cc = cc + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("ccListString") + open fun cc(cc: List): Builder { + mailRequest.cc = cc.map { InternetAddress(it) } + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("bccListInternetAddress") + open fun bcc(bcc: List): Builder { + mailRequest.bcc = bcc + return this + } + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("bccListString") + open fun bcc(bcc: List): Builder { + mailRequest.bcc = bcc.map { InternetAddress(it) } + return this + } + + open fun attachments(attachments: Map): Builder { + mailRequest.attachments = attachments + return this + } + + open fun priority(priority: Int?): Builder { + mailRequest.priority = priority + return this + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailReminderService.kt b/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailReminderService.kt new file mode 100644 index 0000000..12bf8a5 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailReminderService.kt @@ -0,0 +1,88 @@ +package com.ffii.fpsms.modules.common.mail.service + +import com.ffii.fpsms.modules.common.SettingNames +import com.ffii.fpsms.modules.common.mail.pojo.MailRequest +import com.ffii.fpsms.modules.common.mail.web.models.WorkHourRecords +import com.ffii.fpsms.modules.settings.service.SettingsService +import com.ffii.fpsms.modules.user.service.UserService +import jakarta.mail.internet.InternetAddress +import org.apache.commons.logging.Log +import org.apache.commons.logging.LogFactory +import org.springframework.scheduling.annotation.Scheduled +import org.springframework.stereotype.Service +import java.time.DayOfWeek +import java.time.LocalDate +import java.time.YearMonth +import java.time.format.DateTimeFormatter + +data class TableRow( + val staffId: String, + val name: String, + val missingDates: MutableList, +) + +@Service +open class MailReminderService( + val mailService: MailService, + val userService: UserService, + val settingsService: SettingsService, +) { + protected val logger: Log = LogFactory.getLog(javaClass) + private val FULLTIME = "FT" + private val PARTTIME = "PT" + private val dateFormat: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") + + private fun isSettingsConfigValid(): Boolean { + try { + val username = settingsService.findByName(SettingNames.MAIL_SMTP_USERNAME).orElseThrow().value + val pw = settingsService.findByName(SettingNames.MAIL_SMTP_USERNAME).orElseThrow().value + return !username.isNullOrEmpty() && !pw.isNullOrEmpty() + } catch (e: Error) { + return false + } + } + private fun createHTMLTable(naughtyList: MutableList): String { + val tableStarter = StringBuilder(" ") + val header = StringBuilder( + " " + + " " + + " " + + " " + + " " + ) + tableStarter.append(header) + for (per in naughtyList) { + tableStarter.append( + " " + + " " + + " " + + " " + + " " + ) + } + val footer = StringBuilder("
StaffIdNameMissing Dates
${per.staffId}${per.name}${per.missingDates.joinToString(", ")}
") + return tableStarter.toString() + } + + private fun createEmailRequest(content: String, emailTo: List) { +// val subject = settingsService.findByName(SettingNames.TIMESHEET_MAIL_SUBJECT).orElseThrow().value +// val template = settingsService.findByName(SettingNames.TIMESHEET_MAIL_TEMPLATE).orElseThrow().value +// val cc = settingsService.findByName(SettingNames.TIMESHEET_MAIL_CC).orElseThrow().value.split(",") +// val bcc = settingsService.findByName(SettingNames.TIMESHEET_MAIL_BCC).orElseThrow().value.split(",") + val mailRequest = MailRequest.Builder() +// .subject(subject) +// .templateContent(template) + .args( + mapOf( + Pair("date", content), + ) + ) + .addTo(emailTo) +// .addCc(cc) +// .addBcc(bcc) + .build() + val mailRequestList = mutableListOf() + mailRequestList += mailRequest + mailService.send(mailRequestList) + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailSenderService.kt b/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailSenderService.kt new file mode 100644 index 0000000..e8ea93b --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailSenderService.kt @@ -0,0 +1,47 @@ +package com.ffii.fpsms.modules.common.mail.service + +import com.ffii.fpsms.modules.common.MailSMTP +import com.ffii.fpsms.modules.settings.service.SettingsService +import org.springframework.mail.javamail.JavaMailSender +import org.springframework.mail.javamail.JavaMailSenderImpl +import org.springframework.stereotype.Service +import java.util.* + +@Service +open class MailSenderService(private val settingsService: SettingsService) { + private var sender: JavaMailSender? = null + private var mailConfigCachs: MailSMTP? = null + + open fun get(): JavaMailSender { + + val config = MailSMTP(settingsService) + + if (this.sender == null || (mailConfigCachs == null) || !config.equals(this.mailConfigCachs)) { + + this.mailConfigCachs = config + val sender = JavaMailSenderImpl() + + val props = Properties() + val auth = config.auth ?: false + if (auth) { + props["mail.smtp.timeout"] = "20000" + props["mail.smtp.connectiontimeout"] = "10000" + } + props["mail.smtp.auth"] = auth +// The below setting needs to be included when the SMTP has TLS Version +// props["mail.smtp.starttls.enable"] = "true" +// props["mail.smtp.ssl.protocols"] = "TLSv1.2" + + sender.host = config.host + sender.port = config.port!! + if (auth) { + sender.username = config.username + sender.password = config.password + } + sender.javaMailProperties = props + + this.sender = sender + } + return this.sender ?: JavaMailSenderImpl() + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailService.kt b/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailService.kt new file mode 100644 index 0000000..890ab00 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/common/mail/service/MailService.kt @@ -0,0 +1,215 @@ +package com.ffii.fpsms.modules.common.mail.service + +import com.ffii.core.exception.InternalServerErrorException +import com.ffii.core.utils.LocaleUtils +import com.ffii.fpsms.modules.common.ErrorCodes +import com.ffii.fpsms.modules.common.SettingNames +import com.ffii.fpsms.modules.common.mail.pojo.MailRequest +import com.ffii.fpsms.modules.common.mail.web.models.MailSave +import com.ffii.fpsms.modules.settings.entity.Settings +import com.ffii.fpsms.modules.settings.entity.SettingsRepository +import com.ffii.fpsms.modules.settings.service.SettingsService +import freemarker.cache.StringTemplateLoader +import freemarker.template.* +import jakarta.mail.MessagingException +import jakarta.mail.internet.InternetAddress +import org.apache.commons.logging.Log +import org.apache.commons.logging.LogFactory +import org.springframework.core.io.ByteArrayResource +import org.springframework.mail.javamail.MimeMessageHelper +import org.springframework.scheduling.annotation.Async +import org.springframework.security.crypto.password.PasswordEncoder +import org.springframework.stereotype.Service +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils +import java.io.IOException +import java.text.ParseException +import java.util.* + +@Service +open class MailService( + private val mailSenderService: MailSenderService, + private val freemarkerConfig: Configuration, + private val settingsService: SettingsService, + private val passwordEncoder: PasswordEncoder, + private val settingsRepository: SettingsRepository, +) { + protected val logger: Log = LogFactory.getLog(javaClass) + + @Throws( + MessagingException::class, + TemplateNotFoundException::class, + MalformedTemplateNameException::class, + ParseException::class, + IOException::class, + TemplateException::class + ) + open fun doSend(mailRequests: List, locale: Locale) { + + val sender = mailSenderService.get() + + for (mailRequest in mailRequests) { + val mimeMessage = sender.createMimeMessage() + + val helper = MimeMessageHelper(mimeMessage, true, "UTF-8") + mailRequest.subject?.let { helper.setSubject(it) } + + var template: Template? = null + if (mailRequest.template != null) { + template = try { + freemarkerConfig + .getTemplate((mailRequest.template + "_" + LocaleUtils.toLocaleStr(locale)) + ".ftl") + } catch (e: TemplateNotFoundException) { + freemarkerConfig.getTemplate(mailRequest.template + ".ftl") + } + } else { + // Create a FreeMarker configuration + val configuration = Configuration(Configuration.VERSION_2_3_32) + + // Create a template loader and add the template content + val templateLoader = StringTemplateLoader() + templateLoader.putTemplate("myTemplate", mailRequest.templateContent) + configuration.templateLoader = templateLoader + + try { + // Get the template by name + template = configuration.getTemplate("myTemplate") + } catch (e: IOException) { + // Handle any IO exceptions + } + } + + helper.setText( + FreeMarkerTemplateUtils.processTemplateIntoString(template!!, mailRequest.args), + true + ) + + val from: InternetAddress?; + if (mailRequest.from != null) { + helper.setFrom(mailRequest.from!!) + from = mailRequest.from + } else { + helper.setFrom(settingsService.getString(SettingNames.MAIL_SMTP_USERNAME)) + from = InternetAddress(settingsService.getString(SettingNames.MAIL_SMTP_USERNAME)) + } + + if (mailRequest.priority != null) helper.setPriority(mailRequest.priority!!) + if (mailRequest.replyTo != null) helper.setReplyTo(mailRequest.replyTo!!) + if (mailRequest.to.isNotEmpty()) helper.setTo( + mailRequest.to.toTypedArray() + ) + if (mailRequest.cc.isNotEmpty()) helper.setCc( + mailRequest.cc.toTypedArray() + ) + if (mailRequest.bcc.isNotEmpty()) helper.setBcc( + mailRequest.bcc.toTypedArray() + ) + + if (mailRequest.attachments.isNotEmpty()) { + for ((key, value) in mailRequest.attachments.entries) { + helper.addAttachment(key, ByteArrayResource(value)) + } + } + + if (from != null) { + sender.send(mimeMessage) + } + } + } + + @Throws(ParseException::class) + fun send(mailRequests: List, locale: Locale) { + try { + doSend(mailRequests, locale) + } catch (e: MessagingException) { + throw InternalServerErrorException(ErrorCodes.SEND_EMAIL_ERROR, e) + } catch (e: IOException) { + throw InternalServerErrorException(ErrorCodes.SEND_EMAIL_ERROR, e) + } catch (e: TemplateException) { + throw InternalServerErrorException(ErrorCodes.SEND_EMAIL_ERROR, e) + } + } + + @Throws(ParseException::class) + fun send(mailRequests: List) { + send(mailRequests, LocaleUtils.getLocale()) + } + + @Throws(ParseException::class) + fun send(mailRequest: MailRequest, locale: Locale) { + send(mutableListOf(mailRequest), locale) + } + + @Async + @Throws(ParseException::class) + open fun asyncSend(mailRequests: List, locale: Locale) { + try { + doSend(mailRequests, locale) + } catch (e: MessagingException) { + logger.error("send email error", e) + } catch (e: IOException) { + logger.error("send email error", e) + } catch (e: TemplateException) { + logger.error("send email error", e) + } + } + + @Async + @Throws(ParseException::class) + open fun asyncSend(mailRequest: MailRequest, locale: Locale) { + asyncSend(mutableListOf(mailRequest), locale) + } + + @Async + @Throws(ParseException::class) + open fun asyncSend(mailRequests: List) { + asyncSend(mailRequests, LocaleUtils.getLocale()) + } + + @Async + @Throws(ParseException::class) + open fun asyncSend(mailRequest: MailRequest) { + asyncSend(mutableListOf(mailRequest)) + } + + open fun saveMail(mailSave: MailSave): List { + // ------------------ save mail settings ------------------ // + val settings = mutableListOf() + + mailSave.settings.forEach { setting -> + val tempSetting = settingsRepository.findById(setting.id).orElseThrow() + settings += tempSetting.apply { + value = setting.value + } + } + + // ------------------ save timesheet mail details ------------------ // + val mailCc = settingsRepository.findByName("TIMESHEET.mail.cc").orElseThrow() + + settings += mailCc.apply { + value = mailSave.template.cc + } + + val mailBcc = settingsRepository.findByName("TIMESHEET.mail.bcc").orElseThrow() + + settings += mailBcc.apply { + value = mailSave.template.bcc + } + + val mailSubject = settingsRepository.findByName("TIMESHEET.mail.subject").orElseThrow() + + settings += mailSubject.apply { + value = mailSave.template.subject + } + + val mailTemplate = settingsRepository.findByName("TIMESHEET.mail.template").orElseThrow() + + settings += mailTemplate.apply { + value = mailSave.template.template + } + + // ------------------ save all ------------------ // + settingsRepository.saveAll(settings) + + return settings + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/common/mail/web/MailController.kt b/src/main/java/com/ffii/fpsms/modules/common/mail/web/MailController.kt new file mode 100644 index 0000000..06f8235 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/common/mail/web/MailController.kt @@ -0,0 +1,27 @@ +package com.ffii.fpsms.modules.common.mail.web + +import com.ffii.fpsms.modules.common.mail.service.MailReminderService +import com.ffii.fpsms.modules.common.mail.service.MailService +import com.ffii.fpsms.modules.common.mail.web.models.MailSave +import com.ffii.fpsms.modules.settings.entity.Settings +import com.ffii.fpsms.modules.settings.service.SettingsService +import jakarta.validation.Valid +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("/mails") +class MailController( + private val settingsService: SettingsService, + private val mailService: MailService, + private val mailReminderService: MailReminderService, +) { + @GetMapping("/setting") + fun mailSetting(): List { + return settingsService.findAllByCategory("MAIL") + } + + @PostMapping("/save") + fun saveMail(@Valid @RequestBody mailSave: MailSave): List { + return mailService.saveMail(mailSave) + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/common/mail/web/models/MailSave.kt b/src/main/java/com/ffii/fpsms/modules/common/mail/web/models/MailSave.kt new file mode 100644 index 0000000..b7b4736 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/common/mail/web/models/MailSave.kt @@ -0,0 +1,21 @@ +package com.ffii.fpsms.modules.common.mail.web.models + +data class Setting ( + val id: Long, + val name: String, + val value: String, + val category: String, + val type: String, +) + +data class Template ( + val cc: String?, + val bcc: String?, + val subject: String, + val template: String?, +) + +data class MailSave ( + val settings: List, + val template: Template +) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/common/mail/web/models/WorkHourRecords.kt b/src/main/java/com/ffii/fpsms/modules/common/mail/web/models/WorkHourRecords.kt new file mode 100644 index 0000000..c5b6b68 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/common/mail/web/models/WorkHourRecords.kt @@ -0,0 +1,9 @@ +package com.ffii.fpsms.modules.common.mail.web.models + +import java.time.LocalDate + +data class WorkHourRecords( + val staffId: Long, + val recordDate: LocalDate, + val hours: Double, +) diff --git a/src/main/java/com/ffii/fpsms/modules/settings/entity/SettingsRepository.java b/src/main/java/com/ffii/fpsms/modules/settings/entity/SettingsRepository.java index 05994c2..ed766af 100644 --- a/src/main/java/com/ffii/fpsms/modules/settings/entity/SettingsRepository.java +++ b/src/main/java/com/ffii/fpsms/modules/settings/entity/SettingsRepository.java @@ -1,5 +1,6 @@ package com.ffii.fpsms.modules.settings.entity; +import java.util.List; import java.util.Optional; import org.springframework.data.repository.query.Param; @@ -9,4 +10,6 @@ import com.ffii.core.support.AbstractRepository; public interface SettingsRepository extends AbstractRepository { Optional findByName(@Param("name") String name); + + List findAllByCategory(@Param("category") String category); } diff --git a/src/main/java/com/ffii/fpsms/modules/settings/service/SettingsService.java b/src/main/java/com/ffii/fpsms/modules/settings/service/SettingsService.java index d6637ad..6e43c34 100644 --- a/src/main/java/com/ffii/fpsms/modules/settings/service/SettingsService.java +++ b/src/main/java/com/ffii/fpsms/modules/settings/service/SettingsService.java @@ -5,6 +5,7 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import java.util.List; import java.util.Optional; import org.apache.commons.lang3.StringUtils; @@ -29,6 +30,10 @@ public class SettingsService extends AbstractIdEntityService findAllByCategory(String category) { + return this.repository.findAllByCategory(category); + } + public boolean validateType(String type, String value) { if (StringUtils.isBlank(type)) return true; diff --git a/src/main/resources/db/changelog/changes/20250527_01_cyril/01_update_mail_settings.sql b/src/main/resources/db/changelog/changes/20250527_01_cyril/01_update_mail_settings.sql new file mode 100644 index 0000000..0bdb3f1 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20250527_01_cyril/01_update_mail_settings.sql @@ -0,0 +1,13 @@ +-- liquibase formatted sql +-- changeset cyril:settings + +INSERT INTO settings (id,name,value,category,`type`) +VALUES (7,'MAIL.smtp.host','smtp.office365.com','MAIL','string'); +INSERT INTO settings (id,name,value,category,`type`) +VALUES (8,'MAIL.smtp.port','587','MAIL','integer'); +INSERT INTO settings (id,name,value,category,`type`) +VALUES (9,'MAIL.smtp.username','','MAIL','string'); +INSERT INTO settings (id,name,value,category,`type`) +VALUES (10,'MAIL.smtp.password','','MAIL','string'); +INSERT INTO settings (id,name,value,category,`type`) +VALUES (11,'MAIL.smtp.auth','false','MAIL','boolean');