diff --git a/fp/src/main/scala/eu/thoughtway/fsm/fp/domain/service/OrganisationService.scala b/fp/src/main/scala/eu/thoughtway/fsm/fp/domain/service/OrganisationService.scala index 1c6444b..f60e4ec 100644 --- a/fp/src/main/scala/eu/thoughtway/fsm/fp/domain/service/OrganisationService.scala +++ b/fp/src/main/scala/eu/thoughtway/fsm/fp/domain/service/OrganisationService.scala @@ -14,6 +14,7 @@ trait OrganisationService { amount: BigDecimal ): OrganisationEnabled def disable(org: OrganisationEnabled): OrganisationDisabled + def recover(org: OrganisationDisabled): OrganisationEnabled def expedite(id: String)(amount: BigDecimal): OrganisationEnabled = (define _ andThen approve _ andThen credit)(id)(amount) @@ -38,4 +39,7 @@ trait OrganisationServiceImpl extends OrganisationService { override def disable(org: OrganisationEnabled): OrganisationDisabled = org.copy(status = Disabled) + + override def recover(org: OrganisationDisabled): OrganisationEnabled = + org.copy(status = Enabled) } diff --git a/fp/src/test/scala/eu/thoughtway/fsm/fp/domain/service/OrganisationServiceTest.scala b/fp/src/test/scala/eu/thoughtway/fsm/fp/domain/service/OrganisationServiceTest.scala index d5d4232..7364e15 100644 --- a/fp/src/test/scala/eu/thoughtway/fsm/fp/domain/service/OrganisationServiceTest.scala +++ b/fp/src/test/scala/eu/thoughtway/fsm/fp/domain/service/OrganisationServiceTest.scala @@ -50,6 +50,10 @@ class OrganisationServiceTest "disable(defined)" shouldNot typeCheck } + it("should not allow recover") { + "recover(defined)" shouldNot typeCheck + } + describe("When a defined Organisation is approved") { val approved = approve(defined) @@ -73,6 +77,10 @@ class OrganisationServiceTest "approve(approved)" shouldNot typeCheck } + it("should not allow recover") { + "recover(defined)" shouldNot typeCheck + } + describe( "When an approved Organisation is credited with a given amount" ) { @@ -149,6 +157,26 @@ class OrganisationServiceTest it("should not allow disable") { "disable(disabled)" shouldNot typeCheck } + + describe("When a disabled Organisation is recovered") { + val recovered = recover(disabled) + + it("should have its id remain unchanged") { + recovered.id should be(approved.id) + } + + it("should have its created date remain unchanged") { + recovered.created should be(approved.created) + } + + it("should have its status set to the Enabled Status") { + recovered.status should be(Enabled) + } + + it("should have its balance remain unchanged") { + recovered.balance should be(approved.balance) + } + } } } } diff --git a/oo/src/main/scala/eu/thoughtway/fsm/oo/model/Organisation.scala b/oo/src/main/scala/eu/thoughtway/fsm/oo/model/Organisation.scala index 8958973..38c86dc 100644 --- a/oo/src/main/scala/eu/thoughtway/fsm/oo/model/Organisation.scala +++ b/oo/src/main/scala/eu/thoughtway/fsm/oo/model/Organisation.scala @@ -33,6 +33,8 @@ class Organisation(private[this] val _id: String) override def disable(): Unit = _state.disable() + override def recover(): Unit = _state.recover() + sealed trait State extends Organisation.Organisation final class Defined() extends State { @@ -52,6 +54,11 @@ class Organisation(private[this] val _id: String) throw new IllegalStateException( "Can't disable Organisation in Defined state" ) + + override def recover(): Unit = + throw new IllegalStateException( + "Can't recover Organisation in Defined state" + ) } final class Enabled() extends State { @@ -67,6 +74,11 @@ class Organisation(private[this] val _id: String) _balance = balance - amount override def disable(): Unit = _state = _disabled + + override def recover(): Unit = + throw new IllegalStateException( + "Can't recover Organisation in Enabled state" + ) } final class Disabled() extends State { @@ -89,6 +101,8 @@ class Organisation(private[this] val _id: String) throw new IllegalStateException( "Can't disable Organisation in Disabled state" ) + + override def recover(): Unit = _state = _enabled } } @@ -98,5 +112,6 @@ object Organisation { def credit(amount: BigDecimal): Unit def debit(amount: BigDecimal): Unit def disable(): Unit + def recover(): Unit } } diff --git a/oo/src/main/scala/eu/thoughtway/fsm/oo/service/OrganisationService.scala b/oo/src/main/scala/eu/thoughtway/fsm/oo/service/OrganisationService.scala index 56559d6..362bf1d 100644 --- a/oo/src/main/scala/eu/thoughtway/fsm/oo/service/OrganisationService.scala +++ b/oo/src/main/scala/eu/thoughtway/fsm/oo/service/OrganisationService.scala @@ -8,6 +8,7 @@ trait OrganisationService { def credit(org: Organisation, amount: BigDecimal): Unit def debit(org: Organisation, amount: BigDecimal): Unit def disable(org: Organisation): Unit + def recover(org: Organisation): Unit def expedite(amount: BigDecimal)(id: String): Organisation = { val org = define(id) @@ -29,4 +30,6 @@ object OrganisationService extends OrganisationService { org.debit(amount) override def disable(org: Organisation): Unit = org.disable() + + override def recover(org: Organisation): Unit = org.recover() } diff --git a/oo/src/test/scala/eu/thoughtway/fsm/oo/service/OrganisationServiceTest.scala b/oo/src/test/scala/eu/thoughtway/fsm/oo/service/OrganisationServiceTest.scala index 2e8ea74..cca57df 100644 --- a/oo/src/test/scala/eu/thoughtway/fsm/oo/service/OrganisationServiceTest.scala +++ b/oo/src/test/scala/eu/thoughtway/fsm/oo/service/OrganisationServiceTest.scala @@ -43,6 +43,10 @@ class OrganisationServiceTest it("should throw IllegalStateException on disable") { an[IllegalStateException] shouldBe thrownBy(disable(org)) } + + it("should throw IllegalStateException on recover") { + an[IllegalStateException] shouldBe thrownBy(recover(org)) + } } describe("When a defined Organisation is approved") { @@ -73,6 +77,10 @@ class OrganisationServiceTest it("should throw IllegalStateException on approve") { an[IllegalStateException] shouldBe thrownBy(approve(org)) } + + it("should throw IllegalStateException on recover") { + an[IllegalStateException] shouldBe thrownBy(recover(org)) + } } describe( @@ -177,6 +185,34 @@ class OrganisationServiceTest } } + describe("When a disabled Organisation is recovered") { + + val org = define("test") + + val createdOriginal = org.created + val balanceOriginal = org.balance + + approve(org) + disable(org) + recover(org) + + it("should have its id remain unchanged") { + org.id should be("test") + } + + it("should have its created date remain unchanged") { + org.created should be(createdOriginal) + } + + it("should have its status set to the Enabled Status") { + org.state should be(org.enabled) + } + + it("should have its balance remain unchanged") { + org.balance should be(balanceOriginal) + } + } + describe( "When expediting the definition of an Organisation given an amount and the id" ) { diff --git a/proc/src/main/scala/eu/thoughtway/fsm/proc/Organisation.scala b/proc/src/main/scala/eu/thoughtway/fsm/proc/Organisation.scala index 60f4b51..7a456b3 100644 --- a/proc/src/main/scala/eu/thoughtway/fsm/proc/Organisation.scala +++ b/proc/src/main/scala/eu/thoughtway/fsm/proc/Organisation.scala @@ -63,4 +63,13 @@ object Organisation { credit(org, amount) org } + + def recover(org: Organisation): Unit = + if (org.state.equals(Disabled)) { + org.state = Enabled + } else { + throw new IllegalStateException( + s"Can't recover Organisation(${org.id}, ${org.state})" + ) + } } diff --git a/proc/src/test/scala/eu.thoughtway.fsm.proc/OrganisationTest.scala b/proc/src/test/scala/eu.thoughtway.fsm.proc/OrganisationTest.scala index ef91402..5ed9502 100644 --- a/proc/src/test/scala/eu.thoughtway.fsm.proc/OrganisationTest.scala +++ b/proc/src/test/scala/eu.thoughtway.fsm.proc/OrganisationTest.scala @@ -43,6 +43,10 @@ class OrganisationTest it("should throw IllegalStateException on disable") { an[IllegalStateException] shouldBe thrownBy(disable(org)) } + + it("should throw IllegalStateException on recover") { + an[IllegalStateException] shouldBe thrownBy(recover(org)) + } } describe("When a defined Organisation is approved") { @@ -73,6 +77,10 @@ class OrganisationTest it("should throw IllegalStateException on approve") { an[IllegalStateException] shouldBe thrownBy(approve(org)) } + + it("should throw IllegalStateException on recover") { + an[IllegalStateException] shouldBe thrownBy(recover(org)) + } } describe( @@ -177,6 +185,34 @@ class OrganisationTest } } + describe("When a disabled Organisation is recovered") { + + val org = define("test") + + val createdOriginal = org.created + val balanceOriginal = org.balance + + approve(org) + disable(org) + recover(org) + + it("should have its id remain unchanged") { + org.id should be("test") + } + + it("should have its created date remain unchanged") { + org.created should be(createdOriginal) + } + + it("should have its status set to the Enabled Status") { + org.state should be(Enabled) + } + + it("should have its balance remain unchanged") { + org.balance should be(balanceOriginal) + } + } + describe( "When expediting the definition of an Organisation given an amount and the id" ) {