Skip to content
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

Changement du type pour le Mandat #815

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions app/controllers/ApplicationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import java.time.{LocalDate, ZonedDateTime}
import java.util.UUID

import actions._
import cats.implicits.catsSyntaxTuple2Semigroupal
import cats.implicits.{catsSyntaxOptionId, catsSyntaxTuple2Semigroupal}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import cats.implicits.{catsSyntaxOptionId, catsSyntaxTuple2Semigroupal}

tu es sûr que c'est nécessaire ?

import cats.syntax.all._
import constants.Constants
import forms.FormsPlusMap
Expand Down Expand Up @@ -309,9 +309,11 @@ case class ApplicationController @Inject() (
applicationData.selectedSubject.contains[String](applicationData.subject),
category = applicationData.category,
files = newAttachments ++ pendingAttachments,
mandatType = DataModel.Application.MandatType
.dataModelDeserialization(applicationData.mandatType),
mandatDate = Some(applicationData.mandatDate)
mandat = (
DataModel.Application.Mandat.MandatType
.dataModelDeserialization(applicationData.mandatType),
applicationData.mandatDate.some
).mapN(Application.Mandat.apply)
)
if (applicationService.createApplication(application)) {
notificationsService.newApplication(application)
Expand Down
35 changes: 35 additions & 0 deletions app/models/Answer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ package models
import java.time.ZonedDateTime
import java.util.UUID

import anorm.Column.nonNull
import anorm.{MetaDataItem, TypeDoesNotMatch}
import cats.implicits.catsSyntaxEitherId
import helper.Time
import play.api.libs.json.{Json, Reads, Writes}
import serializers.Anorm.className

import serializers.JsonFormats._

case class Answer(
id: UUID,
applicationId: UUID,
Expand All @@ -24,3 +33,29 @@ case class Answer(
}

}

object Answer {

implicit val Reads: Reads[Answer] = Json
.reads[Answer]
.map(answer =>
answer.copy(creationDate = answer.creationDate.withZoneSameInstant(Time.timeZoneParis))
)

implicit val Writes: Writes[Answer] = Json.writes[Answer]

implicit val answerListParser: anorm.Column[List[Answer]] =
nonNull { (value, meta) =>
val MetaDataItem(qualified, _, _) = meta
value match {
case json: org.postgresql.util.PGobject =>
Json.parse(json.getValue).as[List[Answer]].asRight[Nothing]
case json: String => Json.parse(json).as[List[Answer]].asRight[Nothing]
case _ =>
TypeDoesNotMatch(
s"Cannot convert $value: ${className(value)} to List[Answer] for column $qualified"
).asLeft[List[Answer]]
}
}
Comment on lines +39 to +59
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En fait avoir la logique de serialization dans le modèle ça n'a pas de sens. Ce n'est pas clair, ça mixe de la logique métier avec de la logique de serialization. Aussi juste la dépendance "modèle dépends des serializers anorm/json" ça sens pas bon.


}
Comment on lines +36 to +61
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Du coup ces modifs ne sont plus nécessaires ?

34 changes: 21 additions & 13 deletions app/models/Application.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import java.util.UUID
import cats.Eq
import cats.syntax.all._
import helper.BooleanHelper.not
import models.Application.Mandat
import models.Application.Mandat.MandatType
import models.Authorization.{isExpert, isHelper, isInstructor, UserRights}
import serializers.JsonFormats._

case class Application(
id: UUID,
Expand All @@ -21,18 +24,17 @@ case class Application(
invitedUsers: Map[UUID, String],
area: UUID,
irrelevant: Boolean,
answers: List[Answer] = List(),
answers: List[Answer] = List.empty[Answer],
internalId: Int = -1,
closed: Boolean = false,
seenByUserIds: List[UUID] = List(),
seenByUserIds: List[UUID] = List.empty[UUID],
usefulness: Option[String] = None,
closedDate: Option[ZonedDateTime] = None,
closedDate: Option[ZonedDateTime] = Option.empty[ZonedDateTime],
expertInvited: Boolean = false,
hasSelectedSubject: Boolean = false,
category: Option[String] = None,
files: Map[String, Long] = Map(),
mandatType: Option[Application.MandatType],
mandatDate: Option[String]
category: Option[String] = Option.empty[String],
files: Map[String, Long] = Map.empty[String, Long],
mandat: Option[Mandat]
) extends AgeModel {

lazy val filesAvailabilityLeftInDays: Option[Int] = if (ageInDays > 8) {
Expand Down Expand Up @@ -186,14 +188,20 @@ case class Application(

object Application {

sealed trait MandatType
final case class Mandat(type_ : MandatType, date: String)

object MandatType {
case object Sms extends MandatType
case object Phone extends MandatType
case object Paper extends MandatType
object Mandat {

implicit val Eq: Eq[MandatType] = (x: MandatType, y: MandatType) => x == y
sealed trait MandatType

object MandatType {
case object Sms extends MandatType
case object Phone extends MandatType
case object Paper extends MandatType

implicit val Eq: Eq[MandatType] = (x: MandatType, y: MandatType) => x == y

}

}

Expand Down
104 changes: 104 additions & 0 deletions app/models/sql/ApplicationRow.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package models.sql

import java.time.ZonedDateTime
import java.util.UUID

import anorm.{Macro, RowParser}
import cats.implicits.catsSyntaxTuple2Semigroupal
import helper.Time
import models.Application.Mandat
import models.{Answer, Application}
import serializers.DataModel

final case class ApplicationRow(
id: UUID,
creationDate: ZonedDateTime,
creatorUserName: String,
creatorUserId: UUID,
subject: String,
description: String,
userInfos: Map[String, String],
invitedUsers: Map[UUID, String],
area: UUID,
irrelevant: Boolean,
answers: List[Answer] = List.empty[Answer],
internalId: Int = -1,
closed: Boolean = false,
seenByUserIds: List[UUID] = List.empty[UUID],
usefulness: Option[String] = Option.empty[String],
closedDate: Option[ZonedDateTime] = Option.empty[ZonedDateTime],
expertInvited: Boolean = false,
hasSelectedSubject: Boolean = false,
category: Option[String] = Option.empty[String],
files: Map[String, Long] = Map.empty[String, Long],
mandatType: Option[Application.Mandat.MandatType],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pour postgres c'est un varchar, que penses-tu de mettre la conversion dans toApplication plutôt ?

Suggested change
mandatType: Option[Application.Mandat.MandatType],
mandatType: Option[String],

mandatDate: Option[String]
)

object ApplicationRow {

import serializers.Anorm._
import DataModel.Application.Mandat.MandatType.MandatTypeParser

val ApplicationRowParser: RowParser[ApplicationRow] = Macro
.parser[ApplicationRow](
"id",
"creation_date",
"creator_user_name",
"creator_user_id",
"subject",
"description",
"user_infos",
"invited_users",
"area",
"irrelevant",
"answers",
"internal_id",
"closed",
"seen_by_user_ids",
"usefulness",
"closed_date",
"expert_invited",
"has_selected_subject",
"category",
"files",
"mandat_type",
"mandat_date"
)
.map(application =>
application.copy(
creationDate = application.creationDate.withZoneSameInstant(Time.timeZoneParis),
answers = application.answers.map(answer =>
answer.copy(creationDate = answer.creationDate.withZoneSameInstant(Time.timeZoneParis))
)
)
)

def toApplication(row: ApplicationRow): Application = {
import row._
Application(
id,
creationDate,
creatorUserName,
creatorUserId,
subject,
description = description,
userInfos = userInfos,
invitedUsers = invitedUsers,
area = area,
irrelevant = irrelevant,
answers = answers,
internalId = internalId,
closed = closed,
seenByUserIds = seenByUserIds,
usefulness = usefulness,
closedDate = closedDate,
expertInvited = expertInvited,
hasSelectedSubject = hasSelectedSubject,
category = category,
files = files,
mandat = (row.mandatType, row.mandatDate).mapN(Mandat.apply)
)
}

}
69 changes: 39 additions & 30 deletions app/serializers/DataModel.scala
Original file line number Diff line number Diff line change
@@ -1,29 +1,40 @@
package serializers

import models.Application.MandatType
import anorm.Column
import cats.implicits.catsSyntaxOptionId
import models.Application.Mandat.MandatType
import play.api.libs.json._

object DataModel {

object Application {

object MandatType {
import models.Application.MandatType._
object Mandat {

def dataModelSerialization(entity: MandatType): String =
entity match {
case Sms => "sms"
case Phone => "phone"
case Paper => "paper"
}
object MandatType {

def dataModelDeserialization(raw: String): Option[MandatType] =
raw match {
case "sms" => Some(Sms)
case "phone" => Some(Phone)
case "paper" => Some(Paper)
case _ => None
}
import models.Application.Mandat.MandatType._

implicit val MandatTypeParser: Column[Option[MandatType]] =
implicitly[Column[Option[String]]]
.map(_.flatMap(dataModelDeserialization))
Comment on lines +18 to +20
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non utilisé ?


def dataModelSerialization(entity: MandatType): String =
entity match {
case Sms => "sms"
case Phone => "phone"
case Paper => "paper"
}

def dataModelDeserialization(raw: String): Option[MandatType] =
raw match {
case "sms" => Sms.some
case "phone" => Phone.some
case "paper" => Paper.some
case _ => None
}

}

}

Expand Down Expand Up @@ -53,20 +64,18 @@ object DataModel {
}

implicit val smsApiWrites: Writes[Sms] =
Writes(
_ match {
case sms: Sms.Outgoing =>
smsOutgoingFormat.writes(sms) match {
case obj: JsObject => obj + ("tag" -> JsString("outgoing"))
case other => other
}
case sms: Sms.Incoming =>
smsIncomingFormat.writes(sms) match {
case obj: JsObject => obj + ("tag" -> JsString("incoming"))
case other => other
}
}
)
Writes {
case sms: Sms.Outgoing =>
smsOutgoingFormat.writes(sms) match {
case obj: JsObject => obj + ("tag" -> JsString("outgoing"))
case other => other
}
case sms: Sms.Incoming =>
smsIncomingFormat.writes(sms) match {
case obj: JsObject => obj + ("tag" -> JsString("incoming"))
case other => other
}
}

}

Expand Down
35 changes: 15 additions & 20 deletions app/serializers/JsonFormats.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,38 @@ package serializers
import constants.Constants
import helper.{StringHelper, UUIDHelper}
import java.util.UUID

import models.mandat.{Mandat, SmsMandatInitiation}
import play.api.libs.json.Json.JsValueWrapper
import play.api.libs.json._
import play.api.libs.functional.syntax._
import play.api.libs.json.JsonConfiguration.Aux
import play.api.mvc.Results.InternalServerError

object JsonFormats {
implicit val jsonConfiguration = JsonConfiguration(naming = JsonNaming.SnakeCase)

implicit val mapUUIDReads = new Reads[Map[UUID, String]] {

def reads(jv: JsValue): JsResult[Map[UUID, String]] =
JsSuccess(jv.as[Map[String, String]].map { case (k, v) =>
UUIDHelper.fromString(k).get -> v.asInstanceOf[String]
})

}

implicit val mapUUIDWrites = new Writes[Map[UUID, String]] {
implicit val jsonConfiguration: Aux[Json.MacroOptions] =
JsonConfiguration(naming = JsonNaming.SnakeCase)

def writes(map: Map[UUID, String]): JsValue =
Json.obj(map.map { case (s, o) =>
val ret: (String, JsValueWrapper) = s.toString -> JsString(o)
ret
}.toSeq: _*)
implicit val mapUUIDReads: Reads[Map[UUID, String]] = (jv: JsValue) =>
JsSuccess(jv.as[Map[String, String]].map { case (k, v) =>
UUIDHelper.fromString(k).get -> v.asInstanceOf[String]
})

}
implicit val mapUUIDWrites: Writes[Map[UUID, String]] = (map: Map[UUID, String]) =>
Json.obj(map.map { case (s, o) =>
val ret: (String, JsValueWrapper) = s.toString -> JsString(o)
ret
}.toSeq: _*)

implicit val mapUUIDFormat = Format(mapUUIDReads, mapUUIDWrites)
implicit val mapUUIDFormat: Format[Map[UUID, String]] = Format(mapUUIDReads, mapUUIDWrites)

//
// Mandat
//
import serializers.DataModel.SmsFormats._

implicit val mandatIdReads: Reads[Mandat.Id] =
implicitly[Reads[UUID]].map(Mandat.Id.apply)
implicit val mandatIdReads: Reads[Mandat.Id] = implicitly[Reads[UUID]].map(Mandat.Id.apply)

implicit val mandatIdWrites: Writes[Mandat.Id] =
implicitly[Writes[UUID]].contramap((id: Mandat.Id) => id.underlying)
Expand Down
Loading