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

PIN-4332 - Update of daily calls with the same value of the previous version is not allowed #196

Merged
merged 3 commits into from
Jan 15, 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 @@ -211,6 +211,7 @@ final case class PurposeApiServiceImpl(
purposeUUID <- purposeId.toFutureUUID
purpose <- purposeManagementService.getPurposeById(purposeUUID)
_ <- assertOrganizationIsAConsumer(organizationId, purpose.consumerId)
_ <- assertDailyCallsIsDifferentThanBefore(purpose, seed.dailyCalls)
version <- purposeManagementService.createPurposeVersion(purposeUUID, seed.toManagement)
published <- publish(organizationId, purpose, version.toPersistent)
} yield published.toApi
Expand Down Expand Up @@ -734,6 +735,15 @@ final case class PurposeApiServiceImpl(
else Future.failed(PurposeNotInDraftState(purpose.id))
}

private def assertDailyCallsIsDifferentThanBefore(purpose: PersistentPurpose, dailyCalls: Int): Future[Unit] = {
val ordering: Ordering[OffsetDateTime] = Ordering(Ordering.by[OffsetDateTime, Long](_.toEpochSecond).reverse)
val previousDailyCalls = purpose.versions.sortBy(_.createdAt)(ordering).map(_.dailyCalls).headOption
previousDailyCalls match {
case Some(x) if x == dailyCalls => Future.failed(UnchangedDailyCalls(purpose.id))
case _ => Future.successful(())
}
}

private def isRiskAnalysisFormValid(
riskAnalysisForm: Option[RiskAnalysisForm],
schemaOnlyValidation: Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ object ResponseHandlers extends AkkaResponses {
)(result: Try[T])(implicit contexts: Seq[(String, String)], logger: LoggerTakingImplicit[ContextFieldsToLog]): Route =
result match {
case Success(s) => success(s)
case Failure(ex: UnchangedDailyCalls) => badRequest(ex, logMessage)
case Failure(ex: OrganizationIsNotTheConsumer) => forbidden(ex, logMessage)
case Failure(ex: PurposeNotFound) => notFound(ex, logMessage)
case Failure(ex: PurposeVersionConflict) => conflict(ex, logMessage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,6 @@ object PurposeProcessErrors {
extends ComponentError("0026", s"EService ${eServiceId.toString} has not Receive mode")
final case class RiskAnalysisNotFound(eServiceId: UUID, riskAnalysisId: UUID)
extends ComponentError("0027", s"EService $eServiceId does not contain Risk Analysis $riskAnalysisId")

final case class UnchangedDailyCalls(purposeId: UUID)
extends ComponentError("0028", s"Creation of new version without changing daily calls for purpose $purposeId")
}
Original file line number Diff line number Diff line change
Expand Up @@ -2156,19 +2156,20 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
implicit val context: Seq[(String, String)] =
Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> consumerId.toString)

val version2_1 = SpecData.purposeVersion.copy(id = UUID.randomUUID(), state = Active, dailyCalls = 1000)
val version2_1 = SpecData.purposeVersion.copy(id = UUID.randomUUID(), state = Active, dailyCalls = 1002)
val purpose2 = SpecData.purpose.copy(eserviceId = eserviceId, consumerId = consumerId, versions = Seq(version2_1))

val path: String = "/here/there/foo/bar.pdf"
val document: PersistentPurposeVersionDocument =
PersistentPurposeVersionDocument(documentId, "application/pdf", path, SpecData.timestamp)

val version1_1 = SpecData.purposeVersion.copy(id = purposeVersionId1, state = Active)
val version1_1 = SpecData.purposeVersion.copy(id = purposeVersionId1, state = Active, dailyCalls = 1000)
val version1_2 = SpecData.purposeVersion.copy(
id = purposeVersionId2,
state = WaitingForApproval,
riskAnalysis = Some(document),
firstActivationAt = Some(SpecData.timestamp)
firstActivationAt = Some(SpecData.timestamp),
dailyCalls = 1001
)

val purpose =
Expand All @@ -2180,15 +2181,15 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
)

val purposes = Seq(purpose, purpose2)
val seed: PurposeVersionSeed = PurposeVersionSeed(dailyCalls = 1000)
val seed: PurposeVersionSeed = PurposeVersionSeed(dailyCalls = 2000)

val purposeVersion = PersistentPurposeVersion(
id = purposeVersionId3,
state = Active,
createdAt = SpecData.timestamp,
updatedAt = None,
expectedApprovalDate = None,
dailyCalls = seed.dailyCalls,
dailyCalls = 2000,
riskAnalysis = Some(document),
firstActivationAt = Some(SpecData.timestamp),
suspendedAt = None
Expand Down Expand Up @@ -2216,7 +2217,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
riskAnalysis = Some(
PurposeManagementDependency.PurposeVersionDocument(documentId, "application/pdf", path, SpecData.timestamp)
),
firstActivationAt = Some(SpecData.timestamp)
firstActivationAt = Some(SpecData.timestamp),
dailyCalls = 2000
)

mockVersionFirstActivation(purposeId, purposeVersionId3, eService.producerId, purpose.consumerId, updatedVersion)
Expand Down Expand Up @@ -2248,7 +2250,7 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
implicit val context: Seq[(String, String)] =
Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> consumerId.toString)

val version2_1 = SpecData.purposeVersion.copy(id = UUID.randomUUID(), state = Active, dailyCalls = 1000)
val version2_1 = SpecData.purposeVersion.copy(id = UUID.randomUUID(), state = Active, dailyCalls = 1002)
val purpose2 = SpecData.purpose.copy(eserviceId = eserviceId, consumerId = consumerId, versions = Seq(version2_1))

val path: String = "/here/there/foo/bar.pdf"
Expand All @@ -2260,7 +2262,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
id = purposeVersionId2,
state = WaitingForApproval,
riskAnalysis = Some(document),
firstActivationAt = Some(SpecData.timestamp)
firstActivationAt = Some(SpecData.timestamp),
dailyCalls = 1001
)

val purpose =
Expand All @@ -2272,15 +2275,15 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
)

val purposes = Seq(purpose, purpose2)
val seed: PurposeVersionSeed = PurposeVersionSeed(dailyCalls = 1000)
val seed: PurposeVersionSeed = PurposeVersionSeed(dailyCalls = 2000)

val purposeVersion = PersistentPurposeVersion(
id = purposeVersionId3,
state = WaitingForApproval,
createdAt = SpecData.timestamp,
updatedAt = None,
expectedApprovalDate = None,
dailyCalls = seed.dailyCalls,
dailyCalls = 2000,
riskAnalysis = None,
firstActivationAt = Some(SpecData.timestamp),
suspendedAt = None
Expand All @@ -2306,7 +2309,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
id = purposeVersionId3,
state = PurposeManagementDependency.PurposeVersionState.WAITING_FOR_APPROVAL,
riskAnalysis = None,
firstActivationAt = Some(SpecData.timestamp)
firstActivationAt = Some(SpecData.timestamp),
dailyCalls = 2000
)

val payload = PurposeManagementDependency.StateChangeDetails(
Expand All @@ -2325,7 +2329,51 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
responseAs[PurposeVersion] shouldEqual expected
}
}
"fail in case of version with the same dailyCalls than previous version" in {

val consumerId = UUID.randomUUID()
val documentId = UUID.randomUUID()
val purposeId = UUID.randomUUID()
val purposeVersionId1 = UUID.randomUUID()
val purposeVersionId2 = UUID.randomUUID()
val eserviceId = UUID.randomUUID()

implicit val context: Seq[(String, String)] =
Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> consumerId.toString)

val path: String = "/here/there/foo/bar.pdf"
val document: PersistentPurposeVersionDocument =
PersistentPurposeVersionDocument(documentId, "application/pdf", path, SpecData.timestamp)

val version1_1 = SpecData.purposeVersion.copy(id = purposeVersionId1, state = Draft, dailyCalls = 1000)
val version1_2 = SpecData.purposeVersion.copy(
id = purposeVersionId2,
state = WaitingForApproval,
riskAnalysis = Some(document),
firstActivationAt = None,
createdAt = SpecData.timestamp.plusDays(1),
dailyCalls = 1001
)

val purpose =
SpecData.purpose.copy(
id = purposeId,
versions = Seq(version1_1, version1_2),
consumerId = consumerId,
eserviceId = eserviceId
)

val seed: PurposeVersionSeed = PurposeVersionSeed(dailyCalls = 1001)

mockPurposeRetrieve(purposeId, purpose)

Get() ~> service.createPurposeVersion(purposeId.toString, seed) ~> check {
status shouldEqual StatusCodes.BadRequest
val problem = responseAs[Problem]
problem.status shouldBe StatusCodes.BadRequest.intValue
problem.errors.head.code shouldBe "012-0028"
}
}
"fail if Purpose does not exist" in {

val purposeId = UUID.randomUUID()
Expand Down
Loading