Skip to content

PIN-4657 BKE - purpose management - Add route reject purpose #213

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

Merged
merged 5 commits into from
Mar 20, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ object JsonFormats {
case JsString("Draft") => Draft
case JsString("Active") => Active
case JsString("Suspended") => Suspended
case JsString("Rejected") => Rejected
case JsString("Archived") => Archived
case JsString("WaitingForApproval") => WaitingForApproval
case _ => deserializationError("Unable to deserialize json as a PersistentPurposeVersionState")
Expand All @@ -21,6 +22,7 @@ object JsonFormats {
override def write(obj: PersistentPurposeVersionState): JsValue = obj match {
case Archived => JsString("Archived")
case Suspended => JsString("Suspended")
case Rejected => JsString("Rejected")
case Draft => JsString("Draft")
case WaitingForApproval => JsString("WaitingForApproval")
case Active => JsString("Active")
Expand All @@ -31,7 +33,7 @@ object JsonFormats {
PersistentPurposeVersionDocument.apply
)

implicit val ppvFormat: RootJsonFormat[PersistentPurposeVersion] = jsonFormat9(PersistentPurposeVersion.apply)
implicit val ppvFormat: RootJsonFormat[PersistentPurposeVersion] = jsonFormat10(PersistentPurposeVersion.apply)

implicit val pramaFormat: RootJsonFormat[PersistentRiskAnalysisMultiAnswer] = jsonFormat3(
PersistentRiskAnalysisMultiAnswer.apply
Expand All @@ -53,6 +55,7 @@ object JsonFormats {
implicit val pvwfaFormat: RootJsonFormat[PurposeVersionWaitedForApproval] = jsonFormat1(
PurposeVersionWaitedForApproval.apply
)
implicit val pvreFormat: RootJsonFormat[PurposeVersionRejected] = jsonFormat2(PurposeVersionRejected.apply)
implicit val pvarFormat: RootJsonFormat[PurposeVersionArchived] = jsonFormat1(PurposeVersionArchived.apply)
implicit val pvuFormat: RootJsonFormat[PurposeVersionUpdated] = jsonFormat2(PurposeVersionUpdated.apply)
implicit val pvdFormat: RootJsonFormat[PurposeVersionDeleted] = jsonFormat2(PurposeVersionDeleted.apply)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ object PurposeEventsSerde {
case x: PurposeVersionSuspended => x.toJson
case x: PurposeVersionWaitedForApproval => x.toJson
case x: PurposeVersionArchived => x.toJson
case x: PurposeVersionRejected => x.toJson
case x: PurposeVersionUpdated => x.toJson
case x: PurposeVersionDeleted => x.toJson
case x: PurposeDeleted => x.toJson
Expand All @@ -31,6 +32,7 @@ object PurposeEventsSerde {
case `purposeVersionSuspended` => _.convertTo[PurposeVersionSuspended]
case `purposeVersionWaitedForApproval` => _.convertTo[PurposeVersionWaitedForApproval]
case `purposeVersionArchived` => _.convertTo[PurposeVersionArchived]
case `purposeVersionRejected` => _.convertTo[PurposeVersionRejected]
case `purposeVersionUpdated` => _.convertTo[PurposeVersionUpdated]
case `purposeVersionDeleted` => _.convertTo[PurposeVersionDeleted]
case `purposeDeleted` => _.convertTo[PurposeDeleted]
Expand All @@ -44,6 +46,7 @@ object PurposeEventsSerde {
case PurposeVersionSuspended(_) => purposeVersionSuspended
case PurposeVersionWaitedForApproval(_) => purposeVersionWaitedForApproval
case PurposeVersionArchived(_) => purposeVersionArchived
case PurposeVersionRejected(_, _) => purposeVersionRejected
case PurposeVersionUpdated(_, _) => purposeVersionUpdated
case PurposeVersionDeleted(_, _) => purposeVersionDeleted
case PurposeDeleted(_) => purposeDeleted
Expand All @@ -56,6 +59,7 @@ object PurposeEventsSerde {
private val purposeVersionSuspended: String = "purpose_version_suspended"
private val purposeVersionWaitedForApproval: String = "purpose_version_waited_for_approval"
private val purposeVersionArchived: String = "purpose_version_archived"
private val purposeVersionRejected: String = "purpose_version_rejected"
private val purposeVersionUpdated: String = "purpose_version_updated"
private val purposeVersionDeleted: String = "purpose_version_deleted"
private val purposeDeleted: String = "purpose_deleted"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ final case class PurposeVersionActivated(purpose: PersistentPurpose)
final case class PurposeVersionSuspended(purpose: PersistentPurpose) extends Event
final case class PurposeVersionWaitedForApproval(purpose: PersistentPurpose) extends Event
final case class PurposeVersionArchived(purpose: PersistentPurpose) extends Event
final case class PurposeVersionRejected(purpose: PersistentPurpose, versionId: String) extends Event
final case class PurposeVersionUpdated(purposeId: String, version: PersistentPurposeVersion) extends Event
final case class PurposeVersionDeleted(purposeId: String, versionId: String) extends Event
final case class PurposeDeleted(purposeId: String) extends Event
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ final case class PersistentPurposeVersion(
expectedApprovalDate: Option[OffsetDateTime],
riskAnalysis: Option[PersistentPurposeVersionDocument],
dailyCalls: Int,
rejectionReason: Option[String],
createdAt: OffsetDateTime,
updatedAt: Option[OffsetDateTime],
firstActivationAt: Option[OffsetDateTime],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ case object Active extends PersistentPurposeVersionState
case object Suspended extends PersistentPurposeVersionState
case object Archived extends PersistentPurposeVersionState
case object WaitingForApproval extends PersistentPurposeVersionState
case object Rejected extends PersistentPurposeVersionState
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ object ItSpecData {
PersistentPurposeVersionDocument(id = UUID.randomUUID(), contentType = "json", path = "path", createdAt = timestamp)

def riskAnalysisForm: RiskAnalysisForm =
RiskAnalysisForm(id = UUID.randomUUID(), version = UUID.randomUUID().toString, Seq.empty, Seq.empty)
RiskAnalysisForm(
id = UUID.randomUUID(),
riskAnalysisId = Some(UUID.randomUUID()),
version = UUID.randomUUID().toString,
singleAnswers = Seq.empty,
multiAnswers = Seq.empty
)

def persistentPurposeVersion: PersistentPurposeVersion = PersistentPurposeVersion(
id = UUID.randomUUID(),
Expand All @@ -24,11 +30,18 @@ object ItSpecData {
createdAt = timestamp,
updatedAt = Some(timestamp),
firstActivationAt = Some(timestamp),
suspendedAt = None
suspendedAt = None,
rejectionReason = None
)

def persistentRiskAnalysisForm: PersistentRiskAnalysisForm =
PersistentRiskAnalysisForm(id = riskAnalysisForm.id, version = riskAnalysisForm.version, Seq.empty, Seq.empty)
PersistentRiskAnalysisForm(
id = riskAnalysisForm.id,
riskAnalysisId = riskAnalysisForm.riskAnalysisId,
version = riskAnalysisForm.version,
Seq.empty,
Seq.empty
)

def persistentPurpose: PersistentPurpose = PersistentPurpose(
id = UUID.randomUUID(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ class CqrsProjectionSpec extends ScalaTestWithActorTestKit(ItSpecConfiguration.c
title = "New title",
description = "new Description",
isFreeOfCharge = true,
eserviceId = purpose.eserviceId,
freeOfChargeReason = Some("Siamo una Pubblica Amministrazione"),
riskAnalysisForm = Some(persistentRiskAnalysisForm)
)
Expand Down
5 changes: 5 additions & 0 deletions src/main/protobuf/v1/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ message PurposeVersionActivatedV1 {
required PurposeV1 purpose = 1;
}

message PurposeVersionRejectedV1 {
required PurposeV1 purpose = 1;
required string versionId = 2;
}

message PurposeVersionSuspendedV1 {
required PurposeV1 purpose = 1;
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/protobuf/v1/purpose.proto
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ message PurposeVersionV1 {
optional int64 firstActivationAt = 7;
optional int64 expectedApprovalDate = 8;
optional int64 suspendedAt = 9;
optional string rejectionReason = 10;
}

enum PurposeStateV1 {
Expand All @@ -43,6 +44,7 @@ enum PurposeStateV1 {
SUSPENDED = 3;
WAITING_FOR_APPROVAL = 4;
ARCHIVED = 5;
REJECTED = 6;
}

message PurposeVersionDocumentV1 {
Expand Down
56 changes: 56 additions & 0 deletions src/main/resources/interface-specification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,48 @@ paths:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/purposes/{purposeId}/versions/{versionId}/reject:
parameters:
- $ref: '#/components/parameters/CorrelationIdHeader'
- name: purposeId
in: path
required: true
schema:
type: string
format: uuid
- name: versionId
in: path
required: true
schema:
type: string
format: uuid
post:
summary: Rejected Purpose Version
operationId: rejectPurposeVersion
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/RejectPurposeVersionPayload'
required: true
responses:
'204':
description: Purpose Version Rejected
'400':
description: Bad Request
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'404':
description: Purpose not found
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
description: reject the purpose version by id
tags:
- purpose
/purposes/{purposeId}/versions/{versionId}/activate:
parameters:
- $ref: '#/components/parameters/CorrelationIdHeader'
Expand Down Expand Up @@ -521,6 +563,17 @@ components:
schema:
type: string
schemas:
RejectPurposeVersionPayload:
type: object
description: models the reject payload for this purpose version.
properties:
rejectionReason:
type: string
stateChangeDetails:
$ref: '#/components/schemas/StateChangeDetails'
required:
- rejectionReason
- stateChangeDetails
ActivatePurposeVersionPayload:
type: object
description: models the activation payload for this purpose version.
Expand Down Expand Up @@ -556,6 +609,7 @@ components:
- ACTIVE
- DRAFT
- SUSPENDED
- REJECTED
- WAITING_FOR_APPROVAL
- ARCHIVED
PurposeSeed:
Expand Down Expand Up @@ -720,6 +774,8 @@ components:
minimum: 0
riskAnalysis:
$ref: '#/components/schemas/PurposeVersionDocument'
rejectionReason:
type: string
required:
- id
- state
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ akka {
purpose-version-activated = "it.pagopa.interop.purposemanagement.model.persistence.serializer.PurposeVersionActivatedSerializer"
purpose-version-suspended = "it.pagopa.interop.purposemanagement.model.persistence.serializer.PurposeVersionSuspendedSerializer"
purpose-version-archived = "it.pagopa.interop.purposemanagement.model.persistence.serializer.PurposeVersionArchivedSerializer"
purpose-version-rejected = "it.pagopa.interop.purposemanagement.model.persistence.serializer.PurposeVersionRejectedSerializer"
purpose-version-updated = "it.pagopa.interop.purposemanagement.model.persistence.serializer.PurposeVersionUpdatedSerializer"
purpose-version-waiting-for-approval = "it.pagopa.interop.purposemanagement.model.persistence.serializer.PurposeVersionWaitedForApprovalSerializer"
purpose-version-deleted = "it.pagopa.interop.purposemanagement.model.persistence.serializer.PurposeVersionDeletedSerializer"
Expand All @@ -34,6 +35,7 @@ akka {
"it.pagopa.interop.purposemanagement.model.persistence.serializer.PurposeVersionDeletedSerializer" = 100007
"it.pagopa.interop.purposemanagement.model.persistence.serializer.PurposeDeletedSerializer" = 100008
"it.pagopa.interop.purposemanagement.model.persistence.serializer.PurposeUpdatedSerializer" = 100009
"it.pagopa.interop.purposemanagement.model.persistence.serializer.PurposeVersionRejectedSerializer" = 100010
"it.pagopa.interop.purposemanagement.model.persistence.serializer.StateSerializer" = 200000
"java.io.serializable" = none
}
Expand All @@ -43,6 +45,7 @@ akka {
"it.pagopa.interop.purposemanagement.model.persistence.PurposeVersionActivated" = purpose-version-activated
"it.pagopa.interop.purposemanagement.model.persistence.PurposeVersionSuspended" = purpose-version-suspended
"it.pagopa.interop.purposemanagement.model.persistence.PurposeVersionArchived" = purpose-version-archived
"it.pagopa.interop.purposemanagement.model.persistence.PurposeVersionRejected" = purpose-version-rejected
"it.pagopa.interop.purposemanagement.model.persistence.PurposeVersionUpdated" = purpose-version-updated
"it.pagopa.interop.purposemanagement.model.persistence.PurposeVersionWaitedForApproval" = purpose-version-waiting-for-approval
"it.pagopa.interop.purposemanagement.model.persistence.PurposeVersionDeleted" = purpose-version-deleted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,7 @@ object PurposeApiMarshallerImpl extends PurposeApiMarshaller with SprayJsonSuppo

override implicit def fromEntityUnmarshallerPurposeUpdateContent: FromEntityUnmarshaller[PurposeUpdateContent] =
sprayJsonUnmarshaller[PurposeUpdateContent]

override implicit def fromEntityUnmarshallerRejectPurposeVersionPayload
: FromEntityUnmarshaller[RejectPurposeVersionPayload] = sprayJsonUnmarshaller[RejectPurposeVersionPayload]
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,29 @@ final case class PurposeApiServiceImpl(
onComplete(result) { deletePurposeVersionResponse[Unit](operationLabel)(_ => deletePurposeVersion204) }
}

override def rejectPurposeVersion(
purposeId: String,
versionId: String,
rejectPurposeVersionPayload: RejectPurposeVersionPayload
)(implicit toEntityMarshallerProblem: ToEntityMarshaller[Problem], contexts: Seq[(String, String)]): Route = {
val operationLabel = s"Rejecting version $versionId of purpose $purposeId"
logger.info(operationLabel)

val result: Future[Unit] = updateVersionState(
purposeId,
versionId,
RejectPurposeVersion(
purposeId,
versionId,
rejectPurposeVersionPayload.rejectionReason,
rejectPurposeVersionPayload.stateChangeDetails,
_
)
).map(_ => ())

onComplete(result) { rejectPurposeVersionResponse[Unit](operationLabel)(_ => rejectPurposeVersion204) }
}

override def activatePurposeVersion(
purposeId: String,
versionId: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ object ResponseHandlers extends AkkaResponses {
case Failure(ex) => internalServerError(ex, logMessage)
}

def rejectPurposeVersionResponse[T](logMessage: String)(
success: T => Route
)(result: Try[T])(implicit contexts: Seq[(String, String)], logger: LoggerTakingImplicit[ContextFieldsToLog]): Route =
result match {
case Success(s) => success(s)
case Failure(ex: NotAllowedForPurposeVersionState) => badRequest(ex, logMessage)
case Failure(ex: PurposeNotFound) => notFound(ex, logMessage)
case Failure(ex: PurposeVersionNotFound) => notFound(ex, logMessage)
case Failure(ex) => internalServerError(ex, logMessage)
}

def activatePurposeVersionResponse[T](logMessage: String)(
success: T => Route
)(result: Try[T])(implicit contexts: Seq[(String, String)], logger: LoggerTakingImplicit[ContextFieldsToLog]): Route =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@ package object impl extends SprayJsonSupport with DefaultJsonProtocol {
implicit val waitingForApprovalPurposeVersionUpdateFormat
: RootJsonFormat[WaitingForApprovalPurposeVersionUpdateContent] =
jsonFormat1(WaitingForApprovalPurposeVersionUpdateContent)
implicit val purposeVersionFormat: RootJsonFormat[PurposeVersion] = jsonFormat9(PurposeVersion)
implicit val purposeVersionFormat: RootJsonFormat[PurposeVersion] = jsonFormat10(PurposeVersion)
implicit val purposeFormat: RootJsonFormat[Purpose] = jsonFormat13(Purpose)
implicit val purposesFormat: RootJsonFormat[Purposes] = jsonFormat1(Purposes)
implicit val stateChangeDetailsFormat: RootJsonFormat[StateChangeDetails] = jsonFormat2(StateChangeDetails)
implicit val problemErrorFormat: RootJsonFormat[ProblemError] = jsonFormat2(ProblemError)
implicit val problemFormat: RootJsonFormat[Problem] = jsonFormat6(Problem)
implicit val activatePurposeVersionPayloadFormat: RootJsonFormat[ActivatePurposeVersionPayload] =
jsonFormat2(ActivatePurposeVersionPayload)

implicit val rejectPurposeVersionPayloadFormat: RootJsonFormat[RejectPurposeVersionPayload] =
jsonFormat2(RejectPurposeVersionPayload)
final val entityMarshallerProblem: ToEntityMarshaller[Problem] = sprayJsonMarshaller[Problem]

def slices[A, B <: Command](commander: EntityRef[B], sliceSize: Int)(
Expand Down
Loading
Loading