Skip to content

Commit

Permalink
introduce donation-mail for online-usage
Browse files Browse the repository at this point in the history
  • Loading branch information
luechtdiode committed Feb 13, 2024
1 parent 2a0e5f0 commit 5f530e2
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 15 deletions.
4 changes: 4 additions & 0 deletions src/main/scala/ch/seidel/kutu/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ object Config extends KuTuSSLContext {
}

val bestenlisteSchwellwert: Double = if (config.hasPath("app.bestenlisteSchwellwert")) config.getDouble("app.bestenlisteSchwellwert") else 9.0
val donationLink: String = if (config.hasPath("DONATION_LINK")) config.getString("DONATION_LINK") else ""
val donationPrice: String = if (config.hasPath("DONATION_PRICE")) config.getString("DONATION_PRICE") else ""
val donationDonationBegin: String = if (config.hasPath("DONATION_BEGIN")) config.getString("DONATION_BEGIN") else ""

private val jwtConfig = config.getConfig("jwt")
private val appRemoteConfig = config.getConfig("app.remote")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ import ch.seidel.kutu.data.ResourceExchanger
import ch.seidel.kutu.domain._
import ch.seidel.kutu.http.Core.system
import ch.seidel.kutu.http.{EnrichedJson, JsonSupport}
import ch.seidel.kutu.renderer.RiegenBuilder
import ch.seidel.kutu.renderer.{MailTemplates, RiegenBuilder}
import io.prometheus.client
import io.prometheus.client.{Collector, CollectorRegistry}
import org.slf4j.LoggerFactory
import spray.json._

import java.time.{LocalDate, LocalDateTime, LocalTime}
import java.util.UUID
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.DurationInt
Expand Down Expand Up @@ -53,6 +54,8 @@ class CompetitionCoordinatorClientActor(wettkampfUUID: String) extends Persisten
private val wkPgmId = wettkampf.programmId
private val isDNoteUsed = wkPgmId != 20 && wkPgmId != 1
private val snapShotInterval = 100
private val donationDonationBegin = if (Config.donationDonationBegin.nonEmpty) LocalDate.parse(Config.donationDonationBegin) else LocalDate.of(2000,1,1)
private val donationActiv = donationDonationBegin.before(wettkampf.datum) && Config.donationLink.nonEmpty && Config.donationPrice.nonEmpty

private var wsSend: Map[Option[String], List[ActorRef]] = Map.empty
private var deviceWebsocketRefs: Map[String, ActorRef] = Map.empty
Expand Down Expand Up @@ -254,7 +257,9 @@ class CompetitionCoordinatorClientActor(wettkampfUUID: String) extends Persisten
ref ! NewLastResults(state.lastWertungen, state.lastBestenResults)

// system actions
case KeepAlive => wsSend.flatMap(_._2).foreach(ws => ws ! TextMessage("keepAlive"))
case KeepAlive =>
wsSend.flatMap(_._2).foreach(ws => ws ! TextMessage("keepAlive"))
checkDonation()

case MessageAck(txt) => if (txt.equals("keepAlive")) handleKeepAliveAck() else println(txt)

Expand Down Expand Up @@ -300,6 +305,24 @@ class CompetitionCoordinatorClientActor(wettkampfUUID: String) extends Persisten
case _ =>
}

private def checkDonation(): Unit = {
if (donationActiv && LocalDateTime.of(wettkampf.datum, LocalTime.of(7, 0, 0)).plusDays(2).isBefore(LocalDateTime.now()) && !state.completedflags.exists {
case DonationMailSent(_, _, _, wkid) if wkid == this.wettkampfUUID => true
case _ => false
}) {
val teilnehmer = getAllKandidatenWertungen(UUID.fromString(wettkampfUUID))
val results = teilnehmer.flatMap(k => k.wertungen.map(w => w.resultat.endnote)).sum
if (results > 0) {
val price = BigDecimal(Config.donationPrice)
val donationLink = Config.donationLink
KuTuMailerActor.send(
MailTemplates.createDonateMail(wettkampf, donationLink, teilnehmer.size, price)
)
}
handleEvent(DonationMailSent(0, BigDecimal(0), "", wettkampfUUID))
}
}

private def cleanupWebsocketRefs(stoppedWebsocket: ActorRef): Unit = {
deviceWebsocketRefs = deviceWebsocketRefs.filter(x => x._2 != stoppedWebsocket)
val durchgaenge = wsSend
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ sealed trait RegistrationEvent extends RegistrationProtokoll

case class CompetitionCreated(wettkampfUUID: String, link: String) extends RegistrationAction
case class ApproveEMail(wettkampfUUID: String, mail: String) extends RegistrationAction
case class EMailApproved(message: String) extends RegistrationEvent
case class EMailApproved(message: String, success: Boolean) extends RegistrationEvent
case class RegistrationChanged(wettkampfUUID: String) extends RegistrationAction

case class RegistrationResync(wettkampfUUID: String) extends RegistrationAction
Expand Down Expand Up @@ -128,12 +128,17 @@ class CompetitionRegistrationClientActor(wettkampfUUID: String) extends Persiste
case ApproveEMail(_, mail) =>
val notificationEMail = readWettkampf(wettkampfUUID).notificationEMail
if (notificationEMail.equals(mail)) {
syncState = syncState.approved
sender() ! EMailApproved(s"EMail ${mail} erfolgreich verifiziert")
log.info(s"EMail approved ${mail}")
if (!syncState.emailApproved) {
syncState = syncState.approved
sender() ! EMailApproved(s"EMail ${mail} erfolgreich verifiziert", success = true)
log.info(s"EMail approved ${mail}")
} else {
sender() ! EMailApproved(s"EMail ${mail} wurde bereits verifiziert", success = true)
log.info(s"EMail ${mail} was already approved")
}
}
else {
sender() ! EMailApproved(s"EMail ${mail} nicht erfolgreich verifiziert.")
sender() ! EMailApproved(s"EMail ${mail} nicht erfolgreich verifiziert.", success = false)
log.info(s"EMail not approved ${mail} - not matching with competitions notificationEMail: $notificationEMail")
}

Expand Down
21 changes: 15 additions & 6 deletions src/main/scala/ch/seidel/kutu/akka/CompetitionState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ case class CompetitionState (
lastWertungen: Map[String, WertungContainer] = Map.empty,
bestenResults: Map[String, WertungContainer] = Map.empty,
lastBestenResults: Map[String, WertungContainer] = Map.empty,
lastSequenceId: Long = Long.MinValue
lastSequenceId: Long = Long.MinValue,
completedflags: List[KutuAppEvent] = List.empty
) {

def updated(event: KutuAppEvent, isDNoteUsed: Boolean): CompetitionState = event match {
Expand All @@ -26,7 +27,8 @@ case class CompetitionState (
.filter(fds => encodeURIComponent(fds.durchgang) != encodeURIComponent(eventDurchgangStarted.durchgang)),
finishedDurchgaenge - eventDurchgangStarted.durchgang,
startStopEvents :+ eventDurchgangStarted,
lastWertungen, bestenResults, lastBestenResults, lastSequenceId
lastWertungen, bestenResults, lastBestenResults, lastSequenceId,
completedflags
)
}

Expand All @@ -39,7 +41,8 @@ case class CompetitionState (
finishedDurchgangSteps,
finishedDurchgaenge + eventDurchgangFinished.durchgang,
startStopEvents :+ eventDurchgangFinished,
Map.empty, bestenResults, lastBestenResults, lastSequenceId
Map.empty, bestenResults, lastBestenResults, lastSequenceId,
completedflags
)
}

Expand All @@ -55,17 +58,22 @@ case class CompetitionState (
finishedDurchgangSteps + fds,
finishedDurchgaenge,
startStopEvents,
lastWertungen, bestenResults, lastBestenResults, lastSequenceId
lastWertungen, bestenResults, lastBestenResults, lastSequenceId,
completedflags
)

case dms: DonationMailSent =>
copy(completedflags = completedflags :+ dms)

case _: DurchgangStepFinished =>
if (lastWertungen.nonEmpty) {
CompetitionState(
startedDurchgaenge,
finishedDurchgangSteps,
finishedDurchgaenge,
startStopEvents,
Map.empty, Map.empty, bestenResults, lastSequenceId
Map.empty, Map.empty, bestenResults, lastSequenceId,
completedflags
)
} else {
this
Expand Down Expand Up @@ -97,7 +105,8 @@ case class CompetitionState (
finishedDurchgaenge,
startStopEvents,
lastWertungen.updated(wertungContainer.wertung.wettkampfdisziplinId.toString(), wertungContainer),
putBestenResult(wertungContainer), lastBestenResults, lastSequenceId + 1
putBestenResult(wertungContainer), lastBestenResults, lastSequenceId + 1,
completedflags
)

}
1 change: 1 addition & 0 deletions src/main/scala/ch/seidel/kutu/akka/Messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ case class AthletMovedInWettkampf(athlet: AthletView, wettkampfUUID: String, pgm
case class AthletsAddedToWettkampf(athlet: List[AthletView], wettkampfUUID: String, pgmId: Long, team: Int) extends KutuAppEvent
case class DurchgangChanged(durchgang: String, wettkampfUUID: String, athlet: AthletView) extends KutuAppEvent
case class ScoresPublished(scoreId: String, title: String, query: String, published: Boolean, wettkampfUUID: String) extends KutuAppEvent
case class DonationMailSent(teilnehmer: Int, price: BigDecimal, donationLink: String, wettkampfUUID: String) extends KutuAppEvent
case class GeraeteRiegeList(list: List[GeraeteRiege], wettkampfUUID: String) extends KutuAppEvent

case class NewLastResults(results: Map[String, WertungContainer], lastTopResults: Map[String, WertungContainer]) extends KutuAppEvent
Expand Down
5 changes: 3 additions & 2 deletions src/main/scala/ch/seidel/kutu/http/RegistrationRoutes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,9 @@ trait RegistrationRoutes extends SprayJsonSupport with JwtSupport with JsonSuppo
parameters(Symbol("mail").?) {
case Some(mail) =>
complete{
CompetitionRegistrationClientActor.publish(ApproveEMail(wettkampf.uuid.get, mail), clientId).map{ _ =>
s"${wettkampf.easyprint} EMail ${mail} verifiziert"
CompetitionRegistrationClientActor.publish(ApproveEMail(wettkampf.uuid.get, mail), clientId).map{
case EMailApproved(message, success) =>
s"${wettkampf.easyprint}: $message"
}
}
case _ =>
Expand Down
73 changes: 73 additions & 0 deletions src/main/scala/ch/seidel/kutu/renderer/MailTemplates.scala
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,79 @@ object MailTemplates {
wettkampf.notificationEMail)
}

def createDonateMail(wettkampf: Wettkampf, link: String, teilnehmer: Int, preisPerTn: BigDecimal): Mail = {
val logodir = new java.io.File(Config.homedir + "/" + encodeFileName(wettkampf.easyprint))
val logofile = PrintUtil.locateLogoFile(logodir)
val logoHtml = if (logofile.exists()) s"""<img class=logo src="${logofile.imageSrcForWebEngine}" title="Logo"/>""" else ""
val imageData = toQRCodeImage(link)
MultipartMail(s"Spendenaufruf nach Durchführung ${wettkampf.easyprint}",
s"""Hallo ${wettkampf.notificationEMail}
|
|Der Wettkampf '${wettkampf.easyprint}' ist mit $teilnehmer Teilnehmer/-Innen zu Ende gegangen.
|
|Sofern die KuTu Wettkampf-App Eure Erwartungen erfüllen konnte, wäre sie für die Deckung der Betriebskosten um
|einen finanziellen Beitrag sehr dankbar.
|
|In der aktuellen Situation würden z.B. CHF ${preisPerTn.setScale(2)} pro Teilnehmer/-In den vom Server verwendeten
|Strombedarf decken.
|
|Das würde in diesem Fall ein ** Gesamtbetrag von CHF ${(preisPerTn * teilnehmer).setScale(2)} ** ausmachen.
|
|Die Spende kann über folgenden Link getätigt werden (bitte dort den Betrag selbst anpassen und den
|Wettkampfnamen eintragen):
|$link
|
|
|Besten Dank für das Vertrauen und sportliche Grüsse,
|Die Kutuapp
|""".stripMargin,
s"""<html>$htmlhead<body>
| <div class=textbody>
| <div class=headline>
| $logoHtml
| <div class=title><h4>${escaped(wettkampf.easyprint)}</h4></div>
| <div class=subtitle>Spendenaufruf nach der Online-Durchführung des Wettkampfs</br></div>
| </div>
| <div class="textblock">
| <h4>Hallo ${escaped(wettkampf.notificationEMail)}</h4>
| <p>
| Der Wettkampf '${wettkampf.easyprint}' ist mit $teilnehmer Teilnehmer/-Innen zu Ende gegangen.
| </p>
| <p>
| Sofern die KuTu Wettkampf-App Eure Erwartungen erfüllen konnte, wäre sie für die Deckung der Betriebskosten um
| einen finanziellen Beitrag sehr dankbar.
| </p>
| <p>
| In der aktuellen Situation würden z.B. CHF ${preisPerTn.setScale(2)} pro Teilnehmer/-In den vom Server verwendeten
| Strombedarf decken. Das würde in diesem Fall ein <b>Gesamtbetrag von CHF ${(preisPerTn * teilnehmer).setScale(2)} </b> ausmachen.
| </p>
| <p>
| Die Spende kann über folgenden Link getätigt werden <em>(bitte dort den Betrag selbst anpassen und den
| Wettkampfnamen eintragen)</em>:
| </p>
| <div class="catchme">
| <a href='${link}'>
| <h2>Spenden Link für die Online-Benutzung der Kutu Wettkampf-App</h2>
| <img title='${link}' width='300px' height='300px' src='${imageData}'>
| </a><br>
| <a href='${link}'>${link}</a>
| </div>
| <p>
| Besten Dank für das Vertrauen und sportliche Grüsse,<br>
| die KuTu-App
| </p>
| <hr>
| <p>
| <b>PS:</b> <em>Dies ist eine automatisch versendete EMail. Bitte nicht auf diese Mail antworten.</em>
| </p>
| </div>
| </div>
|</body></html>""".stripMargin,
wettkampf.notificationEMail)
}



def createSyncNotificationMail(wettkampf: Wettkampf, syncActions: List[SyncAction], changedJudges: List[JudgeRegistration], removedJudges: List[JudgeRegistration], addedJudges: List[JudgeRegistration]): Mail = {
val logodir = new java.io.File(Config.homedir + "/" + encodeFileName(wettkampf.easyprint))
val logofile = PrintUtil.locateLogoFile(logodir)
Expand Down

0 comments on commit 5f530e2

Please sign in to comment.