Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add duplicate check #2439

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
@Slf4j
public class DocumentationUnitController {
private final DocumentationUnitService service;
private final DuplicateCheckService duplicateCheckService;
private final UserService userService;
private final AttachmentService attachmentService;
private final ConverterService converterService;
Expand All @@ -70,6 +71,7 @@ public class DocumentationUnitController {

public DocumentationUnitController(
DocumentationUnitService service,
DuplicateCheckService duplicateCheckService,
UserService userService,
AttachmentService attachmentService,
ConverterService converterService,
Expand All @@ -79,6 +81,7 @@ public DocumentationUnitController(
DocumentationUnitDocxMetadataInitializationService
documentationUnitDocxMetadataInitializationService) {
this.service = service;
this.duplicateCheckService = duplicateCheckService;
this.userService = userService;
this.attachmentService = attachmentService;
this.converterService = converterService;
Expand Down Expand Up @@ -240,6 +243,14 @@ public ResponseEntity<DocumentationUnit> getByDocumentNumber(
}
}

@GetMapping(value = "/{documentNumber}/duplicates", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("@userHasReadAccessByDocumentNumber.apply(#documentNumber)")
public ResponseEntity<List<DocumentationUnit>> getDuplicatesByDocumentNumber(
@AuthenticationPrincipal OidcUser oidcUser, @NonNull @PathVariable String documentNumber) {
var documentationUnits = duplicateCheckService.getDuplicates(documentNumber);
return ResponseEntity.ok(documentationUnits);
}

@DeleteMapping(value = "/{uuid}")
@PreAuthorize("@userIsInternal.apply(#oidcUser) and @userHasWriteAccess.apply(#uuid)")
public ResponseEntity<String> deleteByUuid(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package de.bund.digitalservice.ris.caselaw.adapter;

import de.bund.digitalservice.ris.caselaw.domain.DocumentationUnit;
import de.bund.digitalservice.ris.caselaw.domain.DocumentationUnitService;
import de.bund.digitalservice.ris.caselaw.domain.DuplicateCheckRepository;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class DuplicateCheckService {
private final DocumentationUnitService documentationUnitService;

private final DuplicateCheckRepository repository;

public DuplicateCheckService(
DuplicateCheckRepository repository, DocumentationUnitService documentationUnitService) {
this.repository = repository;
this.documentationUnitService = documentationUnitService;
}

List<DocumentationUnit> getDuplicates(String docNumber) {
try {
var documentationUnit = documentationUnitService.getByDocumentNumber(docNumber);

var fileNumbers = documentationUnit.coreData().fileNumbers();
var deviatingFileNumbers = documentationUnit.coreData().deviatingFileNumbers();
List<String> allFileNumbers = new ArrayList<>();
if (fileNumbers != null) {
allFileNumbers.addAll(fileNumbers.stream().map(String::toUpperCase).toList());
}
if (deviatingFileNumbers != null) {
allFileNumbers.addAll(deviatingFileNumbers.stream().map(String::toUpperCase).toList());
}

var decisionDate = documentationUnit.coreData().decisionDate();
var deviatingDecisionDates = documentationUnit.coreData().deviatingDecisionDates();
List<LocalDate> allDates = new ArrayList<>();
if (decisionDate != null) allDates.add(decisionDate);
if (!deviatingDecisionDates.isEmpty()) allDates.addAll(deviatingDecisionDates);

List<UUID> allCourtIds = new ArrayList<>();
var court = documentationUnit.coreData().court();
if (court != null) allCourtIds.add(court.id());

List<String> allDeviatingCourts = new ArrayList<>();
var deviatingCourts = documentationUnit.coreData().deviatingCourts();
if (deviatingCourts != null)
allDeviatingCourts.addAll(deviatingCourts.stream().map(String::toUpperCase).toList());

var ecli = documentationUnit.coreData().ecli();
var deviatingEclis = documentationUnit.coreData().deviatingEclis();
List<String> allEclis = new ArrayList<>();
if (ecli != null) allEclis.add(ecli.toUpperCase());
if (deviatingEclis != null)
allEclis.addAll(deviatingEclis.stream().map(String::toUpperCase).toList());

var documentType = documentationUnit.coreData().documentType();
return repository.findDuplicates(
allFileNumbers, allDates, allCourtIds, allDeviatingCourts, allEclis, documentType.uuid());
} catch (Exception e) {
log.debug(e.getMessage());
return List.of();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package de.bund.digitalservice.ris.caselaw.adapter.database.jpa;

import java.time.LocalDate;
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;

@Repository
public interface DatabaseDuplicateCheckRepository
extends JpaRepository<DocumentationUnitDTO, UUID> {

@Query(
nativeQuery = true,
value =
"""
SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.file_number fileNumber
ON documentationUnit.id = fileNumber.documentation_unit_id
WHERE upper(fileNumber.value) IN (:allFileNumbers)
AND documentationUnit.decision_date IN (:allDates)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.file_number fileNumber
ON documentationUnit.id = fileNumber.documentation_unit_id
JOIN incremental_migration.deviating_date deviatingDate
ON documentationUnit.id = deviatingDate.documentation_unit_id
WHERE upper(fileNumber.value) IN (:allFileNumbers)
AND deviatingDate.value IN (:allDates)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.deviating_file_number deviatingFileNumber
ON documentationUnit.id = deviatingFileNumber.documentation_unit_id
WHERE upper(deviatingFileNumber.value) IN (:allFileNumbers)
AND documentationUnit.decision_date IN (:allDates)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.deviating_file_number deviatingFileNumber
ON documentationUnit.id = deviatingFileNumber.documentation_unit_id
JOIN incremental_migration.deviating_date deviatingDate
ON documentationUnit.id = deviatingDate.documentation_unit_id
WHERE upper(deviatingFileNumber.value) IN (:allFileNumbers)
AND deviatingDate.value IN (:allDates)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.file_number fileNumber
ON documentationUnit.id = fileNumber.documentation_unit_id
JOIN incremental_migration.court court
ON documentationUnit.court_id = court.id
WHERE upper(fileNumber.value) IN (:allFileNumbers)
AND court.id IN (:allCourtIds)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.deviating_file_number deviatingFileNumber
ON documentationUnit.id = deviatingFileNumber.documentation_unit_id
JOIN incremental_migration.court court
ON documentationUnit.court_id = court.id
WHERE upper(deviatingFileNumber.value) IN (:allFileNumbers)
AND court.id IN (:allCourtIds)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.file_number fileNumber
ON documentationUnit.id = fileNumber.documentation_unit_id
JOIN incremental_migration.deviating_court deviatingCourt
ON documentationUnit.id = deviatingCourt.documentation_unit_id
WHERE upper(fileNumber.value) IN (:allFileNumbers)
AND upper(deviatingCourt.value) IN (:allDeviatingCourts)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.deviating_file_number deviatingFileNumber
ON documentationUnit.id = deviatingFileNumber.documentation_unit_id
JOIN incremental_migration.deviating_court deviatingCourt
ON documentationUnit.id = deviatingCourt.documentation_unit_id
WHERE upper(deviatingFileNumber.value) IN (:allFileNumbers)
AND upper(deviatingCourt.value) IN (:allDeviatingCourts)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.file_number fileNumber
ON documentationUnit.id = fileNumber.documentation_unit_id
WHERE upper(fileNumber.value) IN (:allFileNumbers)
AND upper(documentationUnit.ecli) IN (:allEclis)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.deviating_file_number deviatingFileNumber
ON documentationUnit.id = deviatingFileNumber.documentation_unit_id
WHERE upper(deviatingFileNumber.value) IN (:allFileNumbers)
AND upper(documentationUnit.ecli) IN (:allEclis)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.file_number fileNumber
ON documentationUnit.id = fileNumber.documentation_unit_id
JOIN incremental_migration.deviating_ecli deviatingEcli
ON documentationUnit.id = deviatingEcli.documentation_unit_id
WHERE upper(fileNumber.value) IN (:allFileNumbers)
AND upper(deviatingEcli.value) IN (:allEclis)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.deviating_file_number deviatingFileNumber
ON documentationUnit.id = deviatingFileNumber.documentation_unit_id
JOIN incremental_migration.deviating_ecli deviatingEcli
ON documentationUnit.id = deviatingEcli.documentation_unit_id
WHERE upper(deviatingFileNumber.value) IN (:allFileNumbers)
AND upper(deviatingEcli.value) IN (:allEclis)

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.file_number fileNumber
ON documentationUnit.id = fileNumber.documentation_unit_id
JOIN incremental_migration.document_type documentType
ON documentationUnit.document_type_id = documentType.id
WHERE upper(fileNumber.value) IN (:allFileNumbers)
AND documentType.id = :documentTypeId

UNION

SELECT documentationUnit.*
FROM incremental_migration.documentation_unit documentationUnit
JOIN incremental_migration.deviating_file_number deviatingFileNumber
ON documentationUnit.id = deviatingFileNumber.documentation_unit_id
JOIN incremental_migration.document_type documentType
ON documentationUnit.document_type_id = documentType.id
WHERE upper(deviatingFileNumber.value) IN (:allFileNumbers)
AND documentType.id = :documentTypeId
""")
List<DocumentationUnitDTO> findDuplicates(
@Param("allFileNumbers") List<String> allFileNumbers,
@Param("allDates") List<LocalDate> allDates,
@Param("allCourtIds") List<UUID> allCourtIds,
@Param("allDeviatingCourts") List<String> allDeviatingCourts,
@Param("allEclis") List<String> allEclis,
@Param("documentTypeId") UUID documentTypeId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package de.bund.digitalservice.ris.caselaw.adapter.database.jpa;

import de.bund.digitalservice.ris.caselaw.adapter.transformer.DocumentationUnitTransformer;
import de.bund.digitalservice.ris.caselaw.domain.DocumentationUnit;
import de.bund.digitalservice.ris.caselaw.domain.DuplicateCheckRepository;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Repository
public class PostgresDuplicateCheckRepositoryImpl implements DuplicateCheckRepository {

private final DatabaseDuplicateCheckRepository repository;

public PostgresDuplicateCheckRepositoryImpl(DatabaseDuplicateCheckRepository repository) {
this.repository = repository;
}

@Override
@Transactional
public List<DocumentationUnit> findDuplicates(
List<String> allFileNumbers,
List<LocalDate> allDates,
List<UUID> allCourtIds,
List<String> allDeviatingCourts,
List<String> allEclis,
UUID documentTypeId) {
long startTime = System.currentTimeMillis();

List<DocumentationUnitDTO> result =
repository.findDuplicates(
allFileNumbers, allDates, allCourtIds, allDeviatingCourts, allEclis, documentTypeId);

long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
log.info("Query executed in: " + duration + " ms");

return result.stream()
.filter(Objects::nonNull)
.distinct()
.map(DocumentationUnitTransformer::transformToDomain)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package de.bund.digitalservice.ris.caselaw.domain;

import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
import org.springframework.data.repository.NoRepositoryBean;

@NoRepositoryBean
public interface DuplicateCheckRepository {

List<DocumentationUnit> findDuplicates(
List<String> allFileNumbers,
List<LocalDate> allDates,
List<UUID> allCourtIds,
List<String> allDeviatingCourts,
List<String> allEclis,
UUID documentTypeId);
}
Loading