Skip to content
Merged
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
2 changes: 1 addition & 1 deletion psc-toggle-manager/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<dependency>
<groupId>fr.ans.psc</groupId>
<artifactId>psc-api-client</artifactId>
<version>2.2.22</version>
<version>2.3.2</version>
Comment thread
edegenetais-nx marked this conversation as resolved.
</dependency>
<dependency>
<groupId>fr.ans.psc</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,20 @@ public ToggleController(ToggleService toggleService) {
@PostMapping(value = "/toggle", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<Void> toggleRegistrySource(@RequestParam("from") String from, @RequestParam("to") String to, @RequestParam("toggleFile") MultipartFile mpFile) {

final PsIdType sourceIdType = decodeIdType(from, "from");
final PsIdType destinationIdType = decodeIdType(to, "to");
toggleService.toggle(mpFile, sourceIdType, destinationIdType);
return new ResponseEntity<>(HttpStatus.ACCEPTED);

}

@PostMapping(value = "/remove", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<Void> removeFromRegistrySource(@RequestParam("from") String from, @RequestParam("to") String to, @RequestParam("toggleFile") MultipartFile mpFile) {
toggleService.removeToggle(mpFile, PsIdType.valueOf(from.toUpperCase()), PsIdType.valueOf(to.toUpperCase()));
return new ResponseEntity<>(HttpStatus.ACCEPTED);
}

private PsIdType decodeIdType(String name, final String parmName) {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright © 2022-2024 Agence du Numérique en Santé (ANS) (https://esante.gouv.fr)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package fr.ans.psc.toggle.model;

import lombok.Getter;
import lombok.Setter;
import org.springframework.http.HttpStatus;

import java.util.Map;

@Getter
@Setter
public class Report {
protected int successful;
protected int failed;
protected int submitted;

public void setReportCounters(Map<String, TogglePsRef> psRefMap) {
submitted = psRefMap.size();
successful = (int) psRefMap.values().stream().filter(psRef -> psRef.getReturnStatus() == HttpStatus.OK.value()).count();
failed = submitted - successful;
}

public String generateReportSummary() {
return String.format("Opérations terminées.\n\n" +
"%s soumis.\n" +
"%s en succès.\n" +
"%s en échec.\n\n" +
"Vous trouverez la liste des opérations en pièce jointe.\n\n" +
"Les erreurs possibles sont les suivantes :\n" +
"- 500 : Erreur côté serveur, veuillez vous rapprocher de l'administrateur.",
submitted, successful, failed);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,23 @@

@Getter
@Setter
public class ToggleReport {
public class ToggleReport extends Report {

private int alreadyToggled;
private int successful;
private int failed;
private int submitted;

public ToggleReport() {
super();
}

@Override
public void setReportCounters(Map<String, TogglePsRef> psRefMap) {
submitted = psRefMap.size();
alreadyToggled = (int) psRefMap.values().stream().filter(psRef -> psRef.getReturnStatus() == HttpStatus.CONFLICT.value()).count();
successful = (int) psRefMap.values().stream().filter(psRef -> psRef.getReturnStatus() == HttpStatus.OK.value()).count();
failed = submitted - (alreadyToggled + successful);
}

@Override
public String generateReportSummary() {
return String.format("Opérations de bascule terminées.\n\n" +
"%s PsRefs soumis à bascule.\n" +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright © 2022-2024 Agence du Numérique en Santé (ANS) (https://esante.gouv.fr)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package fr.ans.psc.toggle.model;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class UntoggleReport extends Report {

@Override
public String generateReportSummary() {
return String.format("Opérations terminées.\n\n" +
"%s PsRefs soumis pour déréférencement.\n" +
"%s PsRefs retirés avec succès.\n" +
"%s PsRefs n'ont pas pu être retirés.\n\n" +
"Vous trouverez la liste des opérations en pièce jointe.\n\n" +
"Les erreurs possibles sont les suivantes :\n" +
"- 404 : Le PsRef proposé n'est pas lié au Ps, n'a pas pu être retiré.\n" +
"- 410 : Le Ps proposé n'est pas présent en base, le PsRef n'a pas été rétiré.\n" +
"- 500 : Erreur côté serveur, veuillez vous rapprocher de l'administrateur.",
submitted, successful, failed);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import fr.ans.psc.toggle.model.PsIdType;
import fr.ans.psc.toggle.model.TogglePsRef;
import fr.ans.psc.toggle.model.ToggleReport;
import fr.ans.psc.toggle.model.UntoggleReport;
import lombok.extern.slf4j.Slf4j;
import org.apache.any23.encoding.TikaEncodingDetector;
import org.junit.jupiter.params.shadow.com.univocity.parsers.common.ParsingContext;
Expand All @@ -45,15 +46,15 @@
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

@Service
@Slf4j
public class ToggleService {

private final String TOGGLE_FILE_NAME = "Table_de_Correspondance_bascule";
private final String FAILURE_REPORT_FILENAME = "pscload_rapport_des_echecs_de_bascule";
private static final String TOGGLE_FILE_NAME = "Table_de_Correspondance_bascule";
private static final String TOGGLE_FAILURE_REPORT_FILENAME = "pscload_rapport_des_echecs_de_bascule";
private static final String UNTOGGLE_FAILURE_REPORT_FILENAME = "pscload_rapport_des_echecs_de_dereferencement";
private static final int TOGGLE_ROW_LENGTH = 2;

@Autowired
Expand All @@ -75,7 +76,33 @@ public void toggle(MultipartFile mpFile, PsIdType originIdType, PsIdType targetI
Map<String, TogglePsRef> psRefMap = loadPSRefMapFromFile(toggleFile, originIdType, targetIdType);
togglePsRefs(psRefMap);
if (enableEmailing) {
reportToggleErrors(psRefMap);
File zipFile = reportToggleErrors(psRefMap, TOGGLE_FAILURE_REPORT_FILENAME);
ToggleReport toggleReport = new ToggleReport();
toggleReport.setReportCounters(psRefMap);
emailService.sendMail(toggleReport.generateReportSummary(), zipFile);
}

} catch (ToggleFileParsingException tpe) {
log.error("Error during parsing toggle file", tpe);
} catch (FileNotFoundException fnfe) {
log.error("Could not find csv output file");
} catch (IOException ioe) {
log.error("Error during tempFile creation", ioe);
}

}

@Async("processExecutor")
public void removeToggle(MultipartFile mpFile, PsIdType originIdType, PsIdType targetIdType) {
try {
File toggleFile = uploadToggleFile(mpFile);
Map<String, TogglePsRef> psRefMap = loadPSRefMapFromFile(toggleFile, originIdType, targetIdType);
untogglePsRefs(psRefMap);
if (enableEmailing) {
File zipFile = reportToggleErrors(psRefMap, UNTOGGLE_FAILURE_REPORT_FILENAME);
UntoggleReport untoggleReport = new UntoggleReport();
untoggleReport.setReportCounters(psRefMap);
emailService.sendMail(untoggleReport.generateReportSummary(), zipFile);
}

} catch (ToggleFileParsingException tpe) {
Expand Down Expand Up @@ -176,28 +203,51 @@ void togglePsRefs(Map<String, TogglePsRef> psRefMap) {
log.info("All PsRefs have been treated.");
}

/**
* @param psRefMap the map of ps to untoggle
*/
void untogglePsRefs(Map<String, TogglePsRef> psRefMap) {
ApiClient client = new ApiClient();
client.setBasePath(apiBaseUrl);
ToggleApi toggleApi = new ToggleApi(client);
PsApi psApi = new PsApi(client);
psRefMap.values().parallelStream().forEach(psRef -> {
try {
String result = toggleApi.removeTogglePsref(psRef);
log.info(result);
psRef.setReturnStatus(HttpStatus.OK.value());
Ps ps = psApi.getPsById(URLEncoder.encode(psRef.getNationalId(), StandardCharsets.UTF_8));
messageProducer.sendPsMessage(ps, "UPDATE");
} catch (RestClientResponseException e) {
log.error(e.getResponseBodyAsString());
psRef.setReturnStatus(e.getRawStatusCode());
}
});
log.info("All PsRefs have been treated.");
}

/**
* @param psRefMap the map of non toggled psref, with api return status
*/
void reportToggleErrors(Map<String, TogglePsRef> psRefMap) throws FileNotFoundException {
File reportToggleErrors(Map<String, TogglePsRef> psRefMap, String filename) throws FileNotFoundException {
List<String> dataLines = new ArrayList<>();

psRefMap.values().forEach(psRef -> {
String[] dataItems = new String[]{psRef.getNationalIdRef(), psRef.getNationalId(), String.valueOf(psRef.getReturnStatus())};
dataLines.add(String.join(";", dataItems));
});

File csvOutputFile = new File("/app", FAILURE_REPORT_FILENAME + ".csv");
File csvOutputFile = new File("/app", filename + ".csv");
try (PrintWriter pw = new PrintWriter(csvOutputFile)) {
pw.println("original_Id;target_Id;returned_code");
dataLines.forEach(pw::println);
}

try {
InputStream fileContent = new FileInputStream(csvOutputFile);
ZipEntry zipEntry = new ZipEntry(FAILURE_REPORT_FILENAME + ".csv");
ZipEntry zipEntry = new ZipEntry(filename + ".csv");
zipEntry.setTime(System.currentTimeMillis());
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("/app" + File.separator + FAILURE_REPORT_FILENAME + ".zip"));
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("/app" + File.separator + filename + ".zip"));
zos.putNextEntry(zipEntry);
StreamUtils.copy(fileContent, zos);

Expand All @@ -211,12 +261,8 @@ void reportToggleErrors(Map<String, TogglePsRef> psRefMap) throws FileNotFoundEx
}

csvOutputFile.delete();
File zipFile = new File("/app", FAILURE_REPORT_FILENAME + ".zip");
File zipFile = new File("/app", filename + ".zip");
log.info("file length is " + zipFile.length());

ToggleReport toggleReport = new ToggleReport();
toggleReport.setReportCounters(psRefMap);
emailService.sendMail(toggleReport.generateReportSummary(), zipFile);

return zipFile;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright © 2022-2024 Agence du Numérique en Santé (ANS) (https://esante.gouv.fr)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package fr.ans.psc.toggle.model;

import fr.ans.psc.toggle.ToggleManagerApplication;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
@ActiveProfiles("test")
@ContextConfiguration(classes = ToggleManagerApplication.class)
public class ReportTest {

@Test
@DisplayName("tata")
void setCounters() {
Map<String, TogglePsRef> psRefMap = TestUtil.createTestPsRefMap();

Report report = new Report();
report.setReportCounters(psRefMap);

assertEquals(3, report.getSubmitted());
assertEquals(1, report.getFailed());
assertEquals(2, report.getSuccessful());
}

@Test
@DisplayName("tutu")
void generateReport() {
Map<String, TogglePsRef> psRefMap = TestUtil.createTestPsRefMap();

String expected = "Opérations terminées.\n\n" +
"3 soumis.\n" +
"2 en succès.\n" +
"1 en échec.\n\n" +
"Vous trouverez la liste des opérations en pièce jointe.\n\n" +
"Les erreurs possibles sont les suivantes :\n" +
"- 500 : Erreur côté serveur, veuillez vous rapprocher de l'administrateur.";

Report report = new Report();
report.setReportCounters(psRefMap);
String actual = report.generateReportSummary();
assertEquals(expected, actual);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright © 2022-2024 Agence du Numérique en Santé (ANS) (https://esante.gouv.fr)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package fr.ans.psc.toggle.model;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class TestUtil {
public static Map<String, TogglePsRef> createTestPsRefMap() {
TogglePsRef psRef1 = new TogglePsRef(new String[]{"123", "823"}, PsIdType.ADELI, PsIdType.RPPS);
psRef1.setReturnStatus(200);
TogglePsRef psRef2 = new TogglePsRef(new String[]{"055", "855"}, PsIdType.ADELI, PsIdType.RPPS);
psRef2.setReturnStatus(200);
TogglePsRef psRef3 = new TogglePsRef(new String[]{"089","889"}, PsIdType.ADELI, PsIdType.RPPS);
psRef3.setReturnStatus(409);

Map<String, TogglePsRef> psRefMap = new ConcurrentHashMap<>();
psRefMap.put(psRef1.getNationalIdRef(), psRef1);
psRefMap.put(psRef2.getNationalIdRef(), psRef2);
psRefMap.put(psRef3.getNationalIdRef(), psRef3);

return psRefMap;
}
}
Loading