From 97ed17dd5f18becd8f8dc3ffe904bb89205fed62 Mon Sep 17 00:00:00 2001 From: jycr Date: Wed, 6 Apr 2022 18:04:21 +0200 Subject: [PATCH 1/9] =?UTF-8?q?:bento:=20Ajout=20solution=20=C3=A9tape=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../courtage/domain/model/Portefeuille.java | 9 +++++++++ .../courtage/domain/port/primaire/.gitkeep | 0 .../domain/port/primaire/Courtage.java | 15 +++++++++++++++ .../domain/port/primaire/ServiceCourtage.java | 9 +++++++++ .../primaire/CourtageStepDefinitions.java | 19 ++++++++++++------- 5 files changed, 45 insertions(+), 7 deletions(-) delete mode 100644 courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/.gitkeep create mode 100644 courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java create mode 100644 courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java index 333d553..39b5fcb 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java @@ -1,4 +1,13 @@ package devoxx.lab.archihexa.courtage.domain.model; public class Portefeuille { + private final String nom; + + public Portefeuille(String nom) { + this.nom = nom; + } + + public String getNom() { + return nom; + } } diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/.gitkeep b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java new file mode 100644 index 0000000..188ffea --- /dev/null +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java @@ -0,0 +1,15 @@ +package devoxx.lab.archihexa.courtage.domain.port.primaire; + +import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; + +public class Courtage implements ServiceCourtage { + @Override + public Portefeuille creerPortefeuille(String nomPortefeuille) { + return new Portefeuille(nomPortefeuille); + } + + @Override + public boolean gere(String nomPortefeuille) { + return true; + } +} diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java new file mode 100644 index 0000000..3dea1c9 --- /dev/null +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java @@ -0,0 +1,9 @@ +package devoxx.lab.archihexa.courtage.domain.port.primaire; + +import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; + +public interface ServiceCourtage { + Portefeuille creerPortefeuille(String nomPortefeuille); + + boolean gere(String nomPortefeuille); +} diff --git a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java index 2ae278f..1e018db 100644 --- a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java +++ b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java @@ -1,5 +1,7 @@ package devoxx.lab.archihexa.courtage.domain.port.primaire; +import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleDejaExistantException; +import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; import devoxx.lab.archihexa.courtage.domain.model.Achat; import io.cucumber.datatable.DataTable; import io.cucumber.java8.DataTableEntryDefinitionBody; @@ -11,18 +13,21 @@ import java.util.Locale; import java.util.Map; +import static org.assertj.core.api.Assertions.assertThat; + public class CourtageStepDefinitions implements Fr { + private final ServiceCourtage serviceCourtage = new Courtage(); + private Portefeuille portefeuilleCree; + public CourtageStepDefinitions() { // étape 1 Quand("on demande au service de courtage la création du portefeuille {string}", (String nomPortefeuille) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("l'id du portefeuille créé doit être {string}", (String nomPortefeuille) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("le portefeuille {string} est géré par le service de courtage", (String nomPortefeuille) -> { - throw new io.cucumber.java8.PendingException(); + portefeuilleCree = serviceCourtage.creerPortefeuille(nomPortefeuille); }); + Alors("l'id du portefeuille créé doit être {string}", (String nomPortefeuille) -> + assertThat(portefeuilleCree.getNom()).isEqualTo(nomPortefeuille)); + Alors("le portefeuille {string} est géré par le service de courtage", (String nomPortefeuille) -> + assertThat(serviceCourtage.gere(nomPortefeuille)).isTrue()); // étape 2 Alors("le portefeuille {string} n'est pas géré par le service de courtage", (String nomPortefeuille) -> { From 79f4003198ed3f8c46bc423734056ac70f1ba30d Mon Sep 17 00:00:00 2001 From: jycr Date: Wed, 6 Apr 2022 18:08:36 +0200 Subject: [PATCH 2/9] =?UTF-8?q?:bento:=20Ajout=20solution=20=C3=A9tape=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/port/primaire/Courtage.java | 30 ++++++++++++-- .../domain/port/primaire/ServiceCourtage.java | 8 +++- .../courtage/domain/port/secondaire/.gitkeep | 0 .../secondaire/PortefeuilleRepository.java | 13 ++++++ .../primaire/CourtageStepDefinitions.java | 41 +++++++++++-------- .../PortefeuilleRepositoryMock.java | 30 ++++++++++++++ 6 files changed, 102 insertions(+), 20 deletions(-) delete mode 100644 courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/.gitkeep create mode 100644 courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java create mode 100644 courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java index 188ffea..fb692f6 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java @@ -1,15 +1,39 @@ package devoxx.lab.archihexa.courtage.domain.port.primaire; +import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleDejaExistantException; +import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleNonGereException; import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; +import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepository; + +import java.math.BigDecimal; public class Courtage implements ServiceCourtage { + private final PortefeuilleRepository portefeuilleRepository; + + public Courtage(PortefeuilleRepository portefeuilleRepository) { + this.portefeuilleRepository = portefeuilleRepository; + } + @Override - public Portefeuille creerPortefeuille(String nomPortefeuille) { - return new Portefeuille(nomPortefeuille); + public Portefeuille creerPortefeuille(String nomPortefeuille) throws PortefeuilleDejaExistantException { + if (gere(nomPortefeuille)) { + throw new PortefeuilleDejaExistantException(); + } + Portefeuille nouveauPortefeuille = new Portefeuille(nomPortefeuille); + this.portefeuilleRepository.sauvegarde(nouveauPortefeuille); + return nouveauPortefeuille; } @Override public boolean gere(String nomPortefeuille) { - return true; + return portefeuilleRepository.existe(nomPortefeuille); + } + + @Override + public BigDecimal calculerValeurPortefeuille(String nomPortefeuille) throws PortefeuilleNonGereException { + if (!gere(nomPortefeuille)) { + throw new PortefeuilleNonGereException(); + } + return BigDecimal.ZERO; } } diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java index 3dea1c9..ac16f36 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java @@ -1,9 +1,15 @@ package devoxx.lab.archihexa.courtage.domain.port.primaire; +import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleDejaExistantException; +import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleNonGereException; import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; +import java.math.BigDecimal; + public interface ServiceCourtage { - Portefeuille creerPortefeuille(String nomPortefeuille); + Portefeuille creerPortefeuille(String nomPortefeuille) throws PortefeuilleDejaExistantException; + + BigDecimal calculerValeurPortefeuille(String nomPortefeuille) throws PortefeuilleNonGereException; boolean gere(String nomPortefeuille); } diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/.gitkeep b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java new file mode 100644 index 0000000..b4941e3 --- /dev/null +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java @@ -0,0 +1,13 @@ +package devoxx.lab.archihexa.courtage.domain.port.secondaire; + +import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; + +import java.util.Optional; + +public interface PortefeuilleRepository { + boolean existe(String nomPortefeuille); + + void sauvegarde(Portefeuille portefeuille); + + Optional recupere(String id); +} diff --git a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java index 1e018db..656a984 100644 --- a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java +++ b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java @@ -1,8 +1,11 @@ package devoxx.lab.archihexa.courtage.domain.port.primaire; import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleDejaExistantException; -import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; +import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleNonGereException; import devoxx.lab.archihexa.courtage.domain.model.Achat; +import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; +import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepository; +import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepositoryMock; import io.cucumber.datatable.DataTable; import io.cucumber.java8.DataTableEntryDefinitionBody; import io.cucumber.java8.Fr; @@ -16,13 +19,20 @@ import static org.assertj.core.api.Assertions.assertThat; public class CourtageStepDefinitions implements Fr { - private final ServiceCourtage serviceCourtage = new Courtage(); + private final PortefeuilleRepository portefeuilleRepository = new PortefeuilleRepositoryMock(); + private final ServiceCourtage serviceCourtage = new Courtage(portefeuilleRepository); private Portefeuille portefeuilleCree; + private Exception thrownException = null; + private BigDecimal valeurPortefeuille = null; public CourtageStepDefinitions() { // étape 1 Quand("on demande au service de courtage la création du portefeuille {string}", (String nomPortefeuille) -> { - portefeuilleCree = serviceCourtage.creerPortefeuille(nomPortefeuille); + try { + portefeuilleCree = serviceCourtage.creerPortefeuille(nomPortefeuille); + } catch (PortefeuilleDejaExistantException e) { + thrownException = e; + } }); Alors("l'id du portefeuille créé doit être {string}", (String nomPortefeuille) -> assertThat(portefeuilleCree.getNom()).isEqualTo(nomPortefeuille)); @@ -30,21 +40,20 @@ public CourtageStepDefinitions() { assertThat(serviceCourtage.gere(nomPortefeuille)).isTrue()); // étape 2 - Alors("le portefeuille {string} n'est pas géré par le service de courtage", (String nomPortefeuille) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("une exception est levée : Portefeuille déjà géré", () -> { - throw new io.cucumber.java8.PendingException(); - }); + Alors("le portefeuille {string} n'est pas géré par le service de courtage", (String nomPortefeuille) -> assertThat(serviceCourtage.gere(nomPortefeuille)).isFalse()); + Alors("une exception est levée : Portefeuille déjà géré", () -> + assertThat(thrownException).isInstanceOf(PortefeuilleDejaExistantException.class)); Quand("on demande le calcul de la valeur du portefeuille {string}", (String nomPortefeuille) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("la valeur du portefeuille est {bigdecimal}", (BigDecimal valeur) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("une exception est levée : Portefeuille non géré", () -> { - throw new io.cucumber.java8.PendingException(); + try { + valeurPortefeuille = serviceCourtage.calculerValeurPortefeuille(nomPortefeuille); + } catch (PortefeuilleNonGereException e) { + thrownException = e; + } }); + Alors("la valeur du portefeuille est {bigdecimal}", (BigDecimal valeur) -> + assertThat(valeurPortefeuille).isEqualByComparingTo(valeur)); + Alors("une exception est levée : Portefeuille non géré", () -> + assertThat(thrownException).isInstanceOf(PortefeuilleNonGereException.class)); // étape 3 DataTableType(CoursBourse.CONVERTER); diff --git a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java new file mode 100644 index 0000000..1c71fbc --- /dev/null +++ b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java @@ -0,0 +1,30 @@ +package devoxx.lab.archihexa.courtage.domain.port.secondaire; + +import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class PortefeuilleRepositoryMock implements PortefeuilleRepository { + private final Map portefeuilles; + + public PortefeuilleRepositoryMock() { + portefeuilles = new HashMap<>(); + } + + @Override + public boolean existe(String nomPortefeuille) { + return portefeuilles.containsKey(nomPortefeuille); + } + + @Override + public void sauvegarde(Portefeuille portefeuille) { + portefeuilles.put(portefeuille.getNom(), portefeuille); + } + + @Override + public Optional recupere(String id) { + return Optional.ofNullable(portefeuilles.get(id)); + } +} From edb7746c28c8e78ae914f44e4165315a19785b73 Mon Sep 17 00:00:00 2001 From: jycr Date: Wed, 6 Apr 2022 18:12:20 +0200 Subject: [PATCH 3/9] =?UTF-8?q?:bento:=20Ajout=20solution=20=C3=A9tape=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../courtage/domain/model/Portefeuille.java | 18 ++++++++++ .../domain/port/primaire/Courtage.java | 27 ++++++++++++--- .../domain/port/primaire/ServiceCourtage.java | 3 ++ .../domain/port/secondaire/ServiceBourse.java | 7 ++++ .../primaire/CourtageStepDefinitions.java | 33 ++++++++++++------- .../port/secondaire/ServiceBourseMock.java | 17 ++++++++++ 6 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/ServiceBourse.java create mode 100644 courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/ServiceBourseMock.java diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java index 39b5fcb..6035c2a 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java @@ -1,7 +1,14 @@ package devoxx.lab.archihexa.courtage.domain.model; +import java.util.HashMap; +import java.util.Map; + +import static java.util.Collections.unmodifiableMap; +import static java.util.Optional.ofNullable; + public class Portefeuille { private final String nom; + private final Map actions = new HashMap<>(); public Portefeuille(String nom) { this.nom = nom; @@ -10,4 +17,15 @@ public Portefeuille(String nom) { public String getNom() { return nom; } + + public void ajouterAction(Achat achat) { + actions.compute( + achat.getAction(), + (action, ancienNbActions) -> ofNullable(ancienNbActions).orElse(0) + achat.getNombre() + ); + } + + public Map getActions() { + return unmodifiableMap(actions); + } } diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java index fb692f6..9779d4f 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java @@ -2,16 +2,20 @@ import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleDejaExistantException; import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleNonGereException; +import devoxx.lab.archihexa.courtage.domain.model.Achat; import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepository; +import devoxx.lab.archihexa.courtage.domain.port.secondaire.ServiceBourse; import java.math.BigDecimal; public class Courtage implements ServiceCourtage { private final PortefeuilleRepository portefeuilleRepository; + private final ServiceBourse serviceBourse; - public Courtage(PortefeuilleRepository portefeuilleRepository) { + public Courtage(PortefeuilleRepository portefeuilleRepository, ServiceBourse serviceBourse) { this.portefeuilleRepository = portefeuilleRepository; + this.serviceBourse = serviceBourse; } @Override @@ -31,9 +35,22 @@ public boolean gere(String nomPortefeuille) { @Override public BigDecimal calculerValeurPortefeuille(String nomPortefeuille) throws PortefeuilleNonGereException { - if (!gere(nomPortefeuille)) { - throw new PortefeuilleNonGereException(); - } - return BigDecimal.ZERO; + return portefeuilleRepository.recupere(nomPortefeuille) + .orElseThrow(PortefeuilleNonGereException::new) + .getActions().entrySet().stream() + .map(entry -> serviceBourse + // entry.getKey(): nom de l'action + .recupererCours(entry.getKey()) + // entry.getValue() : nombre d'action + .multiply(new BigDecimal(entry.getValue()))) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } + + @Override + public void ajouteAction(String nomPortefeuille, Achat achat) throws PortefeuilleNonGereException { + portefeuilleRepository.recupere(nomPortefeuille) + .orElseThrow(PortefeuilleNonGereException::new) + .ajouterAction(achat) + ; } } diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java index ac16f36..0bd06e8 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java @@ -2,6 +2,7 @@ import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleDejaExistantException; import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleNonGereException; +import devoxx.lab.archihexa.courtage.domain.model.Achat; import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; import java.math.BigDecimal; @@ -12,4 +13,6 @@ public interface ServiceCourtage { BigDecimal calculerValeurPortefeuille(String nomPortefeuille) throws PortefeuilleNonGereException; boolean gere(String nomPortefeuille); + + void ajouteAction(String nomPortefeuille, Achat achat) throws PortefeuilleNonGereException; } diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/ServiceBourse.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/ServiceBourse.java new file mode 100644 index 0000000..17f1e41 --- /dev/null +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/ServiceBourse.java @@ -0,0 +1,7 @@ +package devoxx.lab.archihexa.courtage.domain.port.secondaire; + +import java.math.BigDecimal; + +public interface ServiceBourse { + BigDecimal recupererCours(String action); +} diff --git a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java index 656a984..1561e72 100644 --- a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java +++ b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java @@ -6,6 +6,8 @@ import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepository; import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepositoryMock; +import devoxx.lab.archihexa.courtage.domain.port.secondaire.ServiceBourse; +import devoxx.lab.archihexa.courtage.domain.port.secondaire.ServiceBourseMock; import io.cucumber.datatable.DataTable; import io.cucumber.java8.DataTableEntryDefinitionBody; import io.cucumber.java8.Fr; @@ -20,10 +22,12 @@ public class CourtageStepDefinitions implements Fr { private final PortefeuilleRepository portefeuilleRepository = new PortefeuilleRepositoryMock(); - private final ServiceCourtage serviceCourtage = new Courtage(portefeuilleRepository); + private final ServiceBourse serviceBourse = new ServiceBourseMock(); + private final ServiceCourtage serviceCourtage = new Courtage(portefeuilleRepository, serviceBourse); private Portefeuille portefeuilleCree; private Exception thrownException = null; private BigDecimal valeurPortefeuille = null; + private BigDecimal valeurAction = null; public CourtageStepDefinitions() { // étape 1 @@ -40,7 +44,8 @@ public CourtageStepDefinitions() { assertThat(serviceCourtage.gere(nomPortefeuille)).isTrue()); // étape 2 - Alors("le portefeuille {string} n'est pas géré par le service de courtage", (String nomPortefeuille) -> assertThat(serviceCourtage.gere(nomPortefeuille)).isFalse()); + Alors("le portefeuille {string} n'est pas géré par le service de courtage", (String nomPortefeuille) -> + assertThat(serviceCourtage.gere(nomPortefeuille)).isFalse()); Alors("une exception est levée : Portefeuille déjà géré", () -> assertThat(thrownException).isInstanceOf(PortefeuilleDejaExistantException.class)); Quand("on demande le calcul de la valeur du portefeuille {string}", (String nomPortefeuille) -> { @@ -58,20 +63,24 @@ public CourtageStepDefinitions() { // étape 3 DataTableType(CoursBourse.CONVERTER); Quand("(si )les cours de bourse suivants/sont/deviennent :", (DataTable dataTable) -> - dataTable.asList(CoursBourse.class).forEach(coursBourse -> { - throw new io.cucumber.java8.PendingException(); - }) + dataTable.asList(CoursBourse.class).forEach(coursBourse -> + ((ServiceBourseMock) serviceBourse).setCours(coursBourse.action, coursBourse.valeur) + ) ); - Quand("on demande au service de bourse la valeur de l'action {string}", (String nomAction) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("la valeur récupérée pour l'action est {bigdecimal}", (BigDecimal valeurAction) -> { - throw new io.cucumber.java8.PendingException(); - }); + Quand("on demande au service de bourse la valeur de l'action {string}", (String nomAction) -> + this.valeurAction = serviceBourse.recupererCours(nomAction)); + + Alors("la valeur récupérée pour l'action est {bigdecimal}", (BigDecimal valeurAction) -> + assertThat(this.valeurAction).isEqualByComparingTo(valeurAction)); + DataTableType(AjoutAction.CONVERTER); Quand("^on demande au service de courtage d'ajouter (?:l'|les )actions? suivantes? :$", (DataTable dataTable) -> dataTable.asList(AjoutAction.class).forEach(ajoutAction -> { - throw new io.cucumber.java8.PendingException(); + try { + serviceCourtage.ajouteAction(ajoutAction.portefeuille, new Achat(ajoutAction.action, ajoutAction.nombre)); + } catch (PortefeuilleNonGereException e) { + thrownException = e; + } }) ); diff --git a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/ServiceBourseMock.java b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/ServiceBourseMock.java new file mode 100644 index 0000000..fe0700b --- /dev/null +++ b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/ServiceBourseMock.java @@ -0,0 +1,17 @@ +package devoxx.lab.archihexa.courtage.domain.port.secondaire; + +import java.math.BigDecimal; +import java.util.HashMap; + +public class ServiceBourseMock implements ServiceBourse { + HashMap map = new HashMap<>(); + + @Override + public BigDecimal recupererCours(String action) { + return map.get(action); + } + + public void setCours(String action, BigDecimal valeur) { + map.put(action, valeur); + } +} From 50498e87f4a69d970fdbd4b322c4a25124f646fd Mon Sep 17 00:00:00 2001 From: jycr Date: Fri, 11 Mar 2022 05:09:35 +0100 Subject: [PATCH 4/9] =?UTF-8?q?:bento:=20Ajout=20solution=20=C3=A9tape=204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/port/primaire/Courtage.java | 22 ++++++++++++++----- .../domain/port/primaire/ServiceCourtage.java | 2 ++ .../secondaire/PortefeuilleRepository.java | 3 +++ .../primaire/CourtageStepDefinitions.java | 11 +++++----- .../PortefeuilleRepositoryMock.java | 6 +++++ 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java index 9779d4f..3099c3b 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java @@ -33,11 +33,8 @@ public boolean gere(String nomPortefeuille) { return portefeuilleRepository.existe(nomPortefeuille); } - @Override - public BigDecimal calculerValeurPortefeuille(String nomPortefeuille) throws PortefeuilleNonGereException { - return portefeuilleRepository.recupere(nomPortefeuille) - .orElseThrow(PortefeuilleNonGereException::new) - .getActions().entrySet().stream() + private BigDecimal calculerValeurPortefeuille(Portefeuille portefeuille) { + return portefeuille.getActions().entrySet().stream() .map(entry -> serviceBourse // entry.getKey(): nom de l'action .recupererCours(entry.getKey()) @@ -46,6 +43,14 @@ public BigDecimal calculerValeurPortefeuille(String nomPortefeuille) throws Port .reduce(BigDecimal.ZERO, BigDecimal::add); } + @Override + public BigDecimal calculerValeurPortefeuille(String nomPortefeuille) throws PortefeuilleNonGereException { + return calculerValeurPortefeuille( + portefeuilleRepository.recupere(nomPortefeuille) + .orElseThrow(PortefeuilleNonGereException::new) + ); + } + @Override public void ajouteAction(String nomPortefeuille, Achat achat) throws PortefeuilleNonGereException { portefeuilleRepository.recupere(nomPortefeuille) @@ -53,4 +58,11 @@ public void ajouteAction(String nomPortefeuille, Achat achat) throws Portefeuill .ajouterAction(achat) ; } + + @Override + public BigDecimal calculerValeurEnsemblePortefeuilles() { + return portefeuilleRepository.recupereTous().stream() + .map(this::calculerValeurPortefeuille) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } } diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java index 0bd06e8..c2e4c92 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/ServiceCourtage.java @@ -15,4 +15,6 @@ public interface ServiceCourtage { boolean gere(String nomPortefeuille); void ajouteAction(String nomPortefeuille, Achat achat) throws PortefeuilleNonGereException; + + BigDecimal calculerValeurEnsemblePortefeuilles(); } diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java index b4941e3..bceb0f1 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java @@ -2,6 +2,7 @@ import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; +import java.util.Collection; import java.util.Optional; public interface PortefeuilleRepository { @@ -10,4 +11,6 @@ public interface PortefeuilleRepository { void sauvegarde(Portefeuille portefeuille); Optional recupere(String id); + + Collection recupereTous(); } diff --git a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java index 1561e72..44f01f3 100644 --- a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java +++ b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java @@ -28,6 +28,7 @@ public class CourtageStepDefinitions implements Fr { private Exception thrownException = null; private BigDecimal valeurPortefeuille = null; private BigDecimal valeurAction = null; + private BigDecimal valeurEnsemblePortefeuilles = null; public CourtageStepDefinitions() { // étape 1 @@ -85,12 +86,10 @@ public CourtageStepDefinitions() { ); // étape 4 - Quand("on demande au service de courtage le calcul de la valeur de tous les portefeuilles", () -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("la valeur pour l'ensemble des portefeuilles est {bigdecimal}", (BigDecimal valeurPortefeuilles) -> { - throw new io.cucumber.java8.PendingException(); - }); + Quand("on demande au service de courtage le calcul de la valeur de tous les portefeuilles", () -> + valeurEnsemblePortefeuilles = serviceCourtage.calculerValeurEnsemblePortefeuilles()); + Alors("la valeur pour l'ensemble des portefeuilles est {bigdecimal}", (BigDecimal valeurPortefeuilles) -> + assertThat(this.valeurEnsemblePortefeuilles).isEqualByComparingTo(valeurPortefeuilles)); // étape 8 DataTableType((Map data) -> new Achat(data.get("action"), Integer.parseInt(data.get("nombre")))); diff --git a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java index 1c71fbc..7bf0620 100644 --- a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java +++ b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java @@ -2,6 +2,7 @@ import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; +import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -27,4 +28,9 @@ public void sauvegarde(Portefeuille portefeuille) { public Optional recupere(String id) { return Optional.ofNullable(portefeuilles.get(id)); } + + @Override + public Collection recupereTous() { + return portefeuilles.values(); + } } From fe86c77f64cc19cbb5ed95caef43728e2a0000f7 Mon Sep 17 00:00:00 2001 From: jycr Date: Wed, 6 Apr 2022 18:17:49 +0200 Subject: [PATCH 5/9] =?UTF-8?q?:bento:=20Ajout=20solution=20=C3=A9tape=205?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CourtageSpringbootApplication.java | 7 +++ .../PortefeuilleRepositoryInMemoryImpl.java | 39 ++++++++++++++++ .../adapters/rest/ServiceBourseMock.java | 21 +++++++++ .../controller/CourtageResource.java | 38 ++++++++++++++-- .../springboot/CourtageStepDefinitions.java | 44 +++++++++++++------ .../courtage/domain/DomainService.java | 11 +++++ .../domain/port/primaire/Courtage.java | 2 + 7 files changed, 146 insertions(+), 16 deletions(-) create mode 100644 courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositoryInMemoryImpl.java create mode 100644 courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseMock.java create mode 100644 courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/DomainService.java diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java index b7641e2..3319417 100644 --- a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java @@ -1,18 +1,25 @@ package devoxx.lab.archihexa.courtage.application.springboot; import devoxx.lab.archihexa.courtage.application.springboot.adapters.mixin.AchatJsonDto; +import devoxx.lab.archihexa.courtage.domain.DomainService; import devoxx.lab.archihexa.courtage.domain.model.Achat; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; import org.springframework.context.event.EventListener; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import java.util.Optional; @SpringBootApplication +@ComponentScan( + basePackageClasses = {CourtageSpringbootApplication.class, DomainService.class}, + includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {DomainService.class})} +) public class CourtageSpringbootApplication { private static ConfigurableApplicationContext applicationContext = null; private int port = -1; diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositoryInMemoryImpl.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositoryInMemoryImpl.java new file mode 100644 index 0000000..b1b7f97 --- /dev/null +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositoryInMemoryImpl.java @@ -0,0 +1,39 @@ +package devoxx.lab.archihexa.courtage.application.springboot.adapters.persistence; + +import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; +import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepository; +import org.springframework.stereotype.Repository; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +@Repository +public class PortefeuilleRepositoryInMemoryImpl implements PortefeuilleRepository { + private final Map portefeuilles; + + public PortefeuilleRepositoryInMemoryImpl() { + portefeuilles = new HashMap<>(); + } + + @Override + public boolean existe(String nomPortefeuille) { + return portefeuilles.containsKey(nomPortefeuille); + } + + @Override + public void sauvegarde(Portefeuille portefeuille) { + portefeuilles.put(portefeuille.getNom(), portefeuille); + } + + @Override + public Optional recupere(String id) { + return Optional.ofNullable(portefeuilles.get(id)); + } + + @Override + public Collection recupereTous() { + return portefeuilles.values(); + } +} diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseMock.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseMock.java new file mode 100644 index 0000000..40524a6 --- /dev/null +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseMock.java @@ -0,0 +1,21 @@ +package devoxx.lab.archihexa.courtage.application.springboot.adapters.rest; + +import devoxx.lab.archihexa.courtage.domain.port.secondaire.ServiceBourse; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.HashMap; + +@Service +public class ServiceBourseMock implements ServiceBourse { + HashMap map = new HashMap<>(); + + @Override + public BigDecimal recupererCours(String action) { + return map.get(action); + } + + public void setCours(String action, BigDecimal valeur) { + map.put(action, valeur); + } +} diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java index 8a8f388..a4f814c 100644 --- a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java @@ -1,15 +1,47 @@ package devoxx.lab.archihexa.courtage.application.springboot.controller; +import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleDejaExistantException; +import devoxx.lab.archihexa.courtage.domain.port.primaire.ServiceCourtage; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import java.net.URI; import static java.util.Optional.ofNullable; @RestController @RequestMapping("/courtage") public class CourtageResource { + + private final ServiceCourtage serviceCourtage; + + public CourtageResource(ServiceCourtage serviceCourtage) { + this.serviceCourtage = serviceCourtage; + } + + @PostMapping("/portefeuilles/{nomPortefeuille}") + public ResponseEntity creationPortefeuille(@PathVariable(value = "nomPortefeuille") String nomPortefeuille) { + try { + serviceCourtage.creerPortefeuille(nomPortefeuille); + } catch (PortefeuilleDejaExistantException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Portefeuille déjà géré"); + } + URI uri = ServletUriComponentsBuilder.fromCurrentRequest().build(nomPortefeuille); + return ResponseEntity.created(uri).build(); + } + + @GetMapping("/portefeuilles/{nomPortefeuille}") + public ResponseEntity portefeuilleExiste(@PathVariable(value = "nomPortefeuille") String nomPortefeuille) { + if (serviceCourtage.gere(nomPortefeuille)) { + return ResponseEntity.ok().build(); + } + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } + @GetMapping(path = "/version", produces = MediaType.TEXT_PLAIN_VALUE) public String version() { return ofNullable(CourtageResource.class.getPackage().getImplementationVersion()) diff --git a/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java b/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java index b241a4e..e212205 100644 --- a/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java +++ b/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java @@ -6,6 +6,7 @@ import io.restassured.mapper.ObjectMapper; import io.restassured.mapper.ObjectMapperDeserializationContext; import io.restassured.mapper.ObjectMapperSerializationContext; +import io.restassured.response.ValidatableResponse; import java.math.BigDecimal; import java.text.NumberFormat; @@ -14,7 +15,10 @@ import java.util.Map; import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static io.restassured.RestAssured.port; +import static io.restassured.RestAssured.when; import static java.util.Optional.ofNullable; +import static org.hamcrest.Matchers.equalTo; public class CourtageStepDefinitions implements Fr { private static final ObjectMapper BIGDECIMAL_MAPPER = new ObjectMapper() { @@ -32,25 +36,39 @@ public Object serialize(ObjectMapperSerializationContext context) { } }; + private ValidatableResponse response; + public CourtageStepDefinitions() { CourtageSpringbootApplication.raz(); // étape 5 - Quand("on demande au service de courtage la création du portefeuille {string}", (String nomPortefeuille) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("l'id du portefeuille créé doit être {string}", (String nomPortefeuille) -> { - throw new io.cucumber.java8.PendingException(); - }); + Quand("on demande au service de courtage la création du portefeuille {string}", (String nomPortefeuille) -> + response = when() + .post("/courtage/portefeuilles/" + nomPortefeuille) + .then()); + Alors("l'id du portefeuille créé doit être {string}", (String nomPortefeuille) -> + response + .assertThat() + .statusCode(201) + .header("location", "http://localhost:" + port + "/courtage/portefeuilles/" + nomPortefeuille)); Alors("le portefeuille {string} est géré par le service de courtage", (String nomPortefeuille) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("le portefeuille {string} n'est pas géré par le service de courtage", (String nomPortefeuille) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("une exception est levée : Portefeuille déjà géré", () -> { - throw new io.cucumber.java8.PendingException(); + when() + .get("/courtage/portefeuilles/" + nomPortefeuille) + .then() + .assertThat() + .statusCode(200); }); + Alors("le portefeuille {string} n'est pas géré par le service de courtage", (String nomPortefeuille) -> + when() + .get("/courtage/portefeuilles/" + nomPortefeuille) + .then() + .assertThat() + .statusCode(404)); + Alors("une exception est levée : Portefeuille déjà géré", () -> + response + .assertThat() + .statusCode(400) + .body(equalTo("Portefeuille déjà géré"))); // étape 6 Quand("on demande le calcul de la valeur du portefeuille {string}", (String nomPortefeuille) -> { diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/DomainService.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/DomainService.java new file mode 100644 index 0000000..27b480c --- /dev/null +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/DomainService.java @@ -0,0 +1,11 @@ +package devoxx.lab.archihexa.courtage.domain; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE}) +@Retention(value = RetentionPolicy.RUNTIME) +public @interface DomainService { +} diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java index 3099c3b..695c4ee 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java @@ -1,5 +1,6 @@ package devoxx.lab.archihexa.courtage.domain.port.primaire; +import devoxx.lab.archihexa.courtage.domain.DomainService; import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleDejaExistantException; import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleNonGereException; import devoxx.lab.archihexa.courtage.domain.model.Achat; @@ -9,6 +10,7 @@ import java.math.BigDecimal; +@DomainService public class Courtage implements ServiceCourtage { private final PortefeuilleRepository portefeuilleRepository; private final ServiceBourse serviceBourse; From 3f1895b3287fa0b9331b5722f5d4ec9fcb03e3f9 Mon Sep 17 00:00:00 2001 From: jycr Date: Wed, 6 Apr 2022 18:22:33 +0200 Subject: [PATCH 6/9] =?UTF-8?q?:bento:=20Ajout=20solution=20=C3=A9tape=206?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- courtage-application-springboot/pom.xml | 5 --- .../CourtageSpringbootApplication.java | 4 ++ .../PortefeuilleRepositoryInMemoryImpl.java | 39 ----------------- .../PortefeuilleRepositorySpringDataImpl.java | 43 +++++++++++++++++++ .../PortefeuilleSpringDataCrudRepository.java | 10 +++++ .../controller/CourtageResource.java | 26 +++++++++++ .../src/main/resources/META-INF/orm.xml | 17 ++++++++ .../springboot/CourtageStepDefinitions.java | 29 +++++++++---- .../courtage/domain/model/Portefeuille.java | 8 +++- .../domain/port/primaire/Courtage.java | 10 ++--- .../secondaire/PortefeuilleRepository.java | 5 ++- .../PortefeuilleRepositoryMock.java | 11 +++-- 12 files changed, 144 insertions(+), 63 deletions(-) delete mode 100644 courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositoryInMemoryImpl.java create mode 100644 courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositorySpringDataImpl.java create mode 100644 courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleSpringDataCrudRepository.java create mode 100644 courtage-application-springboot/src/main/resources/META-INF/orm.xml diff --git a/courtage-application-springboot/pom.xml b/courtage-application-springboot/pom.xml index fdc5997..d8108de 100644 --- a/courtage-application-springboot/pom.xml +++ b/courtage-application-springboot/pom.xml @@ -53,25 +53,21 @@ cucumber-java8 test - io.cucumber cucumber-junit-platform-engine test - org.junit.platform junit-platform-suite test - org.junit.jupiter junit-jupiter test - org.assertj assertj-core @@ -92,7 +88,6 @@ xml-path test - com.github.tomakehurst wiremock-jre8 diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java index 3319417..2841553 100644 --- a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java @@ -3,6 +3,7 @@ import devoxx.lab.archihexa.courtage.application.springboot.adapters.mixin.AchatJsonDto; import devoxx.lab.archihexa.courtage.domain.DomainService; import devoxx.lab.archihexa.courtage.domain.model.Achat; +import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepository; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent; @@ -42,6 +43,9 @@ public static Optional getPort() { } static void raz() { + Optional.ofNullable(applicationContext) + .map(ctx -> ctx.getBean(PortefeuilleRepository.class)) + .ifPresent(PortefeuilleRepository::purge); } @EventListener diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositoryInMemoryImpl.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositoryInMemoryImpl.java deleted file mode 100644 index b1b7f97..0000000 --- a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositoryInMemoryImpl.java +++ /dev/null @@ -1,39 +0,0 @@ -package devoxx.lab.archihexa.courtage.application.springboot.adapters.persistence; - -import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; -import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepository; -import org.springframework.stereotype.Repository; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -@Repository -public class PortefeuilleRepositoryInMemoryImpl implements PortefeuilleRepository { - private final Map portefeuilles; - - public PortefeuilleRepositoryInMemoryImpl() { - portefeuilles = new HashMap<>(); - } - - @Override - public boolean existe(String nomPortefeuille) { - return portefeuilles.containsKey(nomPortefeuille); - } - - @Override - public void sauvegarde(Portefeuille portefeuille) { - portefeuilles.put(portefeuille.getNom(), portefeuille); - } - - @Override - public Optional recupere(String id) { - return Optional.ofNullable(portefeuilles.get(id)); - } - - @Override - public Collection recupereTous() { - return portefeuilles.values(); - } -} diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositorySpringDataImpl.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositorySpringDataImpl.java new file mode 100644 index 0000000..4e2b559 --- /dev/null +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleRepositorySpringDataImpl.java @@ -0,0 +1,43 @@ +package devoxx.lab.archihexa.courtage.application.springboot.adapters.persistence; + +import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; +import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +@Repository +public class PortefeuilleRepositorySpringDataImpl implements PortefeuilleRepository { + private final PortefeuilleSpringDataCrudRepository repo; + + public PortefeuilleRepositorySpringDataImpl(PortefeuilleSpringDataCrudRepository repo) { + this.repo = repo; + } + + @Override + public boolean existe(String nomPortefeuille) { + return repo.existsById(nomPortefeuille); + } + + @Override + public void sauvegarde(Portefeuille portefeuille) { + repo.save(portefeuille); + } + + @Override + public Optional recupere(String id) { + return repo.findById(id); + } + + @Override + public Stream recupereTous() { + return StreamSupport.stream(repo.findAll().spliterator(), false); + } + + @Override + public void purge() { + repo.deleteAll(); + } +} diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleSpringDataCrudRepository.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleSpringDataCrudRepository.java new file mode 100644 index 0000000..6944464 --- /dev/null +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/persistence/PortefeuilleSpringDataCrudRepository.java @@ -0,0 +1,10 @@ +package devoxx.lab.archihexa.courtage.application.springboot.adapters.persistence; + +import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; + +import java.util.stream.Stream; + +public interface PortefeuilleSpringDataCrudRepository extends CrudRepository { +} diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java index a4f814c..c094426 100644 --- a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java @@ -1,6 +1,8 @@ package devoxx.lab.archihexa.courtage.application.springboot.controller; import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleDejaExistantException; +import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleNonGereException; +import devoxx.lab.archihexa.courtage.domain.model.Achat; import devoxx.lab.archihexa.courtage.domain.port.primaire.ServiceCourtage; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -9,6 +11,8 @@ import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import javax.validation.Valid; +import java.math.BigDecimal; import java.net.URI; import static java.util.Optional.ofNullable; @@ -34,6 +38,19 @@ public ResponseEntity creationPortefeuille(@PathVariable(value = "nomPor return ResponseEntity.created(uri).build(); } + @PostMapping("/portefeuilles/{nomPortefeuille}/actions") + public ResponseEntity ajoutActionsDansPortefeuille( + @PathVariable(value = "nomPortefeuille") String nomPortefeuille, + @Valid @RequestBody Achat achat + ) { + try { + serviceCourtage.ajouteAction(nomPortefeuille, achat); + } catch (PortefeuilleNonGereException e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Portefeuille non géré"); + } + return ResponseEntity.ok().build(); + } + @GetMapping("/portefeuilles/{nomPortefeuille}") public ResponseEntity portefeuilleExiste(@PathVariable(value = "nomPortefeuille") String nomPortefeuille) { if (serviceCourtage.gere(nomPortefeuille)) { @@ -42,6 +59,15 @@ public ResponseEntity portefeuilleExiste(@PathVariable(value = "nomPortefe throw new ResponseStatusException(HttpStatus.NOT_FOUND); } + @GetMapping("/portefeuilles/{nomPortefeuille}/valorisation") + public ResponseEntity calculValorisationPortefeuille(@PathVariable(value = "nomPortefeuille") String nomPortefeuille) { + if (serviceCourtage.gere(nomPortefeuille)) { + return ResponseEntity.ok(BigDecimal.ZERO.toString()); + } else { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Portefeuille non géré"); + } + } + @GetMapping(path = "/version", produces = MediaType.TEXT_PLAIN_VALUE) public String version() { return ofNullable(CourtageResource.class.getPackage().getImplementationVersion()) diff --git a/courtage-application-springboot/src/main/resources/META-INF/orm.xml b/courtage-application-springboot/src/main/resources/META-INF/orm.xml new file mode 100644 index 0000000..0bd4543 --- /dev/null +++ b/courtage-application-springboot/src/main/resources/META-INF/orm.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java b/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java index e212205..c7f8d7b 100644 --- a/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java +++ b/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java @@ -18,6 +18,7 @@ import static io.restassured.RestAssured.port; import static io.restassured.RestAssured.when; import static java.util.Optional.ofNullable; +import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.equalTo; public class CourtageStepDefinitions implements Fr { @@ -71,15 +72,25 @@ public CourtageStepDefinitions() { .body(equalTo("Portefeuille déjà géré"))); // étape 6 - Quand("on demande le calcul de la valeur du portefeuille {string}", (String nomPortefeuille) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("la valeur du portefeuille est {bigdecimal}", (BigDecimal valeur) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("une exception est levée : Portefeuille non géré", () -> { - throw new io.cucumber.java8.PendingException(); - }); + Quand("on demande le calcul de la valeur du portefeuille {string}", (String nomPortefeuille) -> + response = when() + .get("/courtage/portefeuilles/" + nomPortefeuille + "/valorisation") + .then()); + Alors("la valeur du portefeuille est {bigdecimal}", (BigDecimal valeur) -> + assertThat( + response + .assertThat() + .statusCode(200) + .extract() + .body() + .as(BigDecimal.class, BIGDECIMAL_MAPPER) + ) + .isEqualByComparingTo(valeur)); + Alors("une exception est levée : Portefeuille non géré", () -> + response + .assertThat() + .statusCode(404) + .body(equalTo("Portefeuille non géré"))); // étape 7 DataTableType(CoursBourse.CONVERTER); diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java index 6035c2a..3da2a50 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/model/Portefeuille.java @@ -7,9 +7,15 @@ import static java.util.Optional.ofNullable; public class Portefeuille { - private final String nom; + private String nom; private final Map actions = new HashMap<>(); + /** + * Constructeur utilisé pour le mapping JPA. + */ + Portefeuille() { + } + public Portefeuille(String nom) { this.nom = nom; } diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java index 695c4ee..f16d6f8 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java @@ -55,15 +55,15 @@ public BigDecimal calculerValeurPortefeuille(String nomPortefeuille) throws Port @Override public void ajouteAction(String nomPortefeuille, Achat achat) throws PortefeuilleNonGereException { - portefeuilleRepository.recupere(nomPortefeuille) - .orElseThrow(PortefeuilleNonGereException::new) - .ajouterAction(achat) - ; + Portefeuille portefeuille = portefeuilleRepository.recupere(nomPortefeuille) + .orElseThrow(PortefeuilleNonGereException::new); + portefeuille.ajouterAction(achat); + portefeuilleRepository.sauvegarde(portefeuille); } @Override public BigDecimal calculerValeurEnsemblePortefeuilles() { - return portefeuilleRepository.recupereTous().stream() + return portefeuilleRepository.recupereTous() .map(this::calculerValeurPortefeuille) .reduce(BigDecimal.ZERO, BigDecimal::add); } diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java index bceb0f1..9bd5c62 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepository.java @@ -4,6 +4,7 @@ import java.util.Collection; import java.util.Optional; +import java.util.stream.Stream; public interface PortefeuilleRepository { boolean existe(String nomPortefeuille); @@ -12,5 +13,7 @@ public interface PortefeuilleRepository { Optional recupere(String id); - Collection recupereTous(); + Stream recupereTous(); + + void purge(); } diff --git a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java index 7bf0620..5d9b2e2 100644 --- a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java +++ b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/secondaire/PortefeuilleRepositoryMock.java @@ -2,10 +2,10 @@ import devoxx.lab.archihexa.courtage.domain.model.Portefeuille; -import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.stream.Stream; public class PortefeuilleRepositoryMock implements PortefeuilleRepository { private final Map portefeuilles; @@ -30,7 +30,12 @@ public Optional recupere(String id) { } @Override - public Collection recupereTous() { - return portefeuilles.values(); + public Stream recupereTous() { + return portefeuilles.values().stream(); + } + + @Override + public void purge() { + portefeuilles.clear(); } } From 25e7833dd3ddb0c5ec9769ad004d410b277ba520 Mon Sep 17 00:00:00 2001 From: jycr Date: Wed, 6 Apr 2022 18:34:59 +0200 Subject: [PATCH 7/9] =?UTF-8?q?:bento:=20Ajout=20solution=20=C3=A9tape=207?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rest/ServiceBourseHttpAdapter.java | 45 +++++++++++++++ .../adapters/rest/ServiceBourseMock.java | 21 ------- .../controller/CourtageResource.java | 12 ++-- .../springboot/CourtageStepDefinitions.java | 56 +++++++++++++++---- 4 files changed, 98 insertions(+), 36 deletions(-) create mode 100644 courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseHttpAdapter.java delete mode 100644 courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseMock.java diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseHttpAdapter.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseHttpAdapter.java new file mode 100644 index 0000000..d2a264d --- /dev/null +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseHttpAdapter.java @@ -0,0 +1,45 @@ +package devoxx.lab.archihexa.courtage.application.springboot.adapters.rest; + +import devoxx.lab.archihexa.courtage.domain.port.secondaire.ServiceBourse; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.math.BigDecimal; + +import static java.util.Optional.ofNullable; + +@Service +public class ServiceBourseHttpAdapter implements ServiceBourse { + + private final RestTemplate restTemplate; + private final String bourseUri; + + public ServiceBourseHttpAdapter(@Value("${application.bourse.baseUri}") String bourseUri) { + this.bourseUri = bourseUri; + this.restTemplate = new RestTemplate(); + } + + @Override + public BigDecimal recupererCours(String action) { + return ofNullable( + restTemplate + .getForEntity(bourseUri + "/finance/quote/" + action, Quote.class) + .getBody() + ) + .map(Quote::getRegularMarketPriceAsBigDecimal) + .orElseThrow(); + } + + static class Quote { + private String regularMarketPrice; + + void setRegularMarketPrice(String regularMarketPrice) { + this.regularMarketPrice = regularMarketPrice; + } + + BigDecimal getRegularMarketPriceAsBigDecimal() { + return new BigDecimal(regularMarketPrice); + } + } +} diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseMock.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseMock.java deleted file mode 100644 index 40524a6..0000000 --- a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/adapters/rest/ServiceBourseMock.java +++ /dev/null @@ -1,21 +0,0 @@ -package devoxx.lab.archihexa.courtage.application.springboot.adapters.rest; - -import devoxx.lab.archihexa.courtage.domain.port.secondaire.ServiceBourse; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.util.HashMap; - -@Service -public class ServiceBourseMock implements ServiceBourse { - HashMap map = new HashMap<>(); - - @Override - public BigDecimal recupererCours(String action) { - return map.get(action); - } - - public void setCours(String action, BigDecimal valeur) { - map.put(action, valeur); - } -} diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java index c094426..d87ea1b 100644 --- a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java @@ -12,7 +12,6 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import javax.validation.Valid; -import java.math.BigDecimal; import java.net.URI; import static java.util.Optional.ofNullable; @@ -61,13 +60,18 @@ public ResponseEntity portefeuilleExiste(@PathVariable(value = "nomPortefe @GetMapping("/portefeuilles/{nomPortefeuille}/valorisation") public ResponseEntity calculValorisationPortefeuille(@PathVariable(value = "nomPortefeuille") String nomPortefeuille) { - if (serviceCourtage.gere(nomPortefeuille)) { - return ResponseEntity.ok(BigDecimal.ZERO.toString()); - } else { + try { + return ResponseEntity.ok(serviceCourtage.calculerValeurPortefeuille(nomPortefeuille).toString()); + } catch (PortefeuilleNonGereException e) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Portefeuille non géré"); } } + @GetMapping("/portefeuilles/avoirs") + public ResponseEntity valeurEnsemblePortefeuilles() { + return ResponseEntity.ok(serviceCourtage.calculerValeurEnsemblePortefeuilles().toString()); + } + @GetMapping(path = "/version", produces = MediaType.TEXT_PLAIN_VALUE) public String version() { return ofNullable(CourtageResource.class.getPackage().getImplementationVersion()) diff --git a/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java b/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java index c7f8d7b..092f5d9 100644 --- a/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java +++ b/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java @@ -1,8 +1,11 @@ package devoxx.lab.archihexa.courtage.application.springboot; +import devoxx.lab.archihexa.courtage.domain.model.Achat; import io.cucumber.datatable.DataTable; import io.cucumber.java8.DataTableEntryDefinitionBody; import io.cucumber.java8.Fr; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.http.ContentType; import io.restassured.mapper.ObjectMapper; import io.restassured.mapper.ObjectMapperDeserializationContext; import io.restassured.mapper.ObjectMapperSerializationContext; @@ -14,9 +17,10 @@ import java.util.Locale; import java.util.Map; +import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.*; -import static io.restassured.RestAssured.port; -import static io.restassured.RestAssured.when; +import static devoxx.lab.archihexa.courtage.application.springboot.CucumberLifecycleHandler.getApiBourseUrl; +import static io.restassured.RestAssured.*; import static java.util.Optional.ofNullable; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.equalTo; @@ -107,23 +111,53 @@ public CourtageStepDefinitions() { }) ); Quand("on demande au service de bourse la valeur de l'action {string}", (String nomAction) -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("la valeur récupérée pour l'action est {bigdecimal}", (BigDecimal valeurAction) -> { - throw new io.cucumber.java8.PendingException(); + response = given().spec( + new RequestSpecBuilder() + .setBaseUri(getApiBourseUrl()) + .setBasePath("/finance/quote/") + .build() + ).when() + .get(nomAction) + .then(); }); + Alors("la valeur récupérée pour l'action est {bigdecimal}", (BigDecimal valeurAction) -> + assertThat( + new BigDecimal( + response + .assertThat() + .statusCode(200) + .extract() + .jsonPath() + .getString("regularMarketPrice") + ) + ) + .isEqualByComparingTo(valeurAction)); + DataTableType(AjoutAction.CONVERTER); Quand("^on demande au service de courtage d'ajouter (?:l'|les )actions? suivantes? :$", (DataTable dataTable) -> dataTable.asList(AjoutAction.class).forEach(ajoutAction -> { - throw new io.cucumber.java8.PendingException(); + response = given() + .contentType(ContentType.JSON) + .body(new Achat(ajoutAction.action, ajoutAction.nombre)) + .when() + .post("/courtage/portefeuilles/" + ajoutAction.portefeuille + "/actions") + .then(); }) ); Quand("on demande au service de courtage le calcul de la valeur de tous les portefeuilles", () -> { - throw new io.cucumber.java8.PendingException(); - }); - Alors("la valeur pour l'ensemble des portefeuilles est {bigdecimal}", (BigDecimal valeurPortefeuilles) -> { - throw new io.cucumber.java8.PendingException(); + response = when() + .get("/courtage/portefeuilles/avoirs") + .then(); }); + Alors("la valeur pour l'ensemble des portefeuilles est {bigdecimal}", (BigDecimal valeurPortefeuilles) -> assertThat( + response + .assertThat() + .statusCode(200) + .extract() + .body() + .as(BigDecimal.class, BIGDECIMAL_MAPPER) + ) + .isEqualByComparingTo(valeurPortefeuilles)); } private static class CoursBourse { From 9431e9c36dcaa0585d873c4d94f38b36042ce0c1 Mon Sep 17 00:00:00 2001 From: jycr Date: Thu, 7 Apr 2022 00:15:03 +0200 Subject: [PATCH 8/9] =?UTF-8?q?:bento:=20Ajout=20solution=20=C3=A9tape=208?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CourtageResource.java | 14 ++++++++++ .../springboot/CourtageStepDefinitions.java | 6 +++++ .../primaire/CourtageStepDefinitions.java | 26 +++++++++++++++++-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java index d87ea1b..1d3c8d7 100644 --- a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/controller/CourtageResource.java @@ -7,17 +7,21 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.*; import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import javax.validation.Valid; import java.net.URI; +import java.util.stream.Collectors; import static java.util.Optional.ofNullable; @RestController @RequestMapping("/courtage") +@Validated public class CourtageResource { private final ServiceCourtage serviceCourtage; @@ -26,6 +30,16 @@ public CourtageResource(ServiceCourtage serviceCourtage) { this.serviceCourtage = serviceCourtage; } + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + ResponseEntity handleConstraintViolationException(MethodArgumentNotValidException e) { + return ResponseEntity + .status(HttpStatus.BAD_REQUEST) + .body(e.getFieldErrors().stream() + .map(fe -> "\t" + fe.getField() + " " + fe.getDefaultMessage()) + .collect(Collectors.joining("\n", "Donnée(s) erronée(s): \\n\"", ""))); + } + @PostMapping("/portefeuilles/{nomPortefeuille}") public ResponseEntity creationPortefeuille(@PathVariable(value = "nomPortefeuille") String nomPortefeuille) { try { diff --git a/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java b/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java index 092f5d9..ea6fbc1 100644 --- a/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java +++ b/courtage-application-springboot/src/test/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageStepDefinitions.java @@ -158,6 +158,12 @@ public CourtageStepDefinitions() { .as(BigDecimal.class, BIGDECIMAL_MAPPER) ) .isEqualByComparingTo(valeurPortefeuilles)); + // étape 8 + Alors("une exception est levée : Donnée erronée avec le message {string}", (String message) -> + response + .assertThat() + .statusCode(400) + .body(equalTo("Donnée(s) erronée(s): \n" + "\t" + message))); } private static class CoursBourse { diff --git a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java index 44f01f3..5de7bd3 100644 --- a/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java +++ b/courtage-domain/src/test/java/devoxx/lab/archihexa/courtage/domain/port/primaire/CourtageStepDefinitions.java @@ -11,12 +11,19 @@ import io.cucumber.datatable.DataTable; import io.cucumber.java8.DataTableEntryDefinitionBody; import io.cucumber.java8.Fr; +import org.assertj.core.groups.Tuple; +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; import java.math.BigDecimal; import java.text.NumberFormat; import java.text.ParseException; import java.util.Locale; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; @@ -24,13 +31,22 @@ public class CourtageStepDefinitions implements Fr { private final PortefeuilleRepository portefeuilleRepository = new PortefeuilleRepositoryMock(); private final ServiceBourse serviceBourse = new ServiceBourseMock(); private final ServiceCourtage serviceCourtage = new Courtage(portefeuilleRepository, serviceBourse); + private final Validator validator; + private Achat achat; private Portefeuille portefeuilleCree; private Exception thrownException = null; private BigDecimal valeurPortefeuille = null; private BigDecimal valeurAction = null; private BigDecimal valeurEnsemblePortefeuilles = null; + static { + // Pour s'assurer des messages BeanValidation en Fr + Locale.setDefault(Locale.FRANCE); + } + public CourtageStepDefinitions() { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + validator = factory.getValidator(); // étape 1 Quand("on demande au service de courtage la création du portefeuille {string}", (String nomPortefeuille) -> { try { @@ -94,10 +110,16 @@ public CourtageStepDefinitions() { // étape 8 DataTableType((Map data) -> new Achat(data.get("action"), Integer.parseInt(data.get("nombre")))); Soit("l'achat", (Achat achat) -> { - throw new io.cucumber.java8.PendingException(); + this.achat = achat; }); Alors("l'achat est invalide avec l'erreur", (DataTable expected) -> { - throw new io.cucumber.java8.PendingException(); + Set> violations = validator.validate(achat); + assertThat(violations) + .extracting("interpolatedMessage", "propertyPath.currentLeafNode.name") + .containsExactlyInAnyOrderElementsOf( + expected.asMaps().stream() + .map(e -> new Tuple(e.get("message"), e.get("propriété"))) + .collect(Collectors.toList())); }); } From a302839468103e7b91da08e6387f64e8d4fb9931 Mon Sep 17 00:00:00 2001 From: Bastien JANSEN Date: Fri, 8 Apr 2022 10:30:23 +0200 Subject: [PATCH 9/9] refact: remplace l'annotation DomainService par une annotation JSR-330 --- .../springboot/CourtageSpringbootApplication.java | 6 ++---- courtage-domain/pom.xml | 4 ++++ .../lab/archihexa/courtage/domain/DomainService.java | 11 ----------- .../courtage/domain/port/primaire/Courtage.java | 4 ++-- 4 files changed, 8 insertions(+), 17 deletions(-) delete mode 100644 courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/DomainService.java diff --git a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java index 2841553..9ad9710 100644 --- a/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java +++ b/courtage-application-springboot/src/main/java/devoxx/lab/archihexa/courtage/application/springboot/CourtageSpringbootApplication.java @@ -1,8 +1,8 @@ package devoxx.lab.archihexa.courtage.application.springboot; import devoxx.lab.archihexa.courtage.application.springboot.adapters.mixin.AchatJsonDto; -import devoxx.lab.archihexa.courtage.domain.DomainService; import devoxx.lab.archihexa.courtage.domain.model.Achat; +import devoxx.lab.archihexa.courtage.domain.port.primaire.ServiceCourtage; import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepository; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -10,7 +10,6 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.FilterType; import org.springframework.context.event.EventListener; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @@ -18,8 +17,7 @@ @SpringBootApplication @ComponentScan( - basePackageClasses = {CourtageSpringbootApplication.class, DomainService.class}, - includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {DomainService.class})} + basePackageClasses = {CourtageSpringbootApplication.class, ServiceCourtage.class} ) public class CourtageSpringbootApplication { private static ConfigurableApplicationContext applicationContext = null; diff --git a/courtage-domain/pom.xml b/courtage-domain/pom.xml index 5483eb0..aba1b62 100644 --- a/courtage-domain/pom.xml +++ b/courtage-domain/pom.xml @@ -18,6 +18,10 @@ javax.validation validation-api + + jakarta.annotation + jakarta.annotation-api + io.cucumber diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/DomainService.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/DomainService.java deleted file mode 100644 index 27b480c..0000000 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/DomainService.java +++ /dev/null @@ -1,11 +0,0 @@ -package devoxx.lab.archihexa.courtage.domain; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ElementType.TYPE}) -@Retention(value = RetentionPolicy.RUNTIME) -public @interface DomainService { -} diff --git a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java index f16d6f8..b156099 100644 --- a/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java +++ b/courtage-domain/src/main/java/devoxx/lab/archihexa/courtage/domain/port/primaire/Courtage.java @@ -1,6 +1,5 @@ package devoxx.lab.archihexa.courtage.domain.port.primaire; -import devoxx.lab.archihexa.courtage.domain.DomainService; import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleDejaExistantException; import devoxx.lab.archihexa.courtage.domain.exception.PortefeuilleNonGereException; import devoxx.lab.archihexa.courtage.domain.model.Achat; @@ -8,9 +7,10 @@ import devoxx.lab.archihexa.courtage.domain.port.secondaire.PortefeuilleRepository; import devoxx.lab.archihexa.courtage.domain.port.secondaire.ServiceBourse; +import javax.annotation.ManagedBean; import java.math.BigDecimal; -@DomainService +@ManagedBean public class Courtage implements ServiceCourtage { private final PortefeuilleRepository portefeuilleRepository; private final ServiceBourse serviceBourse;