From 1b76363316b52d21a403a69ee2f02d4e09effde3 Mon Sep 17 00:00:00 2001 From: aoezyetimoglu Date: Wed, 8 Sep 2021 12:12:54 +0200 Subject: [PATCH] RED-2115: Added generating dossier status report --- .../v1/api/model/StatusReportResponse.java | 17 ++ .../v1/api/resource/StatusReportResource.java | 20 +++ .../StatusReportGenerationService.java | 155 ++++++++++++++++++ .../StatusReportGenerationServiceTest.java | 102 ++++++++++++ 4 files changed, 294 insertions(+) create mode 100644 redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/model/StatusReportResponse.java create mode 100644 redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/resource/StatusReportResource.java create mode 100644 redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/StatusReportGenerationService.java create mode 100644 redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/service/StatusReportGenerationServiceTest.java diff --git a/redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/model/StatusReportResponse.java b/redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/model/StatusReportResponse.java new file mode 100644 index 0000000..937a503 --- /dev/null +++ b/redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/model/StatusReportResponse.java @@ -0,0 +1,17 @@ +package com.iqser.red.service.redaction.report.v1.api.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class StatusReportResponse { + + private byte [] report; + private String filename; + +} diff --git a/redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/resource/StatusReportResource.java b/redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/resource/StatusReportResource.java new file mode 100644 index 0000000..6e2b9d3 --- /dev/null +++ b/redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/resource/StatusReportResource.java @@ -0,0 +1,20 @@ +package com.iqser.red.service.redaction.report.v1.api.resource; + +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +import com.iqser.red.service.redaction.report.v1.api.model.StatusReportResponse; + +public interface StatusReportResource { + + String STATUS_REPORT = "/statusReport"; + String DOSSIER_ID = "dossierId"; + + String DOSSIER_ID_PATH_VARIABLE = "/{" + DOSSIER_ID + "}"; + + + @GetMapping(value = STATUS_REPORT + DOSSIER_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE) + StatusReportResponse generateStatusReport(@PathVariable(DOSSIER_ID) String dossierId); + +} diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/StatusReportGenerationService.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/StatusReportGenerationService.java new file mode 100644 index 0000000..afcd1d5 --- /dev/null +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/StatusReportGenerationService.java @@ -0,0 +1,155 @@ +package com.iqser.red.service.redaction.report.v1.server.service; + +import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ISO; + +import java.io.ByteArrayOutputStream; +import java.time.OffsetDateTime; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.apache.poi.xssf.usermodel.XSSFFont; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.stereotype.Service; + +import com.iqser.red.service.configuration.v1.api.model.FileAttributeConfig; +import com.iqser.red.service.configuration.v1.api.model.FileAttributesConfig; +import com.iqser.red.service.file.management.v1.api.model.Dossier; +import com.iqser.red.service.file.management.v1.api.model.FileAttributes; +import com.iqser.red.service.file.management.v1.api.model.FileStatus; +import com.iqser.red.service.file.management.v1.api.model.Status; +import com.iqser.red.service.redaction.report.v1.server.client.DossierClient; +import com.iqser.red.service.redaction.report.v1.server.client.FileAttributesClient; +import com.iqser.red.service.redaction.report.v1.server.client.FileStatusClient; + +import io.undertow.util.BadRequestException; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; + +@Service +@RequiredArgsConstructor +public class StatusReportGenerationService { + + private final FileStatusClient fileStatusClient; + private final DossierClient dossierClient; + private final FileAttributesClient fileAttributesClient; + + + public byte[] generateReport(String dossierId) throws BadRequestException { + + Dossier dossier; + try { + dossier = dossierClient.getDossierById(dossierId); + } catch (Exception e) { + throw new BadRequestException("Dossier not found."); + } + + List fileStatuses = fileStatusClient.getDossierStatus(dossierId); + + List fileAttributeConfigs = fileAttributesClient.getFileAttributes(dossier.getDossierTemplateId()) + .getFileAttributeConfigs(); + + XSSFWorkbook workbook = new XSSFWorkbook(); + XSSFSheet sheet = workbook.createSheet(dossier.getDossierName()); + + XSSFFont font = workbook.createFont(); + font.setBold(true); + XSSFCellStyle style = workbook.createCellStyle(); + style.setFont(font); + addHeader(sheet, style); + + XSSFRow headerRow = sheet.getRow(0); + int headerCounter = 5; + Map attributesAssignment = new HashMap<>(); + for (FileAttributeConfig fileAttributeConfig : fileAttributeConfigs) { + sheet.setColumnWidth(headerCounter, 8000); + attributesAssignment.put(fileAttributeConfig.getId(), headerCounter); + XSSFCell cell = headerRow.createCell(headerCounter++); + cell.setCellValue(fileAttributeConfig.getLabel()); + cell.setCellStyle(style); + } + + for (int i = 0; i < fileStatuses.size(); i++) { + + FileStatus fileStatus = fileStatuses.get(i); + + String name = fileStatus.getFilename(); + OffsetDateTime uploadDate = fileStatus.getLastUploaded(); + String assignedTo = fileStatus.getCurrentReviewer(); + Status status = fileStatus.getStatus(); + int pages = fileStatus.getNumberOfPages(); + FileAttributes fileAttributes = fileStatus.getFileAttributes(); + + XSSFRow row = sheet.createRow(i + 1); + + XSSFCell cellName = row.createCell(0); + cellName.setCellValue(name); + XSSFCell cellUploadDate = row.createCell(1); + cellUploadDate.setCellValue(uploadDate.format(FORMAT_DATE_ISO)); + XSSFCell cellAssignedTo = row.createCell(2); + cellAssignedTo.setCellValue(assignedTo); + XSSFCell cellStatus = row.createCell(3); + cellStatus.setCellValue(status.name()); + XSSFCell cellPages = row.createCell(4); + cellPages.setCellValue(pages); + + Iterator> iterator = fileAttributes.getAttributeIdToValue().entrySet().iterator(); + while (iterator.hasNext()) { + var nextElement = iterator.next(); + if(attributesAssignment.get(nextElement.getKey()) != null) { + XSSFCell cell = row.createCell(attributesAssignment.get(nextElement.getKey())); + cell.setCellValue(nextElement.getValue()); + } + } + + } + + return toByteArray(workbook); + } + + + private void addHeader(XSSFSheet sheet, XSSFCellStyle style) { + + sheet.setColumnWidth(0, 10000); + sheet.setColumnWidth(1, 4000); + sheet.setColumnWidth(2, 8000); + sheet.setColumnWidth(3, 5000); + sheet.setColumnWidth(4, 2000); + + XSSFRow row = sheet.createRow(0); + + XSSFCell cellName = row.createCell(0); + cellName.setCellValue("Filename"); + cellName.setCellStyle(style); + XSSFCell cellUploadDate = row.createCell(1); + cellUploadDate.setCellValue("Upload date"); + cellUploadDate.setCellStyle(style); + XSSFCell cellAssignedTo = row.createCell(2); + cellAssignedTo.setCellValue("Assigned to"); + cellAssignedTo.setCellStyle(style); + XSSFCell cellStatus = row.createCell(3); + cellStatus.setCellValue("Status"); + cellStatus.setCellStyle(style); + XSSFCell cellPages = row.createCell(4); + cellPages.setCellValue("Pages"); + cellPages.setCellStyle(style); + + } + + + @SneakyThrows + public byte[] toByteArray(XSSFWorkbook doc) { + + try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { + doc.write(byteArrayOutputStream); + doc.close(); + return byteArrayOutputStream.toByteArray(); + } + } + +} diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/service/StatusReportGenerationServiceTest.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/service/StatusReportGenerationServiceTest.java new file mode 100644 index 0000000..d185d0a --- /dev/null +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/service/StatusReportGenerationServiceTest.java @@ -0,0 +1,102 @@ +package com.iqser.red.service.redaction.report.v1.server.service; + +import static org.mockito.Mockito.when; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.time.OffsetDateTime; +import java.util.List; +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit4.SpringRunner; + +import com.iqser.red.service.configuration.v1.api.model.FileAttributeConfig; +import com.iqser.red.service.configuration.v1.api.model.FileAttributesConfig; +import com.iqser.red.service.file.management.v1.api.model.Dossier; +import com.iqser.red.service.file.management.v1.api.model.FileAttributes; +import com.iqser.red.service.file.management.v1.api.model.FileStatus; +import com.iqser.red.service.file.management.v1.api.model.Status; +import com.iqser.red.service.redaction.report.v1.server.client.DossierClient; +import com.iqser.red.service.redaction.report.v1.server.client.FileAttributesClient; +import com.iqser.red.service.redaction.report.v1.server.client.FileStatusClient; + +import io.undertow.util.BadRequestException; + +@RunWith(SpringRunner.class) +public class StatusReportGenerationServiceTest { + + @Mock + private FileStatusClient fileStatusClient; + + @Mock + private DossierClient dossierClient; + + @Mock + private FileAttributesClient fileAttributesClient; + + @InjectMocks + private StatusReportGenerationService statusReportGenerationService; +// @MockBean +// private ExcelTemplateReportGenerationService excelTemplateReportGenerationService; +// +// @MockBean +// private ReportStorageService reportStorageService; +// +// @MockBean +// private StorageService storageService; +// +// @MockBean +// private AmazonS3 s3Client; + + + @Test + public void testGenerateReport() throws IOException, BadRequestException { + + String dossierId = "dossierId"; + + Dossier dossier = Dossier.builder().dossierName("dossierName").dossierId(dossierId).build(); + when(dossierClient.getDossierById(dossierId)).thenReturn(dossier); + + FileAttributes fileAttributes1 = new FileAttributes(Map.of("a", "A", "config2", "B2")); + FileStatus fileStatus1 = FileStatus.builder() + .dossierId(dossierId) + .filename("file1") + .lastUploaded(OffsetDateTime.now().minusHours(2)) + .currentReviewer("me") + .status(Status.APPROVED) + .numberOfPages(3) + .fileAttributes(fileAttributes1) + .build(); + + FileAttributes fileAttributes2 = new FileAttributes(Map.of("config1", "X1", "y", "Y")); + FileStatus fileStatus2 = FileStatus.builder() + .dossierId(dossierId) + .filename("file2") + .lastUploaded(OffsetDateTime.now()) + .currentReviewer("you") + .status(Status.APPROVED) + .numberOfPages(21) + .fileAttributes(fileAttributes2) + .build(); + + when(fileStatusClient.getDossierStatus(dossierId)).thenReturn(List.of(fileStatus1, fileStatus2)); + + FileAttributeConfig fileAttributeConfig1 = FileAttributeConfig.builder().id("config1").label("Label1").build(); + FileAttributeConfig fileAttributeConfig2 = FileAttributeConfig.builder().id("config2").label("Label2").build(); + + FileAttributesConfig fileAttributesConfig = new FileAttributesConfig(null, null, List.of(fileAttributeConfig1,fileAttributeConfig2)); + when(fileAttributesClient.getFileAttributes(dossier.getDossierTemplateId())).thenReturn(fileAttributesConfig); + + byte[] report = statusReportGenerationService.generateReport(dossierId); + + try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/status_report.xlsx")) { + fileOutputStream.write(report); + } + + } + +} \ No newline at end of file