Skip to content

Commit

Permalink
vastaanottajien sorttaus tiloittain ja sivutus wip
Browse files Browse the repository at this point in the history
  • Loading branch information
marjakari committed Feb 6, 2024
1 parent 2cfe242 commit 659c0a0
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 53 deletions.
24 changes: 12 additions & 12 deletions integraatio/src/test/scala/fi/oph/viestinvalitys/LocalUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,12 @@ object LocalUtil {
"omistaja",
"hakemuspalvelu",
Option.apply("0.1.2.3"),
Kontakti(Option.apply("Testi Virkailija"+counter), "testi.virkailija"+counter+"@oph.fi"),
Option.apply("no-reply@opintopolku.fi"),
Kontakti(Option.apply("Testi Virkailija"+counter), "noreply@opintopolku.fi"),
Option.apply("noreply@opintopolku.fi"),
Prioriteetti.NORMAALI,
365
)
// viestit lähetystunnuksella
// räätälöidyt viestit lähetystunnuksella, yksi vastaanottaja per viesti
Range(0, 25).map(viestinro => {
kantaOperaatiot.tallennaViesti("Viestin testiotsikko " + viestinro,
"Viestin sisältö " + viestinro,
Expand All @@ -197,14 +197,14 @@ object LocalUtil {
"omistaja")
})
})
// lähetys jossa samalla viestillä useita vastaanottajia
// lähetys massaviestillä jossa samalla viestillä useita vastaanottajia
val lahetys2 = kantaOperaatiot.tallennaLahetys(
"Massalähetysotsikko",
"omistaja",
"hakemuspalvelu",
Option.apply("0.1.2.3"),
Kontakti(Option.apply("Joku Virkailija"), "joku.virkailija@oph.fi"),
Option.apply("no-reply@opintopolku.fi"),
Kontakti(Option.apply("Joku Virkailija"), "hakemuspalvelu@ointopolku.fi"),
Option.apply("noreply@opintopolku.fi"),
Prioriteetti.NORMAALI,
365
)
Expand All @@ -231,20 +231,20 @@ object LocalUtil {
"omistaja",
"osoitepalvelu",
Option.apply("0.1.2.3"),
Kontakti(Option.apply("Testi Virkailija"), "testi.virkailija@oph.fi"),
Option.apply("no-reply@opintopolku.fi"),
Kontakti(Option.apply("Testi Virkailija"), "osoitepalvelu@opintopolku.fi"),
Option.apply("noreply@opintopolku.fi"),
Prioriteetti.NORMAALI,
365
)
// viesti ilman lähetystunnusta
kantaOperaatiot.tallennaViesti("Tärkeää asiaa",
"Tärkeä sisältö",
kantaOperaatiot.tallennaViesti("Yksittäinen viesti",
"Tämä on yksittäinen viesti muutamalla vastaanottajalla",
SisallonTyyppi.TEXT,
Set(Kieli.FI),
Map.empty,
Option.apply("0.1.2.3"),
Option.apply(Kontakti(Option.apply("Testi Virkailija"), "testi.virkailija@oph.fi")),
Option.apply("no-reply@opintopolku.fi"),
Option.apply(Kontakti(Option.apply("Testi Virkailija"), "testipalvelu@opintopolku.fi")),
Option.apply("noreply@opintopolku.fi"),
Range(0, 3).map(suffix => Kontakti(Option.apply("Vastaanottaja" + suffix), "vastaanottaja" + suffix + "@example.com")),
Seq.empty,
Option.apply("testipalvelu"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package fi.oph.viestinvalitys.raportointi.resource

import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.ObjectMapper
import fi.oph.viestinvalitys.business.{KantaOperaatiot, Kayttooikeus}
import fi.oph.viestinvalitys.business.{KantaOperaatiot, Kayttooikeus, RaportointiTila, Vastaanottaja, raportointiTilat}
import fi.oph.viestinvalitys.raportointi.resource.RaportointiAPIConstants.*
import fi.oph.viestinvalitys.raportointi.security.{SecurityConstants, SecurityOperaatiot}
import fi.oph.viestinvalitys.util.{DbUtil, LogContext}
Expand Down Expand Up @@ -89,7 +89,8 @@ case class VastaanottajaResponse(
@JsonInclude(JsonInclude.Include.NON_ABSENT)
case class VastaanottajatSuccessResponse(
@BeanProperty vastaanottajat: java.util.List[VastaanottajaResponse],
@BeanProperty seuraavat: Optional[String],
@BeanProperty seuraavatAlkaen: Optional[String],
@BeanProperty viimeisenTila: Optional[String],
) extends VastaanottajatResponse

case class VastaanottajatFailureResponse(
Expand All @@ -104,7 +105,7 @@ case class VastaanottajatFailureResponse(
"liitetään luomisen yhteydessä lähetykseen, joko erikseen tai automaattisesti luotuun.")
class LahetysResource {

val LOG = LoggerFactory.getLogger(classOf[LahetysResource]);
val LOG = LoggerFactory.getLogger(classOf[LahetysResource])

@GetMapping(
path = Array(GET_LAHETYKSET_LISTA_PATH),
Expand All @@ -125,7 +126,6 @@ class LahetysResource {
request: HttpServletRequest): ResponseEntity[PalautaLahetyksetResponse] =
val securityOperaatiot = new SecurityOperaatiot
val kantaOperaatiot = new KantaOperaatiot(DbUtil.database)
val emailRegex = "^[^\\s,@]+@(([a-zA-Z\\-0-9])+\\.)+([a-zA-Z\\-0-9]){2,}$".r
try
Right(None)
.flatMap(_ =>
Expand All @@ -138,16 +138,15 @@ class LahetysResource {
// validoidaan parametrit
val alkaenAika = ParametriUtil.asInstant(alkaen)
val enintaanInt = ParametriUtil.asInt(enintaan)

val vastaanottajaValidEmail = ParametriUtil.asValidEmail(vastaanottajanEmail)
val virheet = Some(Seq.empty.asInstanceOf[Seq[String]])
.map(virheet =>
if (alkaen.isPresent && alkaenAika.isEmpty) virheet.appended(RaportointiAPIConstants.ALKAEN_AIKA_TUNNISTE_INVALID) else virheet)
.map(virheet =>
if (enintaan.isPresent && (enintaanInt.isEmpty || enintaanInt.get < LAHETYKSET_ENINTAAN_MIN || enintaanInt.get > LAHETYKSET_ENINTAAN_MAX))
virheet.appended(LAHETYKSET_ENINTAAN_INVALID) else virheet)
.map(virheet =>
if (vastaanottajanEmail.isPresent && !emailRegex.matches(vastaanottajanEmail.get()))
virheet.appended(VASTAANOTTAJA_INVALID) else virheet)
if (vastaanottajanEmail.isPresent && vastaanottajaValidEmail.isEmpty) virheet.appended(VASTAANOTTAJA_INVALID) else virheet)
.get
if (!virheet.isEmpty)
Left(ResponseEntity.status(HttpStatus.BAD_REQUEST).body(PalautaLahetyksetFailureResponse(virheet.asJava)))
Expand Down Expand Up @@ -258,23 +257,25 @@ class LahetysResource {
* Hakutuloksiin ryhmitellään ensin kaikki virhetilassa olevat, sitten kaikki keskeneräiset ja lopuksi lähetetyt.
* Sivutuksessa täytyy huomioida, että tilat päivittyvät
* @param lahetysTunniste
* @param alkaen
* @param enintaan
* @param request
* @param alkaen sähköposti sivutusta varten
* @param sivutusTila missä tilassa olevia sivutetaan
* @param enintaan sivutuksen koko
* @param tila epaonnistui / kesken / valmis
* @param vastaanottaja
* @return
*/
def lueVastaanottajat(
@PathVariable(LAHETYSTUNNISTE_PARAM_NAME) lahetysTunniste: String,
@RequestParam(name = ALKAEN_PARAM_NAME, required = false) alkaen: Optional[String],
@RequestParam(name = SIVUTUS_TILA_PARAM_NAME, required = false) sivutustila: Optional[String],
@RequestParam(name = ENINTAAN_PARAM_NAME, required = false) enintaan: Optional[String],
@RequestParam(name = TILA_PARAM_NAME, required = false) tila: Optional[String],
@RequestParam(name = VASTAANOTTAJA_PARAM_NAME, required = false) vastaanottajanEmail: Optional[String],
request: HttpServletRequest
): ResponseEntity[VastaanottajatResponse] =
val securityOperaatiot = new SecurityOperaatiot
val kantaOperaatiot = new KantaOperaatiot(DbUtil.database)

// TODO kursorisivutus,
// niputa epäonnistuneet ja kesken tilat
// träkkää viimeisen tila kesken/valmis
LogContext(lahetysTunniste = lahetysTunniste)(() =>
try
Right(None)
Expand All @@ -285,23 +286,38 @@ class LahetysResource {
else
Right(None))
.flatMap(_ =>
// validoidaan parametrit
// validoidaan parametrit TODO tyypitä ja refaktoroi
val uuid = ParametriUtil.asUUID(lahetysTunniste)
val alkaenUuid = ParametriUtil.asUUID(alkaen)
val alkaenValidEmail = ParametriUtil.asValidEmail(alkaen)
val enintaanInt = ParametriUtil.asInt(enintaan)
val vastaanottajaValidEmail = ParametriUtil.asValidEmail(vastaanottajanEmail)
val raportointiTila = ParametriUtil.asValidRaportointitila(tila)
val sivutustilaValid = ParametriUtil.asValidRaportointitila(sivutustila)

val virheet = Some(Seq.empty.asInstanceOf[Seq[String]])
.map(virheet =>
if (uuid.isEmpty) virheet.appended(RaportointiAPIConstants.LAHETYSTUNNISTE_INVALID) else virheet)
.map(virheet =>
if (alkaen.isPresent && alkaenUuid.isEmpty) virheet.appended(RaportointiAPIConstants.ALKAEN_UUID_TUNNISTE_INVALID)
if (alkaen.isPresent && alkaenValidEmail.isEmpty) virheet.appended(RaportointiAPIConstants.ALKAEN_EMAIL_TUNNISTE_INVALID)
else virheet)
.map(virheet =>
if (enintaan.isPresent &&
(enintaanInt.isEmpty || enintaanInt.get < VASTAANOTTAJAT_ENINTAAN_MIN || enintaanInt.get > VASTAANOTTAJAT_ENINTAAN_MAX))
virheet.appended(ENINTAAN_INVALID)
else virheet).get

virheet.appended(VASTAANOTTAJAT_ENINTAAN_INVALID)
else virheet)
.map(virheet =>
if (vastaanottajanEmail.isPresent && vastaanottajaValidEmail.isEmpty)
virheet.appended(VASTAANOTTAJA_INVALID)
else virheet)
.map(virheet =>
if (tila.isPresent && raportointiTila.isEmpty)
virheet.appended(TILA_INVALID)
else virheet)
.map(virheet =>
if (sivutustila.isPresent && sivutustilaValid.isEmpty)
virheet.appended(SIVUTUS_TILA_INVALID)
else virheet)
.get
if (!virheet.isEmpty)
Left(ResponseEntity.status(HttpStatus.BAD_REQUEST).body(VastaanottajatFailureResponse(virheet.asJava)))
else
Expand All @@ -320,27 +336,34 @@ class LahetysResource {
else
Right(lahetys))
.map(lahetys =>
val alkaenUuid = ParametriUtil.asUUID(alkaen)
val enintaanInt = ParametriUtil.asInt(enintaan)
// TODO vaihda uuid->sposti
val enintaanInt = ParametriUtil.asInt(enintaan).getOrElse(VASTAANOTTAJAT_ENINTAAN_DEFAULT)
// TODO tee tyylikkäämmin
// haetaan aina epäonnistuneet
val alkaenValidEmail = ParametriUtil.asValidEmail(alkaen)
val epaonnistuneet = kantaOperaatiot.haeLahetyksenVastaanottajia(lahetys.tunniste, Option.empty, Option.empty, Option.apply("epaonnistui"), securityOperaatiot.getKayttajanOikeudet())
val vastaanottajat = kantaOperaatiot.haeLahetyksenVastaanottajia(lahetys.tunniste, Option.empty, Option.apply(enintaanInt.getOrElse(VASTAANOTTAJAT_ENINTAAN_DEFAULT)), Option.empty, securityOperaatiot.getKayttajanOikeudet())
val seuraavatLinkki = {
if (vastaanottajat.isEmpty || kantaOperaatiot.haeLahetyksenVastaanottajia(lahetys.tunniste, Option.apply(vastaanottajat.last.kontakti.sahkoposti), Option.apply(1), Option.empty,securityOperaatiot.getKayttajanOikeudet()).isEmpty)
var kesken: Seq[Vastaanottaja] = Seq.empty
var valmiit: Seq[Vastaanottaja] = Seq.empty
// sivutuksessa seuraavana on valmiit lähetykset, ei haeta keskeneräisiä
if (sivutustila.isPresent && sivutustila.equals("valmis"))
valmiit = kantaOperaatiot.haeLahetyksenVastaanottajia(lahetys.tunniste, alkaenValidEmail, Option.apply(enintaanInt), Option.apply("valmis"), securityOperaatiot.getKayttajanOikeudet())
else
kesken = kantaOperaatiot.haeLahetyksenVastaanottajia(lahetys.tunniste, alkaenValidEmail, Option.apply(enintaanInt), Option.apply("kesken"), securityOperaatiot.getKayttajanOikeudet())
// jos sivu ei ole täynnä keskeneräisistä, haetaan valmiita
if (kesken.size < enintaanInt)
valmiit = kantaOperaatiot.haeLahetyksenVastaanottajia(lahetys.tunniste, Option.empty, Option.apply(enintaanInt), Option.apply("valmis"), securityOperaatiot.getKayttajanOikeudet())
val vastaanottajat = epaonnistuneet++kesken++valmiit
val viimeisenTila = ParametriUtil.getRaportointiTila(vastaanottajat.last.tila)
val seuraavatAlkaen = {
if (vastaanottajat.isEmpty || kantaOperaatiot.haeLahetyksenVastaanottajia(lahetys.tunniste, Option.apply(vastaanottajat.last.kontakti.sahkoposti), Option.apply(1), viimeisenTila,securityOperaatiot.getKayttajanOikeudet()).isEmpty)
Optional.empty
else
val host = s"https://${request.getServerName}"
val port = s"${if (request.getServerPort != 443) ":" + request.getServerPort else ""}"
val path = s"${RaportointiAPIConstants.GET_VASTAANOTTAJAT_PATH.replace(RaportointiAPIConstants.LAHETYSTUNNISTE_PARAM_PLACEHOLDER, lahetysTunniste)}"
val alkaenParam = s"?${ALKAEN_PARAM_NAME}=${vastaanottajat.last.tunniste}"
val enintaanParam = enintaan.map(v => s"&${ENINTAAN_PARAM_NAME}=${v}").orElse("")
Optional.of(host + port + path + alkaenParam + enintaanParam)
Optional.of(vastaanottajat.last.kontakti.sahkoposti)
}

ResponseEntity.status(HttpStatus.OK).body(VastaanottajatSuccessResponse(
(epaonnistuneet++vastaanottajat).map(vastaanottaja => VastaanottajaResponse(vastaanottaja.tunniste.toString,
vastaanottajat.map(vastaanottaja => VastaanottajaResponse(vastaanottaja.tunniste.toString,
Optional.ofNullable(vastaanottaja.kontakti.nimi.getOrElse(null)), vastaanottaja.kontakti.sahkoposti,
vastaanottaja.viestiTunniste.toString, vastaanottaja.tila.toString)).asJava, seuraavatLinkki)))
vastaanottaja.viestiTunniste.toString, vastaanottaja.tila.toString)).asJava, seuraavatAlkaen, Optional.of(viimeisenTila.get))))
.fold(e => e, r => r).asInstanceOf[ResponseEntity[VastaanottajatResponse]]
catch
case e: Exception =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ object RaportointiAPIConstants {

final val GET_VASTAANOTTAJAT_PATH = GET_LAHETYS_PATH + "/vastaanottajat"
final val ALKAEN_PARAM_NAME = "alkaen"
final val SIVUTUS_TILA_PARAM_NAME = "sivutustila"
final val ENINTAAN_PARAM_NAME = "enintaan"
final val TILA_PARAM_NAME = "tila"
final val VASTAANOTTAJA_PARAM_NAME = "vastaanottaja"

final val VIESTIT_PATH = VERSIONED_RAPORTOINTI_API_PREFIX + "/viestit"
Expand Down Expand Up @@ -66,21 +68,25 @@ object RaportointiAPIConstants {
final val VASTAANOTTAJAT_ENINTAAN_MAX = VASTAANOTTAJAT_ENINTAAN_MAX_STR.toInt
final val VASTAANOTTAJAT_ENINTAAN_DEFAULT = VASTAANOTTAJAT_ENINTAAN_DEFAULT_STR.toInt
final val VASTAANOTTAJAT_ENINTAAN_DEFAULT_STR = "256"
final val emailRegex = "^[^\\s,@]+@(([a-zA-Z\\-0-9])+\\.)+([a-zA-Z\\-0-9]){2,}$".r

/**
* Virhetilanteisiin liittyvät vakiot
*/
final val LAHETYS_LUKEMINEN_EPAONNISTUI = "Lähetyksen lukeminen epäonnistui"
final val LAHETYKSET_LUKEMINEN_EPAONNISTUI = "Lähetysten lukeminen epäonnistui"
final val VIESTIT_LUKEMINEN_EPAONNISTUI = "Viestien lukeminen epäonnistui"
final val VIESTI_LUKEMINEN_EPAONNISTUI = "Viestin lukeminen epäonnistui"
final val VASTAANOTTAJAT_LUKEMINEN_EPAONNISTUI = "Vastaanottajien lukeminen epäonnistui"

final val VIESTITUNNISTE_INVALID = "Tunniste ei ole muodoltaan validi uuid"
final val LAHETYSTUNNISTE_INVALID = "Lahetystunniste ei ole muodoltaan validi uuid"

final val ALKAEN_UUID_TUNNISTE_INVALID = ALKAEN_PARAM_NAME + "-parametri: Tunniste ei ole muodoltaan validi uuid"
final val ENINTAAN_INVALID = ENINTAAN_PARAM_NAME + "-parametri: Arvon pitää olla numero väliltä " + VASTAANOTTAJAT_ENINTAAN_MIN_STR + "-" + VASTAANOTTAJAT_ENINTAAN_MAX_STR
final val ALKAEN_EMAIL_TUNNISTE_INVALID = ALKAEN_PARAM_NAME + "-parametri: Tunniste ei ole muodoltaan validi sähköpostiosoite"
final val VASTAANOTTAJAT_ENINTAAN_INVALID = ENINTAAN_PARAM_NAME + "-parametri: Arvon pitää olla numero väliltä " + VASTAANOTTAJAT_ENINTAAN_MIN_STR + "-" + VASTAANOTTAJAT_ENINTAAN_MAX_STR
final val ALKAEN_AIKA_TUNNISTE_INVALID = ALKAEN_PARAM_NAME + "-parametri: Tunniste ei ole muodoltaan validi aikaleima"
final val LAHETYKSET_ENINTAAN_INVALID = ENINTAAN_PARAM_NAME + "-parametri: Arvon pitää olla numero väliltä " + LAHETYKSET_ENINTAAN_MIN_STR + "-" + LAHETYKSET_ENINTAAN_MAX_STR
final val VASTAANOTTAJA_INVALID = VASTAANOTTAJA_PARAM_NAME + "-parametri: Tunniste ei ole validi sähköposti"
final val VASTAANOTTAJA_INVALID = VASTAANOTTAJA_PARAM_NAME + "-parametri: Tunniste ei ole validi sähköpostiosoite"
final val TILA_INVALID = TILA_PARAM_NAME + "-parametri: Tunniste ei ole validi vastaanoton tila"
final val SIVUTUS_TILA_INVALID = SIVUTUS_TILA_PARAM_NAME + "-parametri: Tunniste ei ole validi vastaanoton tila"

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package fi.oph.viestinvalitys.raportointi.resource

import fi.oph.viestinvalitys.business.{RaportointiTila, VastaanottajanTila, raportointiTilat}
import fi.oph.viestinvalitys.raportointi.resource.RaportointiAPIConstants.emailRegex

import java.time.Instant
import java.util.{Optional, UUID}
import scala.jdk.CollectionConverters.*
Expand Down Expand Up @@ -37,5 +40,34 @@ object ParametriUtil {
Option.apply(Instant.parse(parametri.get))
catch
case e: Exception => Option.empty

def asValidEmail(parametri: Optional[String]): Option[String] =
if (!parametri.isPresent || !RaportointiAPIConstants.emailRegex.matches(parametri.get()))
Option.empty
else
Option.apply(parametri.get())

def asValidRaportointitila(parametri: Optional[String]): Option[String] =
// TODO tee fiksummin
if (!parametri.isPresent || !parametri.equals(RaportointiTila.epaonnistui) || !parametri.equals(RaportointiTila.kesken) || !parametri.equals(RaportointiTila.valmis))
Option.empty
else
Option.apply(parametri.get())

def valmis(p: VastaanottajanTila): Boolean =
raportointiTilat.valmiit.filter(tila => p.equals(tila)).size > 0

def kesken(p: VastaanottajanTila): Boolean =
raportointiTilat.kesken.filter(tila => p.equals(tila)).size > 0

def epaonnistui(p: VastaanottajanTila): Boolean =
raportointiTilat.epaonnistuneet.filter(tila => p.equals(tila)).size > 0
def getRaportointiTila(tila: VastaanottajanTila): Option[String] =
tila match
case t if valmis(t) => Option.apply("valmis")
case t if kesken(t) => Option.apply("kesken")
case t if epaonnistui(t) => Option.apply("epaonnistui")
case _ => Option.empty

}

Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ case class Liite(tunniste: UUID, nimi: String, contentType: String, koko: Int, o
enum VastaanottajanTila:
case SKANNAUS, ODOTTAA, LAHETYKSESSA, VIRHE, LAHETETTY, SEND, DELIVERY, BOUNCE, COMPLAINT, REJECT, DELIVERYDELAY

enum RaportointiTila:
case epaonnistui, kesken, valmis

case object raportointiTilat {
val epaonnistuneet = Seq(VastaanottajanTila.VIRHE, VastaanottajanTila.BOUNCE, VastaanottajanTila.COMPLAINT, VastaanottajanTila.REJECT)
val kesken = Seq(VastaanottajanTila.SKANNAUS, VastaanottajanTila.ODOTTAA, VastaanottajanTila.LAHETYKSESSA, VastaanottajanTila.LAHETETTY, VastaanottajanTila.SEND, VastaanottajanTila.DELIVERYDELAY)
val valmiit = Seq(VastaanottajanTila.DELIVERY)
val epaonnistuneet = Set(VastaanottajanTila.VIRHE, VastaanottajanTila.BOUNCE, VastaanottajanTila.COMPLAINT, VastaanottajanTila.REJECT)
val kesken = Set(VastaanottajanTila.SKANNAUS, VastaanottajanTila.ODOTTAA, VastaanottajanTila.LAHETYKSESSA, VastaanottajanTila.LAHETETTY, VastaanottajanTila.SEND, VastaanottajanTila.DELIVERYDELAY)
val valmiit = Set(VastaanottajanTila.DELIVERY)
}

case class Kontakti(nimi: Option[String], sahkoposti: String)
Expand Down
Loading

0 comments on commit 659c0a0

Please sign in to comment.