From eda5eebbc1a08a811541275ae689c1deb3782222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20Lauk=C3=B6tter?= Date: Tue, 25 Feb 2025 16:21:25 +0100 Subject: [PATCH] Remove link between Announcements and Releases RISDEV-0000 --- .../controller/AnnouncementController.java | 38 ++--- .../output/database/dto/AnnouncementDto.java | 15 -- .../database/mapper/AnnouncementMapper.java | 15 +- .../repository/ReleaseRepository.java | 12 +- .../output/database/service/DBService.java | 41 ++--- ...oadReleasesByNormExpressionEliUseCase.java | 26 +++ .../input/ReleaseAnnouncementUseCase.java | 29 ---- .../input/ReleaseNormExpressionUseCase.java | 26 +++ .../LoadReleasesByNormExpressionEliPort.java | 25 +++ .../port/output/SaveReleasePort.java | 23 +++ .../output/SaveReleaseToAnnouncementPort.java | 25 --- .../service/AnnouncementService.java | 16 +- .../application/service/ReleaseService.java | 47 +++--- .../ris/norms/domain/entity/Announcement.java | 8 - ....31__link_releases_to_norm_expressions.sql | 1 + .../AnnouncementControllerTest.java | 48 ++---- .../service/ReleaseServiceTest.java | 124 +++++++++------ ...AnnouncementControllerIntegrationTest.java | 56 +------ .../database/DBServiceIntegrationTest.java | 149 ++++++++++++++---- 19 files changed, 382 insertions(+), 342 deletions(-) create mode 100644 backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/LoadReleasesByNormExpressionEliUseCase.java delete mode 100644 backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/ReleaseAnnouncementUseCase.java create mode 100644 backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/ReleaseNormExpressionUseCase.java create mode 100644 backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/LoadReleasesByNormExpressionEliPort.java create mode 100644 backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/SaveReleasePort.java delete mode 100644 backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/SaveReleaseToAnnouncementPort.java create mode 100644 backend/src/main/resources/db/migration/V0.31__link_releases_to_norm_expressions.sql diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/input/restapi/controller/AnnouncementController.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/input/restapi/controller/AnnouncementController.java index b7fbad43f..e55b280a4 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/input/restapi/controller/AnnouncementController.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/input/restapi/controller/AnnouncementController.java @@ -8,15 +8,13 @@ import de.bund.digitalservice.ris.norms.adapter.input.restapi.schema.ReleaseResponseSchema; import de.bund.digitalservice.ris.norms.application.port.input.CreateAnnouncementUseCase; import de.bund.digitalservice.ris.norms.application.port.input.LoadAllAnnouncementsUseCase; -import de.bund.digitalservice.ris.norms.application.port.input.LoadAnnouncementByNormEliUseCase; import de.bund.digitalservice.ris.norms.application.port.input.LoadNormUseCase; -import de.bund.digitalservice.ris.norms.application.port.input.ReleaseAnnouncementUseCase; +import de.bund.digitalservice.ris.norms.application.port.input.LoadReleasesByNormExpressionEliUseCase; +import de.bund.digitalservice.ris.norms.application.port.input.ReleaseNormExpressionUseCase; import de.bund.digitalservice.ris.norms.domain.entity.Announcement; import de.bund.digitalservice.ris.norms.domain.entity.Norm; -import de.bund.digitalservice.ris.norms.domain.entity.Release; import de.bund.digitalservice.ris.norms.domain.entity.eli.NormExpressionEli; import java.io.IOException; -import java.util.Comparator; import java.util.List; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -32,21 +30,21 @@ public class AnnouncementController { private final LoadAllAnnouncementsUseCase loadAllAnnouncementsUseCase; - private final LoadAnnouncementByNormEliUseCase loadAnnouncementByNormEliUseCase; - private final ReleaseAnnouncementUseCase releaseAnnouncementUseCase; + private final LoadReleasesByNormExpressionEliUseCase loadReleasesByNormExpressionEliUseCase; + private final ReleaseNormExpressionUseCase releaseNormExpressionUseCase; private final CreateAnnouncementUseCase createAnnouncementUseCase; private final LoadNormUseCase loadNormUseCase; public AnnouncementController( LoadAllAnnouncementsUseCase loadAllAnnouncementsUseCase, - LoadAnnouncementByNormEliUseCase loadAnnouncementByNormEliUseCase, - ReleaseAnnouncementUseCase releaseAnnouncementUseCase, + LoadReleasesByNormExpressionEliUseCase loadReleasesByNormExpressionEliUseCase, + ReleaseNormExpressionUseCase releaseNormExpressionUseCase, CreateAnnouncementUseCase createAnnouncementUseCase, LoadNormUseCase loadNormUseCase ) { this.loadAllAnnouncementsUseCase = loadAllAnnouncementsUseCase; - this.loadAnnouncementByNormEliUseCase = loadAnnouncementByNormEliUseCase; - this.releaseAnnouncementUseCase = releaseAnnouncementUseCase; + this.loadReleasesByNormExpressionEliUseCase = loadReleasesByNormExpressionEliUseCase; + this.releaseNormExpressionUseCase = releaseNormExpressionUseCase; this.createAnnouncementUseCase = createAnnouncementUseCase; this.loadNormUseCase = loadNormUseCase; } @@ -86,13 +84,11 @@ public ResponseEntity> getAllAnnouncements() { produces = { APPLICATION_JSON_VALUE } ) public ResponseEntity> getReleases(final NormExpressionEli eli) { - var announcement = loadAnnouncementByNormEliUseCase.loadAnnouncementByNormEli( - new LoadAnnouncementByNormEliUseCase.Query(eli) + var releases = loadReleasesByNormExpressionEliUseCase.loadReleasesByNormExpressionEli( + new LoadReleasesByNormExpressionEliUseCase.Query(eli) ); - return ResponseEntity.ok( - announcement.getReleases().stream().map(ReleaseResponseMapper::fromRelease).toList() - ); + return ResponseEntity.ok(releases.stream().map(ReleaseResponseMapper::fromRelease).toList()); } /** @@ -109,16 +105,10 @@ public ResponseEntity> getReleases(final NormExpress produces = { APPLICATION_JSON_VALUE } ) public ResponseEntity postReleases(final NormExpressionEli eli) { - var announcement = releaseAnnouncementUseCase.releaseAnnouncement( - new ReleaseAnnouncementUseCase.Query(eli) + var release = releaseNormExpressionUseCase.releaseNormExpression( + new ReleaseNormExpressionUseCase.Query(eli) ); - var latestRelease = announcement - .getReleases() - .stream() - .max(Comparator.comparing(Release::getReleasedAt)) - .orElseThrow(); - - return ResponseEntity.ok(ReleaseResponseMapper.fromRelease(latestRelease)); + return ResponseEntity.ok(ReleaseResponseMapper.fromRelease(release)); } /** diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/dto/AnnouncementDto.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/dto/AnnouncementDto.java index 6576500a7..5570a4801 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/dto/AnnouncementDto.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/dto/AnnouncementDto.java @@ -2,15 +2,9 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.JoinTable; -import jakarta.persistence.OneToMany; import jakarta.persistence.Table; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; import lombok.AllArgsConstructor; import lombok.Builder; @@ -37,13 +31,4 @@ public class AnnouncementDto { @Column(name = "eli_norm_expression") private String eliNormExpression; - - @OneToMany(fetch = FetchType.EAGER) - @JoinTable( - name = "announcement_releases", - joinColumns = @JoinColumn(name = "announcement_id"), - inverseJoinColumns = @JoinColumn(name = "release_id") - ) - @Builder.Default - private List releases = new ArrayList<>(); } diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/mapper/AnnouncementMapper.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/mapper/AnnouncementMapper.java index 4a015701e..bd00a82f7 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/mapper/AnnouncementMapper.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/mapper/AnnouncementMapper.java @@ -3,8 +3,6 @@ import de.bund.digitalservice.ris.norms.adapter.output.database.dto.AnnouncementDto; import de.bund.digitalservice.ris.norms.domain.entity.Announcement; import de.bund.digitalservice.ris.norms.domain.entity.eli.NormExpressionEli; -import java.util.ArrayList; -import java.util.stream.Collectors; /** Mapper class for converting between {@link AnnouncementDto} and {@link Announcement}. */ public class AnnouncementMapper { @@ -22,13 +20,6 @@ public static Announcement mapToDomain(final AnnouncementDto announcementDto) { return Announcement .builder() .eli(NormExpressionEli.fromString(announcementDto.getEliNormExpression())) - .releases( - announcementDto - .getReleases() - .stream() - .map(ReleaseMapper::mapToDomain) - .collect(Collectors.toCollection(ArrayList::new)) - ) .build(); } @@ -39,10 +30,6 @@ public static Announcement mapToDomain(final AnnouncementDto announcementDto) { * @return A new {@link AnnouncementDto} mapped from the input {@link Announcement}. */ public static AnnouncementDto mapToDto(final Announcement announcement) { - return AnnouncementDto - .builder() - .eliNormExpression(announcement.getEli().toString()) - .releases(announcement.getReleases().stream().map(ReleaseMapper::mapToDto).toList()) - .build(); + return AnnouncementDto.builder().eliNormExpression(announcement.getEli().toString()).build(); } } diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/repository/ReleaseRepository.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/repository/ReleaseRepository.java index 19a6ceaf9..33798605b 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/repository/ReleaseRepository.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/repository/ReleaseRepository.java @@ -1,8 +1,11 @@ package de.bund.digitalservice.ris.norms.adapter.output.database.repository; import de.bund.digitalservice.ris.norms.adapter.output.database.dto.ReleaseDto; +import java.util.List; import java.util.UUID; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; /** @@ -11,4 +14,11 @@ * ReleaseDto}. */ @Repository -public interface ReleaseRepository extends JpaRepository {} +public interface ReleaseRepository extends JpaRepository { + @Query( + "SELECT r from ReleaseDto r WHERE elements(r.norms) = ANY (SELECT n from NormManifestationDto n where n.expressionEli = :normExpressionEli)" + ) + List findAllByNormExpressionEli( + @Param("normExpressionEli") final String normExpressionEli + ); +} diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/service/DBService.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/service/DBService.java index a931e002b..15943e53a 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/service/DBService.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/adapter/output/database/service/DBService.java @@ -47,13 +47,14 @@ public class DBService UpdateOrSaveAnnouncementPort, DeleteAnnouncementByNormEliPort, DeleteNormPort, - SaveReleaseToAnnouncementPort, + SaveReleasePort, DeleteQueuedReleasesPort, LoadNormManifestationElisByPublishStatePort, LoadLastMigrationLogPort, LoadRegelungstextPort, LoadDokumentPort, - UpdateDokumentPort { + UpdateDokumentPort, + LoadReleasesByNormExpressionEliPort { private final AnnouncementRepository announcementRepository; private final DokumentRepository dokumentRepository; @@ -222,9 +223,7 @@ public Announcement updateOrSaveAnnouncement(UpdateOrSaveAnnouncementPort.Comman @Override @Transactional public void deleteAnnouncementByNormEli(DeleteAnnouncementByNormEliPort.Command command) { - var announcementDto = announcementRepository.findByEliNormExpression(command.eli().toString()); announcementRepository.deleteByEliNormExpression(command.eli().toString()); - announcementDto.ifPresent(dto -> releaseRepository.deleteAll(dto.getReleases())); } @Override @@ -245,7 +244,7 @@ public void deleteNorm(DeleteNormPort.Command command) { } @Override - public Release saveReleaseToAnnouncement(SaveReleaseToAnnouncementPort.Command command) { + public Release saveRelease(SaveReleasePort.Command command) { final ReleaseDto releaseDto = ReleaseMapper.mapToDto(command.release()); command @@ -258,28 +257,14 @@ public Release saveReleaseToAnnouncement(SaveReleaseToAnnouncementPort.Command c ); var release = releaseRepository.save(releaseDto); - - announcementRepository - .findByEliNormExpression(command.announcement().getEli().toString()) - .ifPresent(announcementDto -> { - announcementDto.getReleases().add(release); - announcementRepository.save(announcementDto); - }); - return ReleaseMapper.mapToDomain(release); } @Override public List deleteQueuedReleases(DeleteQueuedReleasesPort.Command command) { - var announcementDto = announcementRepository.findByEliNormExpression(command.eli().toString()); + var releases = releaseRepository.findAllByNormExpressionEli(command.eli().toString()); - if (announcementDto.isEmpty()) { - return List.of(); - } - - var queuedReleaseDtos = announcementDto - .get() - .getReleases() + var queuedReleaseDtos = releases .stream() .filter(releaseDto -> releaseDto @@ -290,9 +275,6 @@ public List deleteQueuedReleases(DeleteQueuedReleasesPort.Command comma ) .toList(); - queuedReleaseDtos.forEach(releaseDto -> announcementDto.get().getReleases().remove(releaseDto)); - announcementRepository.save(announcementDto.get()); - releaseRepository.deleteAll(queuedReleaseDtos); return queuedReleaseDtos.stream().map(ReleaseMapper::mapToDomain).toList(); @@ -357,4 +339,15 @@ public Optional updateDokument(UpdateDokumentPort.Command command) { return Optional.of(DokumentMapper.mapToDomain(dokumentRepository.saveAndFlush(dokumentDto))); } } + + @Override + public List loadReleasesByNormExpressionEli( + LoadReleasesByNormExpressionEliPort.Command command + ) { + return releaseRepository + .findAllByNormExpressionEli(command.eli().toString()) + .stream() + .map(ReleaseMapper::mapToDomain) + .toList(); + } } diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/LoadReleasesByNormExpressionEliUseCase.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/LoadReleasesByNormExpressionEliUseCase.java new file mode 100644 index 000000000..808b92bd1 --- /dev/null +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/LoadReleasesByNormExpressionEliUseCase.java @@ -0,0 +1,26 @@ +package de.bund.digitalservice.ris.norms.application.port.input; + +import de.bund.digitalservice.ris.norms.domain.entity.Release; +import de.bund.digitalservice.ris.norms.domain.entity.eli.NormExpressionEli; +import java.util.List; + +/** + * Interface representing the use case for loading {@link Release}s of a specific norm expression. + */ +public interface LoadReleasesByNormExpressionEliUseCase { + /** + * Loads all {@link Release}s associated with the norm expression. + * + * @param query Query for loading the releases + * @return A {@link List} of {@link Release} objects, which may be empty if no {@link + * Release}s are found. + */ + List loadReleasesByNormExpressionEli(Query query); + + /** + * A record representing the query for loading {@link Release}s of a specific norm expression. + * + * @param eli The ELI (European Legislation Identifier) used to identify the norm expression. + */ + record Query(NormExpressionEli eli) {} +} diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/ReleaseAnnouncementUseCase.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/ReleaseAnnouncementUseCase.java deleted file mode 100644 index c8b2ef4c6..000000000 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/ReleaseAnnouncementUseCase.java +++ /dev/null @@ -1,29 +0,0 @@ -package de.bund.digitalservice.ris.norms.application.port.input; - -import de.bund.digitalservice.ris.norms.domain.entity.Announcement; -import de.bund.digitalservice.ris.norms.domain.entity.Norm; -import de.bund.digitalservice.ris.norms.domain.entity.eli.NormExpressionEli; - -/** - * Interface representing the use case for releasing an {@link Announcement} and the corresponding - * {@link Norm}s. - */ -public interface ReleaseAnnouncementUseCase { - /** - * Releases an {@link Announcement} and the corresponding {@link Norm}s based on the provided - * query. - * - * @param query The query specifying the {@link Announcement} to be loaded. - * @return The released {@link Announcement}. - */ - Announcement releaseAnnouncement(Query query); - - /** - * A record representing the query for releasing an {@link Announcement}. The query includes the - * ELI (European Legislation Identifier) to identify the {@link Norm} of the {@link Announcement}. - * - * @param eli The ELI (European Legislation Identifier) used to identify the {@link Norm} of the - * {@link Announcement}. - */ - record Query(NormExpressionEli eli) {} -} diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/ReleaseNormExpressionUseCase.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/ReleaseNormExpressionUseCase.java new file mode 100644 index 000000000..a12db3e90 --- /dev/null +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/input/ReleaseNormExpressionUseCase.java @@ -0,0 +1,26 @@ +package de.bund.digitalservice.ris.norms.application.port.input; + +import de.bund.digitalservice.ris.norms.domain.entity.Norm; +import de.bund.digitalservice.ris.norms.domain.entity.Release; +import de.bund.digitalservice.ris.norms.domain.entity.eli.NormExpressionEli; + +/** + * Interface representing the use case for releasing a new expression of a {@link Norm}. + */ +public interface ReleaseNormExpressionUseCase { + /** + * Releases a new expression of a {@link Norm} based on the provided query. + * + * @param query The query specifying the {@link Norm} to be released. + * @return The created {@link Release}. + */ + Release releaseNormExpression(Query query); + + /** + * A record representing the query for releasing a new expression of a {@link Norm}. The query includes the + * ELI (European Legislation Identifier) to identify the {@link Norm}. + * + * @param eli The ELI (European Legislation Identifier) used to identify the {@link Norm}. + */ + record Query(NormExpressionEli eli) {} +} diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/LoadReleasesByNormExpressionEliPort.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/LoadReleasesByNormExpressionEliPort.java new file mode 100644 index 000000000..3ac607e1a --- /dev/null +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/LoadReleasesByNormExpressionEliPort.java @@ -0,0 +1,25 @@ +package de.bund.digitalservice.ris.norms.application.port.output; + +import de.bund.digitalservice.ris.norms.domain.entity.Release; +import de.bund.digitalservice.ris.norms.domain.entity.eli.NormExpressionEli; +import java.util.List; + +/** + * Interface representing a port for loading {@link Release}s of a specific norm expression. + */ +public interface LoadReleasesByNormExpressionEliPort { + /** + * Loads {@link Release}s of a specific norm expression. + * + * @param command The command specifying the ELI to identify the norm. + * @return A {@link List} of {@link Release}s, which may be empty if no {@link Release} is found. + */ + List loadReleasesByNormExpressionEli(final Command command); + + /** + * A record representing the command for loading releases of a norm. + * + * @param eli The ELI (European Legislation Identifier) used to identify the norm in the command. + */ + record Command(NormExpressionEli eli) {} +} diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/SaveReleasePort.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/SaveReleasePort.java new file mode 100644 index 000000000..d1417d571 --- /dev/null +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/SaveReleasePort.java @@ -0,0 +1,23 @@ +package de.bund.digitalservice.ris.norms.application.port.output; + +import de.bund.digitalservice.ris.norms.domain.entity.Release; + +/** + * Interface representing a port for saving a {@link Release}. + */ +public interface SaveReleasePort { + /** + * Saves a {@link Release}. + * + * @param command The command specifying the release. + * @return the {@link Release}. + */ + Release saveRelease(final Command command); + + /** + * A record representing the command for saving a release. + * + * @param release The release to be saved to the announcement + */ + record Command(Release release) {} +} diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/SaveReleaseToAnnouncementPort.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/SaveReleaseToAnnouncementPort.java deleted file mode 100644 index 63519f612..000000000 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/SaveReleaseToAnnouncementPort.java +++ /dev/null @@ -1,25 +0,0 @@ -package de.bund.digitalservice.ris.norms.application.port.output; - -import de.bund.digitalservice.ris.norms.domain.entity.Announcement; -import de.bund.digitalservice.ris.norms.domain.entity.Release; - -/** - * Interface representing a port for saving a {@link Release} to an {@link Announcement}. - */ -public interface SaveReleaseToAnnouncementPort { - /** - * Saves a {@link Release} to the provided {@link Announcement}. - * - * @param command The command specifying the announcement and release. - * @return the {@link Release} added to the announcement. - */ - Release saveReleaseToAnnouncement(final Command command); - - /** - * A record representing the command for saving a release to an announcement. - * - * @param release The release to be saved to the announcement - * @param announcement The announcement to which the release should be saved - */ - record Command(Release release, Announcement announcement) {} -} diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/service/AnnouncementService.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/service/AnnouncementService.java index b4de9b4be..3249b17c6 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/service/AnnouncementService.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/service/AnnouncementService.java @@ -10,7 +10,6 @@ import de.bund.digitalservice.ris.norms.utils.XmlMapper; import java.io.IOException; import java.nio.charset.Charset; -import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.Set; @@ -186,20 +185,7 @@ private void deleteAnnouncement(NormExpressionEli expressionEli) { deleteAnnouncementByNormEliPort.deleteAnnouncementByNormEli( new DeleteAnnouncementByNormEliPort.Command(expressionEli) ); - announcement - .get() - .getReleases() - .stream() - .map(Release::getPublishedNorms) - .flatMap(Collection::stream) - .forEach(norm -> - deleteNormPort.deleteNorm( - new DeleteNormPort.Command( - norm.getManifestationEli(), - NormPublishState.QUEUED_FOR_PUBLISH - ) - ) - ); + // TODO: (Malte Laukötter, 2025-02-25) we originally deleted all releases and published norms from the announcement here as well should we do this again? } Optional normToDelete = loadNormPort.loadNorm(new LoadNormPort.Command(expressionEli)); diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/service/ReleaseService.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/service/ReleaseService.java index 639a7aa58..7c8fc5dd8 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/service/ReleaseService.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/service/ReleaseService.java @@ -3,7 +3,8 @@ import de.bund.digitalservice.ris.norms.application.port.input.*; import de.bund.digitalservice.ris.norms.application.port.output.DeleteNormPort; import de.bund.digitalservice.ris.norms.application.port.output.DeleteQueuedReleasesPort; -import de.bund.digitalservice.ris.norms.application.port.output.SaveReleaseToAnnouncementPort; +import de.bund.digitalservice.ris.norms.application.port.output.LoadReleasesByNormExpressionEliPort; +import de.bund.digitalservice.ris.norms.application.port.output.SaveReleasePort; import de.bund.digitalservice.ris.norms.application.port.output.UpdateOrSaveNormPort; import de.bund.digitalservice.ris.norms.domain.entity.Announcement; import de.bund.digitalservice.ris.norms.domain.entity.Norm; @@ -22,35 +23,36 @@ * component in the Spring context. */ @Service -public class ReleaseService implements ReleaseAnnouncementUseCase { +public class ReleaseService + implements ReleaseNormExpressionUseCase, LoadReleasesByNormExpressionEliUseCase { - private final LoadAnnouncementByNormEliUseCase loadAnnouncementByNormEliUseCase; private final UpdateOrSaveNormPort updateOrSaveNormPort; private final NormService normService; private final CreateNewVersionOfNormService createNewVersionOfNormService; private final DeleteNormPort deleteNormPort; - private final SaveReleaseToAnnouncementPort saveReleaseToAnnouncementPort; + private final SaveReleasePort saveReleasePort; private final DeleteQueuedReleasesPort deleteQueuedReleasesPort; private final LdmlDeValidator ldmlDeValidator; + private final LoadReleasesByNormExpressionEliPort loadReleasesByNormExpressionEliPort; public ReleaseService( - LoadAnnouncementByNormEliUseCase loadAnnouncementByNormEliUseCase, UpdateOrSaveNormPort updateOrSaveNormPort, NormService normService, CreateNewVersionOfNormService createNewVersionOfNormService, DeleteNormPort deleteNormPort, - SaveReleaseToAnnouncementPort saveReleaseToAnnouncementPort, + SaveReleasePort saveReleasePort, DeleteQueuedReleasesPort deleteQueuedReleasesPort, - LdmlDeValidator ldmlDeValidator + LdmlDeValidator ldmlDeValidator, + LoadReleasesByNormExpressionEliPort loadReleasesByNormExpressionEliPort ) { - this.loadAnnouncementByNormEliUseCase = loadAnnouncementByNormEliUseCase; this.updateOrSaveNormPort = updateOrSaveNormPort; this.normService = normService; this.createNewVersionOfNormService = createNewVersionOfNormService; this.deleteNormPort = deleteNormPort; - this.saveReleaseToAnnouncementPort = saveReleaseToAnnouncementPort; + this.saveReleasePort = saveReleasePort; this.deleteQueuedReleasesPort = deleteQueuedReleasesPort; this.ldmlDeValidator = ldmlDeValidator; + this.loadReleasesByNormExpressionEliPort = loadReleasesByNormExpressionEliPort; } /** @@ -66,17 +68,12 @@ public ReleaseService( */ @Override @Transactional - public Announcement releaseAnnouncement(ReleaseAnnouncementUseCase.Query query) { - var announcement = loadAnnouncementByNormEliUseCase.loadAnnouncementByNormEli( - new LoadAnnouncementByNormEliUseCase.Query(query.eli()) - ); - var normToPublish = normService.loadNorm(new LoadNormUseCase.Query(announcement.getEli())); + public Release releaseNormExpression(ReleaseNormExpressionUseCase.Query query) { + var normToPublish = normService.loadNorm(new LoadNormUseCase.Query(query.eli())); - // Delete the files from a previous release of the same announcement if they are still queued for publishing. - // This is to prevent residual files from remaining if some time boundaries changed and this release will create - // different expressions. + // Delete the files from a previous release of the same norm if they are still queued for publishing. var deletedReleases = deleteQueuedReleasesPort.deleteQueuedReleases( - new DeleteQueuedReleasesPort.Command(announcement.getEli()) + new DeleteQueuedReleasesPort.Command(query.eli()) ); deletedReleases .stream() @@ -127,12 +124,16 @@ public Announcement releaseAnnouncement(ReleaseAnnouncementUseCase.Query query) .publishedNorms(List.of(manifestationToPublish)) .releasedAt(Instant.now()) .build(); - announcement.addRelease(release); - saveReleaseToAnnouncementPort.saveReleaseToAnnouncement( - new SaveReleaseToAnnouncementPort.Command(release, announcement) - ); + return saveReleasePort.saveRelease(new SaveReleasePort.Command(release)); + } - return announcement; + @Override + public List loadReleasesByNormExpressionEli( + LoadReleasesByNormExpressionEliUseCase.Query query + ) { + return loadReleasesByNormExpressionEliPort.loadReleasesByNormExpressionEli( + new LoadReleasesByNormExpressionEliPort.Command(query.eli()) + ); } } diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/domain/entity/Announcement.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/domain/entity/Announcement.java index 6e81a007e..54f8258a7 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/domain/entity/Announcement.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/domain/entity/Announcement.java @@ -21,12 +21,4 @@ public class Announcement { @Builder.Default private List releases = new ArrayList<>(); - - /** - * Add a new release to the announcement. - * @param release the new release - */ - public void addRelease(Release release) { - releases.add(release); - } } diff --git a/backend/src/main/resources/db/migration/V0.31__link_releases_to_norm_expressions.sql b/backend/src/main/resources/db/migration/V0.31__link_releases_to_norm_expressions.sql new file mode 100644 index 000000000..af43b17d6 --- /dev/null +++ b/backend/src/main/resources/db/migration/V0.31__link_releases_to_norm_expressions.sql @@ -0,0 +1 @@ +DROP TABLE announcement_releases; diff --git a/backend/src/test/java/de/bund/digitalservice/ris/norms/adapter/input/restapi/controller/AnnouncementControllerTest.java b/backend/src/test/java/de/bund/digitalservice/ris/norms/adapter/input/restapi/controller/AnnouncementControllerTest.java index b4f7ff90e..bc735db0d 100644 --- a/backend/src/test/java/de/bund/digitalservice/ris/norms/adapter/input/restapi/controller/AnnouncementControllerTest.java +++ b/backend/src/test/java/de/bund/digitalservice/ris/norms/adapter/input/restapi/controller/AnnouncementControllerTest.java @@ -9,9 +9,9 @@ import de.bund.digitalservice.ris.norms.application.port.input.CreateAnnouncementUseCase; import de.bund.digitalservice.ris.norms.application.port.input.LoadAllAnnouncementsUseCase; -import de.bund.digitalservice.ris.norms.application.port.input.LoadAnnouncementByNormEliUseCase; import de.bund.digitalservice.ris.norms.application.port.input.LoadNormUseCase; -import de.bund.digitalservice.ris.norms.application.port.input.ReleaseAnnouncementUseCase; +import de.bund.digitalservice.ris.norms.application.port.input.LoadReleasesByNormExpressionEliUseCase; +import de.bund.digitalservice.ris.norms.application.port.input.ReleaseNormExpressionUseCase; import de.bund.digitalservice.ris.norms.domain.entity.*; import de.bund.digitalservice.ris.norms.utils.XmlMapper; import java.io.ByteArrayInputStream; @@ -43,13 +43,13 @@ class AnnouncementControllerTest { private LoadAllAnnouncementsUseCase loadAllAnnouncementsUseCase; @MockitoBean - private LoadAnnouncementByNormEliUseCase loadAnnouncementByNormEliUseCase; + private LoadReleasesByNormExpressionEliUseCase loadReleasesByNormExpressionEliUseCase; @MockitoBean private LoadNormUseCase loadNormUseCase; @MockitoBean - private ReleaseAnnouncementUseCase releaseAnnouncementUseCase; + private ReleaseNormExpressionUseCase releaseNormExpressionUseCase; @MockitoBean private CreateAnnouncementUseCase createAnnouncementUseCase; @@ -193,22 +193,16 @@ void itReturnsRelease() throws Exception { // Given var norm1 = Fixtures.loadNormFromDisk("NormWithMods.xml"); var norm2 = Fixtures.loadNormFromDisk("NormWithPassiveModifications.xml"); - var announcement = Announcement - .builder() - .eli(norm1.getExpressionEli()) - .releases( - List.of( - Release - .builder() - .releasedAt(Instant.parse("2024-01-02T10:20:30.0Z")) - .publishedNorms(List.of(norm1, norm2)) - .build() - ) - ) - .build(); + List releases = List.of( + Release + .builder() + .releasedAt(Instant.parse("2024-01-02T10:20:30.0Z")) + .publishedNorms(List.of(norm1, norm2)) + .build() + ); - when(loadAnnouncementByNormEliUseCase.loadAnnouncementByNormEli(any())) - .thenReturn(announcement); + when(loadReleasesByNormExpressionEliUseCase.loadReleasesByNormExpressionEli(any())) + .thenReturn(releases); // When // Then mockMvc @@ -243,21 +237,13 @@ void itReleaseAnAnnouncement() throws Exception { // Given var norm1 = Fixtures.loadNormFromDisk("NormWithMods.xml"); var norm2 = Fixtures.loadNormFromDisk("NormWithPassiveModifications.xml"); - var announcement = Announcement + var release = Release .builder() - .eli(norm1.getExpressionEli()) - .releases( - List.of( - Release - .builder() - .releasedAt(Instant.parse("2024-01-02T10:20:30.0Z")) - .publishedNorms(List.of(norm1, norm2)) - .build() - ) - ) + .releasedAt(Instant.parse("2024-01-02T10:20:30.0Z")) + .publishedNorms(List.of(norm1, norm2)) .build(); - when(releaseAnnouncementUseCase.releaseAnnouncement(any())).thenReturn(announcement); + when(releaseNormExpressionUseCase.releaseNormExpression(any())).thenReturn(release); // When // Then mockMvc diff --git a/backend/src/test/java/de/bund/digitalservice/ris/norms/application/service/ReleaseServiceTest.java b/backend/src/test/java/de/bund/digitalservice/ris/norms/application/service/ReleaseServiceTest.java index 8ee01ee35..29415cfd0 100644 --- a/backend/src/test/java/de/bund/digitalservice/ris/norms/application/service/ReleaseServiceTest.java +++ b/backend/src/test/java/de/bund/digitalservice/ris/norms/application/service/ReleaseServiceTest.java @@ -8,50 +8,50 @@ import de.bund.digitalservice.ris.norms.application.exception.LdmlDeNotValidException; import de.bund.digitalservice.ris.norms.application.exception.LdmlDeSchematronException; -import de.bund.digitalservice.ris.norms.application.port.input.LoadAnnouncementByNormEliUseCase; -import de.bund.digitalservice.ris.norms.application.port.input.ReleaseAnnouncementUseCase; +import de.bund.digitalservice.ris.norms.application.port.input.LoadReleasesByNormExpressionEliUseCase; +import de.bund.digitalservice.ris.norms.application.port.input.ReleaseNormExpressionUseCase; import de.bund.digitalservice.ris.norms.application.port.output.DeleteNormPort; import de.bund.digitalservice.ris.norms.application.port.output.DeleteQueuedReleasesPort; -import de.bund.digitalservice.ris.norms.application.port.output.SaveReleaseToAnnouncementPort; +import de.bund.digitalservice.ris.norms.application.port.output.LoadReleasesByNormExpressionEliPort; +import de.bund.digitalservice.ris.norms.application.port.output.SaveReleasePort; import de.bund.digitalservice.ris.norms.application.port.output.UpdateOrSaveNormPort; -import de.bund.digitalservice.ris.norms.domain.entity.Announcement; import de.bund.digitalservice.ris.norms.domain.entity.Fixtures; import de.bund.digitalservice.ris.norms.domain.entity.Norm; import de.bund.digitalservice.ris.norms.domain.entity.NormPublishState; +import de.bund.digitalservice.ris.norms.domain.entity.Release; import de.bund.digitalservice.ris.norms.domain.entity.eli.NormExpressionEli; import de.bund.digitalservice.ris.norms.utils.XmlMapper; import java.time.Instant; import java.time.LocalDate; import java.util.List; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; class ReleaseServiceTest { - private final LoadAnnouncementByNormEliUseCase loadAnnouncementByNormEliUseCase = mock( - LoadAnnouncementByNormEliUseCase.class - ); private final UpdateOrSaveNormPort updateOrSaveNormPort = mock(UpdateOrSaveNormPort.class); private final NormService normService = mock(NormService.class); private final CreateNewVersionOfNormService createNewVersionOfNormService = mock( CreateNewVersionOfNormService.class ); private final DeleteNormPort deleteNormPort = mock(DeleteNormPort.class); - private final SaveReleaseToAnnouncementPort saveReleaseToAnnouncementPort = mock( - SaveReleaseToAnnouncementPort.class - ); + private final SaveReleasePort saveReleasePort = mock(SaveReleasePort.class); private final DeleteQueuedReleasesPort deleteQueuedReleasesPort = mock( DeleteQueuedReleasesPort.class ); private final LdmlDeValidator ldmlDeValidator = mock(LdmlDeValidator.class); + private final LoadReleasesByNormExpressionEliPort loadReleasesByNormExpressionEliPort = mock( + LoadReleasesByNormExpressionEliPort.class + ); private final ReleaseService releaseService = new ReleaseService( - loadAnnouncementByNormEliUseCase, updateOrSaveNormPort, normService, createNewVersionOfNormService, deleteNormPort, - saveReleaseToAnnouncementPort, + saveReleasePort, deleteQueuedReleasesPort, - ldmlDeValidator + ldmlDeValidator, + loadReleasesByNormExpressionEliPort ); @Test @@ -65,11 +65,8 @@ void itShouldReleaseAnAnnouncement() { var newNewestUnpublishedManifestationOfNorm = Fixtures.loadNormFromDisk( "NormWithoutPassiveModificationsNoNextVersion.xml" ); + var savedRelease = new Release(Instant.now(), List.of(manifestationOfNormToQueue)); - var announcement = Announcement.builder().eli(norm.getExpressionEli()).build(); - - when(loadAnnouncementByNormEliUseCase.loadAnnouncementByNormEli(any())) - .thenReturn(announcement); when(deleteQueuedReleasesPort.deleteQueuedReleases(any())).thenReturn(List.of()); when(normService.loadNorm(argThat(command -> command.eli().equals(norm.getExpressionEli())))) .thenReturn(norm); @@ -79,10 +76,11 @@ void itShouldReleaseAnAnnouncement() { createNewVersionOfNormService.createNewManifestation(any(), eq(LocalDate.now().plusDays(1))) ) .thenReturn(newNewestUnpublishedManifestationOfNorm); + when(saveReleasePort.saveRelease(any())).thenReturn(savedRelease); // When - releaseService.releaseAnnouncement( - new ReleaseAnnouncementUseCase.Query(norm.getExpressionEli()) + var returnedRelease = releaseService.releaseNormExpression( + new ReleaseNormExpressionUseCase.Query(norm.getExpressionEli()) ); // Then @@ -90,7 +88,7 @@ void itShouldReleaseAnAnnouncement() { verify(createNewVersionOfNormService, times(1)) .createNewManifestation(norm, LocalDate.now().plusDays(1)); verify(deleteQueuedReleasesPort, times(1)) - .deleteQueuedReleases(new DeleteQueuedReleasesPort.Command(announcement.getEli())); + .deleteQueuedReleases(new DeleteQueuedReleasesPort.Command(norm.getExpressionEli())); verify(ldmlDeValidator, times(1)) .parseAndValidateRegelungstext( XmlMapper.toString(manifestationOfNormToQueue.getRegelungstext1().getDocument()) @@ -104,47 +102,45 @@ void itShouldReleaseAnAnnouncement() { .deleteNorm( new DeleteNormPort.Command(norm.getManifestationEli(), NormPublishState.UNPUBLISHED) ); - verify(saveReleaseToAnnouncementPort, times(1)).saveReleaseToAnnouncement(any()); + verify(saveReleasePort, times(1)) + .saveRelease( + assertArg(command -> { + assertThat(command.release().getPublishedNorms()).hasSize(1); + assertThat(command.release().getPublishedNorms()).contains(manifestationOfNormToQueue); + }) + ); assertThat(manifestationOfNormToQueue.getPublishState()) .isEqualTo(NormPublishState.QUEUED_FOR_PUBLISH); assertThat(newNewestUnpublishedManifestationOfNorm.getPublishState()) .isEqualTo(NormPublishState.UNPUBLISHED); - assertThat(announcement.getReleases()).hasSize(1); - assertThat(announcement.getReleases().getFirst().getPublishedNorms()).hasSize(1); - assertThat(announcement.getReleases().getFirst().getPublishedNorms()) - .contains(manifestationOfNormToQueue); + assertThat(returnedRelease).isEqualTo(savedRelease); } @Test void itShouldUpdateTheReleasedByDocumentalistAtDate() { // Given var norm = Fixtures.loadNormFromDisk("SimpleNorm.xml"); - var announcement = Announcement.builder().eli(norm.getExpressionEli()).build(); - when(loadAnnouncementByNormEliUseCase.loadAnnouncementByNormEli(any())) - .thenReturn(announcement); when(normService.loadNorm(any())).thenReturn(norm); when(createNewVersionOfNormService.createNewManifestation(any())).thenReturn(norm); // When var instantBeforeRelease = Instant.now(); - releaseService.releaseAnnouncement( - new ReleaseAnnouncementUseCase.Query( + releaseService.releaseNormExpression( + new ReleaseNormExpressionUseCase.Query( NormExpressionEli.fromString("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu") ) ); // Then - verify(loadAnnouncementByNormEliUseCase, times(1)) - .loadAnnouncementByNormEli( - new LoadAnnouncementByNormEliUseCase.Query(norm.getExpressionEli()) + verify(saveReleasePort, times(1)) + .saveRelease( + assertArg(command -> { + assertThat(command.release().getReleasedAt()).isAfter(instantBeforeRelease); + }) ); - - verify(saveReleaseToAnnouncementPort, times(1)).saveReleaseToAnnouncement(any()); - assertThat(announcement.getReleases()).hasSize(1); - assertThat(announcement.getReleases().getFirst().getReleasedAt()).isAfter(instantBeforeRelease); } @Test @@ -160,10 +156,6 @@ void itShouldThrowWhenTryingToReleaseXsdInvalidNorm() { "NormWithoutPassiveModificationsNoNextVersion.xml" ); - var announcement = Announcement.builder().eli(norm.getExpressionEli()).build(); - - when(loadAnnouncementByNormEliUseCase.loadAnnouncementByNormEli(any())) - .thenReturn(announcement); when(normService.loadNorm(argThat(command -> command.eli().equals(norm.getExpressionEli())))) .thenReturn(norm); when(createNewVersionOfNormService.createNewManifestation(any())) @@ -175,10 +167,10 @@ void itShouldThrowWhenTryingToReleaseXsdInvalidNorm() { when(ldmlDeValidator.parseAndValidateRegelungstext(any())) .thenThrow(new LdmlDeNotValidException(List.of())); - var query = new ReleaseAnnouncementUseCase.Query(norm.getExpressionEli()); + var query = new ReleaseNormExpressionUseCase.Query(norm.getExpressionEli()); // When - assertThatThrownBy(() -> releaseService.releaseAnnouncement(query)) + assertThatThrownBy(() -> releaseService.releaseNormExpression(query)) .isInstanceOf(LdmlDeNotValidException.class); // Then @@ -192,7 +184,7 @@ void itShouldThrowWhenTryingToReleaseXsdInvalidNorm() { .createNewManifestation(norm, LocalDate.now().plusDays(1)); verify(updateOrSaveNormPort, times(0)).updateOrSave(any()); verify(updateOrSaveNormPort, times(0)).updateOrSave(any()); - verify(saveReleaseToAnnouncementPort, times(0)).saveReleaseToAnnouncement(any()); + verify(saveReleasePort, times(0)).saveRelease(any()); assertThat(manifestationOfNormToQueue.getPublishState()) .isEqualTo(NormPublishState.UNPUBLISHED); @@ -211,10 +203,6 @@ void itShouldThrowWhenTryingToReleaseSchematronInvalidNorm() { "NormWithoutPassiveModificationsNoNextVersion.xml" ); - var announcement = Announcement.builder().eli(norm.getExpressionEli()).build(); - - when(loadAnnouncementByNormEliUseCase.loadAnnouncementByNormEli(any())) - .thenReturn(announcement); when(normService.loadNorm(argThat(command -> command.eli().equals(norm.getExpressionEli())))) .thenReturn(norm); when(createNewVersionOfNormService.createNewManifestation(any())) @@ -227,10 +215,10 @@ void itShouldThrowWhenTryingToReleaseSchematronInvalidNorm() { .when(ldmlDeValidator) .validateSchematron(any(Norm.class)); - var query = new ReleaseAnnouncementUseCase.Query(norm.getExpressionEli()); + var query = new ReleaseNormExpressionUseCase.Query(norm.getExpressionEli()); // When - assertThatThrownBy(() -> releaseService.releaseAnnouncement(query)) + assertThatThrownBy(() -> releaseService.releaseNormExpression(query)) .isInstanceOf(LdmlDeSchematronException.class); // Then @@ -244,9 +232,43 @@ void itShouldThrowWhenTryingToReleaseSchematronInvalidNorm() { .createNewManifestation(norm, LocalDate.now().plusDays(1)); verify(updateOrSaveNormPort, times(0)).updateOrSave(any()); verify(updateOrSaveNormPort, times(0)).updateOrSave(any()); - verify(saveReleaseToAnnouncementPort, times(0)).saveReleaseToAnnouncement(any()); + verify(saveReleasePort, times(0)).saveRelease(any()); assertThat(manifestationOfNormToQueue.getPublishState()) .isEqualTo(NormPublishState.UNPUBLISHED); } + + @Nested + class loadReleasesByNormExpressionEli { + + @Test + void itLoadsReleases() { + // Given + var release1 = new Release(Instant.now(), List.of()); + var release2 = new Release(Instant.now(), List.of()); + + when(loadReleasesByNormExpressionEliPort.loadReleasesByNormExpressionEli(any())) + .thenReturn(List.of(release1, release2)); + + // When + var releases = releaseService.loadReleasesByNormExpressionEli( + new LoadReleasesByNormExpressionEliUseCase.Query( + NormExpressionEli.fromString("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu") + ) + ); + + // Then + assertThat(releases).containsExactlyInAnyOrder(release1, release2); + + verify(loadReleasesByNormExpressionEliPort, times(1)) + .loadReleasesByNormExpressionEli( + assertArg(command -> { + assertThat(command.eli()) + .isEqualTo( + NormExpressionEli.fromString("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu") + ); + }) + ); + } + } } diff --git a/backend/src/test/java/de/bund/digitalservice/ris/norms/integration/adapter/input/restapi/AnnouncementControllerIntegrationTest.java b/backend/src/test/java/de/bund/digitalservice/ris/norms/integration/adapter/input/restapi/AnnouncementControllerIntegrationTest.java index 0c163142c..b48c09ce2 100644 --- a/backend/src/test/java/de/bund/digitalservice/ris/norms/integration/adapter/input/restapi/AnnouncementControllerIntegrationTest.java +++ b/backend/src/test/java/de/bund/digitalservice/ris/norms/integration/adapter/input/restapi/AnnouncementControllerIntegrationTest.java @@ -5,7 +5,6 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import de.bund.digitalservice.ris.norms.adapter.output.database.dto.AnnouncementDto; import de.bund.digitalservice.ris.norms.adapter.output.database.dto.ReleaseDto; import de.bund.digitalservice.ris.norms.adapter.output.database.mapper.AnnouncementMapper; import de.bund.digitalservice.ris.norms.adapter.output.database.mapper.DokumentMapper; @@ -106,34 +105,6 @@ void itReturnsAllAnnouncementsNorm() throws Exception { @Nested class getReleases { - @Test - void itDoesNotReturnReleaseBecauseAnnouncementNotFound() throws Exception { - // given no announcement is stored in the database - - // when - mockMvc - .perform( - get("/api/v1/announcements/eli/bund/bgbl-1/2023/413/2023-12-29/1/deu/releases") - .accept(MediaType.APPLICATION_JSON) - ) - // then - .andExpect(status().isNotFound()) - .andExpect(jsonPath("type").value("/errors/announcement-not-found")) - .andExpect(jsonPath("title").value("Announcement not found")) - .andExpect(jsonPath("status").value(404)) - .andExpect( - jsonPath("detail") - .value( - "Announcement for norm with eli eli/bund/bgbl-1/2023/413/2023-12-29/1/deu does not exist" - ) - ) - .andExpect( - jsonPath("instance") - .value("/api/v1/announcements/eli/bund/bgbl-1/2023/413/2023-12-29/1/deu/releases") - ) - .andExpect(jsonPath("eli").value("eli/bund/bgbl-1/2023/413/2023-12-29/1/deu")); - } - @Test void itDoesReturnNoReleasesIfNoneFound() throws Exception { // Given @@ -184,20 +155,13 @@ void itReturnsRelease() throws Exception { .findByManifestationEli("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/2022-08-23") .orElseThrow(); - var releaseDto = releaseRepository.save( + releaseRepository.save( ReleaseDto .builder() .releasedAt(Instant.parse("2024-01-02T10:20:30.0Z")) .norms(List.of(amendingNorm, affectedNorm, affectedNormZf0)) .build() ); - announcementRepository.save( - AnnouncementDto - .builder() - .eliNormExpression("eli/bund/bgbl-1/2017/s419/2017-03-15/1/deu") - .releases(List.of(releaseDto)) - .build() - ); // When mockMvc @@ -228,8 +192,8 @@ void itReturnsRelease() throws Exception { class postReleases { @Test - void itDoesNotReleaseBecauseAnnouncementNotFound() throws Exception { - // given no announcement is stored in the database + void itDoesNotReleaseBecauseNormNotFound() throws Exception { + // given no norm is stored in the database // when mockMvc @@ -239,14 +203,12 @@ void itDoesNotReleaseBecauseAnnouncementNotFound() throws Exception { ) // then .andExpect(status().isNotFound()) - .andExpect(jsonPath("type").value("/errors/announcement-not-found")) - .andExpect(jsonPath("title").value("Announcement not found")) + .andExpect(jsonPath("type").value("/errors/norm-not-found")) + .andExpect(jsonPath("title").value("Norm not found")) .andExpect(jsonPath("status").value(404)) .andExpect( jsonPath("detail") - .value( - "Announcement for norm with eli eli/bund/bgbl-1/2023/413/2023-12-29/1/deu does not exist" - ) + .value("Norm with eli eli/bund/bgbl-1/2023/413/2023-12-29/1/deu does not exist") ) .andExpect( jsonPath("instance") @@ -318,12 +280,6 @@ void releasingAnAnnouncementASecondTimeCreatesTheSameFilesAndCleansUpOldRelease( DokumentMapper.mapToDto(Fixtures.loadRegelungstextFromDisk("NormWithMods.xml")) ); - var announcement = Announcement - .builder() - .eli(NormExpressionEli.fromString("eli/bund/bgbl-1/2017/s419/2017-03-15/1/deu")) - .build(); - announcementRepository.save(AnnouncementMapper.mapToDto(announcement)); - // When // Then mockMvc .perform( diff --git a/backend/src/test/java/de/bund/digitalservice/ris/norms/integration/adapter/output/database/DBServiceIntegrationTest.java b/backend/src/test/java/de/bund/digitalservice/ris/norms/integration/adapter/output/database/DBServiceIntegrationTest.java index fe87bc981..a0be1d19e 100644 --- a/backend/src/test/java/de/bund/digitalservice/ris/norms/integration/adapter/output/database/DBServiceIntegrationTest.java +++ b/backend/src/test/java/de/bund/digitalservice/ris/norms/integration/adapter/output/database/DBServiceIntegrationTest.java @@ -21,6 +21,7 @@ import de.bund.digitalservice.ris.norms.domain.entity.eli.NormExpressionEli; import de.bund.digitalservice.ris.norms.domain.entity.eli.NormManifestationEli; import de.bund.digitalservice.ris.norms.integration.BaseIntegrationTest; +import java.time.Instant; import java.time.LocalDate; import java.time.ZoneOffset; import java.util.List; @@ -370,39 +371,26 @@ void itCreatesNewAnnouncement() { } @Nested - class saveReleaseToAnnouncement { + class saveRelease { @Test - void itUpdatesAnnouncementAndSavesRelease() { + void itSavesRelease() { // Given dokumentRepository.save( DokumentMapper.mapToDto(Fixtures.loadRegelungstextFromDisk("SimpleNorm.xml")) ); - var announcement = Announcement - .builder() - .eli(NormExpressionEli.fromString("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu")) - .build(); - announcementRepository.save(AnnouncementMapper.mapToDto(announcement)); - var norm = Fixtures.loadNormFromDisk("SimpleNorm.xml"); var release = Release.builder().publishedNorms(List.of(norm)).build(); // When - dbService.saveReleaseToAnnouncement( - new SaveReleaseToAnnouncementPort.Command(release, announcement) - ); + dbService.saveRelease(new SaveReleasePort.Command(release)); - var savedAnnouncement = announcementRepository.findByEliNormExpression( - norm.getExpressionEli().toString() - ); + var releases = releaseRepository.findAll(); - assertThat(savedAnnouncement).isPresent(); - assertThat(savedAnnouncement.get().getReleases()).hasSize(1); - assertThat(savedAnnouncement.get().getReleases().getFirst().getNorms()).hasSize(1); - assertThat( - savedAnnouncement.get().getReleases().getFirst().getNorms().getFirst().getManifestationEli() - ) + assertThat(releases).hasSize(1); + assertThat(releases.getFirst().getNorms()).hasSize(1); + assertThat(releases.getFirst().getNorms().getFirst().getManifestationEli()) .isEqualTo("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/1964-08-05"); } } @@ -422,10 +410,6 @@ void itDeletesQueuedReleases() { normDto.setPublishState(NormPublishState.QUEUED_FOR_PUBLISH); normDto = normManifestationRepository.save(normDto); - var announcement = Announcement - .builder() - .eli(NormExpressionEli.fromString("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu")) - .build(); var release = Release .builder() .publishedNorms(List.of(Fixtures.loadNormFromDisk("SimpleNorm.xml"))) @@ -435,19 +419,18 @@ void itDeletesQueuedReleases() { releaseDto.setNorms(List.of(normDto)); releaseRepository.save(releaseDto); - var announcementDto = AnnouncementMapper.mapToDto(announcement); - announcementDto.setReleases(List.of(releaseDto)); - announcementRepository.save(announcementDto); - // When - dbService.deleteQueuedReleases(new DeleteQueuedReleasesPort.Command(announcement.getEli())); + dbService.deleteQueuedReleases( + new DeleteQueuedReleasesPort.Command( + NormExpressionEli.fromString("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu") + ) + ); // Then - var savedAnnouncement = announcementRepository.findByEliNormExpression( + var savedReleases = releaseRepository.findAllByNormExpressionEli( "eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu" ); - assertThat(savedAnnouncement).isPresent(); - assertThat(savedAnnouncement.get().getReleases()).isEmpty(); + assertThat(savedReleases).isEmpty(); var savedNorm = dokumentRepository.findByEliDokumentManifestation( "eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/1964-08-05/regelungstext-1.xml" @@ -538,4 +521,106 @@ void itLoadLastMigrationLogWithSameDate() { .satisfies(log -> assertThat(log).contains(migrationLog2)); } } + + @Nested + class loadReleasesByNormExpressionEli { + + @Test + void itLoadsRelease() { + // Given + dokumentRepository.save( + DokumentMapper.mapToDto(Fixtures.loadRegelungstextFromDisk("SimpleNorm.xml")) + ); + var normDto = normManifestationRepository + .findByManifestationEli("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/1964-08-05") + .orElseThrow(); + normDto.setPublishState(NormPublishState.QUEUED_FOR_PUBLISH); + normDto = normManifestationRepository.save(normDto); + + var release = Release + .builder() + .publishedNorms(List.of(Fixtures.loadNormFromDisk("SimpleNorm.xml"))) + .build(); + + var releaseDto = ReleaseMapper.mapToDto(release); + releaseDto.setNorms(List.of(normDto)); + releaseRepository.save(releaseDto); + releaseRepository.save( + ReleaseMapper.mapToDto(Release.builder().releasedAt(Instant.now()).build()) + ); + + // When + var releases = dbService.loadReleasesByNormExpressionEli( + new LoadReleasesByNormExpressionEliPort.Command( + NormExpressionEli.fromString("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu") + ) + ); + + assertThat(releases).hasSize(1); + assertThat(releases.getFirst().getPublishedNorms()).hasSize(1); + assertThat(releases.getFirst().getPublishedNorms().getFirst().getManifestationEli()) + .isEqualTo( + NormManifestationEli.fromString("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/1964-08-05") + ); + } + + @Test + void itLoadsReleases() { + // Given + dokumentRepository.save( + DokumentMapper.mapToDto(Fixtures.loadRegelungstextFromDisk("SimpleNorm.xml")) + ); + var normDto = normManifestationRepository + .findByManifestationEli("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/1964-08-05") + .orElseThrow(); + normDto.setPublishState(NormPublishState.QUEUED_FOR_PUBLISH); + normDto = normManifestationRepository.save(normDto); + var release = Release + .builder() + .publishedNorms(List.of(Fixtures.loadNormFromDisk("SimpleNorm.xml"))) + .build(); + var releaseDto = ReleaseMapper.mapToDto(release); + releaseDto.setNorms(List.of(normDto)); + releaseRepository.save(releaseDto); + + dokumentRepository.save( + DokumentMapper.mapToDto( + Fixtures.loadRegelungstextFromDisk("NormWithPassiveModifications.xml") + ) + ); + var normDto2 = normManifestationRepository + .findByManifestationEli("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/2022-08-23") + .orElseThrow(); + var release2 = Release + .builder() + .publishedNorms(List.of(Fixtures.loadNormFromDisk("SimpleNorm.xml"))) + .build(); + var releaseDto2 = ReleaseMapper.mapToDto(release2); + releaseDto2.setNorms(List.of(normDto2)); + releaseRepository.save(releaseDto2); + + releaseRepository.save( + ReleaseMapper.mapToDto(Release.builder().releasedAt(Instant.now()).build()) + ); + + // When + var releases = dbService.loadReleasesByNormExpressionEli( + new LoadReleasesByNormExpressionEliPort.Command( + NormExpressionEli.fromString("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu") + ) + ); + + assertThat(releases).hasSize(2); + assertThat(releases.getFirst().getPublishedNorms()).hasSize(1); + assertThat(releases.getFirst().getPublishedNorms().getFirst().getManifestationEli()) + .isEqualTo( + NormManifestationEli.fromString("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/1964-08-05") + ); + assertThat(releases.get(1).getPublishedNorms()).hasSize(1); + assertThat(releases.get(1).getPublishedNorms().getFirst().getManifestationEli()) + .isEqualTo( + NormManifestationEli.fromString("eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/2022-08-23") + ); + } + } }