Resolved conflicts

This commit is contained in:
harish
2024-10-12 21:33:14 +05:30
40 changed files with 1409 additions and 60 deletions

View File

@@ -1,4 +1,5 @@
FROM amazoncorretto:17.0.8-alpine3.17 FROM amazoncorretto:17.0.8-alpine3.17
ENV TZ="Europe/Rome"
EXPOSE 8080 EXPOSE 8080
ADD /target/tendermanagement-0.0.1-SNAPSHOT.jar tendermanagement-0.0.1-SNAPSHOT.jar ADD /target/tendermanagement-0.0.1-SNAPSHOT.jar tendermanagement-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java", "-jar","tendermanagement-0.0.1-SNAPSHOT.jar"] ENTRYPOINT ["java", "-jar","tendermanagement-0.0.1-SNAPSHOT.jar"]

20
pom.xml
View File

@@ -191,6 +191,26 @@
<version>2.3.0</version> <!-- or latest --> <version>2.3.0</version> <!-- or latest -->
</dependency> </dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itext7-core -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>8.0.5</version>
<type>pom</type>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/layout -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>8.0.5</version>
</dependency>
</dependencies> </dependencies>
<repositories> <repositories>

View File

@@ -203,5 +203,12 @@ public class GepafinConstant {
public static final String USER_NOT_AUTHORIZED_TO_CREATE_APPLICATION = "user.not.authorized.create.application"; public static final String USER_NOT_AUTHORIZED_TO_CREATE_APPLICATION = "user.not.authorized.create.application";
public static final String APPLICATION_SUBMITTED_CANNOT_CHANGE = "application.submitted.cannot.change"; public static final String APPLICATION_SUBMITTED_CANNOT_CHANGE = "application.submitted.cannot.change";
public static final String CALL_DOCUMENTS_FETCH_SUCCESS_MSG = "call.documents.fetch.success";
public static final String CALL_DOCUMENTS_NOT_FOUND_MSG = "call.documents.not.found";
public static final String PERMISSION_DENIED = "permission.denied";
public static final String SIGNED_DOCUMENT_FILE_UPLOAD_SUCCESS = "signed.document.file.upload.success";
public static final String GET_SIGNED_DOCUMENT_FILE_SUCCESS = "get.signed.document.file.success";
public static final String APPLICATION_SIGNED_DOCUMENT_NOT_FOUND = "application.signed.document.not.found";
public static final String DELETE_SIGNED_DOCUMENT_FILE_SUCCESS = "delete.signed.document.file.success";
} }

View File

@@ -4,6 +4,7 @@ import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.entities.*;
import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum; import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum;
import net.gepafin.tendermanagement.enums.ApplicationSignedDocumentStatusEnum;
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum;
import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.enums.RoleStatusEnum;
@@ -13,6 +14,7 @@ import net.gepafin.tendermanagement.model.request.ApplicationRequest;
import net.gepafin.tendermanagement.model.request.ApplicationRequestBean; import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.model.response.*;
import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.repositories.*;
import net.gepafin.tendermanagement.service.AmazonS3Service;
import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.service.CallService;
import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.service.CompanyService;
import net.gepafin.tendermanagement.service.DocumentService; import net.gepafin.tendermanagement.service.DocumentService;
@@ -33,8 +35,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Predicate;
import jakarta.servlet.http.HttpServletRequest;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -76,12 +80,13 @@ public class ApplicationDao {
@Autowired @Autowired
private FlowDataRepository flowDataRepository; private FlowDataRepository flowDataRepository;
@Autowired
private UserWithCompanyRepository userWithCompanyRepository;
@Autowired @Autowired
private UserCompanyDelegationRepository userCompanyDelegationRepository; private UserCompanyDelegationRepository userCompanyDelegationRepository;
@Autowired @Autowired
private Validator validator; private Validator validator;
@Autowired @Autowired
private CompanyService companyService; private CompanyService companyService;
@@ -89,6 +94,7 @@ public class ApplicationDao {
private ProtocolRepository protocolRepository; private ProtocolRepository protocolRepository;
@Autowired @Autowired
private SystemEmailTemplatesService systemEmailTemplatesService; private SystemEmailTemplatesService systemEmailTemplatesService;
@Autowired @Autowired
@@ -106,6 +112,13 @@ public class ApplicationDao {
@Value("${carlo_email}") @Value("${carlo_email}")
private String carloEmail; private String carloEmail;
private AmazonS3Service amazonS3Service;
@Autowired
private ApplicationSignedDocumentRepository applicationSignedDocumentRepository;
@Value("${aws.s3.url.folder.signed.document}")
private String signedDocumentS3Folder;
public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId, Long applicationId) { public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId, Long applicationId) {
@@ -689,7 +702,6 @@ public class ApplicationDao {
protocolRepository.save(protocolEntity); protocolRepository.save(protocolEntity);
return protocolEntity; return protocolEntity;
} }
private void sendMailToUserAndCompany(UserEntity userEntity, ApplicationEntity applicationEntity) { private void sendMailToUserAndCompany(UserEntity userEntity, ApplicationEntity applicationEntity) {
CallEntity call =applicationEntity.getCall(); CallEntity call =applicationEntity.getCall();
CompanyEntity company = applicationEntity.getCompany(); CompanyEntity company = applicationEntity.getCompany();
@@ -724,7 +736,7 @@ public class ApplicationDao {
} }
private void sendMailTodefaultSystemAndGepafin(UserEntity userEntity, ApplicationEntity applicationEntity) { private void sendMailTodefaultSystemAndGepafin(UserEntity userEntity, ApplicationEntity applicationEntity) {
CallEntity call =applicationEntity.getCall(); CallEntity call = applicationEntity.getCall();
CompanyEntity company = applicationEntity.getCompany(); CompanyEntity company = applicationEntity.getCompany();
ProtocolEntity protocol = applicationEntity.getProtocol(); ProtocolEntity protocol = applicationEntity.getProtocol();
SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService
@@ -754,4 +766,79 @@ public class ApplicationDao {
mailUtil.sendByMailGun(subject, body, List.of(carloEmail), null); mailUtil.sendByMailGun(subject, body, List.of(carloEmail), null);
} }
public ApplicationSignedDocumentResponse uploadSignedDocument(HttpServletRequest request, Long applicationId,
MultipartFile file) {
ApplicationEntity applicationEntity = validateApplication(applicationId);
validator.validateUserWithCompany(request, applicationEntity.getCompany().getId());
validateFileType(file);
ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository
.findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
if (applicationSignedDocument != null) {
applicationSignedDocument.setStatus(ApplicationSignedDocumentStatusEnum.INACTIVE.getValue());
applicationSignedDocumentRepository.save(applicationSignedDocument);
}
UploadFileOnAmazonS3Response uploadFileOnAmazonS3 = amazonS3Service.uploadFileOnAmazonS3(signedDocumentS3Folder,
file);
applicationSignedDocument = new ApplicationSignedDocumentEntity();
applicationSignedDocument.setApplication(applicationEntity);
applicationSignedDocument.setFileName(uploadFileOnAmazonS3.getFileName());
applicationSignedDocument.setFilePath(uploadFileOnAmazonS3.getFilePath());
applicationSignedDocument.setStatus(ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
applicationSignedDocumentRepository.save(applicationSignedDocument);
return convertApplicationSignedDocumentToApplicationSignedDocumentResponse(applicationSignedDocument);
}
private ApplicationSignedDocumentResponse convertApplicationSignedDocumentToApplicationSignedDocumentResponse(
ApplicationSignedDocumentEntity applicationSignedDocument) {
ApplicationSignedDocumentResponse applicationSignedDocumentResponse = new ApplicationSignedDocumentResponse();
applicationSignedDocumentResponse.setId(applicationSignedDocument.getId());
applicationSignedDocumentResponse.setApplicationId(applicationSignedDocument.getApplication().getId());
applicationSignedDocumentResponse.setFileName(applicationSignedDocument.getFileName());
applicationSignedDocumentResponse.setFilePath(applicationSignedDocument.getFilePath());
applicationSignedDocumentResponse
.setStatus(ApplicationSignedDocumentStatusEnum.valueOf(applicationSignedDocument.getStatus()));
applicationSignedDocumentResponse.setCreatedDate(applicationSignedDocument.getCreatedDate());
applicationSignedDocumentResponse.setUpdatedDate(applicationSignedDocument.getUpdatedDate());
return applicationSignedDocumentResponse;
}
private void validateFileType(MultipartFile file) {
if (file.isEmpty()) {
throw new CustomValidationException(Status.VALIDATION_ERROR,
Translator.toLocale(GepafinConstant.VALIDATION_ERROR_FILE_EMPTY));
}
String filename = file.getOriginalFilename();
if (filename == null || !filename.endsWith(".p7m")) {
throw new CustomValidationException(Status.VALIDATION_ERROR,
Translator.toLocale(GepafinConstant.VALIDATION_ERROR_FILE_INVALIDTYPE));
}
}
public ApplicationSignedDocumentResponse getSignedDocument(HttpServletRequest request, Long applicationId) {
ApplicationEntity applicationEntity = validateApplication(applicationId);
validator.validateUserWithCompany(request, applicationEntity.getCompany().getId());
ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository
.findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
if(applicationSignedDocument == null) {
throw new ResourceNotFoundException(Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.APPLICATION_SIGNED_DOCUMENT_NOT_FOUND));
}
return convertApplicationSignedDocumentToApplicationSignedDocumentResponse(applicationSignedDocument);
}
public void deleteSignedDocument(HttpServletRequest request, Long applicationId) {
ApplicationEntity applicationEntity = validateApplication(applicationId);
validator.validateUserWithCompany(request, applicationEntity.getCompany().getId());
ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository
.findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
if(applicationSignedDocument == null) {
throw new ResourceNotFoundException(Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.APPLICATION_SIGNED_DOCUMENT_NOT_FOUND));
}
applicationSignedDocument.setStatus(ApplicationSignedDocumentStatusEnum.INACTIVE.getValue());
applicationSignedDocumentRepository.save(applicationSignedDocument);
}
} }

View File

@@ -1,5 +1,9 @@
package net.gepafin.tendermanagement.dao; package net.gepafin.tendermanagement.dao;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -8,13 +12,21 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum;
import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.model.response.*;
import net.gepafin.tendermanagement.service.*; import net.gepafin.tendermanagement.service.*;
import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.DateTimeUtil;
import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.util.Utils;
import org.h2.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@@ -85,6 +97,10 @@ public class CallDao {
private FlowDao flowDao; private FlowDao flowDao;
@Autowired @Autowired
private FormDao formDao; private FormDao formDao;
@Value("${aws.s3.url.folder}")
private String s3Folder;
@Autowired
private AmazonS3Service amazonS3Service;
public CallResponse createCallStep1(CreateCallRequestStep1 createCallRequest, Long userId) { public CallResponse createCallStep1(CreateCallRequestStep1 createCallRequest, Long userId) {
UserEntity userEntity = userService.validateUser(userId); UserEntity userEntity = userService.validateUser(userId);
@@ -101,6 +117,35 @@ public class CallDao {
return createCallResponseBean; return createCallResponseBean;
} }
public byte[] downloadCallDocumentsAsZip(Long callId) {
List<DocumentEntity> documents = documentRepository.findBySourceIdAndSourceAndTypeAndIsDeletedFalse(callId, DocumentSourceTypeEnum.CALL.getValue(),DocumentTypeEnum.DOCUMENT.getValue());
if (documents.isEmpty()) {
throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND));
}
try (ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(zipOutputStream)) {
for (DocumentEntity document : documents) {
try (InputStream fileInputStream = amazonS3Service.getFile(s3Folder, document.getFileName())) {
ZipEntry zipEntry = new ZipEntry(document.getFileName());
zos.putNextEntry(zipEntry);
IOUtils.copy(fileInputStream, zos);
zos.closeEntry();
} catch (IOException e) {
throw new RuntimeException("Error downloading or adding document to ZIP: " + document.getFileName(), e);
}
}
zos.finish();
return zipOutputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException("Error while creating ZIP file", e);
}
}
public CallEntity convertToCallEntity(CreateCallRequestStep1 createCallRequest) { public CallEntity convertToCallEntity(CreateCallRequestStep1 createCallRequest) {
CallEntity callEntity = new CallEntity(); CallEntity callEntity = new CallEntity();

View File

@@ -18,6 +18,7 @@ import net.gepafin.tendermanagement.repositories.UserWithCompanyRepository;
import net.gepafin.tendermanagement.service.UserService; import net.gepafin.tendermanagement.service.UserService;
import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import net.gepafin.tendermanagement.web.rest.api.errors.ForbiddenAccessException;
import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status; import net.gepafin.tendermanagement.web.rest.api.errors.Status;
@@ -190,8 +191,8 @@ public class CompanyDao {
} }
public UserWithCompanyEntity validateUserWithCompny(Long userId, Long companyId) { public UserWithCompanyEntity validateUserWithCompny(Long userId, Long companyId) {
return userWithCompanyRepository.findByUserIdAndCompanyId(userId, companyId).orElseThrow(() -> new CustomValidationException(Status.UNAUTHORIZED, return userWithCompanyRepository.findByUserIdAndCompanyId(userId, companyId).orElseThrow(() -> new ForbiddenAccessException(Status.FORBIDDEN,
Translator.toLocale(GepafinConstant.UNAUTHORIZED))); Translator.toLocale(GepafinConstant.PERMISSION_DENIED)));
} }
public UserWithCompanyEntity getUserWithCompany(Long userId, Long compnayId) { public UserWithCompanyEntity getUserWithCompany(Long userId, Long compnayId) {

View File

@@ -0,0 +1,600 @@
package net.gepafin.tendermanagement.dao;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.renderer.CellRenderer;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.text.*;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.*;
import net.gepafin.tendermanagement.model.request.CustomPageEvent;
import net.gepafin.tendermanagement.model.request.FieldLabelValuePairRequest;
import net.gepafin.tendermanagement.model.response.*;
import net.gepafin.tendermanagement.repositories.ApplicationRepository;
import net.gepafin.tendermanagement.service.CallService;
import net.gepafin.tendermanagement.util.Validator;
import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Cell;
//import com.itextpdf.layout.element.
import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class PdfDao {
@Autowired
private CallService callService;
@Autowired
private ApplicationDao applicationDao;
@Autowired
private Validator validator;
public byte[] generatePdf(HttpServletRequest request,Long applicationId) {
try {
UserEntity userEntity = validator.validateUser(request);
ApplicationEntity applicationEntity = applicationDao.validateApplication(applicationId);
validator.validateUserWithCompany(request, applicationEntity.getCompany().getId());
CallEntity call=callService.validateCall(applicationEntity.getCall().getId());
// Create a byte stream to hold the PDF
ByteArrayOutputStream out = new ByteArrayOutputStream();
float leftMargin = 50f; // Adjust this for the left margin
Document document = new Document(PageSize.A4, leftMargin, 36f, 50f, 35);
PdfWriter writer = PdfWriter.getInstance(document, out);
CustomPageEvent pageEvent = new CustomPageEvent(call.getName(), 0);
writer.setPageEvent(pageEvent);
document.open();
pageEvent.setTotalPages(writer.getPageNumber());
addLogo(document, "https://mementoresources.s3.eu-west-1.amazonaws.com/gepafin/logo.jpg"); // Add your image path here
BaseColor customColor = new BaseColor(0, 128, 0); // Adjust RGB values as needed
// Define fonts and styles
BaseColor greenColor = new BaseColor(0, 128, 0); // Adjust RGB values as needed
BaseColor darkGreenColor = new BaseColor(1, 50, 32); // Adjust RGB values as needed
Font titleFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 16, customColor);
Font sectionFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 12,darkGreenColor);
Font labelFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 12,new BaseColor(113,121,126)); // Light grey);
Font smallFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 8,new BaseColor(105, 105, 105));
Font valueFont=FontFactory.getFont(FontFactory.HELVETICA_BOLD,10,new BaseColor(178, 190, 181));
Paragraph title = new Paragraph(call.getName(), titleFont);
title.setAlignment(Element.ALIGN_LEFT);
document.add(title);
BaseColor greyColor=new BaseColor(178, 190, 181); // Very light grey color
addColoredLines(writer,document,greyColor);
document.add(new Paragraph(" "));
// Application ID section (Centered)
pageEvent.setTotalPages(writer.getPageNumber());
Paragraph appId = new Paragraph("ID domanda :" +"XX00");
appId.setAlignment(Element.ALIGN_RIGHT);
document.add(appId);
if(applicationEntity.getProtocol()!=null) {
appId = new Paragraph("ID domanda :"+String.valueOf(applicationEntity.getProtocol().getProtocolNumber()), valueFont);
appId.setAlignment(Element.ALIGN_RIGHT);
document.add(appId);
}
document.add(new Paragraph(" "));
addColoredLines(writer,document,greenColor);
document.add(new Paragraph(" "));
document.add(new Paragraph("\n")); // Add line break
// String companyName= companyEntity.getCompanyName();
// String vatNumber=companyEntity.getVatNumber();
// String address=companyEntity.getAddress();
// // Section: Dati Anagrafici Azienda
// document.add(new Paragraph("Dati Anagrafici Azienda", sectionFont));
// addLabelValuePair(document, "Codice ATECO", "SEZIONE C “ATTIVITÀ MANUFATTURIERE”", regularFont);
// addLabelValuePair(document, "Ragione Sociale", companyName, regularFont);
// addLabelValuePair(document, "Partita IVA", vatNumber, regularFont);
// addLabelValuePair(document, "Indirizzo sede Legale", address, regularFont);
//
// document.add(new Paragraph("\n")); // Add line break
//
// // Section: Domanda presentata da
// document.add(new Paragraph("Domanda presentata da:", sectionFont));
// addLabelValuePair(document, "Nome e cognome", userEntity.getBeneficiary().getFirstName()+" "+userEntity.getBeneficiary().getLastName(), regularFont);
// addLabelValuePair(document, "Codice fiscale", userEntity.getBeneficiary().getCodiceFiscale(), regularFont);
// addLabelValuePair(document, "Telefono", userEntity.getBeneficiary().getPhoneNumber(), regularFont);
// addLabelValuePair(document, "Email", userEntity.getBeneficiary().getEmail(), regularFont);
// addLabelValuePair(document, "Con il titolo di", "Rappresentante legale", regularFont);
document.add(new Paragraph(" "));
ApplicationGetResponseBean applicationGetResponseBean=applicationDao.getApplicationByFormId(applicationId,null, userEntity);
for(FormApplicationResponse formApplicationResponse: applicationGetResponseBean.getForm()) {
document.add(new Paragraph(formApplicationResponse.getLabel(),sectionFont));
document.add(new Paragraph(" ")); // Add line break
List<FieldLabelValuePairRequest> fieldLabelValuePairRequests = getFormFieldsToLabels(formApplicationResponse);
for (FieldLabelValuePairRequest pair : fieldLabelValuePairRequests) {
String label = pair.getLabel();
Object value = pair.getValue();
Integer pages=0;
pages=addLabelValuePair(writer,document, label, value, labelFont,valueFont,call.getName(),pages);
if(pages !=0 ){
pageEvent.setTotalPages(writer.getPageNumber());
}
}
addColoredLines(writer,document,greenColor);
document.add(new Paragraph(" ")); // Add line break
}
document.add(new Paragraph("\n")); // Add line break
Font boldSmallFont = new Font(Font.FontFamily.HELVETICA, 10, Font.BOLD,new BaseColor(105, 105, 105));
// Adding the "Documenti Allegati" section title
document.add(new Paragraph(" "));
pageEvent.setTotalPages(writer.getPageNumber());
document.newPage();
document.add(new Paragraph("Documenti Allegati", sectionFont));
document.add(new Paragraph(" "));
// 1. Autocertificazione possesso Requisiti
Paragraph p1 = new Paragraph();
p1.add(new Chunk("1. ", boldSmallFont));
p1.add(new Chunk("Autocertificazione possesso Requisiti ", boldSmallFont));
p1.add(new Chunk("ai sensi degli artt. 46 e 47 del DPR 445/2000", smallFont));
document.add(p1);
document.add(new Paragraph(" "));
// 2. Informativa Privacy relativa al trattamento dei dati personali
Paragraph p2 = new Paragraph();
p2.add(new Chunk("2. ", boldSmallFont));
p2.add(new Chunk("Informativa Privacy relativa al trattamento dei dati personali", boldSmallFont));
document.add(p2);
document.add(new Paragraph(" "));
// 3. Dati richiesti per la valutazione delladeguatezza dei flussi finanziari
Paragraph p3 = new Paragraph();
p3.add(new Chunk("3. ", boldSmallFont));
p3.add(new Chunk("Dati richiesti per la valutazione delladeguatezza dei flussi finanziari prospettici come da tabella di cui allAppendice 9", boldSmallFont));
document.add(p3);
document.add(new Paragraph(" "));
// 4. Rilevazione Centrale dei Rischi
Paragraph p4 = new Paragraph();
p4.add(new Chunk("4. ", boldSmallFont));
p4.add(new Chunk("Rilevazione Centrale dei Rischi riferita agli ultimi 36 mesi disponibili alla data di presentazione della Domanda", boldSmallFont));
document.add(p4);
document.add(new Paragraph(" "));
// 5. Schema di presentazione dei dati di bilancio
Paragraph p5 = new Paragraph();
p5.add(new Chunk("5. ", boldSmallFont));
p5.add(new Chunk("Schema di presentazione dei dati di bilancio", boldSmallFont));
document.add(p5);
document.add(new Paragraph(" "));
// 6. Dettagli bilanci in forma abbreviata
Paragraph p6 = new Paragraph();
p6.add(new Chunk("6. ", boldSmallFont));
p6.add(new Chunk("Dettagli bilanci in forma abbreviata", boldSmallFont));
document.add(p6);
document.add(new Paragraph(" "));
// 7. Relazione aziendale illustrativa
Paragraph p7 = new Paragraph();
p7.add(new Chunk("7. ", boldSmallFont));
p7.add(new Chunk("Relazione aziendale illustrativa", boldSmallFont));
document.add(p7);
document.add(new Paragraph(" "));
addColoredLines(writer,document,greenColor);
// Close the document
document.close();
// Convert to byte array for response
byte[] pdfBytes = out.toByteArray();
return pdfBytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private Integer addLabelValuePair(PdfWriter writer,Document document, String label, Object value, Font labelFont,Font valueFont,String title,Integer totalPages) throws DocumentException {
// Add label
Paragraph labelParagraph = new Paragraph(label, labelFont);
document.add(labelParagraph);
float leftMargin = 20f;
PdfContentByte canvas = writer.getDirectContent();
// Setting the color and width of the line
float lineWidth = 1.0f; // Thickness of the line
canvas.setLineWidth(lineWidth);
// Get the current vertical position in the document
float yPos = writer.getVerticalPosition(true) - 10f; // Adjust this to move line slightly below current content
// Define start and end points for the line (relative to the page size and margins)
if (yPos <= 140) {
// If xEnd is less than or equal to 200, generate a new page
totalPages++;
document.newPage();
} // Add a gap between the label and value
document.add(new Paragraph(" ")); // Adding an empty paragraph for spacing
// Create value cell with rounded corners
PdfPTable valueTable = new PdfPTable(1);
valueTable.setWidthPercentage(100);
if (value instanceof List<?>) {
// Further check if the list contains Strings
List<?> list = (List<?>) value;
if (!list.isEmpty() && list.get(0) instanceof String) {
// Cast to List<String>
List<String> values = (List<String>) value;
// Loop through the list of strings and create a cell for each string
for (String item : values) {
PdfPCell valueCell = new PdfPCell(new Phrase(item, valueFont));
valueCell.setPadding(5f); // Increase padding for better spacing
valueCell.setPaddingLeft(leftMargin); // Increase left margin for value
valueCell.setBorder(Rectangle.NO_BORDER); // Remove border for value cell
valueCell.setMinimumHeight(30f);
valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
valueCell.setCellEvent(new RoundedCorners()); // Apply rounded corners
// Add the cell to the table
valueTable.addCell(valueCell);
}
// Finally, add the table to the document
document.add(valueTable);
} else {
boolean containsThreeValues = false; // Variable to track if any map contains three keys
List<Map<String, Object>> dataList = (List<Map<String, Object>>) value; // Cast Object to List of Maps
for (Map<String, Object> entry : dataList) {
if (entry.size() == 3) { // Check if the current map has three keys
containsThreeValues = true; // If found, set the variable to true
break; // No need to check further, exit loop
}
}
List<Map<String, String>> extractedData = new ArrayList<>(); // To hold extracted data
for (Map<String, Object> entry : dataList) {
Map<String, String> extractedMap = new HashMap<>(); // To hold the current extracted row of data
List<String> keys = new ArrayList<>(entry.keySet()); // Get all keys in the current map
// Handle based on the number of keys in the map
if (Boolean.FALSE.equals(containsThreeValues) && keys.size() == 2) {
// Treat the first key as the "key" and second key as the "value"
String heading = (String) entry.get(keys.get(0)); // Get value of first key
String value1 = (String) entry.get(keys.get(1)); // Get value of second key
extractedMap.put(heading,value1); // Store the first key's value as "heading"
} if (Boolean.TRUE.equals(containsThreeValues) ) {
String amount="";
// Treat the first as number, second as description, third as amount
if(keys.size()==3){
amount = (String) entry.get(keys.get(2)); // Third key's value
}
String number = (String) entry.get(keys.get(0)); // First key's value
String description = (String) entry.get(keys.get(1)); // Second key's value
// Store the combined result as a value in the map, with a suitable key
String combinedValue = number + ", " + description + ", " + amount; // Concatenate them as a single value
extractedMap.put("combined", combinedValue); // Store as a single entry, key as "combined"
}
extractedData.add(extractedMap); // Add each extracted map to the list
}
document=createPdfTable(extractedData,document);
}
}
else {
PdfPCell valueCell = new PdfPCell(new Phrase(String.valueOf(value), valueFont));
valueCell.setPadding(5f); // Increase padding for better spacing
valueCell.setPaddingLeft(leftMargin); // Increase left margin for value
valueCell.setBorder(Rectangle.NO_BORDER); // Remove border for value cell
valueCell.setMinimumHeight(30f);
valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
valueCell.setCellEvent(new RoundedCorners()); // Apply rounded corners
valueTable.addCell(valueCell);
document.add(valueTable);
}
document.add(new Paragraph("\n")); // Add line break after each value
return totalPages;
}
private Document createPdfTable(List<Map<String, String>> extractedData,Document document) throws DocumentException { // Create a PdfPTable with 2 columns
PdfPTable table = new PdfPTable(2); // Initial assumption for 2 columns
table.setWidthPercentage(100); // Set table width to 100%
Font textFont = FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL, new BaseColor(105, 105, 105)); // Gray text
boolean combinedHeaderAdded = false; // Flag to track if headers for combined have been added
float rowHeight = 50f; // Example row height, adjust as necessary
float maxTableHeight = 700f; // Maximum height of the table before a page break
int rowCount = 0; // Counter for rows
// Add table header
// Populate the table with extracted data and style rows
for (Map<String, String> row : extractedData) {
for (Map.Entry<String, String> entry : row.entrySet()) {
String key = entry.getKey(); // This will give you the key
String value = entry.getValue(); // This will give you the value
// Check if the current entry is for the combined section
if ("combined".equals(key)) {
// Ensure the combined header is added only once
if (!combinedHeaderAdded) {
// Create a new table for combined entries
table = new PdfPTable(3); // 3 columns for combined entries
PdfPCell headerCell1 = new PdfPCell(new Phrase("Number"));
headerCell1.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align
headerCell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
headerCell1.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header
table.addCell(headerCell1);
PdfPCell headerCell2 = new PdfPCell(new Phrase("Details"));
headerCell2.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align
headerCell2.setVerticalAlignment(Element.ALIGN_MIDDLE);
headerCell2.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header
table.addCell(headerCell2);
PdfPCell headerCell3 = new PdfPCell(new Phrase("Amount"));
headerCell3.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align
headerCell3.setVerticalAlignment(Element.ALIGN_MIDDLE);
headerCell3.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header
table.addCell(headerCell3);
combinedHeaderAdded = true; // Mark header as added
}
// Split the value for "combined" into separate parts
String[] combinedValues = value.split(", ");
// Check if we have 3 parts (number, description, amount)
String number = combinedValues[0].trim(); // 1st part (number)
String description = combinedValues[1].trim(); // 2nd part (description)
String amount = "";
if (combinedValues.length == 3) {
amount = combinedValues[2].trim(); // 3rd part (amount)
}
// Create PDF cells using the split values
PdfPCell cellNumber = new PdfPCell(new Phrase(number, textFont)); // Cell for number
PdfPCell cellDescription = new PdfPCell(new Phrase(description, textFont)); // Cell for description
PdfPCell cellAmount = new PdfPCell(new Phrase(amount, textFont)); // Cell for amount
// Set row background color for combined values
cellNumber.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for combined rows
cellDescription.setBackgroundColor(new BaseColor(239, 243, 248));
cellAmount.setBackgroundColor(new BaseColor(239, 243, 248));
// Set cell height and add rounded borders
cellNumber.setFixedHeight(rowHeight);
cellDescription.setFixedHeight(rowHeight);
cellAmount.setFixedHeight(rowHeight);
cellNumber.setPadding(7f);
cellDescription.setPadding(7f);
cellAmount.setPadding(7f);
// Add the cells to the table only once
table.addCell(cellNumber);
table.addCell(cellDescription);
table.addCell(cellAmount);
} else {
if (!combinedHeaderAdded) {
// Create a new table for combined entries
table= new PdfPTable(2); // 3 columns for combined entries
table.setWidthPercentage(100);
PdfPCell headerCell1 = new PdfPCell(new Phrase("Details"));
headerCell1.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align
headerCell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
headerCell1.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header
table.addCell(headerCell1);
PdfPCell headerCell2 = new PdfPCell(new Phrase("Amount"));
headerCell2.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align
headerCell2.setVerticalAlignment(Element.ALIGN_MIDDLE);
headerCell2.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header
table.addCell(headerCell2);
combinedHeaderAdded=true;
}
// Add cells for regular key-value pairs without headers
PdfPCell cellKey = new PdfPCell(new Phrase(key, textFont));
PdfPCell cellValue = new PdfPCell(new Phrase(value, textFont));
// Set background color for both cells
cellKey.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for other rows
cellValue.setBackgroundColor(new BaseColor(239, 243, 248));
// Set cell height and add rounded borders
cellKey.setFixedHeight(rowHeight);
cellValue.setFixedHeight(rowHeight);
// Add the cells to the table
table.addCell(cellKey);
table.addCell(cellValue);
}
if (table.getTotalHeight() + rowHeight > maxTableHeight) {
// Start a new page if needed
document.add(table);
table = new PdfPTable(2); // Reset table for new page
table.setWidthPercentage(100); // Reset width percentage
combinedHeaderAdded = false; // Reset header flag
}
}
}
document.add(table); // Add the last table before returning
// Check if adding a new row would exceed the maximum height
// Return the populated table
return document;
}
public List<FieldLabelValuePairRequest> getFormFieldsToLabels(FormApplicationResponse responseBean) {
List<FieldLabelValuePairRequest> labelValuePairs = new ArrayList<>();
// Iterate through each form in the application response
List<ApplicationFormFieldResponseBean> formFields = responseBean.getFormFields();
List<ContentResponseBean> contents = responseBean.getContent();
// Iterate through each formField in the current form
for (ApplicationFormFieldResponseBean formField : formFields) {
String fieldId = formField.getFieldId();
Object fieldValue = formField.getFieldValue();
// Find the content in the form that matches the fieldId
Optional<ContentResponseBean> matchingContent = contents.stream()
.filter(content -> content.getId().equals(fieldId))
.findFirst();
// If the content with the matching fieldId is found, create a label-value pair
if (matchingContent.isPresent()) {
String name = matchingContent.get().getName();
if (name.equals("fileupload")) {
// Step 1: Check if fieldValue is an instance of List<DocumentResponseBean>
if (fieldValue instanceof List<?> && ((List<?>) fieldValue).stream().allMatch(item -> item instanceof DocumentResponseBean)) {
// Step 2: Safely cast to List<DocumentResponseBean>
List<DocumentResponseBean> documentList = (List<DocumentResponseBean>) fieldValue;
// Step 3: Extract names from the document list
List<String> names = documentList.stream()
.map(DocumentResponseBean::getName) // Extract the name from each DocumentResponseBean
.collect(Collectors.toList());
fieldValue=names;
}
}
if(name.equals("checkboxes")) {
List<String> check = (List<String>) fieldValue;
List<SettingResponseBean> settingResponseBeans = matchingContent.get().getSettings();
for (SettingResponseBean settingResponseBean : settingResponseBeans) {
// Initialize a list to hold matched labels for each SettingResponseBean
List<String> matchedLabels = new ArrayList<>();
if (settingResponseBean.getValue() instanceof List<?>) {
List<?> valueList = (List<?>) settingResponseBean.getValue();
if (!valueList.isEmpty() && valueList.get(0) instanceof Map<?, ?>) {
// Cast to List<Map<String, String>>
List<Map<String, String>> options = (List<Map<String, String>>) valueList;
for (Map<String, String> field : options) {
for (String val : check) {
String name1=field.get("name");
if (val.equals(name1)) { // Check if the key exists in the current field map
String label = field.get("label"); // Extract the label
if (field != null) { // Check if the value is not null
matchedLabels.add(label); // Add the value to the matchedValues list
}
}
}
}
fieldValue = matchedLabels;
}
}
}
}
String label = matchingContent.get().getLabel();
// Add the label-value pair to the list
if (fieldValue != null && !fieldValue.toString().trim().isEmpty()) {
fieldValue = findLabelInOptions(matchingContent.get().getSettings(), fieldValue);
labelValuePairs.add(new FieldLabelValuePairRequest(label, fieldValue));
}
}
}
return labelValuePairs;
}
public static Object findLabelInOptions(List<SettingResponseBean> settings, Object valueToFind) {
ObjectMapper objectMapper = new ObjectMapper();
try {
if (valueToFind instanceof String) {
String searchValue = (String) valueToFind;
for (SettingResponseBean setting : settings) {
Object value = setting.getValue();
if (value instanceof List) {
List<?> options = (List<?>) value;
for (Object option : options) {
JsonNode optionNode = objectMapper.convertValue(option, JsonNode.class);
if (optionNode.get("name").asText().equals(searchValue)) {
return optionNode.get("label").asText();
}
}
}
}
}
} catch (Exception e) {
}
return valueToFind;
}
public void addLogo(Document document, String logoPath) throws Exception {
Image logo = Image.getInstance(logoPath);
logo.scaleToFit(document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin(), // Fit to document width
document.getPageSize().getHeight() / 4); // Adjust the height as needed (1/4th of the page height)
logo.setAlignment(Image.ALIGN_CENTER); // Align logo to center
document.add(logo);
// Add some space after logo
document.add(new Paragraph("\n")); // Adding space after the logo
}
public void addColoredLines(PdfWriter writer, Document document, BaseColor color){
PdfContentByte canvas = writer.getDirectContent();
// Setting the color and width of the line
canvas.setColorStroke(color);
float lineWidth = 1.0f; // Thickness of the line
canvas.setLineWidth(lineWidth);
// Get the current vertical position in the document
float yPos = writer.getVerticalPosition(true) - 10f; // Adjust this to move line slightly below current content
// Define start and end points for the line (relative to the page size and margins)
float xStart = document.leftMargin(); // Start from the left margin
float xEnd = document.getPageSize().getWidth() - document.rightMargin(); // End at the right margin
// Draw the line at the current Y position
canvas.moveTo(xStart, yPos); // Move to the starting point
canvas.lineTo(xEnd, yPos); // Draw the line to the end point
canvas.stroke(); // Apply the stroke (line)
}
}

View File

@@ -0,0 +1,45 @@
package net.gepafin.tendermanagement.dao;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfPTable;
public class RoundedCorners implements PdfPCellEvent {
@Override
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvas) {
// Retrieve the canvas for drawing the background and border
PdfContentByte cbBackground = canvas[PdfPTable.BACKGROUNDCANVAS];
PdfContentByte cb = canvas[PdfPTable.LINECANVAS];
cbBackground.saveState();
cb.saveState();
// Define the rounded rectangle radius and padding
float radius = 10f;
float padding = 2f; // Small padding to avoid overlap
// Get position values with adjusted height and width
float x = position.getLeft() + padding;
float y = position.getBottom() + padding;
float width = position.getWidth() - 2 * padding;
float height = position.getHeight() - 2 * padding;
// Fill the rounded rectangle with lighter grey
cbBackground.setColorFill(new BaseColor(239, 243, 248)); // Very light grey color
cbBackground.roundRectangle(x, y, width, height, radius);
cbBackground.fill(); // Fill the background
// Set the border stroke to thin and draw the rounded rectangle with dark grey color
cb.setLineWidth(0.5f); // Thin border width
cb.setColorStroke(new BaseColor(105, 105, 105)); // Dark grey border
cb.roundRectangle(x, y, width, height, radius);
cb.stroke(); // Draw the border
// Restore the canvas states
cbBackground.restoreState();
cb.restoreState();
}
}

View File

@@ -0,0 +1,28 @@
package net.gepafin.tendermanagement.entities;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.Data;
@Data
@Entity
@Table(name = "application_signed_document")
public class ApplicationSignedDocumentEntity extends BaseEntity {
@ManyToOne
@JoinColumn(name = "APPLICATION_ID")
private ApplicationEntity application;
@Column(name = "FILE_NAME")
private String fileName;
@Column(name = "FILE_PATH")
private String filePath;
@Column(name="STATUS")
private String status;
}

View File

@@ -0,0 +1,18 @@
package net.gepafin.tendermanagement.enums;
import com.fasterxml.jackson.annotation.JsonValue;
public enum ApplicationSignedDocumentStatusEnum {
ACTIVE("ACTIVE"), INACTIVE("INACTIVE");
private String value;
ApplicationSignedDocumentStatusEnum(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
}

View File

@@ -0,0 +1,71 @@
package net.gepafin.tendermanagement.model.request;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
public class CustomPageEvent extends PdfPageEventHelper {
private String title;
private int totalPages;
public CustomPageEvent(String title, int totalPages) {
this.title = title;
this.totalPages = totalPages;
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
PdfContentByte canvas = writer.getDirectContent();
// Header - Add a title to each page at the top
if (writer.getPageNumber() > 1) {
Font headerFont = new Font(Font.FontFamily.HELVETICA, 6, Font.BOLD, new BaseColor(113, 121, 126)); // Gray color for header
ColumnText.showTextAligned(
canvas,
Element.ALIGN_LEFT,
new Phrase(title, headerFont),
document.leftMargin(), // Use left margin to align fully to the left
document.getPageSize().getHeight() - 30, // Positioning header near top
0 // No rotation
);
}
// Footer - Add page number at the bottom
String footerText = String.format("Page %d of %d", writer.getPageNumber(), totalPages);
// Set font for the footer
Font footerFont = new Font(Font.FontFamily.HELVETICA, 10, Font.NORMAL, BaseColor.BLACK);
// Positioning footer near bottom
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_LEFT,
new Phrase(footerText, footerFont),
(document.right() + document.left()) / 2,
document.bottomMargin() - 10, // Positioning footer near bottom
0);
// Draw a yellow line below header
if (writer.getPageNumber() > 1) {
canvas.setLineWidth(1.5f);
canvas.setColorStroke(new BaseColor(255, 219, 88)); // Yellow color
float yPos = document.getPageSize().getHeight() - 50f; // Position for the line below header
canvas.moveTo(0, yPos);
canvas.lineTo(document.getPageSize().getWidth(), yPos);
canvas.stroke();
}
// Draw another line 50 points above the bottom of the document
canvas.setLineWidth(1.5f);
canvas.setColorStroke(new BaseColor(255, 219, 88)); // Yellow color
float lineYPos = document.bottomMargin() + 25f; // Position for the line above the bottom margin
canvas.moveTo(0, lineYPos);
canvas.lineTo(document.getPageSize().getWidth(), lineYPos);
canvas.stroke();
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
}

View File

@@ -0,0 +1,14 @@
package net.gepafin.tendermanagement.model.request;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
public class FieldLabelValuePairRequest {
private String label;
private Object value;
}

View File

@@ -0,0 +1,14 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Data;
import net.gepafin.tendermanagement.enums.ApplicationSignedDocumentStatusEnum;
import net.gepafin.tendermanagement.model.BaseBean;
@Data
public class ApplicationSignedDocumentResponse extends BaseBean{
private Long applicationId;
private String fileName;
private String filePath;
private ApplicationSignedDocumentStatusEnum status;
}

View File

@@ -3,9 +3,10 @@ package net.gepafin.tendermanagement.model.response;
import lombok.Data; import lombok.Data;
import net.gepafin.tendermanagement.entities.BaseEntity; import net.gepafin.tendermanagement.entities.BaseEntity;
import net.gepafin.tendermanagement.enums.UserCompanyDelegationStatusEnum; import net.gepafin.tendermanagement.enums.UserCompanyDelegationStatusEnum;
import net.gepafin.tendermanagement.model.BaseBean;
@Data @Data
public class CompanyDelegationResponse extends BaseEntity{ public class CompanyDelegationResponse extends BaseBean{
private Long userId; private Long userId;
private Long companyId; private Long companyId;
private Long beneficiaryId; private Long beneficiaryId;

View File

@@ -0,0 +1,14 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class UploadFileOnAmazonS3Response {
private String fileName;
private String filePath;
}

View File

@@ -0,0 +1,13 @@
package net.gepafin.tendermanagement.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import net.gepafin.tendermanagement.entities.ApplicationSignedDocumentEntity;
@Repository
public interface ApplicationSignedDocumentRepository extends JpaRepository<ApplicationSignedDocumentEntity, Long> {
ApplicationSignedDocumentEntity findByApplicationIdAndStatus(Long applicationId, String status);
}

View File

@@ -20,6 +20,7 @@ public interface DocumentRepository extends JpaRepository<DocumentEntity, Long>
Optional<DocumentEntity> findByIdAndSourceIdAndIsDeletedFalse(Long id, Long sourceId); Optional<DocumentEntity> findByIdAndSourceIdAndIsDeletedFalse(Long id, Long sourceId);
List<DocumentEntity> findBySource(String source); List<DocumentEntity> findBySource(String source);
List<DocumentEntity> findBySourceIdAndSourceAndTypeAndIsDeletedFalse(Long sourceId, String source, String type);
} }

View File

@@ -3,6 +3,8 @@ package net.gepafin.tendermanagement.service;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import net.gepafin.tendermanagement.model.response.UploadFileOnAmazonS3Response;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -14,4 +16,6 @@ public interface AmazonS3Service {
public Boolean delete(String s3Folder, String fileName); public Boolean delete(String s3Folder, String fileName);
InputStream getFile(String s3Folder, String filePath) throws IOException; InputStream getFile(String s3Folder, String filePath) throws IOException;
public UploadFileOnAmazonS3Response uploadFileOnAmazonS3(String s3Folder, MultipartFile file);
} }

View File

@@ -9,10 +9,13 @@ import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationResponse; import net.gepafin.tendermanagement.model.response.ApplicationResponse;
import net.gepafin.tendermanagement.model.response.ApplicationResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationSignedDocumentResponse;
import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse; import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse;
import java.util.List; import java.util.List;
import org.springframework.web.multipart.MultipartFile;
public interface ApplicationService { public interface ApplicationService {
public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean,Long applicationId, Long formId); public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean,Long applicationId, Long formId);
@@ -31,4 +34,10 @@ public interface ApplicationService {
public ApplicationResponse updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status); public ApplicationResponse updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status);
public ApplicationSignedDocumentResponse uploadSignedDocument(HttpServletRequest request, Long applicationId, MultipartFile file);
public ApplicationSignedDocumentResponse getSignedDocument(HttpServletRequest request, Long applicationId);
public void deleteSignedDocument(HttpServletRequest request, Long applicationId);
} }

View File

@@ -32,5 +32,5 @@ public interface CallService {
CallEntity validateCall(Long callId); CallEntity validateCall(Long callId);
CallEntity validatePublishedCall(Long callId); CallEntity validatePublishedCall(Long callId);
byte[] downloadCallDocumentsAsZip(Long callId);
} }

View File

@@ -0,0 +1,9 @@
package net.gepafin.tendermanagement.service;
import jakarta.servlet.http.HttpServletRequest;
public interface PdfService {
public byte[] generatePdf(HttpServletRequest request, Long applicationId);
}

View File

@@ -2,7 +2,16 @@ package net.gepafin.tendermanagement.service.impl;
import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.*; import com.amazonaws.services.s3.model.*;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.model.response.UploadFileOnAmazonS3Response;
import net.gepafin.tendermanagement.service.AmazonS3Service; import net.gepafin.tendermanagement.service.AmazonS3Service;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@@ -86,4 +95,20 @@ public class AmazonS3ServiceImpl implements AmazonS3Service {
throw new IOException("Error getting file from Amazon S3", e); throw new IOException("Error getting file from Amazon S3", e);
} }
} }
@Override
public UploadFileOnAmazonS3Response uploadFileOnAmazonS3(String s3Folder, MultipartFile file) {
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
String fileName = org.springframework.util.StringUtils.cleanPath(file.getOriginalFilename());
String firstNameContain = fileName.substring(0, fileName.lastIndexOf('.'));
firstNameContain+=Utils.randomKey(5);
fileName = (firstNameContain + "." + extension);
try {
String filepath = upload(fileName, s3Folder, file);
return UploadFileOnAmazonS3Response.builder().fileName(fileName).filePath(filepath).build();
} catch (Exception e) {
throw new CustomValidationException(Status.VALIDATION_ERROR,
Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3));
}
}
} }

View File

@@ -13,12 +13,14 @@ import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationResponse; import net.gepafin.tendermanagement.model.response.ApplicationResponse;
import net.gepafin.tendermanagement.model.response.ApplicationResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationSignedDocumentResponse;
import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse; import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse;
import net.gepafin.tendermanagement.service.ApplicationService; import net.gepafin.tendermanagement.service.ApplicationService;
import net.gepafin.tendermanagement.util.Validator; import net.gepafin.tendermanagement.util.Validator;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.util.List; import java.util.List;
@@ -64,7 +66,7 @@ public class ApplicationServiceImpl implements ApplicationService {
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public ApplicationResponse createApplication(HttpServletRequest request, Long companyId, ApplicationRequest applicationRequest, Long callId) { public ApplicationResponse createApplication(HttpServletRequest request, Long companyId, ApplicationRequest applicationRequest, Long callId) {
UserEntity userEntity = validator.validateUser(request); UserEntity userEntity = validator.validateUser(request);
CompanyEntity companyEntity = validator.validateUSerWithCompany(request, companyId); CompanyEntity companyEntity = validator.validateUserWithCompany(request, companyId);
return applicationDao.createApplicationByCallId(companyEntity, applicationRequest, callId, userEntity); return applicationDao.createApplicationByCallId(companyEntity, applicationRequest, callId, userEntity);
} }
@@ -88,8 +90,26 @@ public class ApplicationServiceImpl implements ApplicationService {
public List<ApplicationResponse> getAllApplications(HttpServletRequest request, Long callId, Long companyId) { public List<ApplicationResponse> getAllApplications(HttpServletRequest request, Long callId, Long companyId) {
UserEntity userEntity = validator.validateUser(request); UserEntity userEntity = validator.validateUser(request);
if (companyId != null) { if (companyId != null) {
validator.validateUSerWithCompany(request, companyId); validator.validateUserWithCompany(request, companyId);
} }
return applicationDao.getAllApplications(userEntity, callId, companyId); return applicationDao.getAllApplications(userEntity, callId, companyId);
} }
@Override
@Transactional(rollbackFor = Exception.class)
public ApplicationSignedDocumentResponse uploadSignedDocument(HttpServletRequest request, Long applicationId, MultipartFile file) {
return applicationDao.uploadSignedDocument(request, applicationId, file);
}
@Override
@Transactional(readOnly = true)
public ApplicationSignedDocumentResponse getSignedDocument(HttpServletRequest request, Long applicationId) {
return applicationDao.getSignedDocument(request, applicationId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteSignedDocument(HttpServletRequest request, Long applicationId) {
applicationDao.deleteSignedDocument(request, applicationId);
}
} }

View File

@@ -92,4 +92,9 @@ public class CallServiceImpl implements CallService {
public CallEntity validatePublishedCall(Long callId) { public CallEntity validatePublishedCall(Long callId) {
return callDao.validatePublishedCall(callId); return callDao.validatePublishedCall(callId);
} }
@Override
@Transactional(readOnly = true)
public byte[] downloadCallDocumentsAsZip(Long callId) {
return callDao.downloadCallDocumentsAsZip(callId);
}
} }

View File

@@ -98,7 +98,8 @@ public class CompanyServiceImpl implements CompanyService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public CompanyDelegationResponse uploadCompanyDelegation(HttpServletRequest request, Long companyId, MultipartFile file) { public CompanyDelegationResponse uploadCompanyDelegation(HttpServletRequest request, Long companyId, MultipartFile file) {
UserEntity userEntity =validator.validateUser(request); UserEntity userEntity = validator.validateUser(request);
validator.validateUserWithCompany(request, companyId);
return delegationDao.uploadCompanyDelegation(userEntity, companyId, file); return delegationDao.uploadCompanyDelegation(userEntity, companyId, file);
} }

View File

@@ -0,0 +1,24 @@
package net.gepafin.tendermanagement.service.impl;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.dao.PdfDao;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.service.PdfService;
import net.gepafin.tendermanagement.util.Validator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PdfServiceImpl implements PdfService {
@Autowired
private PdfDao pdfDao;
@Autowired
private Validator validator;
@Override
public byte[] generatePdf(HttpServletRequest request, Long applicationId) {
return pdfDao.generatePdf(request, applicationId);
}
}

View File

@@ -9,6 +9,7 @@ import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.enums.RoleStatusEnum;
import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.service.CompanyService;
import net.gepafin.tendermanagement.service.UserService; import net.gepafin.tendermanagement.service.UserService;
import net.gepafin.tendermanagement.web.rest.api.errors.ForbiddenAccessException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status; import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import net.gepafin.tendermanagement.web.rest.api.errors.UnauthorizedAccessException; import net.gepafin.tendermanagement.web.rest.api.errors.UnauthorizedAccessException;
@@ -60,7 +61,7 @@ public class Validator {
} }
} }
public CompanyEntity validateUSerWithCompany(HttpServletRequest request, Long companyId) { public CompanyEntity validateUserWithCompany(HttpServletRequest request, Long companyId) {
if (checkIsSuperAdmin()) { if (checkIsSuperAdmin()) {
return companyService.validateCompany(companyId); return companyService.validateCompany(companyId);
} }
@@ -89,7 +90,7 @@ public class Validator {
public UserEntity validateUserId(HttpServletRequest request, Long userId) { public UserEntity validateUserId(HttpServletRequest request, Long userId) {
UserEntity user = validateUser(request); UserEntity user = validateUser(request);
if(user.getRoleEntity().getRoleType().equals(RoleStatusEnum.ROLE_BENEFICIARY.getValue()) && Boolean.FALSE.equals(user.getId().equals(userId))) { if(user.getRoleEntity().getRoleType().equals(RoleStatusEnum.ROLE_BENEFICIARY.getValue()) && Boolean.FALSE.equals(user.getId().equals(userId))) {
throw new UnauthorizedAccessException(Status.UNAUTHORIZED, Translator.toLocale(GepafinConstant.INVALID_REQUEST)); throw new ForbiddenAccessException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PERMISSION_DENIED));
} }
return userService.validateUser(userId); return userService.validateUser(userId);
} }

View File

@@ -6,6 +6,7 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@@ -21,6 +22,8 @@ import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationResponse; import net.gepafin.tendermanagement.model.response.ApplicationResponse;
import net.gepafin.tendermanagement.model.response.ApplicationResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationSignedDocumentResponse;
import net.gepafin.tendermanagement.model.response.CompanyDelegationResponse;
import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse; import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse;
import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.model.util.Response;
import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants;
@@ -131,6 +134,58 @@ public interface ApplicationApi {
@Parameter(description = "The application id", required = true) @PathVariable("applicationId") Long applicationId, @Parameter(description = "The application id", required = true) @PathVariable("applicationId") Long applicationId,
@Parameter(description = "status", required = true)@RequestParam(value = "status", required = true) ApplicationStatusTypeEnum status); @Parameter(description = "status", required = true)@RequestParam(value = "status", required = true) ApplicationStatusTypeEnum status);
@Operation(summary = "API to generate PDF for an application",
responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/pdf")),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) }))
})
@PostMapping(value = "/{applicationId}/download-pdf",
produces = { "application/pdf" })
public ResponseEntity<byte[]> generateApplicationPdf(
HttpServletRequest request,
@Parameter(description = "The application id", required = true)
@PathVariable(value = "applicationId", required = true) Long applicationId);
@Operation(summary = "Api to upload signed document (only p7m file format is supported)", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@PostMapping(value = "{applicationId}/signedDocument/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
ResponseEntity<Response<ApplicationSignedDocumentResponse>> uploadSignedDocument(HttpServletRequest request,
@Parameter(description = "The applicationId id", required = true) @PathVariable("applicationId") Long applicationId,
@Parameter(description = "The signed document", required = true) @RequestParam("file") MultipartFile file);
@Operation(summary = "Api to get signed document", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@GetMapping(value = "{applicationId}/signedDocument", produces = "application/json")
ResponseEntity<Response<ApplicationSignedDocumentResponse>> getSignedDocument(HttpServletRequest request,
@Parameter(description = "The applicationId id", required = true) @PathVariable("applicationId") Long applicationId);
@Operation(summary = "Api to delete signed document", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@DeleteMapping(value = "{applicationId}/signedDocument", produces = "application/json")
ResponseEntity<Response<Void>> deleteSignedDocument(HttpServletRequest request,
@Parameter(description = "The applicationId id", required = true) @PathVariable("applicationId") Long applicationId);
} }

View File

@@ -134,4 +134,19 @@ public interface CallApi {
public ResponseEntity<Response<CallResponse>> updateCallStatus(HttpServletRequest request, public ResponseEntity<Response<CallResponse>> updateCallStatus(HttpServletRequest request,
@Parameter(description = "The call id", required = true) @PathVariable("callId") Long callId, @Parameter(description = "The call id", required = true) @PathVariable("callId") Long callId,
@Parameter(description = "status", required = true)@RequestParam(value = "status", required = true) CallStatusEnum status); @Parameter(description = "status", required = true)@RequestParam(value = "status", required = true) CallStatusEnum status);
@Operation(summary = "Api to download call documents as a ZIP file",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))
})
@GetMapping(value = "/{callId}/documents/zip")
ResponseEntity<byte[]> downloadCallDocumentsAsZip(HttpServletRequest httpServletRequest,
@Parameter(description = "The call ID", required = true) @PathVariable("callId") Long callId);
} }

View File

@@ -0,0 +1,35 @@
package net.gepafin.tendermanagement.web.rest.api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@Validated
public interface PdfApi {
@Operation(summary = "API to generate PDF for an application",
responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/pdf")),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) }))
})
@PostMapping(value = "/{applicationId}/generate-pdf",
produces = { "application/pdf" })
public ResponseEntity<byte[]> generateApplicationPdf(
HttpServletRequest request,
@Parameter(description = "The application id", required = true)
@PathVariable(value = "applicationId", required = true) Long applicationId);
}

View File

@@ -221,6 +221,12 @@ public interface UserApi {
@RequestMapping("favicon.ico")
@ResponseBody
void returnNoFavicon();
} }

View File

@@ -10,17 +10,22 @@ import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationResponse; import net.gepafin.tendermanagement.model.response.ApplicationResponse;
import net.gepafin.tendermanagement.model.response.ApplicationResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationResponseBean;
import net.gepafin.tendermanagement.model.response.ApplicationSignedDocumentResponse;
import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse; import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse;
import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.model.util.Response;
import net.gepafin.tendermanagement.service.ApplicationService; import net.gepafin.tendermanagement.service.ApplicationService;
import net.gepafin.tendermanagement.service.PdfService;
import net.gepafin.tendermanagement.web.rest.api.ApplicationApi; import net.gepafin.tendermanagement.web.rest.api.ApplicationApi;
import net.gepafin.tendermanagement.web.rest.api.errors.Status; import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.util.List; import java.util.List;
@@ -35,17 +40,21 @@ public class ApplicationApiController implements ApplicationApi {
@Autowired @Autowired
private ApplicationService applicationService; private ApplicationService applicationService;
@Autowired
private PdfService pdfService;
@Override @Override
public ResponseEntity<Response<ApplicationResponseBean>> createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean,Long applicationId, Long formId) { public ResponseEntity<Response<ApplicationResponseBean>> createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long applicationId, Long formId) {
ApplicationResponseBean applicationResponseBean= applicationService.createApplication(request,applicationRequestBean,applicationId,formId); ApplicationResponseBean applicationResponseBean = applicationService.createApplication(request, applicationRequestBean, applicationId, formId);
return ResponseEntity.status(HttpStatus.CREATED) return ResponseEntity.status(HttpStatus.CREATED)
.body(new Response<>(applicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_CREATED_SUCCESS_MSG))); } .body(new Response<>(applicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_CREATED_SUCCESS_MSG)));
}
@Override @Override
public ResponseEntity<Response<ApplicationGetResponseBean>> getApplicationByFormId(HttpServletRequest request public ResponseEntity<Response<ApplicationGetResponseBean>> getApplicationByFormId(HttpServletRequest request
, Long applicationId,Long formId) { , Long applicationId, Long formId) {
log.info("Get Application by ID - Application ID: {}", applicationId); log.info("Get Application by ID - Application ID: {}", applicationId);
ApplicationGetResponseBean application = applicationService.getApplicationByFormId(request,applicationId,formId); ApplicationGetResponseBean application = applicationService.getApplicationByFormId(request, applicationId, formId);
return ResponseEntity.status(HttpStatus.OK) return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(application, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG))); .body(new Response<>(application, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG)));
} }
@@ -54,27 +63,28 @@ public class ApplicationApiController implements ApplicationApi {
public ResponseEntity<Response<Void>> deleteApplication(HttpServletRequest request, public ResponseEntity<Response<Void>> deleteApplication(HttpServletRequest request,
Long applicationId) { Long applicationId) {
log.info("Delete Application - Application ID: {}", applicationId); log.info("Delete Application - Application ID: {}", applicationId);
applicationService.deleteApplication(request,applicationId); applicationService.deleteApplication(request, applicationId);
return ResponseEntity.status(HttpStatus.OK) return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELETE_APPLICATION_SUCCESS_MSG))); .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELETE_APPLICATION_SUCCESS_MSG)));
} }
@Override @Override
public ResponseEntity<Response<ApplicationResponse>> createApplicationByCallId(HttpServletRequest request, Long companyId, ApplicationRequest applicationRequest, Long callId) { public ResponseEntity<Response<ApplicationResponse>> createApplicationByCallId(HttpServletRequest request, Long companyId, ApplicationRequest applicationRequest, Long callId) {
ApplicationResponse applicationResponseBean=applicationService.createApplication(request, companyId, applicationRequest, callId); ApplicationResponse applicationResponseBean = applicationService.createApplication(request, companyId, applicationRequest, callId);
return ResponseEntity.status(HttpStatus.CREATED) return ResponseEntity.status(HttpStatus.CREATED)
.body(new Response<>(applicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_CREATED_SUCCESS_MSG))); .body(new Response<>(applicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_CREATED_SUCCESS_MSG)));
} }
@Override @Override
public ResponseEntity<Response<List<ApplicationResponse>>> getAllApplications(HttpServletRequest request,Long callId,Long companyId) { public ResponseEntity<Response<List<ApplicationResponse>>> getAllApplications(HttpServletRequest request, Long callId, Long companyId) {
List<ApplicationResponse> applications = applicationService.getAllApplications(request,callId,companyId); List<ApplicationResponse> applications = applicationService.getAllApplications(request, callId, companyId);
log.info("Get All Applications"); log.info("Get All Applications");
return ResponseEntity.status(HttpStatus.OK) return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(applications, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG))); .body(new Response<>(applications, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG)));
} }
@Override @Override
public ResponseEntity<Response<NextOrPreviousFormResponse>> getNextOrPreviousForm(HttpServletRequest request,Long applicationId, public ResponseEntity<Response<NextOrPreviousFormResponse>> getNextOrPreviousForm(HttpServletRequest request, Long applicationId,
Long formId, FormActionEnum action) { Long formId, FormActionEnum action) {
NextOrPreviousFormResponse data = applicationService.getNextOrPreviousForm(request, applicationId, formId, action); NextOrPreviousFormResponse data = applicationService.getNextOrPreviousForm(request, applicationId, formId, action);
log.info("Get Next Or Previous Form "); log.info("Get Next Or Previous Form ");
@@ -89,4 +99,47 @@ public class ApplicationApiController implements ApplicationApi {
return ResponseEntity.status(HttpStatus.OK) return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(applicationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_STATUS_UPDATED_SUCCESSFULLY))); .body(new Response<>(applicationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_STATUS_UPDATED_SUCCESSFULLY)));
} }
@Override
public ResponseEntity<byte[]> generateApplicationPdf(HttpServletRequest request, Long applicationId) {
byte[] pdfBytes = pdfService.generatePdf(request, applicationId);
// Prepare headers for downloading the PDF
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment; filename=bando-preview.pdf");
// Return the PDF as a response
return ResponseEntity.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_PDF)
.body(pdfBytes);
}
@Override
public ResponseEntity<Response<ApplicationSignedDocumentResponse>> uploadSignedDocument(HttpServletRequest request,
Long applicationId, MultipartFile file) {
log.info("upload signed document applicationId: {}", applicationId);
ApplicationSignedDocumentResponse response = applicationService.uploadSignedDocument(request, applicationId, file);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(response, Status.SUCCESS, Translator.toLocale(GepafinConstant.SIGNED_DOCUMENT_FILE_UPLOAD_SUCCESS)));
}
@Override
public ResponseEntity<Response<ApplicationSignedDocumentResponse>> getSignedDocument(HttpServletRequest request,
Long applicationId) {
ApplicationSignedDocumentResponse response = applicationService.getSignedDocument(request, applicationId);
log.info("get signed document applicationId: {}", applicationId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(response, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_SIGNED_DOCUMENT_FILE_SUCCESS)));
}
@Override
public ResponseEntity<Response<Void>> deleteSignedDocument(HttpServletRequest request,
Long applicationId) {
applicationService.deleteSignedDocument(request, applicationId);
log.info("delete signed document applicationId: {}", applicationId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELETE_SIGNED_DOCUMENT_FILE_SUCCESS)));
}
} }

View File

@@ -4,7 +4,9 @@ import java.util.List;
import net.gepafin.tendermanagement.enums.CallStatusEnum; import net.gepafin.tendermanagement.enums.CallStatusEnum;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@@ -84,4 +86,22 @@ public class CallApiController implements CallApi {
CallResponse updateCall = callService.updateCallStatus(request, callId, status); CallResponse updateCall = callService.updateCallStatus(request, callId, status);
return ResponseEntity.ok(new Response<>(updateCall, Status.SUCCESS, Translator.toLocale(GepafinConstant.UPDATE_CALL_STATUS_SUCCESS_MSG))); return ResponseEntity.ok(new Response<>(updateCall, Status.SUCCESS, Translator.toLocale(GepafinConstant.UPDATE_CALL_STATUS_SUCCESS_MSG)));
} }
@Override
public ResponseEntity<byte[]> downloadCallDocumentsAsZip(HttpServletRequest request, Long callId) {
byte[] zipFile = callService.downloadCallDocumentsAsZip(callId);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", "documents.zip");
if (zipFile == null || zipFile.length == 0) {
String notFoundMessage = Translator.toLocale(GepafinConstant.CALL_DOCUMENTS_NOT_FOUND_MSG);
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(notFoundMessage.getBytes());
}
return new ResponseEntity<>(zipFile, headers, HttpStatus.OK);
}
} }

View File

@@ -0,0 +1,40 @@
package net.gepafin.tendermanagement.web.rest.api.impl;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.dao.RoundedCorners;
import net.gepafin.tendermanagement.service.PdfService;
import net.gepafin.tendermanagement.web.rest.api.PdfApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@RestController
public class PdfController implements PdfApi {
@Autowired
private PdfService pdfService;
@Override
public ResponseEntity<byte[]> generateApplicationPdf(HttpServletRequest request, Long applicationId) {
byte[] pdfBytes =pdfService.generatePdf(request,applicationId);
// Prepare headers for downloading the PDF
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment; filename=bando-preview.pdf");
// Return the PDF as a response
return ResponseEntity.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_PDF)
.body(pdfBytes);
}
}

View File

@@ -140,4 +140,10 @@ public class UserApiController implements UserApi {
return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MSE))); return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MSE)));
} }
@Override
public void returnNoFavicon() {
// Do nothing
}
} }

View File

@@ -6,11 +6,11 @@ spring.datasource.driver-class-name=org.postgresql.Driver
# JPA Configuration # JPA Configuration
spring.h2.console.enabled=true spring.h2.console.enabled=true
base-url=http://bandi-api.gepafin.it base-url=https://bandi-api.gepafin.it
isVatCheckGloballyDisabled = false isVatCheckGloballyDisabled = false
#fe.base.url=http://gepafin-production-fe.s3-website.eu-central-1.amazonaws.com #fe.base.url=http://gepafin-production-fe.s3-website.eu-central-1.amazonaws.com
fe.base.url=http://bandi.gepafin.it fe.base.url=https://bandi.gepafin.it
#SPID configuration #SPID configuration
spid.ipd.base.url=https://login.regione.umbria.it spid.ipd.base.url=https://login.regione.umbria.it
active.profile.folder=production active.profile.folder=production

View File

@@ -32,6 +32,7 @@ aws.s3.bucket.name=mementoresources
aws.s3.url = https://mementoresources.s3.eu-west-1.amazonaws.com/ aws.s3.url = https://mementoresources.s3.eu-west-1.amazonaws.com/
aws.s3.url.folder=gepafin aws.s3.url.folder=gepafin
aws.s3.url.folder.delegation=gepafin/delegation aws.s3.url.folder.delegation=gepafin/delegation
aws.s3.url.folder.signed.document=gepafin/signed-document
# JWT configuration # JWT configuration
# Ensure these values match your expectations # Ensure these values match your expectations
security.authentication.jwt.secret=my-secret-token-to-change-in-prod-environment-your-super-secure-randomly-generated-key security.authentication.jwt.secret=my-secret-token-to-change-in-prod-environment-your-super-secure-randomly-generated-key

View File

@@ -997,5 +997,29 @@
<sqlFile dbms="postgresql" <sqlFile dbms="postgresql"
path="db/dump/insert_system_email_template_for_application_submission.sql" /> path="db/dump/insert_system_email_template_for_application_submission.sql" />
</changeSet> </changeSet>
<changeSet id="12-10-2024_1" author="Rajesh Khore">
<createTable tableName="application_signed_document">
<column name="id" type="INTEGER" autoIncrement="true">
<constraints primaryKey="true" primaryKeyName="application_signed_document_pkey" nullable="false"/>
</column>
<column name="APPLICATION_ID" type="INTEGER">
<constraints nullable="false"/>
</column>
<column name="FILE_NAME" type="VARCHAR(255)"/>
<column name="FILE_PATH" type="VARCHAR(255)"/>
<column name="STATUS" type="VARCHAR(64)"/>
<column name="created_date" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="updated_date" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
<addForeignKeyConstraint baseTableName="application_signed_document"
baseColumnNames="APPLICATION_ID"
referencedTableName="application"
referencedColumnNames="ID"
constraintName="fk_application_signed_document_application"/>
</changeSet>
</databaseChangeLog> </databaseChangeLog>

View File

@@ -226,5 +226,13 @@ user.company.relation.not.found=User with the specified company relation not fou
delegation.delete.success=Delegation deleted successfully. delegation.delete.success=Delegation deleted successfully.
user.not.authorized.create.application=User must be a legal representative or have delegation. user.not.authorized.create.application=User must be a legal representative or have delegation.
application.submitted.cannot.change=The submitted application cannot be changed. application.submitted.cannot.change=The submitted application cannot be changed.
# Call Document Messages
call.documents.fetch.success=Documents fetched successfully.
call.documents.not.found=No documents found for the specified call.
permission.denied=You are not authorized to access this data.
signed.document.file.upload.success=Signed document file uploaded successfully.
get.signed.document.file.success=Signed document file retrieved successfully.
application.signed.document.not.found=Signed document for the application not found.
delete.signed.document.file.success=Signed document deleted successfully.

View File

@@ -222,5 +222,13 @@ delegation.delete.success=Delega eliminata con successo.
user.not.authorized.create.application=L'utente deve essere un rappresentante legale o avere una delega. user.not.authorized.create.application=L'utente deve essere un rappresentante legale o avere una delega.
application.submitted.cannot.change=La domanda inviata non può essere modificata. application.submitted.cannot.change=La domanda inviata non può essere modificata.
# Call Document Messages
call.documents.fetch.success=Documenti recuperati con successo.
call.documents.not.found=Nessun documento trovato per la chiamata specificata.
permission.denied=Non sei autorizzato ad accedere a questi dati.
signed.document.file.upload.success=File del documento firmato caricato con successo.
get.signed.document.file.success=File del documento firmato recuperato con successo.
application.signed.document.not.found=Documento firmato per l'applicazione non trovato.
delete.signed.document.file.success=Documento firmato eliminato con successo.