diff --git a/README.md b/README.md index f8b2e81eb8ea8461f546ccfac69b5cb436c4c63c..d24a9b54217fd8368f8632ef5488574b66a6e7df 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,18 @@ ##### - SpringBoot version 3.4.3 -##### - Maven +##### - Maven version 3.9 ##### - PostgresSQL version 15.7 +##### - Flyway version 10.20.1 + +##### - AssertJ/Junit5 + +##### - Mockito version 5.12.2 + +##### - Lombok + ### L'objectif Une API fonctionnelle avec des endpoints qui permettent de: @@ -37,7 +45,7 @@ L'API est principalement composée en trois domaines : Pour lancer la database, vous devez utilisez la commande au niveau de la racine du projet: ``` -cd db +cd docker docker compose up -d ``` @@ -56,21 +64,27 @@ mvn spring-boot:run Il est possible de visualiser les endpoints via cette URL: http://localhost:8080/swagger-ui/index.html +Un fichier exemple.http est également fourni pour essayer les endpoints + ### Le reste à faire et évolutions envisageables En reste à faire: -- Mettre des tests d'intégrations sur les repository qui n'en ont pas. -- Faire un test end-to-end avec un MockMVC +- Augmenter la couverture de test notamment en mettant en place des tests end-to-end pour m'assurer des retours + des endpoints en s'aidant d'outils comme MockMVC -Évolution possible: +Évolutions métiers: -- Donner la possibilité au bloc d'être associé à plusieurs parcs pour une attribution plus fine et complète de l' - énergie. +- Donner la possibilité au bloc d'être associé à plusieurs parcs pour une attribution plus fine et complète de + l'énergie. - Mettre un prix à l'énergie produit par un parc et rajouter ainsi une contrainte d'attribution d'énergie qui ne peut descendre en dessous du prix plancher du bloc. - Mettre en place de la logique concernant le temps sur les blocs d'une même offre (pour éviter que 2 blocs puissent se chevaucher sur une même période) + +Évolutions techniques pour une MEP: + - Mettre en place une sécurité sur les endpoints et ce que ça implique avec (système de rôle et de permission, utilisation d'outils comme Keycloak, etc...) +- Mise en place de variable d'environnement et de secrets - Création d'une CI/CD pour faciliter le déploiement et s'assurer de la qualité du code. diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 2f515d1291486339667fd618602d908781da0e79..12569e5a501c9899e907027aabc46a9e509ee8d8 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.9" - networks: agregio-network: @@ -9,7 +7,7 @@ services: image: agregio_db container_name: agregio_db networks: - - game + - agregio-network restart: always ports: - "5432:5432" diff --git a/examples.http b/examples.http index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d3145ece75d7d3c94ac3072a46da8053935bb9f5 100644 --- a/examples.http +++ b/examples.http @@ -0,0 +1,43 @@ +### Create a powerplant +POST http://localhost:8080/powerplants +Content-Type: application/json + +{ + "name": "SolarPark1", + "type": "SOLAR", + "capacityProduction": 750 +} + +### Create an offer +POST http://localhost:8080/offers +Content-Type: application/json + +{ + "market": "Réserve Primaire", + "blocks": [ + { + "startTime": "00:00", + "endTime": "03:00", + "production": 500.0, + "floorPrice": 30.0 + }, + { + "startTime": "03:00", + "endTime": "06:00", + "production": 50.0, + "floorPrice": 28.0 + } + ] +} + +### Get a powerplant by his ID +GET http://localhost:8080/powerplants/1 + +### Get all powerplants from a market +GET http://localhost:8080/powerplants?market=Réserve Primaire + +### Get an offer by his ID +GET http://localhost:8080/offers/1 + +### Get all offers of a market +GET http://localhost:8080/offers?market=Réserve Secondaire \ No newline at end of file diff --git a/src/main/java/takima/example/agregiokata/features/block/entity/Block.java b/src/main/java/takima/example/agregiokata/features/block/entity/Block.java index db7938af067e3b0486ca0b72e288b2415307c833..e3ba1e7ea92bb1d9e24a0bc2d8c5d2d45f229145 100644 --- a/src/main/java/takima/example/agregiokata/features/block/entity/Block.java +++ b/src/main/java/takima/example/agregiokata/features/block/entity/Block.java @@ -46,7 +46,7 @@ public class Block { @ManyToOne(fetch = FetchType.LAZY) private Offer offer; - @ManyToOne(fetch = FetchType.EAGER) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "powerplant_id") @ToString.Exclude private PowerPlant plant; diff --git a/src/main/java/takima/example/agregiokata/features/block/mapper/BlockMapper.java b/src/main/java/takima/example/agregiokata/features/block/mapper/BlockMapper.java index acb834146c7019c04256a31a9300b4a81f000082..1264c6360e085448752be4a56cb4a6becf9e0fb4 100644 --- a/src/main/java/takima/example/agregiokata/features/block/mapper/BlockMapper.java +++ b/src/main/java/takima/example/agregiokata/features/block/mapper/BlockMapper.java @@ -2,7 +2,7 @@ package takima.example.agregiokata.features.block.mapper; import org.springframework.stereotype.Component; import takima.example.agregiokata.features.block.entity.Block; -import takima.example.agregiokata.features.block.model.BlockCreationRequest; +import takima.example.agregiokata.features.block.model.BlockCreationDTO; import takima.example.agregiokata.features.block.model.BlockDTO; import takima.example.agregiokata.features.powerplant.mapper.PowerPlantMapper; @@ -28,7 +28,7 @@ public class BlockMapper { ); } - public Block toEntity(BlockCreationRequest request) { + public Block toEntity(BlockCreationDTO request) { return Block.builder() .startTime(request.startTime()) .endTime(request.endTime()) @@ -37,7 +37,7 @@ public class BlockMapper { .build(); } - public List<Block> toEntities(List<BlockCreationRequest> requests) { + public List<Block> toEntities(List<BlockCreationDTO> requests) { return requests.stream().map(this::toEntity).toList(); } } diff --git a/src/main/java/takima/example/agregiokata/features/block/model/BlockCreationDTO.java b/src/main/java/takima/example/agregiokata/features/block/model/BlockCreationDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..7b91280d45b50dfe35e74e71aa0fe7a1b265b705 --- /dev/null +++ b/src/main/java/takima/example/agregiokata/features/block/model/BlockCreationDTO.java @@ -0,0 +1,6 @@ +package takima.example.agregiokata.features.block.model; + +import java.time.LocalTime; + +public record BlockCreationDTO(LocalTime startTime, LocalTime endTime, double production, double floorPrice) { +} diff --git a/src/main/java/takima/example/agregiokata/features/block/model/BlockCreationRequest.java b/src/main/java/takima/example/agregiokata/features/block/model/BlockCreationRequest.java deleted file mode 100644 index 261df5ed117cbbdb8205faf429ab34140ac4fdd1..0000000000000000000000000000000000000000 --- a/src/main/java/takima/example/agregiokata/features/block/model/BlockCreationRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package takima.example.agregiokata.features.block.model; - -import java.time.LocalTime; - -public record BlockCreationRequest(LocalTime startTime, LocalTime endTime, double production, double floorPrice) { -} diff --git a/src/main/java/takima/example/agregiokata/features/block/service/SupplyBlockService.java b/src/main/java/takima/example/agregiokata/features/block/service/SupplyBlockService.java index 924a34eb896fabc1b48d5cd66f1f4334f1de9fe2..fbcd7fb002802ca96b94d2a1221b4a8395baba06 100644 --- a/src/main/java/takima/example/agregiokata/features/block/service/SupplyBlockService.java +++ b/src/main/java/takima/example/agregiokata/features/block/service/SupplyBlockService.java @@ -1,6 +1,5 @@ package takima.example.agregiokata.features.block.service; -import lombok.val; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import takima.example.agregiokata.features.block.entity.Block; @@ -24,22 +23,22 @@ public class SupplyBlockService { @Transactional public void plantsSupplyBlocks(List<Block> blocks) { - val powerPlants = powerPlantRepository.availablePowerPlant(); + var powerPlants = powerPlantRepository.availablePowerPlant(); if (powerPlants.isEmpty()) { throw badRequest("There is no or not enough power plants available for the offer", new InsufficientResourcesException()); } - val sortedBlocks = blocks.stream() + var sortedBlocks = blocks.stream() .sorted(Comparator.comparingDouble(Block::getProduction).reversed()) .toList(); - val sortedPowerPlants = powerPlants.stream() + var sortedPowerPlants = powerPlants.stream() .sorted(Comparator.comparingDouble(PowerPlant::getCapacityProduction).reversed()) .toList(); sortedBlocks.forEach(block -> { - val plantToSupply = sortedPowerPlants.stream().filter(filterByAvailablePowerplant(block.getProduction())) + var plantToSupply = sortedPowerPlants.stream().filter(filterByAvailablePowerplant(block.getProduction())) .findFirst() .orElseThrow(() -> badRequest("There is no or not enough power plants available for the offer", new InsufficientResourcesException())); block.setPlant(plantToSupply); @@ -48,15 +47,14 @@ public class SupplyBlockService { plantToSupply.setBlocks(plantBlocks); } ); - System.out.println("t"); } - private static Predicate<PowerPlant> filterByAvailablePowerplant(Double powerToAdd) { + private Predicate<PowerPlant> filterByAvailablePowerplant(Double powerToAdd) { return plant -> plant.getCapacityProduction() >= getCurrentlySuppliedPlantPowerProduction(plant) + powerToAdd; } - private static double getCurrentlySuppliedPlantPowerProduction(PowerPlant plant) { + private double getCurrentlySuppliedPlantPowerProduction(PowerPlant plant) { if (plant.getBlocks().isEmpty()) { return 0.0; } diff --git a/src/main/java/takima/example/agregiokata/features/offer/controller/OfferController.java b/src/main/java/takima/example/agregiokata/features/offer/controller/OfferController.java index 0237633ae77205952dbea26a78e225d5b2714d90..af519cc6e593fda6525df7804eaa85947d7e13b3 100644 --- a/src/main/java/takima/example/agregiokata/features/offer/controller/OfferController.java +++ b/src/main/java/takima/example/agregiokata/features/offer/controller/OfferController.java @@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import takima.example.agregiokata.features.offer.model.OfferCreationRequest; +import takima.example.agregiokata.features.offer.model.OfferCreationDTO; import takima.example.agregiokata.features.offer.model.OfferDTO; import takima.example.agregiokata.features.offer.service.OfferService; @@ -38,8 +38,8 @@ public class OfferController { @PostMapping @ResponseStatus(HttpStatus.CREATED) - public OfferDTO create(@RequestBody OfferCreationRequest request) { - return offerService.create(request); + public OfferDTO create(@RequestBody OfferCreationDTO offerCreationDTO) { + return offerService.create(offerCreationDTO); } @DeleteMapping("/{id}") diff --git a/src/main/java/takima/example/agregiokata/features/offer/model/OfferCreationRequest.java b/src/main/java/takima/example/agregiokata/features/offer/model/OfferCreationDTO.java similarity index 52% rename from src/main/java/takima/example/agregiokata/features/offer/model/OfferCreationRequest.java rename to src/main/java/takima/example/agregiokata/features/offer/model/OfferCreationDTO.java index 250bad3722d0d702eb5cc7d82412f79b12b41219..4ea32e0c509b49871bf8e85150ab62cf0b1ede28 100644 --- a/src/main/java/takima/example/agregiokata/features/offer/model/OfferCreationRequest.java +++ b/src/main/java/takima/example/agregiokata/features/offer/model/OfferCreationDTO.java @@ -1,9 +1,11 @@ package takima.example.agregiokata.features.offer.model; -import takima.example.agregiokata.features.block.model.BlockCreationRequest; +import takima.example.agregiokata.features.block.model.BlockCreationDTO; import java.util.List; -public record OfferCreationRequest(String market, - List<BlockCreationRequest> blocks) { +public record OfferCreationDTO( + String market, + List<BlockCreationDTO> blocks +) { } diff --git a/src/main/java/takima/example/agregiokata/features/offer/repository/OfferCustomRepository.java b/src/main/java/takima/example/agregiokata/features/offer/repository/OfferCustomRepository.java index 1207faa5f6b91cfe2d5f33dc67f0a22aad2027e6..cf9012717069a50b8fb3bf7723cd453659ce5a88 100644 --- a/src/main/java/takima/example/agregiokata/features/offer/repository/OfferCustomRepository.java +++ b/src/main/java/takima/example/agregiokata/features/offer/repository/OfferCustomRepository.java @@ -17,13 +17,13 @@ public interface OfferCustomRepository { join fetch b.plant where o.id = :id """) - public Optional<Offer> searchById(Long id); + Optional<Offer> searchById(Long id); @Query(""" select o from Offer o - join fetch o.blocks b - join fetch b.plant + left join fetch o.blocks b + left join fetch b.plant where o.market = :market """) - public List<Offer> findAllByMarket(Market market); + List<Offer> findAllByMarket(Market market); } diff --git a/src/main/java/takima/example/agregiokata/features/offer/repository/OfferRepository.java b/src/main/java/takima/example/agregiokata/features/offer/repository/OfferRepository.java index da075c51aafce5e2a56710a5ee693494d4f8d4ef..c43eb79fdadb83c94ea086fe30770bc46c49171a 100644 --- a/src/main/java/takima/example/agregiokata/features/offer/repository/OfferRepository.java +++ b/src/main/java/takima/example/agregiokata/features/offer/repository/OfferRepository.java @@ -4,7 +4,6 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import takima.example.agregiokata.features.offer.entity.Offer; -//TODO créer une interface pour bouger les findbyID, findAll que je redéfini et extends ici @Repository public interface OfferRepository extends JpaRepository<Offer, Long>, OfferCustomRepository { } diff --git a/src/main/java/takima/example/agregiokata/features/offer/service/OfferService.java b/src/main/java/takima/example/agregiokata/features/offer/service/OfferService.java index 8d5b16482bd71c4119ea1e836573aff610dacf5f..697199e557893a0dcbf98ed2044ab5b3d3c768d6 100644 --- a/src/main/java/takima/example/agregiokata/features/offer/service/OfferService.java +++ b/src/main/java/takima/example/agregiokata/features/offer/service/OfferService.java @@ -4,15 +4,14 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import takima.example.agregiokata.features.block.entity.Block; import takima.example.agregiokata.features.block.mapper.BlockMapper; -import takima.example.agregiokata.features.block.model.BlockCreationRequest; +import takima.example.agregiokata.features.block.model.BlockCreationDTO; import takima.example.agregiokata.features.block.service.SupplyBlockService; import takima.example.agregiokata.features.market.model.Market; import takima.example.agregiokata.features.offer.entity.Offer; import takima.example.agregiokata.features.offer.mapper.OfferMapper; -import takima.example.agregiokata.features.offer.model.OfferCreationRequest; +import takima.example.agregiokata.features.offer.model.OfferCreationDTO; import takima.example.agregiokata.features.offer.model.OfferDTO; import takima.example.agregiokata.features.offer.repository.OfferRepository; -import takima.example.agregiokata.features.powerplant.repository.PowerPlantRepository; import java.util.List; @@ -24,15 +23,13 @@ public class OfferService { private final OfferRepository offerRepository; private final OfferMapper offerMapper; private final BlockMapper blockMapper; - private final PowerPlantRepository powerPlantRepository; private final SupplyBlockService supplyBlockService; public OfferService(OfferRepository offerRepository, OfferMapper offerMapper, BlockMapper blockMapper, - PowerPlantRepository powerPlantRepository, SupplyBlockService supplyBlockService) { + SupplyBlockService supplyBlockService) { this.offerRepository = offerRepository; this.offerMapper = offerMapper; this.blockMapper = blockMapper; - this.powerPlantRepository = powerPlantRepository; this.supplyBlockService = supplyBlockService; } @@ -40,18 +37,13 @@ public class OfferService { public OfferDTO getById(Long id) { return offerRepository.searchById(id) .map(offerMapper::toDTO) - .orElseThrow(() -> notFound("Power plant with id " + id + " not found")); + .orElseThrow(() -> notFound("Offer with id " + id + " not found")); } @Transactional(readOnly = true) public List<OfferDTO> search(String search) { var market = Market.fromString(search); - List<Offer> offers; - if (market == null) { - offers = offerRepository.findAll(); - } else { - offers = offerRepository.findAllByMarket(market); - } + List<Offer> offers = market == null ? offerRepository.findAll() : offerRepository.findAllByMarket(market); return offers .stream() .map(offerMapper::toDTO) @@ -59,27 +51,24 @@ public class OfferService { } @Transactional - public OfferDTO create(OfferCreationRequest request) { + public OfferDTO create(OfferCreationDTO offerCreationDTO) { var offer = Offer.builder() - .market(Market.fromString(request.market())) + .market(Market.fromString(offerCreationDTO.market())) .build(); - var blocks = createBlocksWithPowerPlant(request.blocks()); + var blocks = createBlocksWithPowerPlant(offerCreationDTO.blocks()); offer.setBlocks(blocks); - blocks.forEach(block -> { - block.setOffer(offer); - }); + blocks.forEach(block -> block.setOffer(offer)); var offerSaved = offerRepository.save(offer); return offerMapper.toDTO(offerSaved); } @Transactional - public List<Block> createBlocksWithPowerPlant(List<BlockCreationRequest> requests) { + public List<Block> createBlocksWithPowerPlant(List<BlockCreationDTO> requests) { var blocks = blockMapper.toEntities(requests); supplyBlockService.plantsSupplyBlocks(blocks); return blocks; } - @Transactional public void delete(Long id) { offerRepository.deleteById(id); diff --git a/src/main/java/takima/example/agregiokata/features/powerplant/controller/PowerPlantController.java b/src/main/java/takima/example/agregiokata/features/powerplant/controller/PowerPlantController.java index a9683582c94f2bb64ee33aa01fe7552b069c535f..fa278c2b9c45086afbbd01463476897ca9adfbb1 100644 --- a/src/main/java/takima/example/agregiokata/features/powerplant/controller/PowerPlantController.java +++ b/src/main/java/takima/example/agregiokata/features/powerplant/controller/PowerPlantController.java @@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import takima.example.agregiokata.features.powerplant.model.PowerPlantCreationRequest; +import takima.example.agregiokata.features.powerplant.model.PowerPlantCreationDTO; import takima.example.agregiokata.features.powerplant.model.PowerPlantDTO; import takima.example.agregiokata.features.powerplant.service.PowerPlantService; @@ -37,7 +37,7 @@ public class PowerPlantController { @PostMapping @ResponseStatus(HttpStatus.CREATED) - public PowerPlantDTO create(@RequestBody PowerPlantCreationRequest request) { + public PowerPlantDTO create(@RequestBody PowerPlantCreationDTO request) { return powerPlantService.create(request); } diff --git a/src/main/java/takima/example/agregiokata/features/powerplant/mapper/PowerPlantMapper.java b/src/main/java/takima/example/agregiokata/features/powerplant/mapper/PowerPlantMapper.java index ed1960c400968c6fcdab69d75d4f056eeca962c1..b1d1694362a146ce9b1a024b6e291d21950ca7c5 100644 --- a/src/main/java/takima/example/agregiokata/features/powerplant/mapper/PowerPlantMapper.java +++ b/src/main/java/takima/example/agregiokata/features/powerplant/mapper/PowerPlantMapper.java @@ -2,9 +2,10 @@ package takima.example.agregiokata.features.powerplant.mapper; import org.springframework.stereotype.Component; import takima.example.agregiokata.features.powerplant.entity.PowerPlant; -import takima.example.agregiokata.features.powerplant.model.PowerPlantCreationRequest; +import takima.example.agregiokata.features.powerplant.model.PowerPlantCreationDTO; import takima.example.agregiokata.features.powerplant.model.PowerPlantDTO; import takima.example.agregiokata.features.powerplant.model.PowerPlantOfferDTO; +import takima.example.agregiokata.features.powerplant.model.PowerPlantType; import java.util.List; @@ -14,7 +15,7 @@ public class PowerPlantMapper { return new PowerPlantDTO( powerPlant.getId(), powerPlant.getName(), - powerPlant.getType(), + powerPlant.getType().getLabel(), powerPlant.getCapacityProduction() ); } @@ -23,14 +24,14 @@ public class PowerPlantMapper { return new PowerPlantOfferDTO( powerPlant.getId(), powerPlant.getName(), - powerPlant.getType() + powerPlant.getType().getLabel() ); } - public PowerPlant toEntity(PowerPlantCreationRequest request) { + public PowerPlant toEntity(PowerPlantCreationDTO request) { return PowerPlant.builder() .name(request.name()) - .type(request.type()) + .type(PowerPlantType.fromString(request.type())) .capacityProduction(request.capacityProduction()) .build(); } diff --git a/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantCreationDTO.java b/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantCreationDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..b4bd77279739912ebd2be1f4414f061dd78e548c --- /dev/null +++ b/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantCreationDTO.java @@ -0,0 +1,4 @@ +package takima.example.agregiokata.features.powerplant.model; + +public record PowerPlantCreationDTO(String name, String type, double capacityProduction) { +} diff --git a/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantCreationRequest.java b/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantCreationRequest.java deleted file mode 100644 index c30b98a4b74871207bf10c998cc2e47aecd051c0..0000000000000000000000000000000000000000 --- a/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantCreationRequest.java +++ /dev/null @@ -1,4 +0,0 @@ -package takima.example.agregiokata.features.powerplant.model; - -public record PowerPlantCreationRequest(String name, PowerPlantType type, double capacityProduction) { -} diff --git a/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantDTO.java b/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantDTO.java index f6f35b5f7ce1a219e492f677e1c585b52725d338..371050fe5925092a28c2cd20a2d7437afa3ebc85 100644 --- a/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantDTO.java +++ b/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantDTO.java @@ -1,5 +1,5 @@ package takima.example.agregiokata.features.powerplant.model; -public record PowerPlantDTO(Long id, String name, PowerPlantType type, double capacityProduction) { +public record PowerPlantDTO(Long id, String name, String type, double capacityProduction) { } \ No newline at end of file diff --git a/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantOfferDTO.java b/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantOfferDTO.java index dac87e6e2f80ccd37b06473c8cf151d470444a21..ab2fd82704d4940bc4872bb7eb9a77785d91baef 100644 --- a/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantOfferDTO.java +++ b/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantOfferDTO.java @@ -1,4 +1,4 @@ package takima.example.agregiokata.features.powerplant.model; -public record PowerPlantOfferDTO(Long id, String name, PowerPlantType type) { +public record PowerPlantOfferDTO(Long id, String name, String type) { } diff --git a/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantType.java b/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantType.java index c5598cb5ab78e43828fc7dd2e75965767eda3329..c6b6b7162eaa241054855b9aa645538f0313621d 100644 --- a/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantType.java +++ b/src/main/java/takima/example/agregiokata/features/powerplant/model/PowerPlantType.java @@ -1,7 +1,27 @@ package takima.example.agregiokata.features.powerplant.model; +import lombok.Getter; + +import java.util.Arrays; + +import static takima.example.agregiokata.core.exception.ErrorFactory.badRequest; + +@Getter public enum PowerPlantType { - SOLAR, - WIND, - HYDRO + SOLAR("Solaire"), + WIND("Éolien"), + HYDRO("Hydraulique"); + + private final String label; + + PowerPlantType(String label) { + this.label = label; + } + + public static PowerPlantType fromString(String value) { + return Arrays.stream(values()) + .filter(type -> type.name().equalsIgnoreCase(value) || type.label.equalsIgnoreCase(value)) + .findFirst() + .orElseThrow(() -> badRequest("Valeur de type de parc est invalide", new IllegalArgumentException("Valeur de type de parc est invalide : " + value))); + } } diff --git a/src/main/java/takima/example/agregiokata/features/powerplant/service/PowerPlantService.java b/src/main/java/takima/example/agregiokata/features/powerplant/service/PowerPlantService.java index d0a5e095b1f2e544e55cfa54d66e35ff76bd7f55..c628afb2ae5cbf99a6919f44072c71c1e4932e41 100644 --- a/src/main/java/takima/example/agregiokata/features/powerplant/service/PowerPlantService.java +++ b/src/main/java/takima/example/agregiokata/features/powerplant/service/PowerPlantService.java @@ -5,7 +5,7 @@ import org.springframework.transaction.annotation.Transactional; import takima.example.agregiokata.features.market.model.Market; import takima.example.agregiokata.features.powerplant.entity.PowerPlant; import takima.example.agregiokata.features.powerplant.mapper.PowerPlantMapper; -import takima.example.agregiokata.features.powerplant.model.PowerPlantCreationRequest; +import takima.example.agregiokata.features.powerplant.model.PowerPlantCreationDTO; import takima.example.agregiokata.features.powerplant.model.PowerPlantDTO; import takima.example.agregiokata.features.powerplant.repository.PowerPlantRepository; @@ -27,10 +27,10 @@ public class PowerPlantService { public List<PowerPlantDTO> search(String searchMarket) { var market = Market.fromString(searchMarket); var result = powerPlantRepository.findAllByMarket(market); - if(result.isEmpty()) { + if (result.isEmpty()) { return List.of(); } - return result.stream().map(powerPlantMapper::toDTO).toList(); + return powerPlantMapper.toDTOs(result); } @Transactional(readOnly = true) @@ -41,7 +41,7 @@ public class PowerPlantService { } @Transactional - public PowerPlantDTO create(PowerPlantCreationRequest request) { + public PowerPlantDTO create(PowerPlantCreationDTO request) { PowerPlant powerPlant = powerPlantMapper.toEntity(request); return powerPlantMapper.toDTO(powerPlantRepository.save(powerPlant)); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 2c44b0f77af80a74869e147ef12b1a9d7dc6a358..9932a974e4e7125f4e62557ab0a01382b4d099cc 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -12,7 +12,7 @@ spring: open-in-view: false flyway: schemas: public - logging: level: - sql: debug \ No newline at end of file + org.hibernate.SQL: info + org.hibernate.orm.jdbc.bind: info \ No newline at end of file diff --git a/src/test/java/takima/example/agregiokata/data/TestData.java b/src/test/java/takima/example/agregiokata/data/TestData.java deleted file mode 100644 index 937d78661cb6df2fd63c17a35aeb3aae23d056e9..0000000000000000000000000000000000000000 --- a/src/test/java/takima/example/agregiokata/data/TestData.java +++ /dev/null @@ -1,56 +0,0 @@ -package takima.example.agregiokata.data; - -import takima.example.agregiokata.features.block.entity.Block; -import takima.example.agregiokata.features.powerplant.entity.PowerPlant; -import takima.example.agregiokata.features.powerplant.model.PowerPlantType; - -import java.time.LocalTime; -import java.util.ArrayList; - -public class TestData { - - public static final Block blockPlantless1 = Block.builder() - .startTime(LocalTime.of(8, 0)) - .endTime(LocalTime.of(9, 0)) - .floorPrice(100.0) - .production(300.0) - .build(); - - public static final Block blockPlantless2 = Block.builder() - .startTime(LocalTime.of(9, 0)) - .endTime(LocalTime.of(12, 0)) - .floorPrice(300.0) - .production(400.0) - .build(); - - public static final Block blockPlantless3 = Block.builder() - .startTime(LocalTime.of(12, 0)) - .endTime(LocalTime.of(15, 0)) - .floorPrice(50.0) - .production(100.0) - .build(); - - public static PowerPlant solarPlant = PowerPlant.builder() - .id(1L) - .name("Solar Plant") - .type(PowerPlantType.SOLAR) - .capacityProduction(500.0) - .blocks(new ArrayList<>()) - .build(); - - public static final PowerPlant windPlant = PowerPlant.builder() - .id(2L) - .name("Wind Plant") - .type(PowerPlantType.WIND) - .capacityProduction(400.0) - .blocks(new ArrayList<>()) - .build(); - - public static PowerPlant hydroPlant = PowerPlant.builder() - .name("Hydro Plant") - .type(PowerPlantType.HYDRO) - .capacityProduction(500.0) - .blocks(new ArrayList<>()) - .build(); - -} diff --git a/src/test/java/takima/example/agregiokata/features/offer/repository/OfferCustomRepositoryTest.java b/src/test/java/takima/example/agregiokata/features/offer/repository/OfferCustomRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0dc1de81037c3503aacae18c8e472eaa6a05daf4 --- /dev/null +++ b/src/test/java/takima/example/agregiokata/features/offer/repository/OfferCustomRepositoryTest.java @@ -0,0 +1,69 @@ +package takima.example.agregiokata.features.offer.repository; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.testcontainers.utility.TestcontainersConfiguration; +import takima.example.agregiokata.features.market.model.Market; +import takima.example.agregiokata.features.offer.entity.Offer; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +@Import(TestcontainersConfiguration.class) +@Sql(statements = "TRUNCATE TABLE powerplant, block, offer RESTART IDENTITY CASCADE; ", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) +class OfferCustomRepositoryITest { + @Autowired + private OfferRepository offerRepository; + + private Offer offer; + private Offer offer2; + private Offer offer3; + + @BeforeEach + void setUp() { + offer = new Offer().toBuilder() + .market(Market.FAST_RESERVE) + .build(); + + offer2 = new Offer().toBuilder() + .market(Market.SECONDARY_RESERVE) + .build(); + + offer3 = new Offer().toBuilder() + .market(Market.FAST_RESERVE) + .build(); + } + + @Test + void searchById() { + offerRepository.save(offer); + + Optional<Offer> offerRequested = offerRepository.findById(1L); + + assertThat(offerRequested).isNotEmpty(); + assertThat(offerRequested.get().getId()).isEqualTo(1L); + assertThat(offerRequested.get().getMarket()).isEqualTo(Market.FAST_RESERVE); + } + + @Test + void findAllByMarket() { + offerRepository.save(offer); + offerRepository.save(offer2); + offerRepository.save(offer3); + + List<Offer> offersActual = offerRepository.findAllByMarket(Market.FAST_RESERVE); + + assertThat(offersActual).isNotEmpty(); + assertThat(offersActual).extracting(Offer::getId) + .containsExactlyInAnyOrder(1L, 3L); + assertThat(offersActual).extracting(Offer::getMarket) + .allMatch(Market.FAST_RESERVE::equals); + } +} \ No newline at end of file diff --git a/src/test/java/takima/example/agregiokata/features/powerplant/repository/PowerPlantRepositoryTest.java b/src/test/java/takima/example/agregiokata/features/powerplant/repository/PowerPlantRepositoryITest.java similarity index 82% rename from src/test/java/takima/example/agregiokata/features/powerplant/repository/PowerPlantRepositoryTest.java rename to src/test/java/takima/example/agregiokata/features/powerplant/repository/PowerPlantRepositoryITest.java index 33bf50a70016b7cdfb812e33393c97140923cc66..d7cd485175dbfe5b7e17cf71ea37f55e513e8c0f 100644 --- a/src/test/java/takima/example/agregiokata/features/powerplant/repository/PowerPlantRepositoryTest.java +++ b/src/test/java/takima/example/agregiokata/features/powerplant/repository/PowerPlantRepositoryITest.java @@ -27,7 +27,7 @@ import static org.assertj.core.api.Assertions.assertThat; "ALTER SEQUENCE powerplant_id_seq RESTART WITH 1; " + "ALTER SEQUENCE block_id_seq RESTART WITH 1 ;" + "ALTER SEQUENCE offer_id_seq RESTART WITH 1;", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) -class PowerPlantRepositoryTest { +class PowerPlantRepositoryITest { @Autowired private PowerPlantRepository powerPlantRepository; @@ -39,10 +39,6 @@ class PowerPlantRepositoryTest { private PowerPlant hydroPlant; private PowerPlant solarPlant; - private Block blockPlantless1; - private Block blockPlantless3; - private Block blockPlantless2; - private Offer offer; private Offer offer2; @@ -57,7 +53,7 @@ class PowerPlantRepositoryTest { .market(Market.SECONDARY_RESERVE) .build(); - blockPlantless1 = Block.builder() + Block blockPlantless1 = Block.builder() .startTime(LocalTime.of(8, 0)) .endTime(LocalTime.of(9, 0)) .floorPrice(100.0) @@ -65,7 +61,7 @@ class PowerPlantRepositoryTest { .offer(offer) .build(); - blockPlantless2 = Block.builder() + Block blockPlantless2 = Block.builder() .startTime(LocalTime.of(9, 0)) .endTime(LocalTime.of(12, 0)) .floorPrice(300.0) @@ -73,7 +69,7 @@ class PowerPlantRepositoryTest { .offer(offer2) .build(); - blockPlantless3 = Block.builder() + Block blockPlantless3 = Block.builder() .startTime(LocalTime.of(12, 0)) .endTime(LocalTime.of(15, 0)) .floorPrice(50.0) @@ -107,11 +103,9 @@ class PowerPlantRepositoryTest { @DisplayName("should return all plant that still that have not production completely supplied") void availablePowerPlant() { offerRepository.save(offer); - var plantAvailable = powerPlantRepository.save(hydroPlant); - plantNotAvailable.getBlocks().forEach(block -> { - block.setPlant(plantNotAvailable); - }); - var plantAllSupplied = powerPlantRepository.save(plantNotAvailable); + powerPlantRepository.save(hydroPlant); + plantNotAvailable.getBlocks().forEach(block -> block.setPlant(plantNotAvailable)); + powerPlantRepository.save(plantNotAvailable); List<PowerPlant> availablePlants = powerPlantRepository.availablePowerPlant(); @@ -126,15 +120,11 @@ class PowerPlantRepositoryTest { offerRepository.save(offer); offerRepository.save(offer2); - solarPlant.getBlocks().forEach(block -> { - block.setPlant(solarPlant); - }); - var solarPlantSaved = powerPlantRepository.save(solarPlant); + solarPlant.getBlocks().forEach(block -> block.setPlant(solarPlant)); + powerPlantRepository.save(solarPlant); - plantNotAvailable.getBlocks().forEach(block -> { - block.setPlant(plantNotAvailable); - }); - var plantNotAvailableSaved = powerPlantRepository.save(plantNotAvailable); + plantNotAvailable.getBlocks().forEach(block -> block.setPlant(plantNotAvailable)); + powerPlantRepository.save(plantNotAvailable); List<PowerPlant> plantsByMarket = powerPlantRepository.findAllByMarket(Market.FAST_RESERVE); diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 621329a64d3b90b6885b66dc43abc52e8ead9c42..fe58629a65f26113f567665ee6c4fe9152b72e59 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -2,4 +2,8 @@ spring: datasource: url: jdbc:tc:postgresql:15.7:///agregio-db username: takima - password: takima \ No newline at end of file + password: takima +logging: + level: + org.hibernate.SQL: info + org.hibernate.orm.jdbc.bind: info \ No newline at end of file