From b28f5b71fcb2851dcc07783f0cb2967752459c6f Mon Sep 17 00:00:00 2001 From: harish Date: Mon, 23 Sep 2024 18:19:14 +0530 Subject: [PATCH 01/50] Add trigger and function for updated_date and created_date column in gepafin_schema --- .../db/changelog/db.changelog-1.0.0.xml | 33 +++++++++++- .../db/changelog/db.changelog-master.xml | 1 + .../db/changelog/dynamic-triggers.xml | 51 +++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/db/changelog/dynamic-triggers.xml diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index f4a78969..c1a48adb 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -539,7 +539,7 @@ - + TRUNCATE TABLE FORM_FIELD RESTART IDENTITY; @@ -696,7 +696,7 @@ path="classpath:db/dump/inserted_form_field_data_13_09_2024.sql" /> - + @@ -710,4 +710,33 @@ + + + + CREATE OR REPLACE FUNCTION gepafin_schema.clock_timestamp_updated_date_column() + RETURNS TRIGGER + LANGUAGE plpgsql + AS $$ + BEGIN + NEW.updated_date = clock_timestamp(); + RETURN NEW; + END; + $$; + + + + + CREATE OR REPLACE FUNCTION gepafin_schema.clock_timestamp_created_date_column() + RETURNS TRIGGER + LANGUAGE plpgsql + AS $$ + BEGIN + IF NEW.created_date IS NULL THEN + NEW.created_date = clock_timestamp(); + END IF; + RETURN NEW; + END; + $$; + + diff --git a/src/main/resources/db/changelog/db.changelog-master.xml b/src/main/resources/db/changelog/db.changelog-master.xml index f44695c7..bf4c4536 100644 --- a/src/main/resources/db/changelog/db.changelog-master.xml +++ b/src/main/resources/db/changelog/db.changelog-master.xml @@ -5,4 +5,5 @@ xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.23.xsd"> + diff --git a/src/main/resources/db/changelog/dynamic-triggers.xml b/src/main/resources/db/changelog/dynamic-triggers.xml new file mode 100644 index 00000000..23f1101e --- /dev/null +++ b/src/main/resources/db/changelog/dynamic-triggers.xml @@ -0,0 +1,51 @@ + + + + + DO $$ + DECLARE + r RECORD; + BEGIN + -- Loop through all tables in the schema that have the 'updated_date' column + FOR r IN ( + SELECT table_name + FROM information_schema.columns + WHERE column_name = 'updated_date' + AND table_schema = 'gepafin_schema' + ) + LOOP + EXECUTE format( + 'CREATE OR REPLACE TRIGGER tg_gepafin_schema_updated_at_%I + BEFORE UPDATE ON gepafin_schema.%I + FOR EACH ROW + EXECUTE FUNCTION gepafin_schema.clock_timestamp_updated_date_column()', + r.table_name, r.table_name + ); + END LOOP; + + -- Loop through all tables in the schema that have the 'created_date' column + FOR r IN ( + SELECT table_name + FROM information_schema.columns + WHERE column_name = 'created_date' + AND table_schema = 'gepafin_schema' + ) + LOOP + EXECUTE format( + 'CREATE OR REPLACE TRIGGER tg_gepafin_schema_created_at_%I + BEFORE INSERT ON gepafin_schema.%I + FOR EACH ROW + EXECUTE FUNCTION gepafin_schema.clock_timestamp_created_date_column()', + r.table_name, r.table_name + ); + END LOOP; + END; + $$ LANGUAGE plpgsql; + + + From aab64f45525d5326f2967599ed545840918a954f Mon Sep 17 00:00:00 2001 From: nishainnogent Date: Thu, 3 Oct 2024 14:40:51 +0530 Subject: [PATCH 02/50] fixed bug for update published call --- src/main/java/net/gepafin/tendermanagement/dao/CallDao.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index fca314ed..97d0e4b4 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -478,7 +478,7 @@ public class CallDao { if (updateCallRequest.getAmountMin() != null && updateCallRequest.getAmountMin().compareTo(BigDecimal.ZERO) < 0) { throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG)); } - if(updateCallRequest.getEmail()==null || Boolean.FALSE.equals(Utils.isValidEmail(updateCallRequest.getEmail()))){ + if(updateCallRequest.getEmail()==null && Boolean.FALSE.equals(Utils.isValidEmail(updateCallRequest.getEmail()))){ throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.VALIDATION_EMAIL,updateCallRequest.getEmail())); } setIfUpdated(callEntity::getAmountMin, callEntity::setAmountMin, updateCallRequest.getAmountMin()); From f6beb55fc7c8c0480d26b5d7d1b590f49510713d Mon Sep 17 00:00:00 2001 From: nishainnogent Date: Thu, 3 Oct 2024 14:44:57 +0530 Subject: [PATCH 03/50] updated code --- src/main/java/net/gepafin/tendermanagement/dao/CallDao.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index 97d0e4b4..e214e562 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -130,7 +130,7 @@ public class CallDao { throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG)); } callEntity.setAmountMin(createCallRequest.getAmountMin()); - if(createCallRequest.getEmail()==null || Boolean.FALSE.equals(Utils.isValidEmail(createCallRequest.getEmail()))){ + if(createCallRequest.getEmail()!=null && Boolean.FALSE.equals(Utils.isValidEmail(createCallRequest.getEmail()))){ throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.VALIDATION_EMAIL,createCallRequest.getEmail())); } callEntity.setEmail(createCallRequest.getEmail()); @@ -478,7 +478,7 @@ public class CallDao { if (updateCallRequest.getAmountMin() != null && updateCallRequest.getAmountMin().compareTo(BigDecimal.ZERO) < 0) { throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG)); } - if(updateCallRequest.getEmail()==null && Boolean.FALSE.equals(Utils.isValidEmail(updateCallRequest.getEmail()))){ + if(updateCallRequest.getEmail()!=null && Boolean.FALSE.equals(Utils.isValidEmail(updateCallRequest.getEmail()))){ throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.VALIDATION_EMAIL,updateCallRequest.getEmail())); } setIfUpdated(callEntity::getAmountMin, callEntity::setAmountMin, updateCallRequest.getAmountMin()); From a2055e4474bc80ba1995a1b9adb59e7cc580ad9c Mon Sep 17 00:00:00 2001 From: nisha Date: Thu, 3 Oct 2024 14:53:17 +0530 Subject: [PATCH 04/50] Done ticket --- .../db/changelog/db.changelog-1.0.0.xml | 10 +- .../updated_form_field_data_03-10-2024.sql | 99 +++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/db/dump/updated_form_field_data_03-10-2024.sql diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 449727ce..1575f0bb 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -833,5 +833,13 @@ - + + + TRUNCATE TABLE FORM_FIELD RESTART IDENTITY; + + + + + diff --git a/src/main/resources/db/dump/updated_form_field_data_03-10-2024.sql b/src/main/resources/db/dump/updated_form_field_data_03-10-2024.sql new file mode 100644 index 00000000..21a5d11f --- /dev/null +++ b/src/main/resources/db/dump/updated_form_field_data_03-10-2024.sql @@ -0,0 +1,99 @@ +INSERT INTO FORM_FIELD (SORT_ORDER, NAME, LABEL, DESCRIPTION, SETTINGS, VALIDATORS, CREATED_DATE, UPDATED_DATE) +VALUES +(1, 'textinput', 'Testo Breve', 'Per risposte concise (nomi, titoli, brevi descrizioni)', + '[{"name": "label", "value": "Testo Breve"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(2, 'textarea', 'Testo Lungo', 'Campo di testo esteso per paragrafi, descrizioni, proposte', + '[{"name": "label", "value": "Testo Lungo"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(3, 'wysiwyg', 'Campo di Testo Formattato', 'Editor avanzato per testo con formattazione', + '[{"name": "label", "value": "Testo Formattato"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(4, 'numberinput', 'Campo Numerico', 'Per l''inserimento di valori numerici (quantità, importi, percentuali)', + '[{"name": "label", "value": "Numero"}, {"name": "placeholder", "value": "0"}, {"name": "step", "value": "0"}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(5, 'radio', 'Scelta Singola', 'Gruppo di opzioni per selezione singola', + '[{"name": "label", "value": "Scelta Singola"}, {"name": "options", "value": "[]"}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(6, 'select', 'Menu a Tendina', 'Selezione da opzioni predefinite', + '[{"name": "label", "value": "Menu a Tendina"}, {"name": "options", "value": "[]"}]', + '{"isRequired": false,"custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(7, 'checkboxes', 'Scelta Multipla', 'Gruppo di opzioni per selezione singola o multipla', + '[{"name": "label", "value": "Scelta Multipla"}, {"name": "options", "value": "[]"}]', + '{"isRequired": false,"custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(8, 'switch', 'Casella di Spunta', 'Per selezioni binarie, accettazioni, conferme', + '[{"name": "label", "value": "Casella di Spunta"}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(9, 'datepicker', 'Data', 'Selezione di data', + '[{"name": "label", "value": "Data"}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(10, 'fileupload', 'Caricamento File', 'Per l''upload di documenti o immagini', + '[{"name": "label", "value": "Caricamento File"}, {"name": "mime", "value": "[]"}]', + '{"isRequired": false, "maxSize": 100000, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(11, 'textinput', 'Campo Partita IVA', 'Specifico per l''inserimento del numero di Partita IVA', + '[{"name": "label", "value": "Partita IVA"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true,"custom": "isPIVA"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(12, 'textinput', 'Campo Codice Fiscale', 'Specifico per l''inserimento del Codice Fiscale italiano per persone fisiche e giuridiche', + '[{"name": "label", "value": "Codice Fiscale"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true, "custom": "isCodiceFiscale"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(13, 'numberinput', 'Campo CAP', 'Per l''inserimento del Codice di Avviamento Postale', + '[{"name": "label", "value": "CAP"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true,"custom": "isCAP"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(14, 'textinput', 'Campo IBAN', 'Per l''inserimento del codice IBAN', + '[{"name": "label", "value": "IBAN"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true,"custom": "isIBAN"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(15, 'textinput', 'Campo Email', 'Per l''inserimento di indirizzi email standard (non PEC)', + '[{"name": "label", "value": "Campo Email"}, {"name": "placeholder", "value": "nome@esempio.it"}]', + '{"isRequired": false, "custom": "isEmail"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(16, 'textinput', 'Campo PEC', 'Specifico per l''inserimento di un indirizzo di Posta Elettronica Certificata', + '[{"name": "label", "value": "Campo PEC"}, {"name": "placeholder", "value": "nome@pec.it"}]', + '{"isRequired": false, "custom": "isEmailPEC"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(17, 'textinput', 'Campo URL', 'Per l''inserimento di indirizzi web', + '[{"name": "label", "value": "Indirizzo URL"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "custom": "isUrl"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(18, 'textinput', 'Marca da bollo', 'Per inserire codice di marca da bollo', + '[{"name": "label", "value": "Marca da bollo"}, {"name": "placeholder", "value": "Numero identificativo"}]', + '{"isRequired": false, "custom": "isMarcaDaBollo"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(19, 'paragraph', 'Paragrafo', 'Semplice testo formattato', + '[{"name": "text", "value": ""}]', '{}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(20, 'table', 'Tabella', 'Tabella', + '[{"name": "label", "value": "Tabella"}, {"name": "table_columns", "value": {}}]', '{}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); From 241b6cd8e29edca06e098d6408d2929b6012a0eb Mon Sep 17 00:00:00 2001 From: harish Date: Thu, 3 Oct 2024 16:10:16 +0530 Subject: [PATCH 05/50] Updated code --- src/main/resources/db/changelog/db.changelog-1.0.0.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index c1a48adb..86f35aa4 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -710,7 +710,7 @@ - + CREATE OR REPLACE FUNCTION gepafin_schema.clock_timestamp_updated_date_column() @@ -724,7 +724,6 @@ $$; - CREATE OR REPLACE FUNCTION gepafin_schema.clock_timestamp_created_date_column() RETURNS TRIGGER @@ -734,6 +733,7 @@ IF NEW.created_date IS NULL THEN NEW.created_date = clock_timestamp(); END IF; + NEW.updated_date = NEW.created_date; RETURN NEW; END; $$; From 2bae3675f8da306a01018d4ba07737fdda20bcad Mon Sep 17 00:00:00 2001 From: nisha Date: Thu, 3 Oct 2024 19:05:08 +0530 Subject: [PATCH 06/50] Updated form field element --- .../db/changelog/db.changelog-1.0.0.xml | 9 ++ .../updated_form_field_data_03-10-2024_1.sql | 101 ++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/main/resources/db/dump/updated_form_field_data_03-10-2024_1.sql diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index bc49068c..d067df71 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -871,4 +871,13 @@ path="classpath:db/dump/updated_form_field_data_03-10-2024.sql" /> + + + TRUNCATE TABLE FORM_FIELD RESTART IDENTITY; + + + + + diff --git a/src/main/resources/db/dump/updated_form_field_data_03-10-2024_1.sql b/src/main/resources/db/dump/updated_form_field_data_03-10-2024_1.sql new file mode 100644 index 00000000..697903cc --- /dev/null +++ b/src/main/resources/db/dump/updated_form_field_data_03-10-2024_1.sql @@ -0,0 +1,101 @@ +INSERT INTO FORM_FIELD (SORT_ORDER, NAME, LABEL, DESCRIPTION, SETTINGS, VALIDATORS, CREATED_DATE, UPDATED_DATE) +VALUES +(1, 'textinput', 'Testo Breve', 'Per risposte concise (nomi, titoli, brevi descrizioni)', + '[{"name": "label", "value": "Testo Breve"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "minLength": null, "maxLength": null, "pattern": null, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(2, 'textarea', 'Testo Lungo', 'Campo di testo esteso per paragrafi, descrizioni, proposte', + '[{"name": "label", "value": "Testo Lungo"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "minLength": null, "maxLength": null, "pattern": null, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(3, 'wysiwyg', 'Campo di Testo Formattato', 'Editor avanzato per testo con formattazione', + '[{"name": "label", "value": "Testo Formattato"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "minLength": null, "maxLength": null, "pattern": null, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(4, 'numberinput', 'Campo Numerico', 'Per l''inserimento di valori numerici (quantità, importi, percentuali)', + '[{"name": "label", "value": "Numero"}, {"name": "placeholder", "value": "0"}, {"name": "step", "value": "0"}]', + '{"isRequired": false, "min": null, "max": null, "pattern": null, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(5, 'radio', 'Scelta Singola', 'Gruppo di opzioni per selezione singola', + '[{"name": "label", "value": "Scelta Singola"}, {"name": "options", "value": []}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(6, 'select', 'Menu a Tendina', 'Selezione da opzioni predefinite', + '[{"name": "label", "value": "Menu a Tendina"}, {"name": "options", "value": []}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(7, 'checkboxes', 'Scelta Multipla', 'Gruppo di opzioni per selezione singola o multipla', + '[{"name": "label", "value": "Scelta Multipla"}, {"name": "options", "value": []}]', + '{"isRequired": false, "min": null, "max": null, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(8, 'switch', 'Casella di Spunta', 'Per selezioni binarie, accettazioni, conferme', + '[{"name": "label", "value": "Casella di Spunta"}]', + '{"isRequired": false}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(9, 'datepicker', 'Data', 'Selezione di data', + '[{"name": "label", "value": "Data"}]', + '{"isRequired": false}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(10, 'fileupload', 'Caricamento File', 'Per l''upload di documenti o immagini', + '[{"name": "label", "value": "Caricamento File"}, {"name": "mime", "value": []}]', + '{"isRequired": false, "maxSize": 100000}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(11, 'textinput', 'Campo Partita IVA', 'Specifico per l''inserimento del numero di Partita IVA', + '[{"name": "label", "value": "Partita IVA"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true, "custom": "isPIVA"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(12, 'textinput', 'Campo Codice Fiscale','Specifico per l''inserimento del Codice Fiscale italiano per persone fisiche e giuridiche', + '[{"name": "label", "value": "Codice Fiscale"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true, "custom": "isCodiceFiscale"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(13, 'textinput', 'Campo CAP','Per l''inserimento del Codice di Avviamento Postale', + '[{"name": "label", "value": "CAP"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true, "custom": "isCAP"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(14, 'textinput', 'Campo IBAN', 'Per l''inserimento del codice IBAN', + '[{"name": "label", "value": "IBAN"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true, "custom": "isIBAN"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(15, 'textinput', 'Campo Email', 'Per l''inserimento di indirizzi email standard (non PEC)', + '[{"name": "label", "value": "Campo Email"}, {"name": "placeholder", "value": "nome@esempio.it"}]', + '{"isRequired": false, "custom": "isEmail"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(16, 'textinput', 'Campo PEC', 'Specifico per l''inserimento di un indirizzo di Posta Elettronica Certificata', + '[{"name": "label", "value": "Campo PEC"}, {"name": "placeholder", "value": "nome@pec.it"}]', + '{"isRequired": false, "custom": "isEmailPEC"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(17, 'textinput', 'Campo URL', 'Per l''inserimento di indirizzi web', + '[{"name": "label", "value": "Indirizzo URL"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "custom": "isUrl"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(18, 'textinput', 'Marca da bollo', 'Per inserire codice di marca da bollo', + '[{"name": "label", "value": "Marca da bollo"}, {"name": "placeholder", "value": "Numero identificativo"}]', + '{"isRequired": false, "custom": "isMarcaDaBollo"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(19, 'paragraph', 'Paragrafo', 'Semplice testo formattato', + '[{"name": "text", "value": ""}]', + '{}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(20, 'table', 'Tabella', 'Tabella', + '[{"name": "label", "value": "Tabella"}, {"name": "table_columns", "value": []}]', + '{}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); From 837bd63314eb926c0d189009338893a7ea0a48ab Mon Sep 17 00:00:00 2001 From: harish Date: Thu, 3 Oct 2024 19:39:33 +0530 Subject: [PATCH 07/50] Updated validation logic for start and end dates --- .../constants/GepafinConstant.java | 3 +++ .../gepafin/tendermanagement/dao/CallDao.java | 20 +++++++++++++++++++ src/main/resources/message_en.properties | 3 +++ src/main/resources/message_it.properties | 2 ++ 4 files changed, 28 insertions(+) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 3ebf7e5f..70e764f2 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -179,4 +179,7 @@ public class GepafinConstant { public static final String UNAUTHORIZED = "UNAUTHORIZED"; public static final String COMPANY_ID_MANDATORY = "company.id.mandatory"; public static final String USER_ALREADY_CONNECTED_TO_COMPANY = "user.already.connected.to.company"; + + public static final String CALL_NOT_STARTED_YET = "call.not.started.yet"; + public static final String CALL_ALREADY_ENDED = "call.already.ended"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index e214e562..c6345d59 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.dao; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -673,6 +674,25 @@ public class CallDao { Status.NOT_FOUND, Translator.toLocale(GepafinConstant.CALL_NOT_PUBLISHED)); } + LocalDate currentDate = LocalDate.now(); + LocalTime currentTime = LocalTime.now(); + + if (currentDate.isBefore(callEntity.getStartDate().toLocalDate()) || + (currentDate.isEqual(callEntity.getStartDate().toLocalDate()) && currentTime.isBefore(callEntity.getStartTime()))) { + throw new CustomValidationException( + Status.BAD_REQUEST, + Translator.toLocale(GepafinConstant.CALL_NOT_STARTED_YET) + ); + } + + if (currentDate.isAfter(callEntity.getEndDate().toLocalDate()) || + (currentDate.isEqual(callEntity.getEndDate().toLocalDate()) && currentTime.isAfter(callEntity.getEndTime()))) { + throw new CustomValidationException( + Status.BAD_REQUEST, + Translator.toLocale(GepafinConstant.CALL_ALREADY_ENDED) + ); + } + return callEntity; } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index d70c97f4..62de4214 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -206,3 +206,6 @@ vatnumber.already.exists=VatNumber already exists. invalid.email=Invalid email. company.id.mandatory=Company id is mandatory. user.already.connected.to.company=The user is already connected to this company. + +call.not.started.yet = The call has not started yet. Please wait until the specified start date and time. +call.already.ended = The call has already ended. You cannot submit the application after the deadline. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 00e8dcfc..aa29d36e 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -199,3 +199,5 @@ vatnumber.already.exists=Il numero di partita IVA esiste gi invalid.email=Email non valida. company.id.mandatory=L'ID dell'azienda obbligatorio. user.already.connected.to.company=L'utente gi collegato a questa azienda. +call.not.started.yet = La chiamata non ancora iniziata. Attendere fino alla data e all'ora di inizio specificate. +call.already.ended = La chiamata gi terminata. Non possibile inviare l'applicazione dopo la scadenza. From f838da73ef3d074208c8654cee3e88c15a6d2e2c Mon Sep 17 00:00:00 2001 From: harish Date: Fri, 4 Oct 2024 19:03:33 +0530 Subject: [PATCH 08/50] Fixed next pervious issue --- .../tendermanagement/dao/FlowFormDao.java | 31 +++++++++++++------ .../service/impl/ApplicationServiceImpl.java | 2 +- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java index b99ba6c2..013f018c 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java @@ -240,15 +240,17 @@ public class FlowFormDao { List previousFormIds = flowEdgesList.stream() .map(FlowEdgesEntity::getSourceId) .toList(); + if (previousFormIds.size() == 1) { + return previousFormIds.get(0); + } List applicationFormEntities=applicationFormRepository.findByFormIdInAndApplicationId(previousFormIds,applicationEntity.getId()); - applicationFormEntities.sort(Comparator.comparing(ApplicationFormEntity::getCreatedDate).reversed()); return applicationFormEntities.isEmpty() ? null : applicationFormEntities.get(0).getForm().getId(); } - public NextOrPreviousFormResponse getnextOrPreviousForm(ApplicationEntity applicationEntity, Long formId, - FormActionEnum action) { + public NextOrPreviousFormResponse getNextOrPreviousForm(ApplicationEntity applicationEntity, Long formId, + FormActionEnum action) { Long calculatedFormId = null; FormEntity formEntity = null; if (formId == null) { @@ -299,7 +301,7 @@ public class FlowFormDao { List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId()); Long totalFormSteps = calculateTotalSteps(flowEdgesList); - Long currentStep = calculateCurrentStep(formEntity); + Long currentStep = calculateCurrentStep(flowEdgesList, formEntity); nextOrPreviousFormResponse.setTotalFormSteps(totalFormSteps); completedSteps = getCompletedSteps(applicationEntity); nextOrPreviousFormResponse.setCompletedSteps(Long.valueOf(completedSteps)); @@ -321,11 +323,11 @@ public class FlowFormDao { return completedSteps; } - public Long calculateCurrentStep(FormEntity formEntity) { + public Long calculateCurrentStep(List flowEdgesList, FormEntity formEntity) { Long currentStep = 2l; if (formEntity.getId().equals(formEntity.getCall().getInitialForm())) { currentStep = 1l; - } else if (formEntity.getId().equals(formEntity.getCall().getFinalForm())) { + } else if (flowEdgesList.size()>1 && formEntity.getId().equals(formEntity.getCall().getFinalForm())) { currentStep = 3l; } return currentStep; @@ -341,13 +343,22 @@ public class FlowFormDao { private Long getDefaultForm(ApplicationEntity applicationEntity) { List applicationFormList = applicationFormRepository.findByApplicationIdOrderByCreatedDateAsc(applicationEntity.getId()); - if(applicationFormList.isEmpty()) { + if (applicationFormList.isEmpty()) { return applicationEntity.getCall().getInitialForm(); } - if(applicationFormList.get(applicationFormList.size()-1).getForm().getId().equals(applicationEntity.getCall().getFinalForm())) { - return applicationEntity.getCall().getInitialForm(); + if (applicationFormList.get(applicationFormList.size() - 1).getForm().getId().equals(applicationEntity.getCall().getFinalForm())) { + return applicationEntity.getCall().getInitialForm(); } - return getNextForm(applicationFormList.get(applicationFormList.size()-1).getForm(), applicationEntity); + FormEntity currentFormEntity = applicationFormList.get(applicationFormList.size() - 1).getForm(); + + for (ApplicationFormEntity applicationFormEntity : applicationFormList) { + Boolean isCompleted = formDao.validateCompletedSteps(applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId()), applicationEntity, applicationFormEntity.getForm()); + if (Boolean.FALSE.equals(isCompleted)) { + currentFormEntity = applicationFormEntity.getForm(); + break; + } + } + return getNextForm(currentFormEntity, applicationEntity); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java index a64afadf..c69354b2 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java @@ -72,7 +72,7 @@ public class ApplicationServiceImpl implements ApplicationService { public NextOrPreviousFormResponse getNextOrPreviousForm(HttpServletRequest request, Long applicationId, Long formId, FormActionEnum action) { ApplicationEntity applicationEntity = validateApplication(applicationId); - return flowFormDao.getnextOrPreviousForm(applicationEntity, formId, action); + return flowFormDao.getNextOrPreviousForm(applicationEntity, formId, action); } @Override From fa4634972075c1989da9b7e827399760c9e01a74 Mon Sep 17 00:00:00 2001 From: nishainnogent Date: Fri, 4 Oct 2024 19:28:41 +0530 Subject: [PATCH 09/50] updated code --- .../tendermanagement/dao/FlowFormDao.java | 132 +++++++++--------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java index 013f018c..1ffb9059 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java @@ -1,6 +1,7 @@ package net.gepafin.tendermanagement.dao; import java.util.*; +import java.util.stream.Collectors; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; import net.gepafin.tendermanagement.repositories.*; @@ -174,81 +175,81 @@ public class FlowFormDao { .orElse(null); } -// public Long getPreviousForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { -// // Retrieve the flow edges for the previous forms -// List flowEdgesList = flowEdgesRepository.findByTargetIdAndCallId( -// currentFormEntity.getId(), applicationEntity.getCall().getId()); -// -// if (flowEdgesList.isEmpty()) { -// return null; -//// throw new ResourceNotFoundException(Status.NOT_FOUND, -//// Translator.toLocale(GepafinConstant.PREVIOUS_FORM_NOT_FOUND)); -// } -// -// // If only one edge exists, return the source form ID -// if (flowEdgesList.size() == 1) { -// return flowEdgesList.get(0).getSourceId(); -// } -// -// // For multiple edges, find the previous form based on the chosen value -// List previousFormIds = flowEdgesList.stream() -// .map(FlowEdgesEntity::getSourceId) -// .toList(); -// -// // Fetch the flow data based on previous form IDs -// List flowDataList = flowDataRepository.findByFormIdInAndCallId( -// previousFormIds, applicationEntity.getCall().getId()); -// -// List chosenValues = flowDataList.stream() -// .map(FlowDataEntity::getChoosenValue) -// .toList(); -// -// // Fetch the previous forms based on the chosen field values -// Set formList = applicationFormFieldRepository -// .findByFieldValueInAndApplicationFormApplicationId(chosenValues, applicationEntity.getId()).stream() -// .map(fieldEntity -> fieldEntity.getApplicationForm().getForm()) -// .collect(Collectors.toSet()); -// -// // Find next form IDs recursively for all forms in the formList -// List fieldIds = formList.stream() -// .map(formEntity -> getNextForm(formEntity, applicationEntity)) -// .toList(); -// -// // Return the first matching previous form ID that corresponds to a next form -// return previousFormIds.stream() -// .filter(fieldIds::contains) -// .findFirst().orElse(null); -// } - public Long getPreviousForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { + // Retrieve the flow edges for the previous forms + List flowEdgesList = flowEdgesRepository.findByTargetIdAndCallId( + currentFormEntity.getId(), applicationEntity.getCall().getId()); - List flowEdgesList = flowEdgesRepository.findByTargetIdAndCallId( - currentFormEntity.getId(), applicationEntity.getCall().getId()); - - if (flowEdgesList.isEmpty()) { - return null; + if (flowEdgesList.isEmpty()) { + return null; // throw new ResourceNotFoundException(Status.NOT_FOUND, // Translator.toLocale(GepafinConstant.PREVIOUS_FORM_NOT_FOUND)); } - // // If only one edge exists, return the source form ID - // if (flowEdgesList.size() == 1) { - // return flowEdgesList.get(0).getSourceId(); - // } + // If only one edge exists, return the source form ID + if (flowEdgesList.size() == 1) { + return flowEdgesList.get(0).getSourceId(); + } // For multiple edges, find the previous form based on the chosen value - List previousFormIds = flowEdgesList.stream() - .map(FlowEdgesEntity::getSourceId) - .toList(); - if (previousFormIds.size() == 1) { - return previousFormIds.get(0); - } + List previousFormIds = flowEdgesList.stream() + .map(FlowEdgesEntity::getSourceId) + .toList(); - List applicationFormEntities=applicationFormRepository.findByFormIdInAndApplicationId(previousFormIds,applicationEntity.getId()); - applicationFormEntities.sort(Comparator.comparing(ApplicationFormEntity::getCreatedDate).reversed()); + // Fetch the flow data based on previous form IDs + List flowDataList = flowDataRepository.findByFormIdInAndCallId( + previousFormIds, applicationEntity.getCall().getId()); - return applicationFormEntities.isEmpty() ? null : applicationFormEntities.get(0).getForm().getId(); + List chosenValues = flowDataList.stream() + .map(FlowDataEntity::getChoosenValue) + .toList(); + + // Fetch the previous forms based on the chosen field values + Set formList = applicationFormFieldRepository + .findByFieldValueInAndApplicationFormApplicationId(chosenValues, applicationEntity.getId()).stream() + .map(fieldEntity -> fieldEntity.getApplicationForm().getForm()) + .collect(Collectors.toSet()); + + // Find next form IDs recursively for all forms in the formList + List fieldIds = formList.stream() + .map(formEntity -> getNextForm(formEntity, applicationEntity)) + .toList(); + + // Return the first matching previous form ID that corresponds to a next form + return previousFormIds.stream() + .filter(fieldIds::contains) + .findFirst().orElse(null); } + +// public Long getPreviousForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { +// +// List flowEdgesList = flowEdgesRepository.findByTargetIdAndCallId( +// currentFormEntity.getId(), applicationEntity.getCall().getId()); +// +// if (flowEdgesList.isEmpty()) { +// return null; +//// throw new ResourceNotFoundException(Status.NOT_FOUND, +//// Translator.toLocale(GepafinConstant.PREVIOUS_FORM_NOT_FOUND)); +// } +// +// // // If only one edge exists, return the source form ID +// // if (flowEdgesList.size() == 1) { +// // return flowEdgesList.get(0).getSourceId(); +// // } +// +// // For multiple edges, find the previous form based on the chosen value +// List previousFormIds = flowEdgesList.stream() +// .map(FlowEdgesEntity::getSourceId) +// .toList(); +// if (previousFormIds.size() == 1) { +// return previousFormIds.get(0); +// } +// +// List applicationFormEntities=applicationFormRepository.findByFormIdInAndApplicationId(previousFormIds,applicationEntity.getId()); +// applicationFormEntities.sort(Comparator.comparing(ApplicationFormEntity::getCreatedDate).reversed()); +// +// return applicationFormEntities.isEmpty() ? null : applicationFormEntities.get(0).getForm().getId(); +// } public NextOrPreviousFormResponse getNextOrPreviousForm(ApplicationEntity applicationEntity, Long formId, FormActionEnum action) { Long calculatedFormId = null; @@ -354,8 +355,7 @@ public class FlowFormDao { for (ApplicationFormEntity applicationFormEntity : applicationFormList) { Boolean isCompleted = formDao.validateCompletedSteps(applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId()), applicationEntity, applicationFormEntity.getForm()); if (Boolean.FALSE.equals(isCompleted)) { - currentFormEntity = applicationFormEntity.getForm(); - break; + return applicationFormEntity.getForm().getId(); } } return getNextForm(currentFormEntity, applicationEntity); From 9477c8fe14efaf335ec8ac18190f74602e3fae02 Mon Sep 17 00:00:00 2001 From: harish Date: Mon, 7 Oct 2024 12:45:34 +0530 Subject: [PATCH 10/50] Updated application status api response --- .../gepafin/tendermanagement/constants/GepafinConstant.java | 2 ++ .../net/gepafin/tendermanagement/dao/ApplicationDao.java | 6 ++++-- .../tendermanagement/service/ApplicationService.java | 2 +- .../service/impl/ApplicationServiceImpl.java | 4 ++-- .../tendermanagement/web/rest/api/ApplicationApi.java | 2 +- .../web/rest/api/impl/ApplicationApiController.java | 6 +++--- src/main/resources/message_en.properties | 1 + src/main/resources/message_it.properties | 1 + 8 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 3ebf7e5f..cffcc815 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -179,4 +179,6 @@ public class GepafinConstant { public static final String UNAUTHORIZED = "UNAUTHORIZED"; public static final String COMPANY_ID_MANDATORY = "company.id.mandatory"; public static final String USER_ALREADY_CONNECTED_TO_COMPANY = "user.already.connected.to.company"; + public static final String STATUS_UPDATED_SUCCESSFULLY = "status.updated.successfully"; + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index a76b9de3..50ed07b1 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -492,7 +492,7 @@ public class ApplicationDao { } } - public void updateApplicationStatus(Long applicationId, ApplicationStatusTypeEnum status) { + public ApplicationResponse updateApplicationStatus(Long applicationId, ApplicationStatusTypeEnum status) { ApplicationEntity applicationEntity = validateApplication(applicationId); if (status.equals(ApplicationStatusTypeEnum.SUBMIT)) { @@ -518,7 +518,9 @@ public class ApplicationDao { } else { applicationEntity.setStatus(status.getValue()); } - saveApplicationEntity(applicationEntity); + applicationEntity = saveApplicationEntity(applicationEntity); + + return getApplicationResponse(applicationEntity); } public Integer calculateProgress(Long totalSteps, Long completedSteps) { diff --git a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java index a8f6ad53..edb62c93 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java @@ -29,6 +29,6 @@ public interface ApplicationService { public NextOrPreviousFormResponse getNextOrPreviousForm(HttpServletRequest request, Long applicationId, Long formId, FormActionEnum action); - public void updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status); + public ApplicationResponse updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java index c69354b2..142d4b01 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java @@ -76,8 +76,8 @@ public class ApplicationServiceImpl implements ApplicationService { } @Override - public void updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status) { - applicationDao.updateApplicationStatus(applicationId, status); + public ApplicationResponse updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status) { + return applicationDao.updateApplicationStatus(applicationId, status); } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java index c56680ef..1869655c 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java @@ -127,7 +127,7 @@ public interface ApplicationApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PutMapping(value = "/{applicationId}/status", produces = { "application/json" }) - ResponseEntity> updateApplicationStatus(HttpServletRequest request, + ResponseEntity> updateApplicationStatus(HttpServletRequest request, @Parameter(description = "The application id", required = true) @PathVariable("applicationId") Long applicationId, @Parameter(description = "status", required = true)@RequestParam(value = "status", required = true) ApplicationStatusTypeEnum status); diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java index 69f28492..6de3f812 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java @@ -83,10 +83,10 @@ public class ApplicationApiController implements ApplicationApi { } @Override - public ResponseEntity> updateApplicationStatus(HttpServletRequest request, Long applicationId, + public ResponseEntity> updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status) { - applicationService.updateApplicationStatus(request, applicationId, status); + ApplicationResponse applicationResponse = applicationService.updateApplicationStatus(request, applicationId, status); return ResponseEntity.status(HttpStatus.OK) - .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG))); + .body(new Response<>(applicationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.STATUS_UPDATED_SUCCESSFULLY))); } } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index d70c97f4..b921d880 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -206,3 +206,4 @@ vatnumber.already.exists=VatNumber already exists. invalid.email=Invalid email. company.id.mandatory=Company id is mandatory. user.already.connected.to.company=The user is already connected to this company. +status.updated.successfully=Status updated successfully. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 00e8dcfc..c81ee2df 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -199,3 +199,4 @@ vatnumber.already.exists=Il numero di partita IVA esiste gi invalid.email=Email non valida. company.id.mandatory=L'ID dell'azienda obbligatorio. user.already.connected.to.company=L'utente gi collegato a questa azienda. +status.updated.successfully=Stato aggiornato con successo. From 32f075a03dd8163b183234ad88fa9404a90eada7 Mon Sep 17 00:00:00 2001 From: harish Date: Mon, 7 Oct 2024 15:09:16 +0530 Subject: [PATCH 11/50] Added DateOfBirth in UserSamlResponse --- .../tendermanagement/model/response/UserSamlResponse.java | 4 ++++ .../service/impl/AuthenticationService.java | 8 ++++++++ src/main/resources/application-production.properties | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/UserSamlResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/UserSamlResponse.java index da732bd4..8fdcbdea 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/UserSamlResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/UserSamlResponse.java @@ -2,6 +2,8 @@ package net.gepafin.tendermanagement.model.response; import lombok.Data; +import java.time.LocalDateTime; + @Data public class UserSamlResponse { @@ -10,4 +12,6 @@ public class UserSamlResponse { private String firstName; private String lastName; + + private LocalDateTime dateOfBirth; } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java index a84b325c..03ce8b1c 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -33,6 +33,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.stereotype.Service; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -182,6 +183,13 @@ public class AuthenticationService { && !userAttributes.get("cognome").isEmpty()) { userSamlResponse.setLastName(userAttributes.get("cognome").get(0).toString()); } + if (userAttributes.containsKey("dataNascita") && userAttributes.get("dataNascita") != null + && !userAttributes.get("dataNascita").isEmpty()) { + String dateString =userAttributes.get("dataNascita").get(0).toString(); + LocalDate dateOfBirth = LocalDate.parse(dateString); + LocalDateTime dateOfBirthWithTime = dateOfBirth.atStartOfDay(); + userSamlResponse.setDateOfBirth(dateOfBirthWithTime); + } userSamlResponse.setCodiceFiscale(cf); return userSamlResponse; } diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index f4ea18fa..968d5ac5 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -9,8 +9,8 @@ spring.h2.console.enabled=true base-url=http://bandi-api.gepafin.it 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 #SPID configuration spid.ipd.base.url=https://login.regione.umbria.it active.profile.folder=production \ No newline at end of file From 65169e54c3d07b7d89e703da06289b256258cd77 Mon Sep 17 00:00:00 2001 From: harish Date: Mon, 7 Oct 2024 15:17:03 +0530 Subject: [PATCH 12/50] Updated message for application status api response --- .../net/gepafin/tendermanagement/constants/GepafinConstant.java | 2 +- .../web/rest/api/impl/ApplicationApiController.java | 2 +- src/main/resources/message_en.properties | 1 + src/main/resources/message_it.properties | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index cffcc815..89c1e475 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -179,6 +179,6 @@ public class GepafinConstant { public static final String UNAUTHORIZED = "UNAUTHORIZED"; public static final String COMPANY_ID_MANDATORY = "company.id.mandatory"; public static final String USER_ALREADY_CONNECTED_TO_COMPANY = "user.already.connected.to.company"; - public static final String STATUS_UPDATED_SUCCESSFULLY = "status.updated.successfully"; + public static final String APPLICATION_STATUS_UPDATED_SUCCESSFULLY = "application.status.updated.successfully"; } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java index 6de3f812..bcbf8e80 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java @@ -87,6 +87,6 @@ public class ApplicationApiController implements ApplicationApi { ApplicationStatusTypeEnum status) { ApplicationResponse applicationResponse = applicationService.updateApplicationStatus(request, applicationId, status); return ResponseEntity.status(HttpStatus.OK) - .body(new Response<>(applicationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.STATUS_UPDATED_SUCCESSFULLY))); + .body(new Response<>(applicationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_STATUS_UPDATED_SUCCESSFULLY))); } } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index b921d880..3b11067b 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -207,3 +207,4 @@ invalid.email=Invalid email. company.id.mandatory=Company id is mandatory. user.already.connected.to.company=The user is already connected to this company. status.updated.successfully=Status updated successfully. +application.status.updated.successfully = Application status updated successfully. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index c81ee2df..27ebd36d 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -200,3 +200,4 @@ invalid.email=Email non valida. company.id.mandatory=L'ID dell'azienda obbligatorio. user.already.connected.to.company=L'utente gi collegato a questa azienda. status.updated.successfully=Stato aggiornato con successo. +application.status.updated.successfully = Stato dell'applicazione aggiornato con successo. From 654beb1c8ab6424c22be92dfed842cfb1ec45eaa Mon Sep 17 00:00:00 2001 From: harish Date: Mon, 7 Oct 2024 18:42:59 +0530 Subject: [PATCH 13/50] Beneficiary GDPR --- .../gepafin/tendermanagement/dao/UserDao.java | 27 ++++++++++++++++ .../entities/BeneficiaryEntity.java | 32 +++++++++++++++++-- .../model/request/UpdateUserReq.java | 10 ++++++ .../model/request/UserReq.java | 11 +++++++ .../model/response/UserResponseBean.java | 12 +++++++ .../db/changelog/db.changelog-1.0.0.xml | 19 +++++++++++ 6 files changed, 108 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 53825d01..eb28600b 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -83,6 +83,15 @@ public class UserDao { beneficiaryEntity.setLastName(userReq.getLastName()); beneficiaryEntity.setOrganization(userReq.getOrganization()); beneficiaryEntity.setPhoneNumber(userReq.getPhoneNumber()); + beneficiaryEntity.setGdprRead(userReq.getGdprRead()); + beneficiaryEntity.setGdprComunicazione(userReq.getGdprComunicazione()); + beneficiaryEntity.setGdprElaborazione(userReq.getGdprElaborazione()); + beneficiaryEntity.setGdprMateriale(userReq.getGdprMateriale()); + beneficiaryEntity.setPrivacy(userReq.getPrivacy()); + beneficiaryEntity.setTerms(userReq.getTerms()); + beneficiaryEntity.setOffers(userReq.getOffers()); + beneficiaryEntity.setMarketing(userReq.getMarketing()); + beneficiaryEntity.setThirdParty(userReq.getThirdParty()); beneficiaryEntity =beneficiaryRepository.save(beneficiaryEntity); } return beneficiaryEntity; @@ -148,6 +157,14 @@ public class UserDao { setIfUpdated(userEntity::getOrganization, userEntity::setOrganization, userReq.getOrganization()); setIfUpdated(userEntity::getAddress, userEntity::setAddress, userReq.getAddress()); setIfUpdated(userEntity::getPhoneNumber, userEntity::setPhoneNumber, userReq.getPhoneNumber()); + setIfUpdated(userEntity::getDateOfBirth, userEntity::setDateOfBirth, userReq.getDateOfBirth()); + setIfUpdated(userEntity.getBeneficiary()::getCodiceFiscale, userEntity.getBeneficiary()::setCodiceFiscale, userReq.getCodiceFiscale()); + setIfUpdated(userEntity.getBeneficiary()::getGdprComunicazione, userEntity.getBeneficiary()::setGdprComunicazione, userReq.getGdprComunicazione()); + setIfUpdated(userEntity.getBeneficiary()::getGdprElaborazione, userEntity.getBeneficiary()::setGdprElaborazione, userReq.getGdprElaborazione()); + setIfUpdated(userEntity.getBeneficiary()::getGdprMateriale, userEntity.getBeneficiary()::setGdprMateriale, userReq.getGdprMateriale()); + setIfUpdated(userEntity.getBeneficiary()::getMarketing, userEntity.getBeneficiary()::setMarketing, userReq.getMarketing()); + setIfUpdated(userEntity.getBeneficiary()::getOffers, userEntity.getBeneficiary()::setOffers, userReq.getOffers()); + setIfUpdated(userEntity.getBeneficiary()::getThirdParty, userEntity.getBeneficiary()::setThirdParty, userReq.getThirdParty()); if (userReq.getRoleId() != null) { RoleEntity roleEntity = roleDao.validateRole(userReq.getRoleId()); setIfUpdated(userEntity::getRoleEntity, userEntity::setRoleEntity, roleEntity); @@ -167,6 +184,7 @@ public class UserDao { userEntity.setStatus(UserStatusEnum.ACTIVE.getValue()); userEntity.setBeneficiary(beneficiary); if (Boolean.FALSE.equals(RoleStatusEnum.ROLE_BENEFICIARY.getValue().equals(roleEntity.getRoleType()))) { + userEntity.setFirstName(userReq.getFirstName()); userEntity.setLastName(userReq.getLastName()); userEntity.setOrganization(userReq.getOrganization()); @@ -216,6 +234,15 @@ public class UserDao { userResponseBean.setCountry(userEntity.getBeneficiary().getCountry()); userResponseBean.setCodiceFiscale(userEntity.getBeneficiary().getCodiceFiscale()); userResponseBean.setDateOfBirth(userEntity.getBeneficiary().getDateOfBirth()); + userResponseBean.setGdprRead(userEntity.getBeneficiary().getGdprRead()); + userResponseBean.setGdprComunicazione(userEntity.getBeneficiary().getGdprComunicazione()); + userResponseBean.setGdprElaborazione(userEntity.getBeneficiary().getGdprElaborazione()); + userResponseBean.setGdprMateriale(userEntity.getBeneficiary().getGdprMateriale()); + userResponseBean.setPrivacy(userEntity.getBeneficiary().getPrivacy()); + userResponseBean.setTerms(userEntity.getBeneficiary().getTerms()); + userResponseBean.setOffers(userEntity.getBeneficiary().getOffers()); + userResponseBean.setMarketing(userEntity.getBeneficiary().getMarketing()); + userResponseBean.setThirdParty(userEntity.getBeneficiary().getThirdParty()); } return userResponseBean; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java index 302f2af5..9ea91cb8 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java @@ -37,11 +37,37 @@ public class BeneficiaryEntity extends BaseEntity { @Column(name = "COUNTRY") private String country; - + @Column(name = "CODICE_FISCALE") private String codiceFiscale; - + @Column(name = "DATE_OF_BIRTH") private LocalDateTime dateOfBirth; - + + @Column(name = "PRIVACY") + private Boolean privacy; + + @Column(name = "TERMS") + private Boolean terms; + + @Column(name = "GDPR_READ") + private Boolean gdprRead; + + @Column(name = "MARKETING") + private Boolean marketing; + + @Column(name = "OFFERS") + private Boolean offers; + + @Column(name = "THIRD_PARTY") + private Boolean thirdParty; + + @Column(name = "GDPR_MATERIALE") + private Boolean gdprMateriale; + + @Column(name = "GDPR_ELABORAZIONE") + private Boolean gdprElaborazione; + + @Column(name = "GDPR_COMUNICAZIONE") + private Boolean gdprComunicazione; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java index 65eba841..1b4ae81b 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java @@ -4,6 +4,8 @@ import lombok.Getter; import lombok.Setter; import net.gepafin.tendermanagement.enums.UserStatusEnum; +import java.time.LocalDateTime; + @Getter @Setter public class UpdateUserReq { @@ -17,4 +19,12 @@ public class UpdateUserReq { private String city; private UserStatusEnum status; private String country; + private String codiceFiscale; + private LocalDateTime dateOfBirth; + private Boolean marketing; + private Boolean offers; + private Boolean thirdParty; + private Boolean gdprMateriale; + private Boolean gdprElaborazione; + private Boolean gdprComunicazione; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java index c53d65aa..68d9fdc8 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java @@ -31,5 +31,16 @@ public class UserReq { private String codiceFiscale; private LocalDateTime dateOfBirth; + private Boolean privacy; + private Boolean terms; + private Boolean gdprRead; + + private Boolean marketing; + private Boolean offers; + private Boolean thirdParty; + + private Boolean gdprMateriale; + private Boolean gdprElaborazione; + private Boolean gdprComunicazione; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java index c0457120..056a8677 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java @@ -39,4 +39,16 @@ public class UserResponseBean extends BaseBean { private LocalDateTime dateOfBirth; private List companies; + private Boolean privacy; + private Boolean terms; + + private Boolean gdprRead; + + private Boolean marketing; + private Boolean offers; + private Boolean thirdParty; + + private Boolean gdprMateriale; + private Boolean gdprElaborazione; + private Boolean gdprComunicazione; } diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index d067df71..cdad0a33 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -879,5 +879,24 @@ + + + + + + + + + + + + + + + + + + + From 543963f22d4996a41ff26e8dcd729746983c408e Mon Sep 17 00:00:00 2001 From: nisha Date: Mon, 7 Oct 2024 20:11:30 +0530 Subject: [PATCH 14/50] Updated request body for form data --- .../tendermanagement/dao/ApplicationDao.java | 27 ++++++++---- .../gepafin/tendermanagement/dao/FormDao.java | 35 ++++++++++++--- .../ApplicationFormFieldRequestBean.java | 2 +- .../gepafin/tendermanagement/util/Utils.java | 43 +++++++++++++++++++ .../db/changelog/db.changelog-1.0.0.xml | 7 ++- 5 files changed, 98 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index a76b9de3..3d1f7de7 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -323,9 +323,13 @@ public class ApplicationDao { } } Utils.setIfUpdated(applicationFormFieldEntity::getFieldId, applicationFormFieldEntity::setFieldId, applicationFormFieldRequestBean.getFieldId()); - if(applicationFormFieldRequestBean.getFieldValue() ==null || Boolean.FALSE.equals(applicationFormFieldRequestBean.getFieldValue().isEmpty())) { - applicationFormFieldEntity.setFieldValue(applicationFormFieldRequestBean.getFieldValue()); + + if(applicationFormFieldRequestBean.getFieldValue() !=null ) { + applicationFormFieldEntity.setFieldValue(Utils.convertObjectToJsonString(applicationFormFieldRequestBean.getFieldValue())); } + if(applicationFormFieldRequestBean.getFieldValue() ==null ) { + applicationFormFieldEntity.setFieldValue(null); + } return applicationFormFieldRepository.save(applicationFormFieldEntity); } @@ -333,10 +337,15 @@ public class ApplicationDao { List documentIds=null; List contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class); for (ContentResponseBean contentResponseBean:contentResponseBeans){ - if(Boolean.TRUE.equals(contentResponseBean.getName().equals("fileupload"))){ - if(contentResponseBean.getId().equals(applicationFormFieldRequestBean.getFieldId())) { - String documentId = applicationFormFieldRequestBean.getFieldValue(); - documentIds = validateDocumentIds(documentId); + if(Boolean.TRUE.equals(contentResponseBean.getName().equals("fileupload"))) { + if (contentResponseBean.getId().equals(applicationFormFieldRequestBean.getFieldId())) { + Object fieldValueObject = applicationFormFieldRequestBean.getFieldValue(); + if (fieldValueObject instanceof String) { + // Safely cast the object to a string + String documentId = (String) fieldValueObject; + // Now you can use documentId as needed + documentIds = validateDocumentIds(documentId); + } } } } @@ -377,7 +386,9 @@ public class ApplicationDao { ApplicationFormFieldResponseBean applicationFormFieldResponseBean = new ApplicationFormFieldResponseBean(); applicationFormFieldResponseBean.setApplicationFormId(applicationFormId); applicationFormFieldResponseBean.setFieldId(applicationFormFieldEntity.getFieldId()); - applicationFormFieldResponseBean.setFieldValue(applicationFormFieldEntity.getFieldValue()); + if(applicationFormFieldEntity.getFieldValue() != null) { + applicationFormFieldResponseBean.setFieldValue(Utils.getFieldValueAsObject(applicationFormFieldEntity.getFieldValue())); + } applicationFormFieldResponseBean.setId(applicationFormFieldEntity.getId()); applicationFormFieldResponseBean.setCreatedDate(applicationFormFieldEntity.getCreatedDate()); applicationFormFieldResponseBean.setUpdatedDate(applicationFormFieldEntity.getUpdatedDate()); @@ -447,7 +458,7 @@ public class ApplicationDao { } private ApplicationGetResponseBean createApplicationGetResponseBean(ApplicationEntity applicationEntity, List formEntities, List formApplicationResponses) { - ApplicationGetResponseBean applicationGetResponseBean =createApplicationGetResponseBean(applicationEntity); + ApplicationGetResponseBean applicationGetResponseBean = createApplicationGetResponseBean(applicationEntity); applicationGetResponseBean.setForm(formApplicationResponses); return applicationGetResponseBean; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java index 9cdf3fed..bee7885c 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java @@ -205,12 +205,14 @@ public class FormDao { public void validateFormField(List applicationFormFieldRequestList, ApplicationEntity applicationEntity, FormEntity formEntity) { Map formFieldMap = new LinkedHashMap(); for(ApplicationFormFieldRequestBean applicationFormFieldRequestBean:applicationFormFieldRequestList) { - if(applicationFormFieldRequestBean.getFieldValue()==null || applicationFormFieldRequestBean.getFieldValue().isEmpty()) + if(applicationFormFieldRequestBean.getFieldValue()==null ) continue; - formFieldMap.put(applicationFormFieldRequestBean.getFieldId(),applicationFormFieldRequestBean.getFieldValue()); - } + if (applicationFormFieldRequestBean.getFieldValue() != null ) { + Object fieldValue = applicationFormFieldRequestBean.getFieldValue(); + checkObjectData(applicationFormFieldRequestBean.getFieldId(), fieldValue, formFieldMap); + }} - FormResponseBean formResponseBean = convertFormEntityToFormResponseBean(formEntity); + FormResponseBean formResponseBean = convertFormEntityToFormResponseBean(formEntity); ApplicationFormEntity applicationFormEntity=applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(),formEntity.getId()); Boolean isApplicationFormExist= getApplicationFormExist(applicationFormEntity); FieldValidator validator = FieldValidator.create(); @@ -238,6 +240,27 @@ public class FormDao { validator.validate(); } + private void checkObjectData(String fieldId, Object fieldValue, Map formFieldMap) { + if (fieldValue instanceof List) { + List list = (List) fieldValue; + + // Only map if the list is not empty and contains Strings + if (!list.isEmpty() && list.get(0) instanceof String) { + for (Object value : list) { + setFormFieldMap(fieldId, fieldValue, formFieldMap, value); + } + } + } + else setFormFieldMap(fieldId, fieldValue, formFieldMap, fieldValue); + } + + private void setFormFieldMap(String fieldId, Object fieldValue, Map formFieldMap, Object value) { + if (value instanceof String) { + if(fieldValue !=null && ((String) fieldValue).isEmpty()) + formFieldMap.put(fieldId, value); + } + } + private Boolean getApplicationFormExist(ApplicationFormEntity applicationFormEntity) { if(applicationFormEntity !=null) { return true; @@ -249,8 +272,8 @@ public class FormDao { Map formFieldMap = new LinkedHashMap(); for(ApplicationFormFieldEntity applicationFormFieldEntity:applicationFormFieldEntityList) { formFieldMap.put(applicationFormFieldEntity.getFieldId(),applicationFormFieldEntity.getFieldValue()); - } - + } + FormResponseBean formResponseBean = convertFormEntityToFormResponseBean(formEntity); FieldValidator validator = FieldValidator.create(); formResponseBean.getContent().forEach(contentResponseBean -> { diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationFormFieldRequestBean.java b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationFormFieldRequestBean.java index 029eb470..993fc7e4 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationFormFieldRequestBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationFormFieldRequestBean.java @@ -9,6 +9,6 @@ public class ApplicationFormFieldRequestBean { private String fieldId; - private String fieldValue; + private Object fieldValue; } diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index af0bc684..0c76c78c 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -227,4 +227,47 @@ public class Utils { Pattern pattern = Pattern.compile(EMAIL_REGEX); return pattern.matcher(email).matches(); } + public static String convertObjectToJsonString(Object object) { + try { + // Check if the object is a string + if (object instanceof String) { + String str = (String) object; + // Return null if the string is null or empty + if (str != null && !str.trim().isEmpty()) { + return str; // Return the non-empty string + } else { + return null; // Return null for null or empty string + } + } else if (object != null) { + // Convert non-string objects (arrays, objects) to JSON strings + return mapper.writeValueAsString(object); + } + return null; // Return null if the object is null + } catch (JsonProcessingException e) { + log.error("Error while converting object to string: {}", e.getMessage(), e); + return null; // Return null in case of exception + } + } + + + public static Object getFieldValueAsObject(String fieldValue) { + ObjectMapper mapper = new ObjectMapper(); + try { + // Check if the string is a valid JSON object, array, or simple string + if (fieldValue.startsWith("{")) { + // Convert to a Map (representing an object) + return mapper.readValue(fieldValue, Map.class); + } else if (fieldValue.startsWith("[")) { + // Convert to a List (representing an array) + return mapper.readValue(fieldValue, List.class); + } else { + // Return the raw string (it's a simple value) + return fieldValue; + } + } catch (JsonProcessingException e) { + log.error("Error while converting string to object: {}", e.getMessage(), e); + return fieldValue; // If there's an error, return the raw string + } + } + } diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index d067df71..85054439 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -879,5 +879,10 @@ - + + + From a82aad907331df511fc9cc8d5f2d37f4c3f4b007 Mon Sep 17 00:00:00 2001 From: nisha Date: Mon, 7 Oct 2024 20:33:21 +0530 Subject: [PATCH 15/50] Fixed bug for GEPAFINBE-30 --- .../java/net/gepafin/tendermanagement/dao/FormDao.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java index bee7885c..84c9d9b1 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java @@ -15,6 +15,7 @@ import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; @@ -247,17 +248,18 @@ public class FormDao { // Only map if the list is not empty and contains Strings if (!list.isEmpty() && list.get(0) instanceof String) { for (Object value : list) { - setFormFieldMap(fieldId, fieldValue, formFieldMap, value); + setFormFieldMap(fieldId, formFieldMap, value); } } } - else setFormFieldMap(fieldId, fieldValue, formFieldMap, fieldValue); + else setFormFieldMap(fieldId, formFieldMap, fieldValue); } - private void setFormFieldMap(String fieldId, Object fieldValue, Map formFieldMap, Object value) { + private void setFormFieldMap(String fieldId, Map formFieldMap, Object value) { if (value instanceof String) { - if(fieldValue !=null && ((String) fieldValue).isEmpty()) + if(value !=null && Boolean.FALSE.equals(StringUtils.isEmpty((String)value))) { formFieldMap.put(fieldId, value); + } } } From d4f8d0251c99ef7c91b9dc0134e868d28f4d02f2 Mon Sep 17 00:00:00 2001 From: harish Date: Mon, 7 Oct 2024 23:06:31 +0530 Subject: [PATCH 16/50] updated start and end date validation --- .../net/gepafin/tendermanagement/dao/ApplicationDao.java | 5 +++-- .../service/impl/ApplicationServiceImpl.java | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 19a999ca..ae8db433 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -75,7 +75,7 @@ public class ApplicationDao { public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId, Long applicationId) { FormEntity formEntity = formService.validateForm(formId); - callService.validatePublishedCall(formEntity.getCall().getId()); +// callService.validatePublishedCall(formEntity.getCall().getId()); validateFormFields(applicationRequestBean,formEntity); ApplicationEntity applicationEntity = validateApplication(applicationId); if(Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.SUBMIT.getValue()))) { @@ -488,7 +488,7 @@ public class ApplicationDao { public ApplicationResponse createApplicationByCallId(CompanyEntity companyEntity, ApplicationRequest applicationRequest, Long callId, UserEntity userEntity) { CallEntity call = callService.validateCall(callId); - call = callService.validatePublishedCall(call.getId()); +// call = callService.validatePublishedCall(call.getId()); checkIfApplicationExists(call, companyEntity); ApplicationEntity applicationEntity = createApplicationEntity(userEntity, call, companyEntity); applicationEntity.setComments(applicationRequest.getComments()); @@ -507,6 +507,7 @@ public class ApplicationDao { ApplicationEntity applicationEntity = validateApplication(applicationId); if (status.equals(ApplicationStatusTypeEnum.SUBMIT)) { + callService.validatePublishedCall(applicationEntity.getCall().getId()); // CallEntity callEntity = applicationEntity.getCall(); // Long initialFormId = callEntity.getInitialForm(); // Long finalFormId = callEntity.getFinalForm(); diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java index 142d4b01..a082a092 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java @@ -76,6 +76,7 @@ public class ApplicationServiceImpl implements ApplicationService { } @Override + @Transactional(rollbackFor = Exception.class) public ApplicationResponse updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status) { return applicationDao.updateApplicationStatus(applicationId, status); From c7727254c202c85bd6c891c3e253abd3cdc49489 Mon Sep 17 00:00:00 2001 From: nisha Date: Tue, 8 Oct 2024 17:31:38 +0530 Subject: [PATCH 17/50] Done ticket GEPAFINBE-35 --- .../tendermanagement/dao/CompanyDao.java | 34 ++++++++++++------- .../gepafin/tendermanagement/dao/UserDao.java | 16 +++------ .../entities/BeneficiaryEntity.java | 13 ++----- .../entities/CompanyEntity.java | 6 ++++ .../model/request/CompanyRequest.java | 3 +- .../model/request/UpdateUserReq.java | 5 ++- .../model/request/UserReq.java | 6 +--- .../model/response/CompanyResponse.java | 3 +- .../model/response/LoginResponse.java | 12 +++++++ .../model/response/UserResponseBean.java | 6 +--- .../service/impl/AuthenticationService.java | 6 ++++ .../db/changelog/db.changelog-1.0.0.xml | 12 +++---- 12 files changed, 65 insertions(+), 57 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java index 219b1579..ceec5a8c 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java @@ -21,6 +21,8 @@ import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationExceptio import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; + @Component public class CompanyDao { @@ -97,6 +99,8 @@ public class CompanyDao { entity.setEmail(request.getEmail()); entity.setNumberOfEmployees(request.getNumberOfEmployees()); entity.setAnnualRevenue(request.getAnnualRevenue()); + entity.setContactName(request.getContactName()); + entity.setContactEmail(request.getContactEmail()); return entity; } @@ -118,29 +122,33 @@ public class CompanyDao { response.setAnnualRevenue(entity.getAnnualRevenue()); response.setCreatedDate(entity.getCreatedDate()); response.setUpdatedDate(entity.getUpdatedDate()); + response.setContactName(entity.getContactName()); + response.setContactEmail(entity.getContactEmail()); return response; } public CompanyResponse updateCompany(UserEntity userEntity, Long companyId, CompanyRequest companyRequest) { CompanyEntity companyEntity = validateCompany(companyId); - Utils.setIfUpdated(companyEntity::getCompanyName, companyEntity::setCompanyName, + setIfUpdated(companyEntity::getCompanyName, companyEntity::setCompanyName, companyRequest.getCompanyName()); - Utils.setIfUpdated(companyEntity::getVatNumber, companyEntity::setVatNumber, companyRequest.getVatNumber()); - Utils.setIfUpdated(companyEntity::getCodiceFiscale, companyEntity::setCodiceFiscale, + setIfUpdated(companyEntity::getVatNumber, companyEntity::setVatNumber, companyRequest.getVatNumber()); + setIfUpdated(companyEntity::getCodiceFiscale, companyEntity::setCodiceFiscale, companyRequest.getCodiceFiscale()); - Utils.setIfUpdated(companyEntity::getAddress, companyEntity::setAddress, companyRequest.getAddress()); - Utils.setIfUpdated(companyEntity::getPhoneNumber, companyEntity::setPhoneNumber, + setIfUpdated(companyEntity::getAddress, companyEntity::setAddress, companyRequest.getAddress()); + setIfUpdated(companyEntity::getPhoneNumber, companyEntity::setPhoneNumber, companyRequest.getPhoneNumber()); - Utils.setIfUpdated(companyEntity::getCity, companyEntity::setCity, companyRequest.getCity()); - Utils.setIfUpdated(companyEntity::getProvince, companyEntity::setProvince, companyRequest.getProvince()); - Utils.setIfUpdated(companyEntity::getCap, companyEntity::setCap, companyRequest.getCap()); - Utils.setIfUpdated(companyEntity::getCountry, companyEntity::setCountry, companyRequest.getCountry()); - Utils.setIfUpdated(companyEntity::getPec, companyEntity::setPec, companyRequest.getPec()); - Utils.setIfUpdated(companyEntity::getEmail, companyEntity::setEmail, companyRequest.getEmail()); - Utils.setIfUpdated(companyEntity::getNumberOfEmployees, companyEntity::setNumberOfEmployees, + setIfUpdated(companyEntity::getCity, companyEntity::setCity, companyRequest.getCity()); + setIfUpdated(companyEntity::getProvince, companyEntity::setProvince, companyRequest.getProvince()); + setIfUpdated(companyEntity::getCap, companyEntity::setCap, companyRequest.getCap()); + setIfUpdated(companyEntity::getCountry, companyEntity::setCountry, companyRequest.getCountry()); + setIfUpdated(companyEntity::getPec, companyEntity::setPec, companyRequest.getPec()); + setIfUpdated(companyEntity::getEmail, companyEntity::setEmail, companyRequest.getEmail()); + setIfUpdated(companyEntity::getNumberOfEmployees, companyEntity::setNumberOfEmployees, companyRequest.getNumberOfEmployees()); - Utils.setIfUpdated(companyEntity::getAnnualRevenue, companyEntity::setAnnualRevenue, + setIfUpdated(companyEntity::getAnnualRevenue, companyEntity::setAnnualRevenue, companyRequest.getAnnualRevenue()); + setIfUpdated(companyEntity::getContactName,companyEntity::setContactName,companyRequest.getContactName()); + setIfUpdated(companyEntity::getContactEmail,companyEntity::setContactEmail,companyRequest.getContactEmail()); companyRepository.save(companyEntity); return convertCompanyEntityToCompanyResponse(companyEntity); } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index eb28600b..04608206 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -83,15 +83,12 @@ public class UserDao { beneficiaryEntity.setLastName(userReq.getLastName()); beneficiaryEntity.setOrganization(userReq.getOrganization()); beneficiaryEntity.setPhoneNumber(userReq.getPhoneNumber()); - beneficiaryEntity.setGdprRead(userReq.getGdprRead()); - beneficiaryEntity.setGdprComunicazione(userReq.getGdprComunicazione()); - beneficiaryEntity.setGdprElaborazione(userReq.getGdprElaborazione()); - beneficiaryEntity.setGdprMateriale(userReq.getGdprMateriale()); beneficiaryEntity.setPrivacy(userReq.getPrivacy()); beneficiaryEntity.setTerms(userReq.getTerms()); beneficiaryEntity.setOffers(userReq.getOffers()); beneficiaryEntity.setMarketing(userReq.getMarketing()); beneficiaryEntity.setThirdParty(userReq.getThirdParty()); + beneficiaryEntity.setEmailPec(userReq.getEmailPec()); beneficiaryEntity =beneficiaryRepository.save(beneficiaryEntity); } return beneficiaryEntity; @@ -159,16 +156,14 @@ public class UserDao { setIfUpdated(userEntity::getPhoneNumber, userEntity::setPhoneNumber, userReq.getPhoneNumber()); setIfUpdated(userEntity::getDateOfBirth, userEntity::setDateOfBirth, userReq.getDateOfBirth()); setIfUpdated(userEntity.getBeneficiary()::getCodiceFiscale, userEntity.getBeneficiary()::setCodiceFiscale, userReq.getCodiceFiscale()); - setIfUpdated(userEntity.getBeneficiary()::getGdprComunicazione, userEntity.getBeneficiary()::setGdprComunicazione, userReq.getGdprComunicazione()); - setIfUpdated(userEntity.getBeneficiary()::getGdprElaborazione, userEntity.getBeneficiary()::setGdprElaborazione, userReq.getGdprElaborazione()); - setIfUpdated(userEntity.getBeneficiary()::getGdprMateriale, userEntity.getBeneficiary()::setGdprMateriale, userReq.getGdprMateriale()); - setIfUpdated(userEntity.getBeneficiary()::getMarketing, userEntity.getBeneficiary()::setMarketing, userReq.getMarketing()); + setIfUpdated(userEntity.getBeneficiary()::getMarketing, userEntity.getBeneficiary()::setMarketing, userReq.getMarketing()); setIfUpdated(userEntity.getBeneficiary()::getOffers, userEntity.getBeneficiary()::setOffers, userReq.getOffers()); setIfUpdated(userEntity.getBeneficiary()::getThirdParty, userEntity.getBeneficiary()::setThirdParty, userReq.getThirdParty()); if (userReq.getRoleId() != null) { RoleEntity roleEntity = roleDao.validateRole(userReq.getRoleId()); setIfUpdated(userEntity::getRoleEntity, userEntity::setRoleEntity, roleEntity); } + setIfUpdated(userEntity.getBeneficiary()::getEmailPec, userEntity.getBeneficiary()::setEmailPec, userReq.getEmailPec()); userEntity = userRepository.save(userEntity); log.info("User updated with ID: {}", userEntity.getId()); return convertUserEntityToUserResponse(userEntity); @@ -234,15 +229,12 @@ public class UserDao { userResponseBean.setCountry(userEntity.getBeneficiary().getCountry()); userResponseBean.setCodiceFiscale(userEntity.getBeneficiary().getCodiceFiscale()); userResponseBean.setDateOfBirth(userEntity.getBeneficiary().getDateOfBirth()); - userResponseBean.setGdprRead(userEntity.getBeneficiary().getGdprRead()); - userResponseBean.setGdprComunicazione(userEntity.getBeneficiary().getGdprComunicazione()); - userResponseBean.setGdprElaborazione(userEntity.getBeneficiary().getGdprElaborazione()); - userResponseBean.setGdprMateriale(userEntity.getBeneficiary().getGdprMateriale()); userResponseBean.setPrivacy(userEntity.getBeneficiary().getPrivacy()); userResponseBean.setTerms(userEntity.getBeneficiary().getTerms()); userResponseBean.setOffers(userEntity.getBeneficiary().getOffers()); userResponseBean.setMarketing(userEntity.getBeneficiary().getMarketing()); userResponseBean.setThirdParty(userEntity.getBeneficiary().getThirdParty()); + userResponseBean.setEmailPec(userEntity.getBeneficiary().getEmailPec()); } return userResponseBean; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java index 9ea91cb8..bae88c90 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java @@ -50,9 +50,6 @@ public class BeneficiaryEntity extends BaseEntity { @Column(name = "TERMS") private Boolean terms; - @Column(name = "GDPR_READ") - private Boolean gdprRead; - @Column(name = "MARKETING") private Boolean marketing; @@ -62,12 +59,6 @@ public class BeneficiaryEntity extends BaseEntity { @Column(name = "THIRD_PARTY") private Boolean thirdParty; - @Column(name = "GDPR_MATERIALE") - private Boolean gdprMateriale; - - @Column(name = "GDPR_ELABORAZIONE") - private Boolean gdprElaborazione; - - @Column(name = "GDPR_COMUNICAZIONE") - private Boolean gdprComunicazione; + @Column(name = "EMAIL_PEC") + private String emailPec; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java index 347e4db1..c35a8cf0 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java @@ -50,4 +50,10 @@ public class CompanyEntity extends BaseEntity{ @Column(name = "ANNUAL_REVENUE") private BigDecimal annualRevenue; + + @Column(name = "CONTACT_NAME") + private String contactName; + + @Column(name = "CONTACT_EMAIL") + private String contactEmail; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java index bfd6829d..cc90380b 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java @@ -20,5 +20,6 @@ public class CompanyRequest { private String email; private String numberOfEmployees; private BigDecimal annualRevenue; - + private String contactName; + private String contactEmail; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java index 1b4ae81b..ff267f33 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java @@ -24,7 +24,6 @@ public class UpdateUserReq { private Boolean marketing; private Boolean offers; private Boolean thirdParty; - private Boolean gdprMateriale; - private Boolean gdprElaborazione; - private Boolean gdprComunicazione; + + private String emailPec; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java index 68d9fdc8..14111818 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java @@ -34,13 +34,9 @@ public class UserReq { private Boolean privacy; private Boolean terms; - private Boolean gdprRead; - private Boolean marketing; private Boolean offers; private Boolean thirdParty; - private Boolean gdprMateriale; - private Boolean gdprElaborazione; - private Boolean gdprComunicazione; + private String emailPec; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java index 254d05a0..3d414414 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java @@ -21,5 +21,6 @@ public class CompanyResponse extends BaseBean{ private String email; private String numberOfEmployees; private BigDecimal annualRevenue; - + private String contactName; + private String contactEmail; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java index d9cf63e9..39fdfb63 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java @@ -41,6 +41,18 @@ public class LoginResponse { private LocalDateTime dateOfBirth; + private Boolean privacy; + + private Boolean terms; + + private Boolean marketing; + + private Boolean offers; + + private Boolean thirdParty; + + private String emailPec; + private LocalDateTime createdDate; private LocalDateTime updatedDate; diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java index 056a8677..b0a5ef38 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java @@ -42,13 +42,9 @@ public class UserResponseBean extends BaseBean { private Boolean privacy; private Boolean terms; - private Boolean gdprRead; - private Boolean marketing; private Boolean offers; private Boolean thirdParty; - private Boolean gdprMateriale; - private Boolean gdprElaborazione; - private Boolean gdprComunicazione; + private String emailPec; } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java index 03ce8b1c..1227b0e0 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -125,6 +125,12 @@ public class AuthenticationService { loginResponse.setCity(user.getBeneficiary().getCity()); loginResponse.setCodiceFiscale(user.getBeneficiary().getCodiceFiscale()); loginResponse.setDateOfBirth(user.getBeneficiary().getDateOfBirth()); + loginResponse.setPrivacy(user.getBeneficiary().getPrivacy()); + loginResponse.setMarketing(user.getBeneficiary().getMarketing()); + loginResponse.setOffers(user.getBeneficiary().getOffers()); + loginResponse.setTerms(user.getBeneficiary().getTerms()); + loginResponse.setThirdParty(user.getBeneficiary().getThirdParty()); + loginResponse.setEmailPec(user.getBeneficiary().getEmailPec()); } return loginResponse; diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index cdad0a33..ad3056c5 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -887,15 +887,15 @@ - - - - - - + + + + + + From 2f13e0c9d7a4c15298bd28fad571708ca09cc2d2 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 8 Oct 2024 19:12:22 +0530 Subject: [PATCH 18/50] updated changeset --- .../resources/db/changelog/db.changelog-1.0.0.xml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index e0839786..b0842eff 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -881,18 +881,15 @@ - - - - - - + + - + + From c64316c514be29a7ccfae470e842272130a7f4d7 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 8 Oct 2024 21:34:11 +0530 Subject: [PATCH 19/50] Done ticket GEPAFINBE-32 --- pom.xml | 8 +- .../constants/GepafinConstant.java | 12 + .../tendermanagement/dao/CompanyDao.java | 32 ++- .../tendermanagement/dao/DelegationDao.java | 240 ++++++++++++++++++ .../tendermanagement/dao/DocumentDao.java | 8 +- .../entities/UserCompanyDelegationEntity.java | 31 +++ .../entities/UserWithCompanyEntity.java | 3 + .../UserCompanyDelegationStatusEnum.java | 18 ++ .../request/CompanyDelegationRequest.java | 13 + .../model/request/CompanyRequest.java | 1 + .../response/CompanyDelegationResponse.java | 15 ++ .../model/response/CompanyResponse.java | 1 + .../repositories/DocumentRepository.java | 2 + .../UserCompanyDelegationRepository.java | 10 + .../service/AmazonS3Service.java | 6 +- .../service/CompanyService.java | 11 + .../service/impl/AmazonS3ServiceImpl.java | 22 +- .../service/impl/CompanyServiceImpl.java | 30 ++- .../tendermanagement/util/DateTimeUtil.java | 14 +- .../gepafin/tendermanagement/util/Utils.java | 6 + .../tendermanagement/util/Validator.java | 16 +- .../web/rest/api/CompanyApi.java | 40 ++- .../rest/api/impl/CompanyApiController.java | 35 +++ src/main/resources/application.properties | 5 +- .../db/changelog/db.changelog-1.0.0.xml | 40 +++ src/main/resources/message_en.properties | 11 + src/main/resources/message_it.properties | 11 + 27 files changed, 604 insertions(+), 37 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/UserCompanyDelegationEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/enums/UserCompanyDelegationStatusEnum.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/CompanyDelegationRequest.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/CompanyDelegationResponse.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java diff --git a/pom.xml b/pom.xml index a2a1e712..b0a632d8 100644 --- a/pom.xml +++ b/pom.xml @@ -94,7 +94,7 @@ commons-io commons-io - 2.11.0 + 2.17.0 @@ -173,6 +173,12 @@ 4.1.3 + + org.apache.poi + poi-ooxml + 5.3.0 + + org.apache.santuario xmlsec diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 3ebf7e5f..5caf97bc 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -179,4 +179,16 @@ public class GepafinConstant { public static final String UNAUTHORIZED = "UNAUTHORIZED"; public static final String COMPANY_ID_MANDATORY = "company.id.mandatory"; public static final String USER_ALREADY_CONNECTED_TO_COMPANY = "user.already.connected.to.company"; + public static final String YYYY_MM_DD_DASH = "yyyy-MM-dd"; + public static final String YYYY_MM_DD_SLASH = "yyyy/MM/dd"; + public static final String DELEGATION_TEMPLATE = "DELEGATION_TEMPLATE"; + public static final String VALIDATION_ERROR_MISSING_FIRSTNAME = "validation.error.missing.firstName"; + public static final String VALIDATION_ERROR_MISSING_LASTNAME = "validation.error.missing.lastName"; + public static final String VALIDATION_ERROR_MISSING_CODICEFISCALE = "validation.error.missing.codiceFiscale"; + public static final String DELEGATION_FILE_UPLOAD_SUCCESS = "delegation.file.upload.success"; + public static final String DELEGATION_FETCH_SUCCESS = "delegation.fetch.success"; + public static final String DELEGATION_TEMPLATE_GENERATION_ERROR = "delegation.template.generation.error"; + public static final String VALIDATION_ERROR_FILE_EMPTY = "validation.error.file.empty"; + public static final String VALIDATION_ERROR_FILE_INVALIDTYPE = "validation.error.file.invalidType"; + public static final String UPLOAD_ERROR_S3 = "upload.error.s3"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java index 219b1579..089c210b 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java @@ -33,24 +33,26 @@ public class CompanyDao { @Autowired private UserWithCompanyRepository userWithCompanyRepository; + public CompanyResponse createCompany(UserEntity userEntity, CompanyRequest companyRequest) { CompanyEntity existingCompany = companyRepository.findByVatNumber(companyRequest.getVatNumber()); + UserWithCompanyEntity userWithCompanyEntity = null; if (existingCompany != null) { UserWithCompanyEntity existingRelation = userWithCompanyRepository.findByUserIdAndCompanyId(userEntity.getId(), existingCompany.getId()) .orElse(null); if (existingRelation == null) { - createUserWithCompanyRelation(userEntity, existingCompany); + userWithCompanyEntity = createUserWithCompanyRelation(userEntity, existingCompany, companyRequest.getIsLegalRepresentant()); } else { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.USER_ALREADY_CONNECTED_TO_COMPANY)); } - return convertCompanyEntityToCompanyResponse(existingCompany); + return convertCompanyEntityToCompanyResponse(existingCompany, userWithCompanyEntity); } else { validateCompany(companyRequest); CompanyEntity companyEntity = convertCompanyRequestToCompanyEntity(companyRequest); companyRepository.save(companyEntity); - createUserWithCompanyRelation(userEntity, companyEntity); - return convertCompanyEntityToCompanyResponse(companyEntity); + userWithCompanyEntity = createUserWithCompanyRelation(userEntity, companyEntity, companyRequest.getIsLegalRepresentant()); + return convertCompanyEntityToCompanyResponse(companyEntity, userWithCompanyEntity); } } @@ -72,13 +74,14 @@ public class CompanyDao { } } - private UserWithCompanyEntity createUserWithCompanyRelation(UserEntity userEntity, CompanyEntity companyEntity) { + private UserWithCompanyEntity createUserWithCompanyRelation(UserEntity userEntity, CompanyEntity companyEntity, Boolean isLegalRepresentant) { UserWithCompanyEntity userWithCompanyEntity = new UserWithCompanyEntity(); if (userEntity.getBeneficiary() != null) { userWithCompanyEntity.setBeneficiaryId(userEntity.getBeneficiary().getId()); } userWithCompanyEntity.setCompanyId(companyEntity.getId()); userWithCompanyEntity.setUserId(userEntity.getId()); + userWithCompanyEntity.setIsLegalRepresentant(isLegalRepresentant); return userWithCompanyRepository.save(userWithCompanyEntity); } @@ -100,7 +103,7 @@ public class CompanyDao { return entity; } - private CompanyResponse convertCompanyEntityToCompanyResponse(CompanyEntity entity) { + private CompanyResponse convertCompanyEntityToCompanyResponse(CompanyEntity entity, UserWithCompanyEntity userWithCompanyEntity) { CompanyResponse response = new CompanyResponse(); response.setId(entity.getId()); response.setCompanyName(entity.getCompanyName()); @@ -116,6 +119,9 @@ public class CompanyDao { response.setEmail(entity.getEmail()); response.setNumberOfEmployees(entity.getNumberOfEmployees()); response.setAnnualRevenue(entity.getAnnualRevenue()); + if(userWithCompanyEntity!=null) { + response.setIsLegalRepresentant(userWithCompanyEntity.getIsLegalRepresentant()); + } response.setCreatedDate(entity.getCreatedDate()); response.setUpdatedDate(entity.getUpdatedDate()); return response; @@ -142,7 +148,11 @@ public class CompanyDao { Utils.setIfUpdated(companyEntity::getAnnualRevenue, companyEntity::setAnnualRevenue, companyRequest.getAnnualRevenue()); companyRepository.save(companyEntity); - return convertCompanyEntityToCompanyResponse(companyEntity); + UserWithCompanyEntity userWithCompanyEntity = userWithCompanyRepository.findByUserIdAndCompanyId(userEntity.getId(), companyId).orElse(null); + Utils.setIfUpdated(userWithCompanyEntity::getIsLegalRepresentant, userWithCompanyEntity::setIsLegalRepresentant, + companyRequest.getIsLegalRepresentant()); + userWithCompanyRepository.save(userWithCompanyEntity); + return convertCompanyEntityToCompanyResponse(companyEntity, userWithCompanyEntity); } public CompanyEntity validateCompany(Long companyId) { @@ -151,7 +161,8 @@ public class CompanyDao { } public CompanyResponse getCompany(UserEntity userEntity, Long companyId) { - return convertCompanyEntityToCompanyResponse(validateCompany(companyId)); + UserWithCompanyEntity userWithCompanyEntity = userWithCompanyRepository.findByUserIdAndCompanyId(userEntity.getId(), companyId).orElse(null); + return convertCompanyEntityToCompanyResponse(validateCompany(companyId), userWithCompanyEntity); } public void deleteCompany(UserEntity userEntity, Long companyId) { @@ -164,7 +175,10 @@ public class CompanyDao { UserEntity userEntity = userService.validateUser(userId); List companyIds = userWithCompanyRepository.findCompanyIdByUserId(userEntity.getId()); List list = companyRepository.findByIdIn(companyIds); - return list.stream().map(this::convertCompanyEntityToCompanyResponse).toList(); + return list.stream().map(companyEntity->{ + UserWithCompanyEntity userWithCompanyEntity = userWithCompanyRepository.findByUserIdAndCompanyId(userEntity.getId(), companyEntity.getId()).orElse(null); + return convertCompanyEntityToCompanyResponse(companyEntity, userWithCompanyEntity); + }).toList(); } public UserWithCompanyEntity validateUserWithCompny(Long userId, Long companyId) { diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java new file mode 100644 index 00000000..4d4f2c03 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java @@ -0,0 +1,240 @@ +package net.gepafin.tendermanagement.dao; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.CompanyEntity; +import net.gepafin.tendermanagement.entities.DocumentEntity; +import net.gepafin.tendermanagement.entities.UserCompanyDelegationEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.enums.UserCompanyDelegationStatusEnum; +import net.gepafin.tendermanagement.model.request.CompanyDelegationRequest; +import net.gepafin.tendermanagement.model.response.CompanyDelegationResponse; +import net.gepafin.tendermanagement.model.response.UserResponseBean; +import net.gepafin.tendermanagement.repositories.DocumentRepository; +import net.gepafin.tendermanagement.repositories.UserCompanyDelegationRepository; +import net.gepafin.tendermanagement.service.AmazonS3Service; +import net.gepafin.tendermanagement.service.UserService; +import net.gepafin.tendermanagement.util.DateTimeUtil; +import net.gepafin.tendermanagement.util.Utils; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; + +@Component +public class DelegationDao { + + private static final String DEFAULT_PLACEHOLDER = "____________________"; + + @Autowired + private UserService userService; + + @Autowired + private CompanyDao companyDao; + + @Autowired + private AmazonS3Service amazonS3Service; + + @Autowired + private DocumentRepository documentRepository; + + @Value("${aws.s3.url.folder.delegation}") + private String s3Folder; + + @Autowired + private UserCompanyDelegationRepository userCompanyDelegationRepository; + + + public ByteArrayOutputStream generateDocument(Map placeholders, String templateName) { + try { + InputStream templateStream = amazonS3Service.getFile(s3Folder ,templateName); + XWPFDocument doc = loadTemplate(templateStream); + replacePlaceholders(doc, placeholders); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + doc.write(byteArrayOutputStream); + return byteArrayOutputStream; + } catch (Exception e) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.DELEGATION_TEMPLATE_GENERATION_ERROR)); + } + } + + public void replacePlaceholders(XWPFDocument doc, Map placeholders) { + doc.getParagraphs().forEach(paragraph -> { + placeholders.forEach((placeholder, value) -> { + if (paragraph.getText().contains(placeholder)) { + String updatedText = paragraph.getText().replace(placeholder, value); + paragraph.getRuns().forEach(run -> run.setText("", 0)); // Clear the existing text + paragraph.createRun().setText(updatedText); // Insert updated text + } + }); + }); + } + + public XWPFDocument loadTemplate(InputStream templateStream) throws IOException { + return new XWPFDocument(templateStream); + } + + public ByteArrayOutputStream downloadCompanyDelegation(UserEntity userEntity, Long companyId, CompanyDelegationRequest companyDelegationRequest) { + Map placeholders = getDefaultPlaceholders(); + UserResponseBean user = userService.getUserById(userEntity.getId()); + CompanyEntity companyEntity = companyDao.validateCompany(companyId); + updatePlaceholdersForDelegation(user, companyEntity, placeholders, companyDelegationRequest); + DocumentEntity documentEntity = documentRepository.findBySource(GepafinConstant.DELEGATION_TEMPLATE).get(0); + return generateDocument(placeholders, documentEntity.getFileName()); + } + + private Map updatePlaceholdersForDelegation(UserResponseBean user, CompanyEntity companyEntity, + Map placeholders, CompanyDelegationRequest companyDelegationRequest) { + validateMandatoryFields(companyDelegationRequest); + addIfNotEmpty(placeholders, "{{company_first_name}}", companyDelegationRequest.getFirstName()); + addIfNotEmpty(placeholders, "{{company_last_name}}", companyDelegationRequest.getLastName()); + addIfNotEmpty(placeholders, "{{company_codice_fiscale}}", companyDelegationRequest.getCodiceFiscale()); + addIfNotEmpty(placeholders, "{{company_name}}", companyEntity.getCompanyName()); + addIfNotEmpty(placeholders, "{{company_city}}", companyEntity.getCity()); + addIfNotEmpty(placeholders, "{{company_address}}", companyEntity.getAddress()); + addIfNotEmpty(placeholders, "{{company_province}}", companyEntity.getProvince()); + addIfNotEmpty(placeholders, "{{company_cap}}", companyEntity.getCap()); + addIfNotEmpty(placeholders, "{{company_vat_number}}", companyEntity.getVatNumber()); + + addIfNotEmpty(placeholders, "{{user_first_name}}", user.getFirstName()); + addIfNotEmpty(placeholders, "{{user_last_name}}", user.getLastName()); + addIfNotNull(placeholders, "{{user_date_of_birth}}", user.getDateOfBirth(), + date -> DateTimeUtil.formatLocalDateTime(date, GepafinConstant.YYYY_MM_DD_SLASH)); + addIfNotEmpty(placeholders, "{{user_codice_fiscale}}", user.getCodiceFiscale()); + + return placeholders; + } + + private Map getDefaultPlaceholders() { + Map placeholders = new HashMap<>(); + placeholders.put("{{company_first_name}}", ""); + placeholders.put("{{company_last_name}}", ""); + placeholders.put("{{company_codice_fiscale}}", ""); + placeholders.put("{{company_name}}", ""); + placeholders.put("{{company_city}}", DEFAULT_PLACEHOLDER); + placeholders.put("{{company_address}}", DEFAULT_PLACEHOLDER); + placeholders.put("{{company_province}}", DEFAULT_PLACEHOLDER); + placeholders.put("{{company_cap}}", DEFAULT_PLACEHOLDER); + placeholders.put("{{company_vat_number}}", ""); + + placeholders.put("{{user_first_name}}", ""); + placeholders.put("{{user_last_name}}", ""); + placeholders.put("{{user_date_of_birth}}", DEFAULT_PLACEHOLDER); + placeholders.put("{{user_codice_fiscale}}", ""); + return placeholders; + } + + private void validateMandatoryFields(CompanyDelegationRequest companyDelegationRequest) { + if (StringUtils.isAllEmpty(companyDelegationRequest.getFirstName())) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.VALIDATION_ERROR_MISSING_FIRSTNAME)); + } + if (StringUtils.isAllEmpty(companyDelegationRequest.getLastName())) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.VALIDATION_ERROR_MISSING_LASTNAME)); + } + if (StringUtils.isAllEmpty(companyDelegationRequest.getCodiceFiscale())) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.VALIDATION_ERROR_MISSING_CODICEFISCALE)); + } + } + + private void addIfNotEmpty(Map placeholders, String key, String value) { + if (Boolean.FALSE.equals(StringUtils.isAllEmpty(value))) { + placeholders.put(key, value); + } + } + + private void addIfNotNull(Map placeholders, String key, T value, Function formatter) { + if (value != null) { + placeholders.put(key, formatter.apply(value)); + } + } + + + public CompanyDelegationResponse uploadCompanyDelegation(UserEntity userEntity, Long companyId, MultipartFile file) { + companyDao.validateCompany(companyId); + validateFileType(file); + UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository + .findByUserIdAndCompanyIdAndStatus(userEntity.getId(), companyId, + UserCompanyDelegationStatusEnum.ACTIVE.getValue()); + if (userCompanyDelegationEntity != null) { + userCompanyDelegationEntity.setStatus(UserCompanyDelegationStatusEnum.INACTIVE.getValue()); + userCompanyDelegationRepository.save(userCompanyDelegationEntity); + } + UploadFileOnAmazonS3 uploadFileOnAmazonS3 = uploadFileOnAmazonS3(file); + userCompanyDelegationEntity = new UserCompanyDelegationEntity(); + userCompanyDelegationEntity.setCompanyId(companyId); + userCompanyDelegationEntity.setUserId(userEntity.getId()); + if (userEntity.getBeneficiary() != null) { + userCompanyDelegationEntity.setBeneficiaryId(userEntity.getBeneficiary().getId()); + } + userCompanyDelegationEntity.setStatus(UserCompanyDelegationStatusEnum.ACTIVE.getValue()); + userCompanyDelegationEntity.setFileName(uploadFileOnAmazonS3.fileName()); + userCompanyDelegationEntity.setFilePath(uploadFileOnAmazonS3.filepath()); + userCompanyDelegationRepository.save(userCompanyDelegationEntity); + return convertUserCompanyDelegationToCompanyDelegationResponse(userCompanyDelegationEntity); + } + + private CompanyDelegationResponse convertUserCompanyDelegationToCompanyDelegationResponse( + UserCompanyDelegationEntity userCompanyDelegationEntity) { + return Utils.convertSourceObjectToDestinationObject(userCompanyDelegationEntity, CompanyDelegationResponse.class); + } + + private UploadFileOnAmazonS3 uploadFileOnAmazonS3(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 = amazonS3Service.upload(fileName, s3Folder, file); + return new UploadFileOnAmazonS3(fileName, filepath); + } catch (Exception e) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3)); + } + + } + + private record UploadFileOnAmazonS3(String fileName, String filepath) { + } + + 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 CompanyDelegationResponse getCompanyDelegation(UserEntity userEntity, Long companyId) { + UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository + .findByUserIdAndCompanyIdAndStatus(userEntity.getId(), companyId, + UserCompanyDelegationStatusEnum.ACTIVE.getValue()); + if(userCompanyDelegationEntity == null) { + throw new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale("validation.error.file.invalidType")); + } + return convertUserCompanyDelegationToCompanyDelegationResponse(userCompanyDelegationEntity); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java index 374c741b..224a21ec 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java @@ -6,6 +6,7 @@ import java.util.stream.Collectors; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; @@ -40,6 +41,9 @@ public class DocumentDao { @Autowired private CallService callService; + + @Value("${aws.s3.url.folder}") + private String s3Folder; public List uploadFiles(List files, Long sourceId, DocumentSourceTypeEnum sourceType, DocumentTypeEnum fileType) { List documentEntities = new ArrayList<>(); @@ -81,7 +85,7 @@ public class DocumentDao { String fileName = StringUtils.cleanPath(file.getOriginalFilename()); String firstNameContain = fileName.substring(0, fileName.lastIndexOf('.')); fileName = (firstNameContain + "." + extension); - String filepath = amazonS3Service.upload(fileName, file); + String filepath = amazonS3Service.upload(fileName, s3Folder, file); uploadFileOnAmazonS3 result = new uploadFileOnAmazonS3(fileName, filepath); return result; } @@ -99,7 +103,7 @@ public class DocumentDao { private DocumentEntity deleteFileOnAmazonS3(String fileName) { try { - amazonS3Service.delete(fileName); + amazonS3Service.delete(s3Folder, fileName); } catch (Exception e) { } return null; diff --git a/src/main/java/net/gepafin/tendermanagement/entities/UserCompanyDelegationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/UserCompanyDelegationEntity.java new file mode 100644 index 00000000..d682747d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/UserCompanyDelegationEntity.java @@ -0,0 +1,31 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Data; + +@Data +@Entity +@Table(name = "user_company_delegation") +public class UserCompanyDelegationEntity extends BaseEntity{ + + @Column(name="USER_ID") + private Long userId; + + @Column(name="COMPANY_ID") + private Long companyId; + + @Column(name = "BENEFICIARY_ID") + private Long beneficiaryId; + + @Column(name = "FILE_NAME") + private String fileName; + + @Column(name = "FILE_PATH") + private String filePath; + + @Column(name="STATUS") + private String status; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java index fce47e66..f2d175e2 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java @@ -18,5 +18,8 @@ public class UserWithCompanyEntity extends BaseEntity{ @Column(name = "COMPANY_ID") Long companyId; + + @Column(name = "IS_LEGAL_REPRESENTANT") + private Boolean isLegalRepresentant; } diff --git a/src/main/java/net/gepafin/tendermanagement/enums/UserCompanyDelegationStatusEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/UserCompanyDelegationStatusEnum.java new file mode 100644 index 00000000..1f8f9725 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/UserCompanyDelegationStatusEnum.java @@ -0,0 +1,18 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum UserCompanyDelegationStatusEnum { + ACTIVE("ACTIVE"), INACTIVE("INACTIVE"); + + private String value; + + UserCompanyDelegationStatusEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CompanyDelegationRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/CompanyDelegationRequest.java new file mode 100644 index 00000000..b47ed579 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CompanyDelegationRequest.java @@ -0,0 +1,13 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class CompanyDelegationRequest { + + private String firstName; + + private String lastName; + + private String codiceFiscale; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java index bfd6829d..0d8a3185 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java @@ -20,5 +20,6 @@ public class CompanyRequest { private String email; private String numberOfEmployees; private BigDecimal annualRevenue; + private Boolean isLegalRepresentant; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CompanyDelegationResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyDelegationResponse.java new file mode 100644 index 00000000..7c23b3b8 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyDelegationResponse.java @@ -0,0 +1,15 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; +import net.gepafin.tendermanagement.entities.BaseEntity; +import net.gepafin.tendermanagement.enums.UserCompanyDelegationStatusEnum; + +@Data +public class CompanyDelegationResponse extends BaseEntity{ + private Long userId; + private Long companyId; + private Long beneficiaryId; + private String fileName; + private String filePath; + private UserCompanyDelegationStatusEnum status; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java index 254d05a0..92e79384 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java @@ -21,5 +21,6 @@ public class CompanyResponse extends BaseBean{ private String email; private String numberOfEmployees; private BigDecimal annualRevenue; + private Boolean isLegalRepresentant; } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java index 40361cd9..339efd13 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java @@ -19,5 +19,7 @@ public interface DocumentRepository extends JpaRepository Optional findByIdAndSourceIdAndIsDeletedFalse(Long id, Long sourceId); + List findBySource(String source); + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java new file mode 100644 index 00000000..1224dd70 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java @@ -0,0 +1,10 @@ +package net.gepafin.tendermanagement.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import net.gepafin.tendermanagement.entities.UserCompanyDelegationEntity; + +public interface UserCompanyDelegationRepository extends JpaRepository { + + UserCompanyDelegationEntity findByUserIdAndCompanyIdAndStatus(Long userId, Long companyId, String status); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java b/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java index 1ff3a7fd..ce34cd7d 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java +++ b/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java @@ -9,9 +9,9 @@ import java.io.InputStream; @Component public interface AmazonS3Service { - public String upload(String fileName, MultipartFile file) throws IOException; + public String upload(String fileName, String s3Folder, MultipartFile file) throws IOException; - public Boolean delete(String fileName); + public Boolean delete(String s3Folder, String fileName); - InputStream getFile(String filePath) throws IOException; + InputStream getFile(String s3Folder, String filePath) throws IOException; } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java index d0d7ce20..8382d37f 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java @@ -1,12 +1,17 @@ package net.gepafin.tendermanagement.service; +import java.io.ByteArrayOutputStream; import java.util.List; import java.util.Map; +import org.springframework.web.multipart.MultipartFile; + import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.entities.CompanyEntity; import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; +import net.gepafin.tendermanagement.model.request.CompanyDelegationRequest; import net.gepafin.tendermanagement.model.request.CompanyRequest; +import net.gepafin.tendermanagement.model.response.CompanyDelegationResponse; import net.gepafin.tendermanagement.model.response.CompanyResponse; public interface CompanyService { @@ -27,4 +32,10 @@ public interface CompanyService { UserWithCompanyEntity validateUserWithCompny(Long userId, Long companyId); + ByteArrayOutputStream downloadCompanyDelegation(HttpServletRequest request, Long companyId, CompanyDelegationRequest companyDelegationRequest); + + CompanyDelegationResponse uploadCompanyDelegation(HttpServletRequest request, Long companyId, MultipartFile file); + + CompanyDelegationResponse getCompanyDelegation(HttpServletRequest request, Long companyId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java index 3657d115..756e4360 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java @@ -29,18 +29,16 @@ public class AmazonS3ServiceImpl implements AmazonS3Service { @Value("${aws.s3.bucket.name}") private String bucketName; - @Value("${aws.s3.url.folder}") - private String s3Folder; - @Value("${aws.s3.url}") private String s3Url; @Override - public String upload(String fileName, + public String upload(String fileName, String s3Folder, MultipartFile file) throws IOException { - String path = bucketName+"/"+s3Folder; +// String path = bucketName+"/"+s3Folder; + String path = s3Folder +"/"+fileName; InputStream inputStream = file.getInputStream(); @@ -57,15 +55,15 @@ public class AmazonS3ServiceImpl implements AmazonS3Service { }); if(Boolean.FALSE.equals(isTestProfileActivated())) { - amazonS3.putObject(path, fileName, inputStream, objectMetadata); + amazonS3.putObject(bucketName, path, inputStream, objectMetadata); } return s3Url + s3Folder +"/"+ fileName; } @Override - public Boolean delete(String fileName) { - - final DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(bucketName, fileName); + public Boolean delete(String s3Folder, String fileName) { + String path = s3Folder +"/"+fileName; + final DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(bucketName, path); if(Boolean.FALSE.equals(isTestProfileActivated())) { amazonS3.deleteObject(deleteObjectRequest); } @@ -78,10 +76,10 @@ public class AmazonS3ServiceImpl implements AmazonS3Service { } @Override - public InputStream getFile(String filePath) throws IOException { + public InputStream getFile(String s3Folder, String filePath) throws IOException { try { - String path = bucketName+ s3Folder +"/"; - GetObjectRequest getObjectRequest = new GetObjectRequest(path, filePath); + String path = s3Folder +"/"+filePath; + GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, path); S3Object s3Object = amazonS3.getObject(getObjectRequest); return s3Object.getObjectContent(); } catch (AmazonS3Exception e) { diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java index 6dfec87a..d8c4f429 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java @@ -1,19 +1,24 @@ package net.gepafin.tendermanagement.service.impl; +import java.io.ByteArrayOutputStream; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.dao.CompanyDao; +import net.gepafin.tendermanagement.dao.DelegationDao; import net.gepafin.tendermanagement.dao.VatCheckDao; import net.gepafin.tendermanagement.entities.CompanyEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; +import net.gepafin.tendermanagement.model.request.CompanyDelegationRequest; import net.gepafin.tendermanagement.model.request.CompanyRequest; +import net.gepafin.tendermanagement.model.response.CompanyDelegationResponse; import net.gepafin.tendermanagement.model.response.CompanyResponse; import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.util.Validator; @@ -30,6 +35,9 @@ public class CompanyServiceImpl implements CompanyService { @Autowired private VatCheckDao vatCheckDao; + @Autowired + private DelegationDao delegationDao; + @Override @Transactional(rollbackFor = Exception.class) public CompanyResponse createCompany(HttpServletRequest request, CompanyRequest companyRequest) { @@ -61,7 +69,7 @@ public class CompanyServiceImpl implements CompanyService { @Override @Transactional(readOnly = true) public List getCompanyByUserId(HttpServletRequest request, Long userId) { - UserEntity userEntity = validator.validateUser(request); + validator.validateUser(request); return companyDao.getCompanyByUserId(userId); } @@ -80,4 +88,24 @@ public class CompanyServiceImpl implements CompanyService { return companyDao.validateUserWithCompny(userId, companyId); } + @Override + @Transactional(readOnly = true) + public ByteArrayOutputStream downloadCompanyDelegation(HttpServletRequest request, Long companyId, CompanyDelegationRequest companyDelegationRequest) { + UserEntity userEntity =validator.validateUser(request); + return delegationDao.downloadCompanyDelegation(userEntity, companyId, companyDelegationRequest); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public CompanyDelegationResponse uploadCompanyDelegation(HttpServletRequest request, Long companyId, MultipartFile file) { + UserEntity userEntity =validator.validateUser(request); + return delegationDao.uploadCompanyDelegation(userEntity, companyId, file); + } + + @Override + @Transactional(readOnly = true) + public CompanyDelegationResponse getCompanyDelegation(HttpServletRequest request, Long companyId) { + UserEntity userEntity =validator.validateUser(request); + return delegationDao.getCompanyDelegation(userEntity, companyId); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java index 63ed91a5..342ca2b2 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java +++ b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java @@ -1,13 +1,9 @@ package net.gepafin.tendermanagement.util; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.springframework.stereotype.Component; -import java.io.IOException; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; @@ -86,4 +82,14 @@ public class DateTimeUtil { // If all parsing attempts fail, throw an exception throw new CustomValidationException(Status.BAD_REQUEST,"Failed to parse time: " + timeString); } + + public static String formatLocalDateTime(LocalDateTime dateTime, String pattern) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); + return dateTime.format(formatter); + } + + public static LocalDateTime parseStringToLocalDateTime(String dateTimeStr, String pattern) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); + return LocalDateTime.parse(dateTimeStr, formatter); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index af0bc684..2238cc1b 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -227,4 +227,10 @@ public class Utils { Pattern pattern = Pattern.compile(EMAIL_REGEX); return pattern.matcher(email).matches(); } + + public static String randomKey(Integer range) { + String data = String.valueOf(System.currentTimeMillis()); + return data.substring(data.length() - range); + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/util/Validator.java b/src/main/java/net/gepafin/tendermanagement/util/Validator.java index 44ba62af..e123988a 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Validator.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Validator.java @@ -37,8 +37,7 @@ public class Validator { } public UserEntity validateUser(HttpServletRequest request) { - Map userInfo= tokenProvider.getUserInfoAndUserIdFromToken(request); - return userService.validateUser(Long.parseLong(userInfo.get("userId").toString())); + return userService.validateUser(getUserIdFromToken(request)); } public Boolean checkIsSuperAdmin() { @@ -86,5 +85,18 @@ public class Validator { } return false; } + + public UserEntity validateUserId(HttpServletRequest request, Long userId) { + UserEntity user = validateUser(request); + 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)); + } + return userService.validateUser(userId); + } + + private Long getUserIdFromToken(HttpServletRequest request) { + Map userInfo= tokenProvider.getUserInfoAndUserIdFromToken(request); + return Long.parseLong(userInfo.get("userId").toString()); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java index 53ff4102..7b908ee1 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java @@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -19,7 +20,9 @@ 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.model.request.CompanyDelegationRequest; import net.gepafin.tendermanagement.model.request.CompanyRequest; +import net.gepafin.tendermanagement.model.response.CompanyDelegationResponse; import net.gepafin.tendermanagement.model.response.CompanyResponse; import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; @@ -81,7 +84,7 @@ public interface CompanyApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @GetMapping(value = "/user/{userId}", produces = { "application/json" }) ResponseEntity>> getCompanyByUserId(HttpServletRequest request, - @Parameter(description = "The company id", required = true) @PathVariable("userId") Long userId); + @Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId); @Operation(summary = "Api to check vatNumber", responses = { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @@ -93,5 +96,40 @@ public interface CompanyApi { @GetMapping(value = "/vatNumber", produces = { "application/json" }) ResponseEntity>> checkVatNumber(HttpServletRequest request, @Parameter(description = "The vatNumber of company", required = true) @RequestParam("vatNumber") String vatNumber); + + @Operation(summary = "Api to download company delegation template", 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 = "{companyId}/delegation/download", produces = { "application/json" }) + ResponseEntity downloadCompanyDelegation(HttpServletRequest request, + @Parameter(description = "The company id", required = true) @PathVariable("companyId") Long companyId, + @Parameter(description = "Company delegation request object", required = true) @RequestBody CompanyDelegationRequest companyDelegationRequest); + + @Operation(summary = "Api to upload company delegation", 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 = "{companyId}/delegation/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + ResponseEntity> uploadCompanyDelegation(HttpServletRequest request, + @Parameter(description = "The company id", required = true) @PathVariable("companyId") Long companyId, + @Parameter(description = "The company delegation", required = true) @RequestParam("file") MultipartFile file); + + @Operation(summary = "Api to get company delegation", 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 = "{companyId}/delegation", produces = { "application/json" }) + ResponseEntity> getCompanyDelegation(HttpServletRequest request, + @Parameter(description = "The company id", required = true) @PathVariable("companyId") Long companyId); } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java index c4428f04..a3ab214c 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java @@ -1,20 +1,26 @@ package net.gepafin.tendermanagement.web.rest.api.impl; +import java.io.ByteArrayOutputStream; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.model.request.CompanyDelegationRequest; import net.gepafin.tendermanagement.model.request.CompanyRequest; +import net.gepafin.tendermanagement.model.response.CompanyDelegationResponse; import net.gepafin.tendermanagement.model.response.CompanyResponse; import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.service.CompanyService; @@ -86,4 +92,33 @@ public class CompanyApiController implements CompanyApi{ .body(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.CHECK_VATNUMBER_SUCCESS_MSG))); } + @Override + public ResponseEntity downloadCompanyDelegation(HttpServletRequest request, Long companyId, CompanyDelegationRequest companyDelegationRequest) { + log.info("download company delegation with companyId: {}", companyId); + ByteArrayOutputStream data = companyService.downloadCompanyDelegation(request, companyId, companyDelegationRequest); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + headers.setContentDispositionFormData("attachment", "delegation-template.docx"); + + return new ResponseEntity<>(data.toByteArray(), headers, HttpStatus.OK); + } + + @Override + public ResponseEntity> uploadCompanyDelegation(HttpServletRequest request, Long companyId, + MultipartFile file) { + log.info("upload company delegation with companyId: {}", companyId); + CompanyDelegationResponse companyDelegationResponse = companyService.uploadCompanyDelegation(request, companyId, file); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(companyDelegationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELEGATION_FILE_UPLOAD_SUCCESS))); + } + + @Override + public ResponseEntity> getCompanyDelegation(HttpServletRequest request, + Long companyId) { + + log.info("get company delegation with companyId: {}", companyId); + CompanyDelegationResponse companyDelegationResponse = companyService.getCompanyDelegation(request, companyId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(companyDelegationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELEGATION_FETCH_SUCCESS))); + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3ce9ed17..eb6606ff 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,8 +1,8 @@ spring.application.name=tendermanagement # Multipart Configuration -spring.servlet.multipart.max-file-size=50MB -spring.servlet.multipart.max-request-size=50MB +spring.servlet.multipart.max-file-size=15MB +spring.servlet.multipart.max-request-size=15MB spring.profiles.active=testing @@ -31,6 +31,7 @@ aws.s3.region=eu-west-1 aws.s3.bucket.name=mementoresources aws.s3.url = https://mementoresources.s3.eu-west-1.amazonaws.com/ aws.s3.url.folder=gepafin +aws.s3.url.folder.delegation=gepafin/delegation # JWT configuration # Ensure these values match your expectations security.authentication.jwt.secret=my-secret-token-to-change-in-prod-environment-your-super-secure-randomly-generated-key diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 1575f0bb..56c4b841 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -841,5 +841,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index d70c97f4..324d5b79 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -206,3 +206,14 @@ vatnumber.already.exists=VatNumber already exists. invalid.email=Invalid email. company.id.mandatory=Company id is mandatory. user.already.connected.to.company=The user is already connected to this company. +validation.error.missing.firstName=First name is required. +validation.error.missing.lastName=Last name is required. +validation.error.missing.codiceFiscale=Codice Fiscale is required. +delegation.file.upload.success=Delegation file uploaded successfully. +delegation.fetch.success=Delegation fetched successfully. +delegation.template.generation.error=Something went wrong while generating the delegation template. +validation.error.file.empty=The uploaded file is empty. +validation.error.file.invalidType=Only .p7m files are accepted. +upload.error.s3=Failed to upload the file to S3. + + diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 00e8dcfc..e22bc3b4 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -199,3 +199,14 @@ vatnumber.already.exists=Il numero di partita IVA esiste gi invalid.email=Email non valida. company.id.mandatory=L'ID dell'azienda obbligatorio. user.already.connected.to.company=L'utente gi collegato a questa azienda. +validation.error.missing.firstName=Il nome obbligatorio. +validation.error.missing.lastName=Il cognome obbligatorio. +validation.error.missing.codiceFiscale=Il Codice Fiscale obbligatorio. +delegation.file.upload.success=File di delega caricato con successo. +delegation.fetch.success=Delega recuperata con successo. +delegation.template.generation.error=Si verificato un errore durante la generazione del modello di delega. +validation.error.file.empty=Il file caricato vuoto. +validation.error.file.invalidType=Sono accettati solo file .p7m. +upload.error.s3=Impossibile caricare il file su S3. + + From ed1e20664a5b79bdd3c7a2f9f555a1698d7d3291 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 8 Oct 2024 20:03:48 -0700 Subject: [PATCH 20/50] Updated config --- .../net/gepafin/tendermanagement/config/SamlFailureHandler.java | 2 +- .../net/gepafin/tendermanagement/config/SecurityConfig.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java index 81df79e3..171b7e12 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java @@ -15,7 +15,7 @@ import jakarta.servlet.http.HttpServletResponse; @Component public class SamlFailureHandler implements AuthenticationFailureHandler { - private final Logger logger = LoggerFactory.getLogger(SamlSuccessHandler.class); + private final Logger logger = LoggerFactory.getLogger(SamlFailureHandler.class); @Value("${fe.base.url}") private String feBaseUrl; diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 91424195..ec38b268 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -107,7 +107,7 @@ public class SecurityConfig { .requestMatchers("/swagger-ui/**").permitAll() // Swagger docs .requestMatchers("/v1/api-docs/**").permitAll() // API docs .anyRequest().authenticated()) - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)) .addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class) // Add SAML2 login configuration (for BENEFICIARI) From 293b0f06f77f2c9b0021989e89f973b0f0a15e52 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 8 Oct 2024 20:19:31 -0700 Subject: [PATCH 21/50] Temp commented code --- .../tendermanagement/service/impl/AuthenticationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java index 1227b0e0..4153c2f2 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -159,7 +159,7 @@ public class AuthenticationService { UserEntity userEntity = userRepository.findByBeneficiaryCodiceFiscale(cf) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); - samlResponseLogRepository.delete(samlResponseLogEntity); + //samlResponseLogRepository.delete(samlResponseLogEntity); return getJWTTokenBean(userEntity, Boolean.TRUE); } From e8fc901b3fefedf04f59cb46c804bd0484d62045 Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 9 Oct 2024 12:52:34 +0530 Subject: [PATCH 22/50] added delete API for delegation --- .../constants/GepafinConstant.java | 3 +++ .../tendermanagement/dao/CompanyDao.java | 11 +++++++--- .../tendermanagement/dao/DelegationDao.java | 20 +++++++++++++++++-- .../service/CompanyService.java | 2 ++ .../service/impl/CompanyServiceImpl.java | 6 ++++++ .../web/rest/api/CompanyApi.java | 11 ++++++++++ .../rest/api/impl/CompanyApiController.java | 11 ++++++++-- src/main/resources/message_en.properties | 5 +++++ src/main/resources/message_it.properties | 5 +++++ 9 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 3375765a..f67a2ee2 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -195,5 +195,8 @@ public class GepafinConstant { public static final String CALL_NOT_STARTED_YET = "call.not.started.yet"; public static final String CALL_ALREADY_ENDED = "call.already.ended"; public static final String APPLICATION_STATUS_UPDATED_SUCCESSFULLY = "application.status.updated.successfully"; + public static final String DELEGATION_NOT_FOUND = "delegation.not.found"; + public static final String USER_COMPANY_RELATION_NOT_FOUND = "user.company.relation.not.found"; + public static final String DELEGATION_DELETE_SUCCESS = "delegation.delete.success"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java index 2e148665..728990b5 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java @@ -156,7 +156,7 @@ public class CompanyDao { setIfUpdated(companyEntity::getContactName,companyEntity::setContactName,companyRequest.getContactName()); setIfUpdated(companyEntity::getContactEmail,companyEntity::setContactEmail,companyRequest.getContactEmail()); companyRepository.save(companyEntity); - UserWithCompanyEntity userWithCompanyEntity = userWithCompanyRepository.findByUserIdAndCompanyId(userEntity.getId(), companyId).orElse(null); + UserWithCompanyEntity userWithCompanyEntity = getUserWithCompany(userEntity.getId(), companyId); Utils.setIfUpdated(userWithCompanyEntity::getIsLegalRepresentant, userWithCompanyEntity::setIsLegalRepresentant, companyRequest.getIsLegalRepresentant()); userWithCompanyRepository.save(userWithCompanyEntity); @@ -169,7 +169,7 @@ public class CompanyDao { } public CompanyResponse getCompany(UserEntity userEntity, Long companyId) { - UserWithCompanyEntity userWithCompanyEntity = userWithCompanyRepository.findByUserIdAndCompanyId(userEntity.getId(), companyId).orElse(null); + UserWithCompanyEntity userWithCompanyEntity = getUserWithCompany(userEntity.getId(), companyId); return convertCompanyEntityToCompanyResponse(validateCompany(companyId), userWithCompanyEntity); } @@ -184,7 +184,7 @@ public class CompanyDao { List companyIds = userWithCompanyRepository.findCompanyIdByUserId(userEntity.getId()); List list = companyRepository.findByIdIn(companyIds); return list.stream().map(companyEntity->{ - UserWithCompanyEntity userWithCompanyEntity = userWithCompanyRepository.findByUserIdAndCompanyId(userEntity.getId(), companyEntity.getId()).orElse(null); + UserWithCompanyEntity userWithCompanyEntity = getUserWithCompany(userEntity.getId(), companyEntity.getId()); return convertCompanyEntityToCompanyResponse(companyEntity, userWithCompanyEntity); }).toList(); } @@ -193,5 +193,10 @@ public class CompanyDao { return userWithCompanyRepository.findByUserIdAndCompanyId(userId, companyId).orElseThrow(() -> new CustomValidationException(Status.UNAUTHORIZED, Translator.toLocale(GepafinConstant.UNAUTHORIZED))); } + + public UserWithCompanyEntity getUserWithCompany(Long userId, Long compnayId) { + return userWithCompanyRepository.findByUserIdAndCompanyId(userId, compnayId).orElseThrow( + () -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_COMPANY_RELATION_NOT_FOUND))); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java index 4d4f2c03..525c657a 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java @@ -93,6 +93,7 @@ public class DelegationDao { Map placeholders = getDefaultPlaceholders(); UserResponseBean user = userService.getUserById(userEntity.getId()); CompanyEntity companyEntity = companyDao.validateCompany(companyId); + companyDao.getUserWithCompany(userEntity.getId(), companyId); updatePlaceholdersForDelegation(user, companyEntity, placeholders, companyDelegationRequest); DocumentEntity documentEntity = documentRepository.findBySource(GepafinConstant.DELEGATION_TEMPLATE).get(0); return generateDocument(placeholders, documentEntity.getFileName()); @@ -165,10 +166,11 @@ public class DelegationDao { placeholders.put(key, formatter.apply(value)); } } - + public CompanyDelegationResponse uploadCompanyDelegation(UserEntity userEntity, Long companyId, MultipartFile file) { companyDao.validateCompany(companyId); + companyDao.getUserWithCompany(userEntity.getId(), companyId); validateFileType(file); UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository .findByUserIdAndCompanyIdAndStatus(userEntity.getId(), companyId, @@ -231,10 +233,24 @@ public class DelegationDao { UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository .findByUserIdAndCompanyIdAndStatus(userEntity.getId(), companyId, UserCompanyDelegationStatusEnum.ACTIVE.getValue()); + companyDao.getUserWithCompany(userEntity.getId(), companyId); if(userCompanyDelegationEntity == null) { throw new ResourceNotFoundException(Status.NOT_FOUND, - Translator.toLocale("validation.error.file.invalidType")); + Translator.toLocale(GepafinConstant.DELEGATION_NOT_FOUND)); } return convertUserCompanyDelegationToCompanyDelegationResponse(userCompanyDelegationEntity); } + + public void deleteCompanyDelegation(UserEntity userEntity, Long companyId) { + UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository + .findByUserIdAndCompanyIdAndStatus(userEntity.getId(), companyId, + UserCompanyDelegationStatusEnum.ACTIVE.getValue()); + companyDao.getUserWithCompany(userEntity.getId(), companyId); + if(userCompanyDelegationEntity == null) { + throw new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.DELEGATION_NOT_FOUND)); + } + userCompanyDelegationEntity.setStatus(UserCompanyDelegationStatusEnum.INACTIVE.getValue()); + userCompanyDelegationRepository.save(userCompanyDelegationEntity); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java index 8382d37f..da05c544 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java @@ -38,4 +38,6 @@ public interface CompanyService { CompanyDelegationResponse getCompanyDelegation(HttpServletRequest request, Long companyId); + void deleteCompanyDelegation(HttpServletRequest request, Long companyId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java index d8c4f429..0e43265a 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java @@ -108,4 +108,10 @@ public class CompanyServiceImpl implements CompanyService { UserEntity userEntity =validator.validateUser(request); return delegationDao.getCompanyDelegation(userEntity, companyId); } + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteCompanyDelegation(HttpServletRequest request, Long companyId) { + UserEntity userEntity =validator.validateUser(request); + delegationDao.deleteCompanyDelegation(userEntity, companyId); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java index b4029444..4f996dab 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java @@ -131,5 +131,16 @@ public interface CompanyApi { @GetMapping(value = "{companyId}/delegation", produces = { "application/json" }) ResponseEntity> getCompanyDelegation(HttpServletRequest request, @Parameter(description = "The company id", required = true) @PathVariable("companyId") Long companyId); + + @Operation(summary = "Api to delete company delegation", 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 = "{companyId}/delegation", produces = { "application/json" }) + ResponseEntity> deleteCompanyDelegation(HttpServletRequest request, + @Parameter(description = "The company id", required = true) @PathVariable("companyId") Long companyId); } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java index a3ab214c..8de4b176 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java @@ -108,17 +108,24 @@ public class CompanyApiController implements CompanyApi{ MultipartFile file) { log.info("upload company delegation with companyId: {}", companyId); CompanyDelegationResponse companyDelegationResponse = companyService.uploadCompanyDelegation(request, companyId, file); - return ResponseEntity.status(HttpStatus.OK) + return ResponseEntity.status(HttpStatus.CREATED) .body(new Response<>(companyDelegationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELEGATION_FILE_UPLOAD_SUCCESS))); } @Override public ResponseEntity> getCompanyDelegation(HttpServletRequest request, Long companyId) { - log.info("get company delegation with companyId: {}", companyId); CompanyDelegationResponse companyDelegationResponse = companyService.getCompanyDelegation(request, companyId); return ResponseEntity.status(HttpStatus.OK) .body(new Response<>(companyDelegationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELEGATION_FETCH_SUCCESS))); } + @Override + public ResponseEntity> deleteCompanyDelegation(HttpServletRequest request, + Long companyId) { + log.info("delete company delegation with companyId: {}", companyId); + companyService.deleteCompanyDelegation(request, companyId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELEGATION_DELETE_SUCCESS))); + } } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 3be65f9f..84279127 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -220,3 +220,8 @@ call.not.started.yet = The call has not started yet. Please wait until the speci call.already.ended = The call has already ended. You cannot submit the application after the deadline. status.updated.successfully=Status updated successfully. application.status.updated.successfully = Application status updated successfully. +delegation.not.found=Delegation not found. +user.company.relation.not.found=User with the specified company relation not found. +delegation.delete.success=Delegation deleted successfully. + + diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index bd6a09f7..4dfec2b0 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -215,3 +215,8 @@ call.not.started.yet = La chiamata non � ancora iniziata. Attendere fino alla call.already.ended = La chiamata � gi� terminata. Non � possibile inviare l'applicazione dopo la scadenza. status.updated.successfully=Stato aggiornato con successo. application.status.updated.successfully = Stato dell'applicazione aggiornato con successo. +delegation.not.found=Delega non trovata. +user.company.relation.not.found=Relazione utente con l'azienda specificata non trovata. +delegation.delete.success=Delega eliminata con successo. + + From f5aae53ca1680db61de212befb5f1dba62dd21e3 Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 9 Oct 2024 12:38:05 -0700 Subject: [PATCH 23/50] Updated config --- .../net/gepafin/tendermanagement/config/SecurityConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index ec38b268..91424195 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -107,7 +107,7 @@ public class SecurityConfig { .requestMatchers("/swagger-ui/**").permitAll() // Swagger docs .requestMatchers("/v1/api-docs/**").permitAll() // API docs .anyRequest().authenticated()) - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class) // Add SAML2 login configuration (for BENEFICIARI) From fb71a70caa4b54823ef49de8e8940bd54fdab7cc Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 9 Oct 2024 12:56:01 -0700 Subject: [PATCH 24/50] Updated config --- .../config/SecurityConfig.java | 51 +++++++++++++------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 91424195..59132951 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -96,32 +96,53 @@ public class SecurityConfig { } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(auth -> auth - // Allow public access to the login endpoints + // Apply stateless session management globally + http.csrf(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(auth -> auth + // Public endpoints .requestMatchers("/v1/user/login").permitAll() // JWT-based login .requestMatchers("/v1/user").permitAll() // User registration .requestMatchers("/v1/user/sso/validate/existing-user/{token}").permitAll() .requestMatchers("/v1/user/sso/validate/new-user/{token}").permitAll() - .requestMatchers("/v1/saml/**").permitAll() // JWT-based login - .requestMatchers("/saml2/**").permitAll() // SAML login initiation .requestMatchers("/swagger-ui/**").permitAll() // Swagger docs .requestMatchers("/v1/api-docs/**").permitAll() // API docs - .anyRequest().authenticated()) - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class) - .addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class) - // Add SAML2 login configuration (for BENEFICIARI) - /* - * .saml2Login(saml -> saml.loginPage("/saml/login") // Entry point for SAML - * login .defaultSuccessUrl("/") // Redirect after successful SAML login ); - */ - .saml2Login(saml -> saml.defaultSuccessUrl("/").successHandler(samlSuccessHandler) - .failureHandler(samlFailureHandler)); + // SAML-related endpoints + .requestMatchers("/v1/saml/**", "/saml2/**").permitAll() + + // Other authenticated requests + .anyRequest().authenticated()) + + // Globally use stateless session management for most requests + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + + // SAML2 login configuration + .saml2Login(saml -> saml + .defaultSuccessUrl("/") + .successHandler(samlSuccessHandler) + .failureHandler(samlFailureHandler)); return http.build(); } + // Add another SecurityFilterChain for SAML requests with stateful session management + @Bean + public SecurityFilterChain samlSecurityFilterChain(HttpSecurity http) throws Exception { + // Apply stateful session management for SAML-related endpoints + http + .securityMatcher("/v1/saml/**", "/saml2/**") // Match SAML requests + .authorizeHttpRequests(auth -> auth + .requestMatchers("/v1/saml/**", "/saml2/**").permitAll() + .anyRequest().authenticated()) + + // Use stateful session management for SAML requests + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)); + + return http.build(); + } + + + @Bean public OpenAPI customOpenAPI() { return new OpenAPI() From ec987d93dd6531afaf61480ebff469a739e63f77 Mon Sep 17 00:00:00 2001 From: nisha Date: Wed, 9 Oct 2024 13:16:02 +0530 Subject: [PATCH 25/50] Done ticket GEPAFINBE-38 --- .../constants/GepafinConstant.java | 135 +++++++++--------- .../tendermanagement/dao/ApplicationDao.java | 31 ++++ .../tendermanagement/dao/FlowFormDao.java | 3 + .../entities/ApplicationEntity.java | 3 + .../entities/ProtocolEntity.java | 28 ++++ .../response/ApplicationGetResponseBean.java | 2 + .../model/response/ApplicationResponse.java | 2 + .../response/ApplicationResponseBean.java | 2 + .../response/NextOrPreviousFormResponse.java | 2 + .../repositories/ProtocolRepository.java | 13 ++ .../db/changelog/db.changelog-1.0.0.xml | 31 ++++ src/main/resources/message_en.properties | 1 + src/main/resources/message_it.properties | 1 + 13 files changed, 187 insertions(+), 67 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/ProtocolEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/ProtocolRepository.java diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 1a2bd78c..f1a8eb3c 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -24,7 +24,7 @@ public class GepafinConstant { public static final String GET_REGION_SUCCESS_MSG = "get.region.success"; public static final String DELETE_REGION_SUCCESS_MSG = "delete.region.success"; public static final String REGION_NOT_FOUND_MSG = "user.region.not.found"; - public static final String PASSWORD_DOESNT_MATCH ="password.doesnt.match"; + public static final String PASSWORD_DOESNT_MATCH = "password.doesnt.match"; public static final String USER_NOT_EXIST_MSG = "user.not.exist"; public static final String REGION_NOT_FOUND = "region.not.found"; public static final String USER_ID_NOT_NULL_MSG = "user.id.not.null"; @@ -36,13 +36,13 @@ public class GepafinConstant { public static final String LOOK_UP_DATA_NOT_VALID_MSG = "look.up.data.not.valid"; public static final String FILES_UPLOADED_MSG = "files.uploaded"; public static final String CALL_CREATED_SUCCESSFULLY_MSG = "call.created.successfully"; - public static final String FILE_DELETED_SUCCESSFULLY_MSG="file.deleted.successfully"; - public static final String DOCUMENT_NOT_FOUND="document.not.found"; - public static final String LOGIN_SUCCESS_MSG="login.successfully"; - public static final String PASSWORD_MIN_LEN ="pass.min.len.msg"; + public static final String FILE_DELETED_SUCCESSFULLY_MSG = "file.deleted.successfully"; + public static final String DOCUMENT_NOT_FOUND = "document.not.found"; + public static final String LOGIN_SUCCESS_MSG = "login.successfully"; + public static final String PASSWORD_MIN_LEN = "pass.min.len.msg"; public static final String EMAIL_ALREADY_EXISTS = "email.already.exists"; - public static final String DOCUMENT_ID_NOT_FOUND="document.id.not.found"; - public static final String INVALID_DATE_MSG = "call.invalid.date"; + public static final String DOCUMENT_ID_NOT_FOUND = "document.id.not.found"; + public static final String INVALID_DATE_MSG = "call.invalid.date"; public static final String FORM_NOT_FOUND = "form.not.found"; public static final String FORM_CREATED_SUCCESSFULLY = "form.created.successfully"; public static final String FORM_UPDATED_SUCCESSFULLY = "form.updated.suucessfully"; @@ -61,12 +61,12 @@ public class GepafinConstant { public static final String FORM_TEMPLATE_DELETED_SUCCESSFULLY = "form.template.deleted.successfully"; public static final String FORM_TEMPLATE_FETCHED_SUCCESSFULLY = "form.template.fetched.successfully"; public static final String REQUIRED_PARAMETER_NOT_FOUND_FOR_FORM_TEMPLATE = "required.parameter.not.found.for.form.template"; - public static final String FORM_NOT_FOUND_FOR_CALL_ID="form.not.found.for.call.id"; - public static final String STEP_1 = "STEP_1"; - public static final String STEP_2 = "STEP_2"; - public static final String VALIDATE_REQUEST = "VALIDATE_REQUEST"; - public static final String CALL_UPDATE_SUCCESSFULLY_MSG = "call.update.successfully"; - public static final String CALL_NOT_FOUND = "call.not.found"; + public static final String FORM_NOT_FOUND_FOR_CALL_ID = "form.not.found.for.call.id"; + public static final String STEP_1 = "STEP_1"; + public static final String STEP_2 = "STEP_2"; + public static final String VALIDATE_REQUEST = "VALIDATE_REQUEST"; + public static final String CALL_UPDATE_SUCCESSFULLY_MSG = "call.update.successfully"; + public static final String CALL_NOT_FOUND = "call.not.found"; public static final String CALL_FETCH_SUCCESS_MSG = "call.fetch.success"; public static final String EVALUATION_CRITERIA_NOT_FOUND = "evaluation.criteria.not.found"; @@ -74,7 +74,7 @@ public class GepafinConstant { public static final String EVALUATION_CRITERIA_FETCH_SUCCESSFULLY = "evaluation.criteria.fetch.successfully"; public static final String EVALUATION_CRITERIA_UPDATED_SUCCESSFULLY = "evaluation.criteria.updated.successfully"; public static final String EVALUATION_CRITERIA_DELETED_SUCCESSFULLY = "evaluation.criteria.deleted.successfully"; - public static final String SCORE_NOT_NULL_MSG="score.not.null"; + public static final String SCORE_NOT_NULL_MSG = "score.not.null"; public static final String FAQ_NOT_FOUND = "faq.not.found"; public static final String FAQ_CREATED_SUCCESSFULLY = "faq.created.successfully"; public static final String FAQ_FETCHED_SUCCESSFULLY = "faq.fetched.successfully"; @@ -102,41 +102,41 @@ public class GepafinConstant { public static final String INVALID_STATUS_CHANGE_FROM_DRAFT = "invalid.status.change.from.draft"; public static final String INVALID_STATUS_CHANGE_FROM_PUBLISH = "invalid.status.change.from.publish"; public static final String STATUS_CANNOT_BE_CHANGED = "status.cannot.be.changed"; - public static final String PUBLISHED_CALL_NOT_UPDATE = "published.call.not.update"; + public static final String PUBLISHED_CALL_NOT_UPDATE = "published.call.not.update"; public static final String INVALID_USER = "invalid_user"; - public static final String FLOW_CREATED_SUCCESSFULLY="flow.created.successfully"; - public static final String FLOW_FETCHED_SUCCESSFULLY="flow.fetched.successfully"; - public static final String FLOW_ALREADY_EXISTS="flow.already.exists"; - public static final String FLOW_REQUEST_NOT_PROPER="flow.request.not.complete"; + public static final String FLOW_CREATED_SUCCESSFULLY = "flow.created.successfully"; + public static final String FLOW_FETCHED_SUCCESSFULLY = "flow.fetched.successfully"; + public static final String FLOW_ALREADY_EXISTS = "flow.already.exists"; + public static final String FLOW_REQUEST_NOT_PROPER = "flow.request.not.complete"; public static final String APPLICATION_CREATED_SUCCESS_MSG = "application.created.success"; public static final String APPLICATION_UPDATED_SUCCESS_MSG = "application.updated.success"; public static final String DELETE_APPLICATION_SUCCESS_MSG = "application.deleted.success"; public static final String GET_APPLICATION_SUCCESS_MSG = "application.get.success"; public static final String APPLICATION_NOT_FOUND_MSG = "application.not.found"; - public static final String APPLICATION_FORM_FIELD_NOT_FOUND="application.form.field.not.found"; - public static final String FORM_ID_DOES_NOT_MACTHES="Form.not.matches.to.call.initial.form"; + public static final String APPLICATION_FORM_FIELD_NOT_FOUND = "application.form.field.not.found"; + public static final String FORM_ID_DOES_NOT_MACTHES = "Form.not.matches.to.call.initial.form"; public static final String VALIDATION_FIELD_REQUIRED = "validation.field.required"; public static final String VALIDATION_FIELD_MIN_LENGTH = "validation.field.min_length"; public static final String VALIDATION_FIELD_MAX_LENGTH = "validation.field.max_length"; public static final String VALIDATION_FIELD_PATTERN = "validation.field.pattern"; public static final String VALIDATION_FIELD_NOT_NULL = "validation.field.not_null"; public static final String VALIDATION_FIELD_NOT_EMPTY = "validation.field.not_empty"; - public static final String APPLICATION_ALREADY_EXISTS="application.already.exists"; - // public static final String NEXT_FORM_NOT_FOUND = "next.form.not.found"; - // public static final String PREVIOUS_FORM_NOT_FOUND = "previous.form.not.found"; - public static final String CURRENT_FORM_INCOMPLETE = "current.form.incomplete"; + public static final String APPLICATION_ALREADY_EXISTS = "application.already.exists"; + // public static final String NEXT_FORM_NOT_FOUND = "next.form.not.found"; + // public static final String PREVIOUS_FORM_NOT_FOUND = "previous.form.not.found"; + public static final String CURRENT_FORM_INCOMPLETE = "current.form.incomplete"; public static final String FLOW_NOT_FOUND = "flow.not.found"; - public static final String VALIDATION_MESSAGE = "validation.message"; - public static final String ACTION_REQUIRED = "action.required"; - public static final String CALL_NOT_PUBLISHED="call.not.published"; - public static final String APPLICATION_ALREADY_SUBMITTED="application.already.submitted"; - public static final String INITAL_AND_FINAL_FORM_CANNOT_NULL="initial.and.final.form.cannot.null"; - public static final String APPLICATION_FORM_NOT_FOUND="application.form.not.found"; - public static final String UPDATING_FORM_VALUE_IMPACT_ON_FLOW="updating.form.value.impact.on.flow"; + public static final String VALIDATION_MESSAGE = "validation.message"; + public static final String ACTION_REQUIRED = "action.required"; + public static final String CALL_NOT_PUBLISHED = "call.not.published"; + public static final String APPLICATION_ALREADY_SUBMITTED = "application.already.submitted"; + public static final String INITAL_AND_FINAL_FORM_CANNOT_NULL = "initial.and.final.form.cannot.null"; + public static final String APPLICATION_FORM_NOT_FOUND = "application.form.not.found"; + public static final String UPDATING_FORM_VALUE_IMPACT_ON_FLOW = "updating.form.value.impact.on.flow"; public static final String APPLICATION_IS_INCOMPLETE_MSG = "application.is.incomplete"; public static final String AUTHORIZATION = "Authorization"; public static final String CHECK_VATNUMBER_V2_NEW_URL = "https://imprese.openapi.it/advance"; - public static final String VALIDATION_FIELD_CUSTOM="validation.field.custom"; + public static final String VALIDATION_FIELD_CUSTOM = "validation.field.custom"; public static final String VALIDATION_CODICE_FISCALE = "validation.codice.fiscale"; public static final String VALIDATION_CAP = "validation.cap"; public static final String VALIDATION_IBAN = "validation.iban"; @@ -145,43 +145,44 @@ public class GepafinConstant { public static final String VALIDATION_URL = "validation.url"; public static final String VALIDATION_MARCA_DA_BOLLO = "validation.marca.da.bollo"; public static final String VALIDATION_PIVA = "validation.piva"; - public static final String VALIDATION_VALID_PIVA="valid.vat.number"; - public static final String IS_MARCA_DA_BOLLO="isMarcaDaBollo"; - public static final String IS_URL="isUrl"; - public static final String IS_EMAIL_PEC="isEmailPEC"; - public static final String IS_EMAIL="isEmail"; - public static final String IS_IBAN="isIBAN"; - public static final String IS_CAP="isCAP"; - public static final String IS_CODICE_FISCALE="isCodiceFiscale"; - public static final String IS_PIVA="isPIVA"; - public static final String FAILED_RETAIN_FIELD="failed.retain.field"; - public static final String USER_ALREADY_EXIST_MSG = "user.already.exist.msg"; - public static final String TOKEN_VALIDATE_SUCCESS_MSE = "token.validate.success"; - public static final String INVALID_REQUEST = "invalid.request"; - public static final String CODICE_FISCALE_EXISTS = "codice.fiscale.exists"; - public static final String TOTAL_STEPS_NOT_BE_ZERO="total.steps.not.zero"; - public static final String COMPLETED_STEPS_NOT_VALID="completed.steps.not.valid"; - public static final String FIELD_ID_NOT_FOUND="field.id.not.found"; - public static final String VALIDATE_EMAIL = "validate.email"; - public static final String ROLE_ID_MANDATORY = "role.id.mandatory"; - public static final String VALIDATE_PASSWORD = "validate.password"; - - public static final String COMPANY_CREATED_SUCCESS_MSG = "company.created.success"; - public static final String COMPANY_UPDATED_SUCCESS_MSG = "company.updated.success"; - public static final String COMPANY_DELETE_SUCCESS_MSG = "company.delete.success"; - public static final String COMPANY_GET_SUCCESS_MSG = "company.get.success"; - public static final String COMPANY_NOT_FOUND_MSG = "company.not.found"; - public static final String CHECK_VATNUMBER_SUCCESS_MSG = "check.vatnumber.success"; - public static final String INVALID_VATNUMBER = "invalid.vatnumber"; - public static final String VATNUMBER_MANDATORY = "vatnumber.mandatory"; - public static final String VATNUMBER_ALREADY_EXISTS = "vatnumber.already.exists"; - public static final String INVALID_EMAIL = "invalid.email"; - public static final String UNAUTHORIZED = "UNAUTHORIZED"; - public static final String COMPANY_ID_MANDATORY = "company.id.mandatory"; + public static final String VALIDATION_VALID_PIVA = "valid.vat.number"; + public static final String IS_MARCA_DA_BOLLO = "isMarcaDaBollo"; + public static final String IS_URL = "isUrl"; + public static final String IS_EMAIL_PEC = "isEmailPEC"; + public static final String IS_EMAIL = "isEmail"; + public static final String IS_IBAN = "isIBAN"; + public static final String IS_CAP = "isCAP"; + public static final String IS_CODICE_FISCALE = "isCodiceFiscale"; + public static final String IS_PIVA = "isPIVA"; + public static final String FAILED_RETAIN_FIELD = "failed.retain.field"; + public static final String USER_ALREADY_EXIST_MSG = "user.already.exist.msg"; + public static final String TOKEN_VALIDATE_SUCCESS_MSE = "token.validate.success"; + public static final String INVALID_REQUEST = "invalid.request"; + public static final String CODICE_FISCALE_EXISTS = "codice.fiscale.exists"; + public static final String TOTAL_STEPS_NOT_BE_ZERO = "total.steps.not.zero"; + public static final String COMPLETED_STEPS_NOT_VALID = "completed.steps.not.valid"; + public static final String FIELD_ID_NOT_FOUND = "field.id.not.found"; + public static final String VALIDATE_EMAIL = "validate.email"; + public static final String ROLE_ID_MANDATORY = "role.id.mandatory"; + public static final String VALIDATE_PASSWORD = "validate.password"; + + public static final String COMPANY_CREATED_SUCCESS_MSG = "company.created.success"; + public static final String COMPANY_UPDATED_SUCCESS_MSG = "company.updated.success"; + public static final String COMPANY_DELETE_SUCCESS_MSG = "company.delete.success"; + public static final String COMPANY_GET_SUCCESS_MSG = "company.get.success"; + public static final String COMPANY_NOT_FOUND_MSG = "company.not.found"; + public static final String CHECK_VATNUMBER_SUCCESS_MSG = "check.vatnumber.success"; + public static final String INVALID_VATNUMBER = "invalid.vatnumber"; + public static final String VATNUMBER_MANDATORY = "vatnumber.mandatory"; + public static final String VATNUMBER_ALREADY_EXISTS = "vatnumber.already.exists"; + public static final String INVALID_EMAIL = "invalid.email"; + public static final String UNAUTHORIZED = "UNAUTHORIZED"; + public static final String COMPANY_ID_MANDATORY = "company.id.mandatory"; public static final String USER_ALREADY_CONNECTED_TO_COMPANY = "user.already.connected.to.company"; public static final String CALL_NOT_STARTED_YET = "call.not.started.yet"; public static final String CALL_ALREADY_ENDED = "call.already.ended"; public static final String APPLICATION_STATUS_UPDATED_SUCCESSFULLY = "application.status.updated.successfully"; - + public static final String APPLICATION_ALREADY_IN_PREVIOUS_STATUS = "application.already.in.provided.status"; } + diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index ae8db433..ba6339a7 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -31,6 +31,7 @@ import jakarta.persistence.criteria.Predicate; import java.text.MessageFormat; import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.*; import java.util.stream.Collectors; @@ -72,6 +73,9 @@ public class ApplicationDao { @Autowired private Validator validator; + @Autowired + private ProtocolRepository protocolRepository; + public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId, Long applicationId) { FormEntity formEntity = formService.validateForm(formId); @@ -260,6 +264,9 @@ public class ApplicationDao { responseBean.setComments(applicationEntity.getComments()); responseBean.setCompanyId(applicationEntity.getCompany().getId()); responseBean.setCompanyName(applicationEntity.getCompany().getCompanyName()); + if(applicationEntity.getProtocol() != null) { + responseBean.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber()); + } return responseBean; } @@ -279,6 +286,9 @@ public class ApplicationDao { response.setCallId(entity.getCall().getId()); response.setCreatedDate(entity.getCreatedDate()); response.setUpdatedDate(entity.getUpdatedDate()); + if(entity.getProtocol() != null) { + response.setProtocolNumber(entity.getProtocol().getProtocolNumber()); + } return response; } @@ -472,6 +482,9 @@ public class ApplicationDao { applicationGetResponseBean.setCallId(applicationEntity.getCall().getId()); applicationGetResponseBean.setCallTitle(applicationEntity.getCall().getName()); applicationGetResponseBean.setCompanyId(applicationEntity.getCompany().getId()); + if(applicationEntity.getProtocol() != null) { + applicationGetResponseBean.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber()); + } applicationGetResponseBean.setCompanyName(applicationEntity.getCompany().getCompanyName()); return applicationGetResponseBean; } @@ -506,6 +519,9 @@ public class ApplicationDao { public ApplicationResponse updateApplicationStatus(Long applicationId, ApplicationStatusTypeEnum status) { ApplicationEntity applicationEntity = validateApplication(applicationId); + if(Boolean.TRUE.equals(applicationEntity.getStatus().equals(status.getValue()))){ + throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_IN_PREVIOUS_STATUS)); + } if (status.equals(ApplicationStatusTypeEnum.SUBMIT)) { callService.validatePublishedCall(applicationEntity.getCall().getId()); // CallEntity callEntity = applicationEntity.getCall(); @@ -525,6 +541,10 @@ public class ApplicationDao { if (totalSteps.intValue() != completedSteps) { throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_IS_INCOMPLETE_MSG)); } + Integer maxProtocolNumber=protocolRepository.findMaxProtocolNumber(); + Integer protocolNumber = (maxProtocolNumber != null) ? maxProtocolNumber + 1 : 10000; + ProtocolEntity protocolEntity=createProtocolEntity(applicationEntity,protocolNumber); + applicationEntity.setProtocol(protocolEntity); applicationEntity.setStatus(ApplicationStatusTypeEnum.SUBMIT.getValue()); applicationEntity.setSubmissionDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); } else { @@ -608,4 +628,15 @@ public class ApplicationDao { } } + public ProtocolEntity createProtocolEntity(ApplicationEntity applicationEntity,Integer protocolNumber){ + ProtocolEntity protocolEntity=new ProtocolEntity(); + protocolEntity.setCall(applicationEntity.getCall().getId()); + LocalDateTime utcDateTime = DateTimeUtil.DateServerToUTC(LocalDateTime.now()); + protocolEntity.setYear(utcDateTime.getYear()); + protocolEntity.setProtocolNumber(Long.valueOf(protocolNumber)); + protocolEntity.setTime(LocalTime.now()); + protocolEntity.setApplicationId(applicationEntity.getId()); + protocolRepository.save(protocolEntity); + return protocolEntity; + } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java index 1ffb9059..4ad912f4 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java @@ -307,6 +307,9 @@ public class FlowFormDao { completedSteps = getCompletedSteps(applicationEntity); nextOrPreviousFormResponse.setCompletedSteps(Long.valueOf(completedSteps)); nextOrPreviousFormResponse.setCurrentStep(currentStep); + if(applicationEntity.getProtocol() != null) { + nextOrPreviousFormResponse.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber()); + } return nextOrPreviousFormResponse; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java index 01648c67..cc0f929e 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java @@ -36,4 +36,7 @@ public class ApplicationEntity extends BaseEntity { @Column(name="IS_DELETED") private Boolean isDeleted; + @OneToOne + @JoinColumn(name = "PROTOCOL_NUMBER") + private ProtocolEntity protocol; } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ProtocolEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ProtocolEntity.java new file mode 100644 index 00000000..0924c922 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/ProtocolEntity.java @@ -0,0 +1,28 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; + +import java.time.LocalTime; + +@Entity +@Table(name = "PROTOCOL") +@Data +public class ProtocolEntity extends BaseEntity { + + @Column(name = "PROTOCOL_NUMBER", nullable = false) + private Long protocolNumber; + + @Column(name = "YEAR", nullable = false) + private Integer year; + + @Column(name="CALL_ID") + private Long call; + + @Column(name = "TIME", nullable = false) + private LocalTime time; + + @Column(name="APPLICATION_ID") + private Long applicationId; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java index 9078f3a2..aa686023 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java @@ -24,6 +24,8 @@ public class ApplicationGetResponseBean { private String companyName; + private Long protocolNumber; + private List form; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java index 4283637f..d5df459e 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java @@ -31,4 +31,6 @@ public class ApplicationResponse{ private String companyName; + private Long protocolNumber; + } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponseBean.java index e621197c..6b99961f 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponseBean.java @@ -17,6 +17,8 @@ public class ApplicationResponseBean extends BaseBean { private String comments; + private Long protocolNumber; + private List formFields; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java index 7864e831..8925e7f6 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java @@ -22,6 +22,8 @@ public class NextOrPreviousFormResponse { private String companyName; + private Long protocolNumber; + private ApplicationStatusTypeEnum applicationStatus; private FormApplicationResponse applicationFormResponse; diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ProtocolRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ProtocolRepository.java new file mode 100644 index 00000000..8bdfb553 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ProtocolRepository.java @@ -0,0 +1,13 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.ProtocolEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface ProtocolRepository extends JpaRepository { + + @Query("SELECT MAX(p.protocolNumber) FROM ProtocolEntity p") + Integer findMaxProtocolNumber(); +} diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 85054439..b7d0b8c1 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -885,4 +885,35 @@ columnName="field_value" newDataType="TEXT"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 83d51d11..47a8db96 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -211,3 +211,4 @@ call.not.started.yet = The call has not started yet. Please wait until the speci call.already.ended = The call has already ended. You cannot submit the application after the deadline. status.updated.successfully=Status updated successfully. application.status.updated.successfully = Application status updated successfully. +application.already.in.provided.status=Application is already in provided status. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 42453b8a..cf663bee 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -203,3 +203,4 @@ call.not.started.yet = La chiamata non � ancora iniziata. Attendere fino alla call.already.ended = La chiamata � gi� terminata. Non � possibile inviare l'applicazione dopo la scadenza. status.updated.successfully=Stato aggiornato con successo. application.status.updated.successfully = Stato dell'applicazione aggiornato con successo. +application.already.in.provided.status=L'applicazione gi nello stato fornito. \ No newline at end of file From 4a68348a7bc6ab0704cad11bbc97c852099d9f23 Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 9 Oct 2024 13:22:06 +0530 Subject: [PATCH 26/50] updated security config --- .../config/SecurityConfig.java | 49 ++++++------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 59132951..91424195 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -96,53 +96,32 @@ public class SecurityConfig { } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - // Apply stateless session management globally - http.csrf(AbstractHttpConfigurer::disable) - .authorizeHttpRequests(auth -> auth - // Public endpoints + http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(auth -> auth + // Allow public access to the login endpoints .requestMatchers("/v1/user/login").permitAll() // JWT-based login .requestMatchers("/v1/user").permitAll() // User registration .requestMatchers("/v1/user/sso/validate/existing-user/{token}").permitAll() .requestMatchers("/v1/user/sso/validate/new-user/{token}").permitAll() + .requestMatchers("/v1/saml/**").permitAll() // JWT-based login + .requestMatchers("/saml2/**").permitAll() // SAML login initiation .requestMatchers("/swagger-ui/**").permitAll() // Swagger docs .requestMatchers("/v1/api-docs/**").permitAll() // API docs - - // SAML-related endpoints - .requestMatchers("/v1/saml/**", "/saml2/**").permitAll() - - // Other authenticated requests .anyRequest().authenticated()) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class) + .addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class) + // Add SAML2 login configuration (for BENEFICIARI) + /* + * .saml2Login(saml -> saml.loginPage("/saml/login") // Entry point for SAML + * login .defaultSuccessUrl("/") // Redirect after successful SAML login ); + */ + .saml2Login(saml -> saml.defaultSuccessUrl("/").successHandler(samlSuccessHandler) + .failureHandler(samlFailureHandler)); - // Globally use stateless session management for most requests - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - - // SAML2 login configuration - .saml2Login(saml -> saml - .defaultSuccessUrl("/") - .successHandler(samlSuccessHandler) - .failureHandler(samlFailureHandler)); return http.build(); } - // Add another SecurityFilterChain for SAML requests with stateful session management - @Bean - public SecurityFilterChain samlSecurityFilterChain(HttpSecurity http) throws Exception { - // Apply stateful session management for SAML-related endpoints - http - .securityMatcher("/v1/saml/**", "/saml2/**") // Match SAML requests - .authorizeHttpRequests(auth -> auth - .requestMatchers("/v1/saml/**", "/saml2/**").permitAll() - .anyRequest().authenticated()) - - // Use stateful session management for SAML requests - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)); - - return http.build(); - } - - - @Bean public OpenAPI customOpenAPI() { return new OpenAPI() From 1a063662c906f3f82fa68a48d4da1f0ed1a14d79 Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 9 Oct 2024 13:48:03 +0530 Subject: [PATCH 27/50] updated fe base url --- src/main/resources/application.properties | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index eb6606ff..27151cbc 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -36,14 +36,15 @@ aws.s3.url.folder.delegation=gepafin/delegation # 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.token-validity-in-seconds=86400 -base-url=https://api-dev-gepafin.memento.credit +# Default system base URLs +base-url=https://api-dev-gepafin.memento.credit +fe.base.url=https://bandi-staging.memento.credit spring.main.allow-circular-references=true isVatCheckGloballyDisabled = true vatCheckNewToken: 66026bd891a51044e90e08c4 -fe.base.url=http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com #SPID configuration spid.ipd.base.url=https://federatest.umbriadigitale.it From db23bd5ec4115d76beb43378c7bd476e5b9d3a75 Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 9 Oct 2024 13:51:30 +0530 Subject: [PATCH 28/50] removed un used url --- src/main/resources/application-dev.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 930cbd9f..19588213 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -6,6 +6,5 @@ spring.datasource.driver-class-name=org.postgresql.Driver # JPA Configuration spring.h2.console.enabled=true -base-url=https://api-dev-gepafin.memento.credit isVatCheckGloballyDisabled = false From e94be7eb3380b4c43960f95e5ecca15b6a6a4bca Mon Sep 17 00:00:00 2001 From: harish Date: Wed, 9 Oct 2024 20:13:08 +0530 Subject: [PATCH 29/50] Updated application validation related to company delegation --- .../constants/GepafinConstant.java | 1 + .../tendermanagement/dao/ApplicationDao.java | 28 +++++++++++++++++-- .../service/CompanyService.java | 2 ++ .../service/impl/CompanyServiceImpl.java | 3 ++ src/main/resources/message_en.properties | 2 +- src/main/resources/message_it.properties | 2 ++ 6 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index f67a2ee2..e27e9d65 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -198,5 +198,6 @@ public class GepafinConstant { public static final String DELEGATION_NOT_FOUND = "delegation.not.found"; public static final String USER_COMPANY_RELATION_NOT_FOUND = "user.company.relation.not.found"; public static final String DELEGATION_DELETE_SUCCESS = "delegation.delete.success"; + public static final String USER_NOT_AUTHORIZED_TO_CREATE_APPLICATION = "user.not.authorized.create.application"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index ae8db433..69be125a 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -6,12 +6,14 @@ import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.enums.RoleStatusEnum; +import net.gepafin.tendermanagement.enums.UserCompanyDelegationStatusEnum; import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBean; import net.gepafin.tendermanagement.model.request.ApplicationRequest; import net.gepafin.tendermanagement.model.request.ApplicationRequestBean; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.CallService; +import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.service.DocumentService; import net.gepafin.tendermanagement.service.FormService; import net.gepafin.tendermanagement.util.DateTimeUtil; @@ -68,10 +70,14 @@ public class ApplicationDao { @Autowired private FlowDataRepository flowDataRepository; - + @Autowired + private UserWithCompanyRepository userWithCompanyRepository; + @Autowired + private UserCompanyDelegationRepository userCompanyDelegationRepository; @Autowired private Validator validator; - + @Autowired + private CompanyService companyService; public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId, Long applicationId) { FormEntity formEntity = formService.validateForm(formId); @@ -86,6 +92,19 @@ public class ApplicationDao { createOrUpdateMultipleFormFields(applicationRequestBean.getFormFields(), applicationFormEntity,formEntity); return getApplicationById(applicationEntity.getId(),formEntity.getId()); } + public void validateDelegation(UserEntity user, CompanyEntity company) { + UserWithCompanyEntity userWithCompany = companyService.getUserWithCompanyEntity(user.getId(), company.getId()); + + UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository + .findByUserIdAndCompanyIdAndStatus(user.getId(), company.getId(), + UserCompanyDelegationStatusEnum.ACTIVE.getValue()); + + if (!userWithCompany.getIsLegalRepresentant() && userCompanyDelegationEntity == null) { + throw new CustomValidationException(Status.BAD_REQUEST, + Translator.toLocale(GepafinConstant.USER_NOT_AUTHORIZED_TO_CREATE_APPLICATION)); + } + } + public ApplicationFormEntity saveApplicationFormEntity(ApplicationFormEntity applicationFormEntity) { ApplicationFormEntity applicationFormEntity1 = applicationFormRepository.save(applicationFormEntity); @@ -101,6 +120,7 @@ public class ApplicationDao { } public ApplicationEntity createApplicationEntity(UserEntity user, CallEntity call, CompanyEntity companyEntity) { + validateDelegation(user,companyEntity); ApplicationEntity entity = new ApplicationEntity(); entity.setUserId(user.getId()); entity.setCompany(companyEntity); @@ -505,7 +525,9 @@ public class ApplicationDao { public ApplicationResponse updateApplicationStatus(Long applicationId, ApplicationStatusTypeEnum status) { ApplicationEntity applicationEntity = validateApplication(applicationId); - + if (ApplicationStatusTypeEnum.SUBMIT.getValue().equals(applicationEntity.getStatus())) { + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_SUBMITTED)); + } if (status.equals(ApplicationStatusTypeEnum.SUBMIT)) { callService.validatePublishedCall(applicationEntity.getCall().getId()); // CallEntity callEntity = applicationEntity.getCall(); diff --git a/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java index da05c544..18b6db0c 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java @@ -39,5 +39,7 @@ public interface CompanyService { CompanyDelegationResponse getCompanyDelegation(HttpServletRequest request, Long companyId); void deleteCompanyDelegation(HttpServletRequest request, Long companyId); + UserWithCompanyEntity getUserWithCompanyEntity(Long userId,Long companyId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java index 0e43265a..1f80b223 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java @@ -114,4 +114,7 @@ public class CompanyServiceImpl implements CompanyService { UserEntity userEntity =validator.validateUser(request); delegationDao.deleteCompanyDelegation(userEntity, companyId); } + public UserWithCompanyEntity getUserWithCompanyEntity(Long userId,Long companyId){ + return companyDao.getUserWithCompany(userId,companyId); + } } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 84279127..d5d8dd0c 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -223,5 +223,5 @@ application.status.updated.successfully = Application status updated successfull delegation.not.found=Delegation not found. user.company.relation.not.found=User with the specified company relation not found. delegation.delete.success=Delegation deleted successfully. - +user.not.authorized.create.application=User must be a legal representative or have delegation. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 4dfec2b0..7086144c 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -218,5 +218,7 @@ application.status.updated.successfully = Stato dell'applicazione aggiornato con delegation.not.found=Delega non trovata. user.company.relation.not.found=Relazione utente con l'azienda specificata non trovata. delegation.delete.success=Delega eliminata con successo. +user.not.authorized.create.application=L'utente deve essere un rappresentante legale o avere una delega. + From 75ae714a2d22d3bea1e6f51d6d4019fb0692ef7a Mon Sep 17 00:00:00 2001 From: harish Date: Wed, 9 Oct 2024 20:22:25 +0530 Subject: [PATCH 30/50] Updated code --- .../net/gepafin/tendermanagement/constants/GepafinConstant.java | 2 +- src/main/resources/message_en.properties | 2 ++ src/main/resources/message_it.properties | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 944edbe2..afbfbea3 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -200,6 +200,6 @@ public class GepafinConstant { public static final String USER_COMPANY_RELATION_NOT_FOUND = "user.company.relation.not.found"; public static final String DELEGATION_DELETE_SUCCESS = "delegation.delete.success"; 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"; } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 44fcb751..0d68c6d7 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -225,4 +225,6 @@ delegation.not.found=Delegation not found. user.company.relation.not.found=User with the specified company relation not found. delegation.delete.success=Delegation deleted successfully. user.not.authorized.create.application=User must be a legal representative or have delegation. +application.submitted.cannot.change=The submitted application cannot be changed. + diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 419c44fb..3e665e82 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -220,6 +220,7 @@ delegation.not.found=Delega non trovata. user.company.relation.not.found=Relazione utente con l'azienda specificata non trovata. delegation.delete.success=Delega eliminata con successo. 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. From b1a2fc891c627d7cdf5a0ed2a5bfbc7027398f78 Mon Sep 17 00:00:00 2001 From: rajesh Date: Thu, 10 Oct 2024 15:42:43 +0530 Subject: [PATCH 31/50] updated default placeholder --- .../gepafin/tendermanagement/dao/DelegationDao.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java index 525c657a..ca58f8be 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java @@ -127,15 +127,15 @@ public class DelegationDao { placeholders.put("{{company_last_name}}", ""); placeholders.put("{{company_codice_fiscale}}", ""); placeholders.put("{{company_name}}", ""); - placeholders.put("{{company_city}}", DEFAULT_PLACEHOLDER); - placeholders.put("{{company_address}}", DEFAULT_PLACEHOLDER); - placeholders.put("{{company_province}}", DEFAULT_PLACEHOLDER); - placeholders.put("{{company_cap}}", DEFAULT_PLACEHOLDER); + placeholders.put("{{company_city}}", ""); + placeholders.put("{{company_address}}", ""); + placeholders.put("{{company_province}}", ""); + placeholders.put("{{company_cap}}", ""); placeholders.put("{{company_vat_number}}", ""); placeholders.put("{{user_first_name}}", ""); placeholders.put("{{user_last_name}}", ""); - placeholders.put("{{user_date_of_birth}}", DEFAULT_PLACEHOLDER); + placeholders.put("{{user_date_of_birth}}", ""); placeholders.put("{{user_codice_fiscale}}", ""); return placeholders; } From b842bcee73e08bfd3265d206d669881fa98afcdd Mon Sep 17 00:00:00 2001 From: harish Date: Thu, 10 Oct 2024 18:03:02 +0530 Subject: [PATCH 32/50] Beneficiario must be abfle to dowload Call Documents --- .../constants/GepafinConstant.java | 2 + .../gepafin/tendermanagement/dao/CallDao.java | 45 +++++++++++++++++++ .../repositories/DocumentRepository.java | 1 + .../tendermanagement/service/CallService.java | 2 +- .../service/impl/CallServiceImpl.java | 5 +++ .../web/rest/api/CallApi.java | 15 +++++++ .../web/rest/api/impl/CallApiController.java | 20 +++++++++ src/main/resources/message_en.properties | 3 ++ src/main/resources/message_it.properties | 3 ++ 9 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index afbfbea3..d72853c7 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -201,5 +201,7 @@ public class GepafinConstant { public static final String DELEGATION_DELETE_SUCCESS = "delegation.delete.success"; 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 CALL_DOCUMENTS_FETCH_SUCCESS_MSG = "call.documents.fetch.success"; + public static final String CALL_DOCUMENTS_NOT_FOUND_MSG = "call.documents.not.found"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index c6345d59..0827b62a 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -1,5 +1,9 @@ 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.time.LocalDate; import java.time.LocalDateTime; @@ -8,13 +12,21 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; 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.model.response.*; import net.gepafin.tendermanagement.service.*; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.Utils; +import org.h2.util.IOUtils; 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.util.StringUtils; @@ -85,6 +97,10 @@ public class CallDao { private FlowDao flowDao; @Autowired private FormDao formDao; + @Value("${aws.s3.url.folder}") + private String s3Folder; + @Autowired + private AmazonS3Service amazonS3Service; public CallResponse createCallStep1(CreateCallRequestStep1 createCallRequest, Long userId) { UserEntity userEntity = userService.validateUser(userId); @@ -101,6 +117,35 @@ public class CallDao { return createCallResponseBean; } + public byte[] downloadCallDocumentsAsZip(Long callId) { + List 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) { CallEntity callEntity = new CallEntity(); diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java index 339efd13..1543def3 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java @@ -20,6 +20,7 @@ public interface DocumentRepository extends JpaRepository Optional findByIdAndSourceIdAndIsDeletedFalse(Long id, Long sourceId); List findBySource(String source); + List findBySourceIdAndSourceAndTypeAndIsDeletedFalse(Long sourceId, String source, String type); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/CallService.java b/src/main/java/net/gepafin/tendermanagement/service/CallService.java index aa6ea872..9a62d89d 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/CallService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/CallService.java @@ -32,5 +32,5 @@ public interface CallService { CallEntity validateCall(Long callId); CallEntity validatePublishedCall(Long callId); - + byte[] downloadCallDocumentsAsZip(Long callId); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java index a6a6a901..f6ca0b66 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java @@ -92,4 +92,9 @@ public class CallServiceImpl implements CallService { public CallEntity validatePublishedCall(Long callId) { return callDao.validatePublishedCall(callId); } + @Override + @Transactional(readOnly = true) + public byte[] downloadCallDocumentsAsZip(Long callId) { + return callDao.downloadCallDocumentsAsZip(callId); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java index cc7f985a..3e2861ff 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java @@ -134,4 +134,19 @@ public interface CallApi { public ResponseEntity> updateCallStatus(HttpServletRequest request, @Parameter(description = "The call id", required = true) @PathVariable("callId") Long callId, @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 downloadCallDocumentsAsZip(HttpServletRequest httpServletRequest, + @Parameter(description = "The call ID", required = true) @PathVariable("callId") Long callId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java index e4680428..926dccab 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java @@ -4,7 +4,9 @@ import java.util.List; import net.gepafin.tendermanagement.enums.CallStatusEnum; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; @@ -84,4 +86,22 @@ public class CallApiController implements CallApi { CallResponse updateCall = callService.updateCallStatus(request, callId, status); return ResponseEntity.ok(new Response<>(updateCall, Status.SUCCESS, Translator.toLocale(GepafinConstant.UPDATE_CALL_STATUS_SUCCESS_MSG))); } + @Override + public ResponseEntity 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); + } + + } \ No newline at end of file diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 0d68c6d7..8ae7bcfa 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -226,5 +226,8 @@ user.company.relation.not.found=User with the specified company relation not fou delegation.delete.success=Delegation deleted successfully. user.not.authorized.create.application=User must be a legal representative or have delegation. 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. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 3e665e82..9b998124 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -222,5 +222,8 @@ delegation.delete.success=Delega eliminata con successo. 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. +# Call Document Messages +call.documents.fetch.success=Documenti recuperati con successo. +call.documents.not.found=Nessun documento trovato per la chiamata specificata. From f7c97c108088c10e13f9100424bc76d17cd9b67e Mon Sep 17 00:00:00 2001 From: rajesh Date: Thu, 10 Oct 2024 11:56:08 -0700 Subject: [PATCH 33/50] Updated config --- .../tendermanagement/config/SecurityConfig.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 91424195..90c278d4 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -24,12 +24,12 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.handler.HandlerMappingIntrospector; - import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.servers.Server; +import jakarta.servlet.http.HttpServletResponse; import net.gepafin.tendermanagement.config.jwt.JWTFilter; import net.gepafin.tendermanagement.config.jwt.TokenProvider; @@ -107,7 +107,13 @@ public class SecurityConfig { .requestMatchers("/swagger-ui/**").permitAll() // Swagger docs .requestMatchers("/v1/api-docs/**").permitAll() // API docs .anyRequest().authenticated()) - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)) + .exceptionHandling(exceptionHandling -> exceptionHandling + .authenticationEntryPoint((request, response, authException) -> { + // Send 403 Forbidden when there is no JWT token provided + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Forbidden: Authentication token is missing or invalid"); + }) + ) .addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class) // Add SAML2 login configuration (for BENEFICIARI) From 8a14059b0c73d7ae166106b31f9347055ae0a21c Mon Sep 17 00:00:00 2001 From: rajesh Date: Fri, 11 Oct 2024 10:19:23 +0530 Subject: [PATCH 34/50] Done ticket GEPAFINBE-39 --- pom.xml | 6 + .../constants/GepafinConstant.java | 1 + .../tendermanagement/dao/ApplicationDao.java | 84 ++++++++++++- .../dao/SystemEmailTemplatesDao.java | 116 ++++++++++++++++++ .../entities/SystemEmailTemplatesEntity.java | 56 +++++++++ .../response/SystemEmailTemplateResponse.java | 16 +++ .../SystemEmailTemplatesRespository.java | 17 +++ .../service/SystemEmailTemplatesService.java | 13 ++ .../service/impl/ApplicationServiceImpl.java | 3 +- .../impl/SystemEmailTemplatesServiceImpl.java | 27 ++++ .../tendermanagement/util/DateTimeUtil.java | 16 +++ .../tendermanagement/util/MailUtil.java | 78 ++++++++++++ .../gepafin/tendermanagement/util/Utils.java | 27 ++++ src/main/resources/application-dev.properties | 1 + .../application-production.properties | 3 +- src/main/resources/application.properties | 12 ++ .../db/changelog/db.changelog-1.0.0.xml | 25 ++++ ...il_template_for_application_submission.sql | 34 +++++ 18 files changed, 531 insertions(+), 4 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/SystemEmailTemplatesDao.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/SystemEmailTemplateResponse.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/SystemEmailTemplatesRespository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/SystemEmailTemplatesService.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/SystemEmailTemplatesServiceImpl.java create mode 100644 src/main/java/net/gepafin/tendermanagement/util/MailUtil.java create mode 100644 src/main/resources/db/dump/insert_system_email_template_for_application_submission.sql diff --git a/pom.xml b/pom.xml index b0a632d8..db1f4b8f 100644 --- a/pom.xml +++ b/pom.xml @@ -179,6 +179,12 @@ 5.3.0 + + com.mailgun + mailgun-java + 1.0.2 + + org.apache.santuario xmlsec diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 2effa6d2..62e90058 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -199,6 +199,7 @@ public class GepafinConstant { public static final String DELEGATION_NOT_FOUND = "delegation.not.found"; public static final String USER_COMPANY_RELATION_NOT_FOUND = "user.company.relation.not.found"; public static final String DELEGATION_DELETE_SUCCESS = "delegation.delete.success"; + public static final String HH_MM_SS = "HH:mm:ss"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index ba6339a7..b690a3e6 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.dao; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.*; +import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.enums.RoleStatusEnum; @@ -14,16 +15,20 @@ import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.service.DocumentService; import net.gepafin.tendermanagement.service.FormService; +import net.gepafin.tendermanagement.service.SystemEmailTemplatesService; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.FieldValidator; +import net.gepafin.tendermanagement.util.MailUtil; import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.util.Validator; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Component; @@ -75,6 +80,19 @@ public class ApplicationDao { @Autowired private ProtocolRepository protocolRepository; + + @Autowired + private SystemEmailTemplatesService systemEmailTemplatesService; + + @Autowired + private MailUtil mailUtil; + + @Value("${default_System_Receiver_Email}") + private String defaultSystemReceiverEmail; + + @Value("${gepafin_email}") + private String gepafinEmail; + public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId, Long applicationId) { @@ -516,7 +534,7 @@ public class ApplicationDao { } } - public ApplicationResponse updateApplicationStatus(Long applicationId, ApplicationStatusTypeEnum status) { + public ApplicationResponse updateApplicationStatus(UserEntity userEntity, Long applicationId, ApplicationStatusTypeEnum status) { ApplicationEntity applicationEntity = validateApplication(applicationId); if(Boolean.TRUE.equals(applicationEntity.getStatus().equals(status.getValue()))){ @@ -547,6 +565,8 @@ public class ApplicationDao { applicationEntity.setProtocol(protocolEntity); applicationEntity.setStatus(ApplicationStatusTypeEnum.SUBMIT.getValue()); applicationEntity.setSubmissionDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + sendMailToUserAndCompany(userEntity, applicationEntity); + sendMailTodefaultSystemAndGepafin(userEntity, applicationEntity); } else { applicationEntity.setStatus(status.getValue()); } @@ -555,7 +575,7 @@ public class ApplicationDao { return getApplicationResponse(applicationEntity); } - public Integer calculateProgress(Long totalSteps, Long completedSteps) { + public Integer calculateProgress(Long totalSteps, Long completedSteps) { if (FieldValidator.isNullOrZero(totalSteps)) { throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.TOTAL_STEPS_NOT_BE_ZERO)); } @@ -639,4 +659,64 @@ public class ApplicationDao { protocolRepository.save(protocolEntity); return protocolEntity; } + + private void sendMailToUserAndCompany(UserEntity userEntity, ApplicationEntity applicationEntity) { + CallEntity call =applicationEntity.getCall(); + CompanyEntity company = applicationEntity.getCompany(); + ProtocolEntity protocol = applicationEntity.getProtocol(); + SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService + .retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum.APPLICATION_SUBMISSION_TO_USER_AND_COMPANY, + call, null); + + // Create the map for subject placeholders + Map subjectPlaceholders = new HashMap<>(); + subjectPlaceholders.put("{{call_name}}", call.getName()); + subjectPlaceholders.put("{{company_name}}", company.getCompanyName()); + + // Create the map for body placeholders + Map bodyPlaceholders = new HashMap<>(); + bodyPlaceholders.put("{{call_name}}", call.getName()); + bodyPlaceholders.put("{{protocol_number}}", protocol.getProtocolNumber().toString()); + bodyPlaceholders.put("{{date}}", DateTimeUtil.formatLocalDateTime(protocol.getCreatedDate(), GepafinConstant.YYYY_MM_DD_SLASH)); + bodyPlaceholders.put("{{time}}", DateTimeUtil.parseLocalTimeToString(protocol.getTime(), GepafinConstant.HH_MM_SS)); + + // Replace placeholders in the subject and body + String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders); + String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); + + + mailUtil.sendByMailGun(subject, body, List.of(userEntity.getEmail()), null); + mailUtil.sendByMailGun(subject, body, List.of(applicationEntity.getCompany().getEmail()), null); + + } + + private void sendMailTodefaultSystemAndGepafin(UserEntity userEntity, ApplicationEntity applicationEntity) { + CallEntity call =applicationEntity.getCall(); + CompanyEntity company = applicationEntity.getCompany(); + ProtocolEntity protocol = applicationEntity.getProtocol(); + SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService + .retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum.APPLICATION_SUBMISSION_TO_GEPAFIN, + call, null); + + // Create the map for subject placeholders + Map subjectPlaceholders = new HashMap<>(); + subjectPlaceholders.put("{{call_name}}", call.getName()); + subjectPlaceholders.put("{{company_name}}", company.getCompanyName()); + + // Create the map for body placeholders + Map bodyPlaceholders = new HashMap<>(); + bodyPlaceholders.put("{{call_name}}", call.getName()); + bodyPlaceholders.put("{{protocol_number}}", protocol.getProtocolNumber().toString()); + bodyPlaceholders.put("{{date}}", DateTimeUtil.formatLocalDateTime(protocol.getCreatedDate(), GepafinConstant.YYYY_MM_DD_SLASH)); + bodyPlaceholders.put("{{time}}", DateTimeUtil.parseLocalTimeToString(protocol.getTime(), GepafinConstant.HH_MM_SS)); + + // Replace placeholders in the subject and body + String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders); + String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); + + + mailUtil.sendByMailGun(subject, body, List.of(defaultSystemReceiverEmail), null); + mailUtil.sendByMailGun(subject, body, List.of(gepafinEmail), null); + + } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/SystemEmailTemplatesDao.java b/src/main/java/net/gepafin/tendermanagement/dao/SystemEmailTemplatesDao.java new file mode 100644 index 00000000..9218a33d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/SystemEmailTemplatesDao.java @@ -0,0 +1,116 @@ +package net.gepafin.tendermanagement.dao; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import net.gepafin.tendermanagement.entities.CallEntity; +import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity; +import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum; +import net.gepafin.tendermanagement.model.response.SystemEmailTemplateResponse; +import net.gepafin.tendermanagement.repositories.SystemEmailTemplatesRespository; +import net.gepafin.tendermanagement.util.Utils; + +@Component +public class SystemEmailTemplatesDao { + + @Autowired + private SystemEmailTemplatesRespository systemEmailTemplatesRespository; + + @Value("${fe.base.url}") + private String feBaseUrl; + + + public SystemEmailTemplateResponse retrieveTemplate(SystemEmailTemplatesEntityTypeEnum type, CallEntity call, Locale language) { + SystemEmailTemplatesEntity dbSystemEmailTemplatesEntity = null; + if(call != null){ +// dbSystemEmailTemplatesEntity = systemEmailTemplatesRespository +// .findByTypeAndCallId(type.getValue(), call.getId()); + } + if(dbSystemEmailTemplatesEntity == null){ + dbSystemEmailTemplatesEntity = systemEmailTemplatesRespository + .findByType(type.getValue()); + } + + SystemEmailTemplateResponse systemEmailTemplateResponse = replaceHtmlContant(dbSystemEmailTemplatesEntity, call, language, Boolean.TRUE); + return systemEmailTemplateResponse; + } + + private SystemEmailTemplateResponse replaceHtmlContant(SystemEmailTemplatesEntity dbSystemEmailTemplatesEntity, + CallEntity call, Locale language1, Boolean isDefaultReplace) { + String language = null; + String htmlContent = dbSystemEmailTemplatesEntity.getHtmlContent(); + String subject = dbSystemEmailTemplatesEntity.getSubject(); + + if (language1 == null) { +// language = getLanguage(LocaleContextHolder.getLocale()); + language="italian"; + }else{ + language="italian"; + } + Map languageMap = new HashMap<>(); + String jsonContent = dbSystemEmailTemplatesEntity.getJson(); + if (Boolean.FALSE.equals(StringUtils.isEmpty(jsonContent))) { + Map> jsonMap = Utils.parseJsonContent(jsonContent); + if (jsonMap != null && jsonMap.containsKey(language)) { + languageMap = jsonMap.get(language); + htmlContent = replacePlaceholders(htmlContent, languageMap); + subject = replaceSubjectPlaceholders(subject, languageMap); + + } + } + if(Boolean.TRUE.equals(StringUtils.isEmpty(subject))){ + subject = ""; + } + + + htmlContent = replacePlatformLinkPlaceholder(call, htmlContent, languageMap); + SystemEmailTemplateResponse systemEmailTemplateResponse = new SystemEmailTemplateResponse(); + systemEmailTemplateResponse.setHtmlContent(htmlContent); + systemEmailTemplateResponse.setSubject(subject); + systemEmailTemplateResponse.setJsonMap(languageMap); + return systemEmailTemplateResponse; + } + + + +// private String getLanguage(Locale locale) { +// return switch (locale.getLanguage()) { +// case "en" -> "english"; +// case "it" -> "italian"; +// default -> "italian"; +// }; +// } + + private String replacePlaceholders(String htmlContent, Map languageMap) { + for (Map.Entry entry : languageMap.entrySet()) { + htmlContent = htmlContent.replace("{{" + entry.getKey() + "}}", entry.getValue()); + } + return htmlContent; + } + + private String replaceSubjectPlaceholders(String subject, Map languageMap) { + if(languageMap.containsKey("subject") && subject != null){ + String value = languageMap.get("subject"); + subject = subject.replace("{{subject}}", value); + return subject; + } + return ""; + } + private String replacePlatformLinkPlaceholder(CallEntity call, String htmlContent, + Map languageMap) { + String platformLink = feBaseUrl; + +// if(hubEntity != null && Boolean.FALSE.equals(isEmpty(hubEntity.getDomainName()))){ +// platformLink = hubEntity.getDomainName(); +// } + htmlContent = htmlContent.replace("{{platform_link}}", platformLink); + return htmlContent; + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java new file mode 100644 index 00000000..9ae12cbf --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java @@ -0,0 +1,56 @@ +package net.gepafin.tendermanagement.entities; + +import com.fasterxml.jackson.annotation.JsonValue; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.Data; + +@Entity +@Table(name = "system_email_template") +@Data +public class SystemEmailTemplatesEntity extends BaseEntity { + + + @Column(name = "TEMPLATE_NAME") + private String templateName; + + @Column(name = "TYPE") + private String type; + + @Column(name = "HTML_CONTENT", columnDefinition = "TEXT") + private String htmlContent; + + @Column(name = "SUBJECT") + private String subject; + + @Column(name = "JSON", columnDefinition = "TEXT") + private String json; + + @Column(name = "SYSTEM") + private Boolean system; + + @Column(name ="IS_DELETED", nullable = false) + private Boolean isDeleted = false; + + public enum SystemEmailTemplatesEntityTypeEnum { + + APPLICATION_SUBMISSION_TO_USER_AND_COMPANY("APPLICATION_SUBMISSION_TO_USER_AND_COMPANY"), + APPLICATION_SUBMISSION_TO_GEPAFIN("APPLICATION_SUBMISSION_TO_GEPAFIN"); + + private String value; + + SystemEmailTemplatesEntityTypeEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/SystemEmailTemplateResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/SystemEmailTemplateResponse.java new file mode 100644 index 00000000..cd65e6e4 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/SystemEmailTemplateResponse.java @@ -0,0 +1,16 @@ +package net.gepafin.tendermanagement.model.response; + +import java.util.Map; + +import lombok.Data; + +@Data +public class SystemEmailTemplateResponse { + + String htmlContent; + + String subject; + + Map jsonMap; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/SystemEmailTemplatesRespository.java b/src/main/java/net/gepafin/tendermanagement/repositories/SystemEmailTemplatesRespository.java new file mode 100644 index 00000000..9e3e9bb9 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/SystemEmailTemplatesRespository.java @@ -0,0 +1,17 @@ +package net.gepafin.tendermanagement.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity; + +public interface SystemEmailTemplatesRespository extends JpaRepository { + +// @Query("select s from SystemEmailTemplatesEntity s where s.type=:type and s.call.id=:callId and s.isDeleted =false and s.system = false") +// SystemEmailTemplatesEntity findByTypeAndCallId(@Param("type") String type, @Param("callId") Long callId); + + @Query("select s from SystemEmailTemplatesEntity s where s.type=:type and s.isDeleted =false and s.system = true") + SystemEmailTemplatesEntity findByType(@Param("type") String type); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/SystemEmailTemplatesService.java b/src/main/java/net/gepafin/tendermanagement/service/SystemEmailTemplatesService.java new file mode 100644 index 00000000..b40dc80f --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/SystemEmailTemplatesService.java @@ -0,0 +1,13 @@ +package net.gepafin.tendermanagement.service; + +import java.util.Locale; + +import net.gepafin.tendermanagement.entities.CallEntity; +import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum; +import net.gepafin.tendermanagement.model.response.SystemEmailTemplateResponse; + +public interface SystemEmailTemplatesService { + + SystemEmailTemplateResponse retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum type, CallEntity call, Locale language); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java index a082a092..bd6341de 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java @@ -78,7 +78,8 @@ public class ApplicationServiceImpl implements ApplicationService { @Override @Transactional(rollbackFor = Exception.class) public ApplicationResponse updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status) { - return applicationDao.updateApplicationStatus(applicationId, status); + UserEntity userEntity = validator.validateUser(request); + return applicationDao.updateApplicationStatus(userEntity, applicationId, status); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/SystemEmailTemplatesServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/SystemEmailTemplatesServiceImpl.java new file mode 100644 index 00000000..802f2580 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/SystemEmailTemplatesServiceImpl.java @@ -0,0 +1,27 @@ +package net.gepafin.tendermanagement.service.impl; + +import java.util.Locale; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import net.gepafin.tendermanagement.dao.SystemEmailTemplatesDao; +import net.gepafin.tendermanagement.entities.CallEntity; +import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum; +import net.gepafin.tendermanagement.model.response.SystemEmailTemplateResponse; +import net.gepafin.tendermanagement.service.SystemEmailTemplatesService; + +@Service +public class SystemEmailTemplatesServiceImpl implements SystemEmailTemplatesService { + + @Autowired + private SystemEmailTemplatesDao systemEmailTemplatesDao; + + + @Override + public SystemEmailTemplateResponse retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum type, CallEntity call, Locale language) { + return systemEmailTemplatesDao.retrieveTemplate(type, call, language); + } + + +} diff --git a/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java index 342ca2b2..92da73eb 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java +++ b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java @@ -92,4 +92,20 @@ public class DateTimeUtil { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); return LocalDateTime.parse(dateTimeStr, formatter); } + + public static String parseLocalTimeToString(LocalTime time, String format) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); + return time.format(formatter); + } + + // Method 2: Convert String and format to LocalTime + public static LocalTime parseStringToLocalTime(String timeString, String format) { + try { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); + return LocalTime.parse(timeString, formatter); + } catch (DateTimeParseException e) { + System.out.println("Invalid time format: " + e.getMessage()); + return null; + } + } } diff --git a/src/main/java/net/gepafin/tendermanagement/util/MailUtil.java b/src/main/java/net/gepafin/tendermanagement/util/MailUtil.java new file mode 100644 index 00000000..8b41ea3f --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/util/MailUtil.java @@ -0,0 +1,78 @@ +package net.gepafin.tendermanagement.util; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import com.mailgun.api.v3.MailgunMessagesApi; +import com.mailgun.client.MailgunClient; + +@Component +public class MailUtil { + + @Value("${apiKey}") + private String apiKeyValue; + + @Value("${mailGun_user}") + private String mailGunUser; + + @Value("${mailGun_apiKey}") + private String mailGunApiKey; + + @Value("${mailGun_domainName}") + private String mailGunDomainName; + + @Value("${mailGun_base_url}") + private String mailGunBaseUrl; + + @Value("${isMailSendingEnabled}") + private String isEmailSendingEnabled; + + @Autowired + private Environment environment; + + public Boolean isTestProfileActivated() { + String[] activeProfiles = environment.getActiveProfiles(); + return Arrays.stream(activeProfiles).anyMatch("test"::equals); + } + + public void sendMailByMailGunAPI(List recipents, List CC, List BCC, String subject, + String body, String replyTo) { + if (Boolean.FALSE.equals(Boolean.parseBoolean(isEmailSendingEnabled))) { + return; + } + + MailgunMessagesApi mailgunMessagesApi = MailgunClient.config(mailGunBaseUrl, mailGunApiKey) + .createApi(MailgunMessagesApi.class); + + String mailFrom = mailGunUser; + + com.mailgun.model.message.Message.MessageBuilder temp = com.mailgun.model.message.Message.builder() + .replyTo(replyTo).from(mailFrom).to(recipents).subject(subject).html(body); + + if (Boolean.FALSE.equals(CollectionUtils.isEmpty(CC))) { + temp.cc(CC); + } + + if (Boolean.FALSE.equals(CollectionUtils.isEmpty(BCC))) { + temp.bcc(BCC); + } + + if (Boolean.FALSE.equals(isTestProfileActivated())) { + com.mailgun.model.message.Message message = temp.build(); + mailgunMessagesApi.sendMessage(mailGunDomainName, message); + } + + } + + public void sendByMailGun(String subject, String body, List receiverEmails, String replyTo) { + sendMailByMailGunAPI(receiverEmails, null, null, subject, body, replyTo); + + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index 746c8e8d..d7da174b 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -5,6 +5,7 @@ import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.util.Base64; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -276,4 +277,30 @@ public class Utils { } } + public static Map> parseJsonContent(String jsonContent) { + ObjectMapper objectMapper = new ObjectMapper(); + try { + return mapper.readValue(jsonContent, HashMap.class); + } catch (Exception exception) { + log.error(exception.getMessage()); + } + return new HashMap<>(); + } + + // Utility method to replace placeholders with their values, handling nulls + public static String replacePlaceholders(String text, Map placeholders) { + if (text == null) { + return ""; + } + for (Map.Entry entry : placeholders.entrySet()) { + text = replaceNull(text, entry.getKey(), entry.getValue()); + } + return text; + } + + // Method to safely replace nulls with an empty string or a default value + private static String replaceNull(String text, String target, String replacement) { + return text.replace(target, replacement != null ? replacement : ""); + } + } diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 19588213..5b6ca7a9 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -8,3 +8,4 @@ spring.datasource.driver-class-name=org.postgresql.Driver spring.h2.console.enabled=true isVatCheckGloballyDisabled = false +isMailSendingEnabled = true diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index 968d5ac5..986dd51b 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -13,4 +13,5 @@ isVatCheckGloballyDisabled = false fe.base.url=http://bandi.gepafin.it #SPID configuration spid.ipd.base.url=https://login.regione.umbria.it -active.profile.folder=production \ No newline at end of file +active.profile.folder=production +isMailSendingEnabled = true \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 27151cbc..0472eb61 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -50,3 +50,15 @@ vatCheckNewToken: 66026bd891a51044e90e08c4 spid.ipd.base.url=https://federatest.umbriadigitale.it active.profile.folder=dev +# MailGun API Key +mailGun_apiKey= 398e3dea1911fe941af261906ec99362-07e2c238-8094421f +mailGun_user=comunicazione@paghiamoci.ai +mailGun_domainName=paghiamoci.ai +mailGun_base_url=https://api.eu.mailgun.net/ +# SendinBlue API key +apiKey=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 +#senderEmail=mailer@bflows.net +isMailSendingEnabled = false +default_System_Receiver_Email=attivazione@bflows.net +gepafin_email=bandi@pec.gepafin.it + diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 98016d3c..446334d6 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -973,4 +973,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/dump/insert_system_email_template_for_application_submission.sql b/src/main/resources/db/dump/insert_system_email_template_for_application_submission.sql new file mode 100644 index 00000000..acd205bd --- /dev/null +++ b/src/main/resources/db/dump/insert_system_email_template_for_application_submission.sql @@ -0,0 +1,34 @@ +INSERT INTO gepafin_schema.system_email_template (id, template_name, "type", html_content, subject, "json", "system", is_deleted, created_date, updated_date) VALUES(1, 'Application submission template to beneficiary and company', 'APPLICATION_SUBMISSION_TO_USER_AND_COMPANY', ' + +
+

Buongiorno,

+

+ Si comunica che, in riferimento alla domanda di concessione di + Finanziamento agevolato a valere sul Fondo prestiti + {{call_name}} di cui all''oggetto, la stessa è stata + regolarmente acquisita ed è stata registrata con Protocollo n. + {{protocol_number}} del {{date}} alle + {{time}}. +

+

Distinti Saluti,

+

+ Gepafin S.p.a. +

+
+ +', 'BANDO {{call_name}} - Domanda di concessione di finanziamento agevolato {{company_name}}', NULL, true, false, '2024-10-10 16:10:31.035', '2024-10-11 10:09:23.037'); +INSERT INTO gepafin_schema.system_email_template (id, template_name, "type", html_content, subject, "json", "system", is_deleted, created_date, updated_date) VALUES(2, 'Application submission template to gepafin', 'APPLICATION_SUBMISSION_TO_GEPAFIN', ' + +
+

+ In riferimento alla domanda di concessione di Finanziamento agevolato a valere sul Fondo prestiti + {{call_name}} di cui all’oggetto, la stessa è stata regolarmente acquisita ed è stata + registrata con Protocollo n. {{protocol_number}} del {{date}} e {{time}}. +

+

Distinti Saluti,

+

+ Gepafin S.p.a. +

+
+ +', 'BANDO {{call_name}} - Domanda di concessione di finanziamento agevolato {{company_name}}', NULL, true, false, '2024-10-10 16:10:31.035', '2024-10-11 10:09:57.224'); \ No newline at end of file From 478f16d5660481e7468ce1af1a4d9150102a42eb Mon Sep 17 00:00:00 2001 From: harish Date: Fri, 11 Oct 2024 14:25:30 +0530 Subject: [PATCH 35/50] Refactored code --- .../constants/GepafinConstant.java | 2 + .../gepafin/tendermanagement/dao/CallDao.java | 45 +++++++++++++++++++ .../repositories/DocumentRepository.java | 1 + .../tendermanagement/service/CallService.java | 2 +- .../service/impl/CallServiceImpl.java | 5 +++ .../web/rest/api/CallApi.java | 15 +++++++ .../web/rest/api/impl/CallApiController.java | 20 +++++++++ src/main/resources/message_en.properties | 3 ++ src/main/resources/message_it.properties | 3 ++ 9 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index afbfbea3..d72853c7 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -201,5 +201,7 @@ public class GepafinConstant { public static final String DELEGATION_DELETE_SUCCESS = "delegation.delete.success"; 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 CALL_DOCUMENTS_FETCH_SUCCESS_MSG = "call.documents.fetch.success"; + public static final String CALL_DOCUMENTS_NOT_FOUND_MSG = "call.documents.not.found"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index c6345d59..0827b62a 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -1,5 +1,9 @@ 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.time.LocalDate; import java.time.LocalDateTime; @@ -8,13 +12,21 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; 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.model.response.*; import net.gepafin.tendermanagement.service.*; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.Utils; +import org.h2.util.IOUtils; 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.util.StringUtils; @@ -85,6 +97,10 @@ public class CallDao { private FlowDao flowDao; @Autowired private FormDao formDao; + @Value("${aws.s3.url.folder}") + private String s3Folder; + @Autowired + private AmazonS3Service amazonS3Service; public CallResponse createCallStep1(CreateCallRequestStep1 createCallRequest, Long userId) { UserEntity userEntity = userService.validateUser(userId); @@ -101,6 +117,35 @@ public class CallDao { return createCallResponseBean; } + public byte[] downloadCallDocumentsAsZip(Long callId) { + List 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) { CallEntity callEntity = new CallEntity(); diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java index 339efd13..1543def3 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java @@ -20,6 +20,7 @@ public interface DocumentRepository extends JpaRepository Optional findByIdAndSourceIdAndIsDeletedFalse(Long id, Long sourceId); List findBySource(String source); + List findBySourceIdAndSourceAndTypeAndIsDeletedFalse(Long sourceId, String source, String type); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/CallService.java b/src/main/java/net/gepafin/tendermanagement/service/CallService.java index aa6ea872..9a62d89d 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/CallService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/CallService.java @@ -32,5 +32,5 @@ public interface CallService { CallEntity validateCall(Long callId); CallEntity validatePublishedCall(Long callId); - + byte[] downloadCallDocumentsAsZip(Long callId); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java index a6a6a901..f6ca0b66 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java @@ -92,4 +92,9 @@ public class CallServiceImpl implements CallService { public CallEntity validatePublishedCall(Long callId) { return callDao.validatePublishedCall(callId); } + @Override + @Transactional(readOnly = true) + public byte[] downloadCallDocumentsAsZip(Long callId) { + return callDao.downloadCallDocumentsAsZip(callId); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java index cc7f985a..3e2861ff 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java @@ -134,4 +134,19 @@ public interface CallApi { public ResponseEntity> updateCallStatus(HttpServletRequest request, @Parameter(description = "The call id", required = true) @PathVariable("callId") Long callId, @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 downloadCallDocumentsAsZip(HttpServletRequest httpServletRequest, + @Parameter(description = "The call ID", required = true) @PathVariable("callId") Long callId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java index e4680428..926dccab 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java @@ -4,7 +4,9 @@ import java.util.List; import net.gepafin.tendermanagement.enums.CallStatusEnum; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; @@ -84,4 +86,22 @@ public class CallApiController implements CallApi { CallResponse updateCall = callService.updateCallStatus(request, callId, status); return ResponseEntity.ok(new Response<>(updateCall, Status.SUCCESS, Translator.toLocale(GepafinConstant.UPDATE_CALL_STATUS_SUCCESS_MSG))); } + @Override + public ResponseEntity 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); + } + + } \ No newline at end of file diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 0d68c6d7..8ae7bcfa 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -226,5 +226,8 @@ user.company.relation.not.found=User with the specified company relation not fou delegation.delete.success=Delegation deleted successfully. user.not.authorized.create.application=User must be a legal representative or have delegation. 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. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 3e665e82..9b998124 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -222,5 +222,8 @@ delegation.delete.success=Delega eliminata con successo. 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. +# Call Document Messages +call.documents.fetch.success=Documenti recuperati con successo. +call.documents.not.found=Nessun documento trovato per la chiamata specificata. From d637fd70bdd5aef96b7c72d44ca1487d3b07ab97 Mon Sep 17 00:00:00 2001 From: rajesh Date: Fri, 11 Oct 2024 12:39:04 -0700 Subject: [PATCH 36/50] Added temp API to disbaled faviocn logs --- .../net/gepafin/tendermanagement/web/rest/api/UserApi.java | 6 ++++++ .../web/rest/api/impl/UserApiController.java | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java index 18281f96..6bb6a388 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java @@ -218,6 +218,12 @@ public interface UserApi { produces = { "application/json" }) ResponseEntity> validateNewUserToken(HttpServletRequest request, @Parameter(description = "The spid token", required = true) @PathVariable("token") String token); + + + + @RequestMapping("favicon.ico") + @ResponseBody + void returnNoFavicon(); diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java index ca13268a..4ffd3e87 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java @@ -140,4 +140,10 @@ public class UserApiController implements UserApi { return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MSE))); } + + @Override + public void returnNoFavicon() { + // Do nothing + } + } \ No newline at end of file From 9c4a5f3ee56b7cd50a6e2b3fd845ecb87d43a25d Mon Sep 17 00:00:00 2001 From: rajesh Date: Fri, 11 Oct 2024 17:04:00 +0530 Subject: [PATCH 37/50] updated code --- .../net/gepafin/tendermanagement/dao/ApplicationDao.java | 8 ++++++++ src/main/resources/application.properties | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index bca8f0d1..5033ee00 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -99,6 +99,12 @@ public class ApplicationDao { @Value("${gepafin_email}") private String gepafinEmail; + + @Value("${rinaldo_email}") + private String rinaldoEmail; + + @Value("${carlo_email}") + private String carloEmail; @@ -741,6 +747,8 @@ public class ApplicationDao { mailUtil.sendByMailGun(subject, body, List.of(defaultSystemReceiverEmail), null); mailUtil.sendByMailGun(subject, body, List.of(gepafinEmail), null); + mailUtil.sendByMailGun(subject, body, List.of(rinaldoEmail), null); + mailUtil.sendByMailGun(subject, body, List.of(carloEmail), null); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 0472eb61..f50d4088 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -61,4 +61,6 @@ apiKey=xkeysib-d15439fedd7ff36d86676ac248153fc2c496ed9b879ca9dc8cee9a27fa309087- isMailSendingEnabled = false default_System_Receiver_Email=attivazione@bflows.net gepafin_email=bandi@pec.gepafin.it +rinaldo_email=rinaldo.bonazzo@bflows.net +carlo_email=carlo.mancosu@bflows.net From 3102300f647cfca06dcb637ba47b6a04c16869e1 Mon Sep 17 00:00:00 2001 From: rajesh Date: Fri, 11 Oct 2024 17:20:35 +0530 Subject: [PATCH 38/50] updated code --- .../net/gepafin/tendermanagement/dao/ApplicationDao.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 5033ee00..1a621072 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -714,8 +714,11 @@ public class ApplicationDao { String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders); String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); - - mailUtil.sendByMailGun(subject, body, List.of(userEntity.getEmail()), null); + String email = userEntity.getEmail(); + if (userEntity.getBeneficiary() != null) { + email = userEntity.getBeneficiary().getEmail(); + } + mailUtil.sendByMailGun(subject, body, List.of(email), null); mailUtil.sendByMailGun(subject, body, List.of(applicationEntity.getCompany().getEmail()), null); } From e9b7a123fe46c02010a14e72d54423ae92ffe596 Mon Sep 17 00:00:00 2001 From: rajesh Date: Fri, 11 Oct 2024 18:19:24 +0530 Subject: [PATCH 39/50] Done ticket GEPAFINBE-47 --- .../gepafin/tendermanagement/constants/GepafinConstant.java | 1 + .../java/net/gepafin/tendermanagement/dao/CompanyDao.java | 5 +++-- src/main/resources/message_en.properties | 1 + src/main/resources/message_it.properties | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index d72853c7..9fdb1936 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -203,5 +203,6 @@ public class GepafinConstant { 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"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java index 728990b5..3a9b92ad 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java @@ -18,6 +18,7 @@ import net.gepafin.tendermanagement.repositories.UserWithCompanyRepository; import net.gepafin.tendermanagement.service.UserService; import net.gepafin.tendermanagement.util.Utils; 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.Status; @@ -190,8 +191,8 @@ public class CompanyDao { } public UserWithCompanyEntity validateUserWithCompny(Long userId, Long companyId) { - return userWithCompanyRepository.findByUserIdAndCompanyId(userId, companyId).orElseThrow(() -> new CustomValidationException(Status.UNAUTHORIZED, - Translator.toLocale(GepafinConstant.UNAUTHORIZED))); + return userWithCompanyRepository.findByUserIdAndCompanyId(userId, companyId).orElseThrow(() -> new ForbiddenAccessException(Status.FORBIDDEN, + Translator.toLocale(GepafinConstant.PERMISSION_DENIED))); } public UserWithCompanyEntity getUserWithCompany(Long userId, Long compnayId) { diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 8ae7bcfa..bbf010f5 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -229,5 +229,6 @@ 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. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 9b998124..2235bb51 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -225,5 +225,6 @@ application.submitted.cannot.change=La domanda inviata non pu # 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. From eb12433a31ba54fcdd57af4b128fedef3125ff58 Mon Sep 17 00:00:00 2001 From: rajesh Date: Sat, 12 Oct 2024 14:47:05 +0530 Subject: [PATCH 40/50] Done ticket GEPAFINBE-41 --- .../constants/GepafinConstant.java | 3 + .../tendermanagement/dao/ApplicationDao.java | 81 ++++++++++++++++++- .../ApplicationSignedDocumentEntity.java | 28 +++++++ .../ApplicationSignedDocumentStatusEnum.java | 18 +++++ .../ApplicationSignedDocumentResponse.java | 14 ++++ .../response/CompanyDelegationResponse.java | 3 +- .../UploadFileOnAmazonS3Response.java | 14 ++++ .../ApplicationSignedDocumentRepository.java | 13 +++ .../service/AmazonS3Service.java | 4 + .../service/ApplicationService.java | 7 ++ .../service/impl/AmazonS3ServiceImpl.java | 25 ++++++ .../service/impl/ApplicationServiceImpl.java | 16 +++- .../service/impl/CompanyServiceImpl.java | 3 +- .../tendermanagement/util/Validator.java | 5 +- .../web/rest/api/ApplicationApi.java | 27 +++++++ .../api/impl/ApplicationApiController.java | 22 +++++ src/main/resources/application.properties | 1 + .../db/changelog/db.changelog-1.0.0.xml | 25 ++++++ src/main/resources/message_en.properties | 3 + src/main/resources/message_it.properties | 3 + 20 files changed, 307 insertions(+), 8 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/ApplicationSignedDocumentEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/enums/ApplicationSignedDocumentStatusEnum.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/ApplicationSignedDocumentResponse.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/UploadFileOnAmazonS3Response.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/ApplicationSignedDocumentRepository.java diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 9fdb1936..4580af18 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -204,5 +204,8 @@ public class GepafinConstant { 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"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 634594ba..c12f6d4e 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.dao; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.*; +import net.gepafin.tendermanagement.enums.ApplicationSignedDocumentStatusEnum; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.enums.RoleStatusEnum; @@ -12,6 +13,7 @@ import net.gepafin.tendermanagement.model.request.ApplicationRequest; import net.gepafin.tendermanagement.model.request.ApplicationRequestBean; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.repositories.*; +import net.gepafin.tendermanagement.service.AmazonS3Service; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.service.DocumentService; @@ -26,10 +28,13 @@ import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; import jakarta.persistence.criteria.Predicate; +import jakarta.servlet.http.HttpServletRequest; import java.text.MessageFormat; import java.time.LocalDateTime; @@ -71,17 +76,27 @@ public class ApplicationDao { @Autowired private FlowDataRepository flowDataRepository; - @Autowired - private UserWithCompanyRepository userWithCompanyRepository; + @Autowired private UserCompanyDelegationRepository userCompanyDelegationRepository; + @Autowired private Validator validator; + @Autowired private CompanyService companyService; @Autowired private ProtocolRepository protocolRepository; + + @Autowired + 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) { @@ -663,4 +678,66 @@ public class ApplicationDao { protocolRepository.save(protocolEntity); return protocolEntity; } + + 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); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationSignedDocumentEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationSignedDocumentEntity.java new file mode 100644 index 00000000..58975cca --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationSignedDocumentEntity.java @@ -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; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationSignedDocumentStatusEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationSignedDocumentStatusEnum.java new file mode 100644 index 00000000..c0064d87 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationSignedDocumentStatusEnum.java @@ -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; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationSignedDocumentResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationSignedDocumentResponse.java new file mode 100644 index 00000000..64b380f5 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationSignedDocumentResponse.java @@ -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; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CompanyDelegationResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyDelegationResponse.java index 7c23b3b8..f1b69b33 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/CompanyDelegationResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyDelegationResponse.java @@ -3,9 +3,10 @@ package net.gepafin.tendermanagement.model.response; import lombok.Data; import net.gepafin.tendermanagement.entities.BaseEntity; import net.gepafin.tendermanagement.enums.UserCompanyDelegationStatusEnum; +import net.gepafin.tendermanagement.model.BaseBean; @Data -public class CompanyDelegationResponse extends BaseEntity{ +public class CompanyDelegationResponse extends BaseBean{ private Long userId; private Long companyId; private Long beneficiaryId; diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/UploadFileOnAmazonS3Response.java b/src/main/java/net/gepafin/tendermanagement/model/response/UploadFileOnAmazonS3Response.java new file mode 100644 index 00000000..d0d78428 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/UploadFileOnAmazonS3Response.java @@ -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; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationSignedDocumentRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationSignedDocumentRepository.java new file mode 100644 index 00000000..35322a6a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationSignedDocumentRepository.java @@ -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 findByApplicationIdAndStatus(Long applicationId, String status); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java b/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java index ce34cd7d..ea3937a3 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java +++ b/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java @@ -3,6 +3,8 @@ package net.gepafin.tendermanagement.service; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; +import net.gepafin.tendermanagement.model.response.UploadFileOnAmazonS3Response; + import java.io.IOException; import java.io.InputStream; @@ -14,4 +16,6 @@ public interface AmazonS3Service { public Boolean delete(String s3Folder, String fileName); InputStream getFile(String s3Folder, String filePath) throws IOException; + + public UploadFileOnAmazonS3Response uploadFileOnAmazonS3(String s3Folder, MultipartFile file); } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java index edb62c93..d05ee2eb 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java @@ -9,10 +9,13 @@ import net.gepafin.tendermanagement.model.request.ApplicationRequestBean; import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationResponse; import net.gepafin.tendermanagement.model.response.ApplicationResponseBean; +import net.gepafin.tendermanagement.model.response.ApplicationSignedDocumentResponse; import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse; import java.util.List; +import org.springframework.web.multipart.MultipartFile; + public interface ApplicationService { public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean,Long applicationId, Long formId); @@ -31,4 +34,8 @@ public interface ApplicationService { 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); + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java index 756e4360..a0470c15 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java @@ -2,7 +2,16 @@ package net.gepafin.tendermanagement.service.impl; import com.amazonaws.services.s3.AmazonS3; 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.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.Value; 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); } } + + @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)); + } + } } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java index a082a092..56658ee3 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java @@ -13,12 +13,14 @@ import net.gepafin.tendermanagement.model.request.ApplicationRequestBean; import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationResponse; 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.service.ApplicationService; import net.gepafin.tendermanagement.util.Validator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import java.util.List; @@ -64,7 +66,7 @@ public class ApplicationServiceImpl implements ApplicationService { @Transactional(rollbackFor = Exception.class) public ApplicationResponse createApplication(HttpServletRequest request, Long companyId, ApplicationRequest applicationRequest, Long callId) { UserEntity userEntity = validator.validateUser(request); - CompanyEntity companyEntity = validator.validateUSerWithCompany(request, companyId); + CompanyEntity companyEntity = validator.validateUserWithCompany(request, companyId); return applicationDao.createApplicationByCallId(companyEntity, applicationRequest, callId, userEntity); } @@ -87,8 +89,18 @@ public class ApplicationServiceImpl implements ApplicationService { public List getAllApplications(HttpServletRequest request, Long callId, Long companyId) { UserEntity userEntity = validator.validateUser(request); if (companyId != null) { - validator.validateUSerWithCompany(request, companyId); + validator.validateUserWithCompany(request, 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 + public ApplicationSignedDocumentResponse getSignedDocument(HttpServletRequest request, Long applicationId) { + return applicationDao.getSignedDocument(request, applicationId); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java index 1f80b223..033ddba3 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java @@ -98,7 +98,8 @@ public class CompanyServiceImpl implements CompanyService { @Override @Transactional(rollbackFor = Exception.class) 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); } diff --git a/src/main/java/net/gepafin/tendermanagement/util/Validator.java b/src/main/java/net/gepafin/tendermanagement/util/Validator.java index e123988a..bb7d4053 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Validator.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Validator.java @@ -9,6 +9,7 @@ import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.service.CompanyService; 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.UnauthorizedAccessException; @@ -60,7 +61,7 @@ public class Validator { } } - public CompanyEntity validateUSerWithCompany(HttpServletRequest request, Long companyId) { + public CompanyEntity validateUserWithCompany(HttpServletRequest request, Long companyId) { if (checkIsSuperAdmin()) { return companyService.validateCompany(companyId); } @@ -89,7 +90,7 @@ public class Validator { public UserEntity validateUserId(HttpServletRequest request, Long userId) { UserEntity user = validateUser(request); 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); } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java index 1869655c..eee93d90 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java @@ -6,6 +6,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; 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.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.ApplicationResponse; 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.util.Response; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; @@ -131,6 +134,30 @@ public interface ApplicationApi { @Parameter(description = "The application id", required = true) @PathVariable("applicationId") Long applicationId, @Parameter(description = "status", required = true)@RequestParam(value = "status", required = true) ApplicationStatusTypeEnum status); + @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> 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> getSignedDocument(HttpServletRequest request, + @Parameter(description = "The applicationId id", required = true) @PathVariable("applicationId") Long applicationId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java index bcbf8e80..b79196c3 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java @@ -10,6 +10,8 @@ import net.gepafin.tendermanagement.model.request.ApplicationRequestBean; import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationResponse; 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.util.Response; import net.gepafin.tendermanagement.service.ApplicationService; @@ -21,6 +23,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; import org.slf4j.Logger; import java.util.List; @@ -89,4 +92,23 @@ public class ApplicationApiController implements ApplicationApi { return ResponseEntity.status(HttpStatus.OK) .body(new Response<>(applicationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_STATUS_UPDATED_SUCCESSFULLY))); } + + @Override + public ResponseEntity> 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> 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))); + } + } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 27151cbc..175c7e6c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -32,6 +32,7 @@ aws.s3.bucket.name=mementoresources aws.s3.url = https://mementoresources.s3.eu-west-1.amazonaws.com/ aws.s3.url.folder=gepafin aws.s3.url.folder.delegation=gepafin/delegation +aws.s3.url.folder.signed.document=gepafin/signed-document # JWT configuration # Ensure these values match your expectations security.authentication.jwt.secret=my-secret-token-to-change-in-prod-environment-your-super-secure-randomly-generated-key diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 98016d3c..a1369e93 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -973,4 +973,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index bbf010f5..49208615 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -230,5 +230,8 @@ application.submitted.cannot.change=The submitted application cannot be changed. 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. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 2235bb51..7fe8f0ff 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -226,5 +226,8 @@ application.submitted.cannot.change=La domanda inviata non pu 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. From 628a350959bd4b4bcf5efeb1f553cd29d5685f56 Mon Sep 17 00:00:00 2001 From: rajesh Date: Sat, 12 Oct 2024 15:19:35 +0530 Subject: [PATCH 41/50] updated code --- .../constants/GepafinConstant.java | 1 + .../tendermanagement/dao/ApplicationDao.java | 14 ++++++++++++++ .../service/ApplicationService.java | 2 ++ .../service/impl/ApplicationServiceImpl.java | 8 ++++++++ .../web/rest/api/ApplicationApi.java | 11 +++++++++++ .../rest/api/impl/ApplicationApiController.java | 9 +++++++++ src/main/resources/message_en.properties | 1 + src/main/resources/message_it.properties | 1 + 8 files changed, 47 insertions(+) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 4580af18..13ca091b 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -207,5 +207,6 @@ public class GepafinConstant { 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"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index c12f6d4e..c79f7f99 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -740,4 +740,18 @@ public class ApplicationDao { } 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); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java index d05ee2eb..2d914b64 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java @@ -38,4 +38,6 @@ public interface ApplicationService { public ApplicationSignedDocumentResponse getSignedDocument(HttpServletRequest request, Long applicationId); + public void deleteSignedDocument(HttpServletRequest request, Long applicationId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java index 56658ee3..faa890d3 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java @@ -100,7 +100,15 @@ public class ApplicationServiceImpl implements ApplicationService { } @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); + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java index eee93d90..e19484b1 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java @@ -157,6 +157,17 @@ public interface ApplicationApi { @GetMapping(value = "{applicationId}/signedDocument", produces = "application/json") ResponseEntity> 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> deleteSignedDocument(HttpServletRequest request, + @Parameter(description = "The applicationId id", required = true) @PathVariable("applicationId") Long applicationId); } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java index b79196c3..85c1efbb 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java @@ -110,5 +110,14 @@ public class ApplicationApiController implements ApplicationApi { return ResponseEntity.status(HttpStatus.OK) .body(new Response<>(response, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_SIGNED_DOCUMENT_FILE_SUCCESS))); } + + @Override + public ResponseEntity> 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))); + } } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 49208615..d09b9d29 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -233,5 +233,6 @@ 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. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 7fe8f0ff..1b9b3203 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -229,5 +229,6 @@ 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. From b6f16d388e0a923172d9ab1dce6dcb004f7acaad Mon Sep 17 00:00:00 2001 From: nisha Date: Sat, 12 Oct 2024 15:43:38 +0530 Subject: [PATCH 42/50] Done ticket --- pom.xml | 20 + .../gepafin/tendermanagement/dao/PdfDao.java | 574 ++++++++++++++++++ .../tendermanagement/dao/RoundedCorners.java | 45 ++ .../model/request/CustomPageEvent.java | 71 +++ .../request/FieldLabelValuePairRequest.java | 14 + .../tendermanagement/service/PdfService.java | 9 + .../service/impl/PdfServiceImpl.java | 25 + .../tendermanagement/web/rest/api/PdfApi.java | 35 ++ .../web/rest/api/impl/PdfController.java | 40 ++ 9 files changed, 833 insertions(+) create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/RoundedCorners.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/CustomPageEvent.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/FieldLabelValuePairRequest.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/PdfService.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/PdfServiceImpl.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/PdfApi.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/PdfController.java diff --git a/pom.xml b/pom.xml index b0a632d8..9a6ef12d 100644 --- a/pom.xml +++ b/pom.xml @@ -185,6 +185,26 @@ 2.3.0
+ + com.itextpdf + itextpdf + 5.5.13.3 + + + + + com.itextpdf + itext7-core + 8.0.5 + pom + + + + + com.itextpdf + layout + 8.0.5 + diff --git a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java new file mode 100644 index 00000000..11e39dc4 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java @@ -0,0 +1,574 @@ +package net.gepafin.tendermanagement.dao; + +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 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.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 ApplicationRepository applicationRepository; + + @Autowired + private CallService callService; + + @Autowired + private ApplicationDao applicationDao; + + + public byte[] generatePdf(UserEntity userEntity,Long applicationId) { + try { + ApplicationEntity applicationEntity = applicationRepository + .findByIdAndUserIdAndIsDeletedFalse(applicationId, userEntity.getId()) + .orElseThrow(() -> new ResourceNotFoundException( + Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG) + )); + + CompanyEntity companyEntity=applicationEntity.getCompany(); + 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 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 dell’adeguatezza dei flussi finanziari + Paragraph p3 = new Paragraph(); + p3.add(new Chunk("3. ", boldSmallFont)); + p3.add(new Chunk("Dati richiesti per la valutazione dell’adeguatezza dei flussi finanziari prospettici come da tabella di cui all’Appendice 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 + List values = (List) 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> dataList = (List>) value; // Cast Object to List of Maps + for (Map 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> extractedData = new ArrayList<>(); // To hold extracted data + for (Map entry : dataList) { + Map extractedMap = new HashMap<>(); // To hold the current extracted row of data + + List 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> 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 row : extractedData) { + for (Map.Entry 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 getFormFieldsToLabels(FormApplicationResponse responseBean) { + List labelValuePairs = new ArrayList<>(); + + // Iterate through each form in the application response + + List formFields = responseBean.getFormFields(); + List 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 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 + if (fieldValue instanceof List && ((List) fieldValue).stream().allMatch(item -> item instanceof DocumentResponseBean)) { + // Step 2: Safely cast to List + List documentList = (List) fieldValue; + + // Step 3: Extract names from the document list + List names = documentList.stream() + .map(DocumentResponseBean::getName) // Extract the name from each DocumentResponseBean + .collect(Collectors.toList()); + + fieldValue=names; + } + } + if(name.equals("checkboxes")) { + List check = (List) fieldValue; + List settingResponseBeans = matchingContent.get().getSettings(); + for (SettingResponseBean settingResponseBean : settingResponseBeans) { + // Initialize a list to hold matched labels for each SettingResponseBean + List matchedLabels = new ArrayList<>(); + if (settingResponseBean.getValue() instanceof List) { + + List valueList = (List) settingResponseBean.getValue(); + if (!valueList.isEmpty() && valueList.get(0) instanceof Map) { + // Cast to List> + List> options = (List>) valueList; + for (Map 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()) { + labelValuePairs.add(new FieldLabelValuePairRequest(label, fieldValue)); + } + } + } + + return labelValuePairs; + } + 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) + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/dao/RoundedCorners.java b/src/main/java/net/gepafin/tendermanagement/dao/RoundedCorners.java new file mode 100644 index 00000000..9aa82dc1 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/RoundedCorners.java @@ -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(); + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CustomPageEvent.java b/src/main/java/net/gepafin/tendermanagement/model/request/CustomPageEvent.java new file mode 100644 index 00000000..72aef09a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CustomPageEvent.java @@ -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; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/FieldLabelValuePairRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/FieldLabelValuePairRequest.java new file mode 100644 index 00000000..8eb5f7b5 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/FieldLabelValuePairRequest.java @@ -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; +} + diff --git a/src/main/java/net/gepafin/tendermanagement/service/PdfService.java b/src/main/java/net/gepafin/tendermanagement/service/PdfService.java new file mode 100644 index 00000000..e4e6b528 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/PdfService.java @@ -0,0 +1,9 @@ +package net.gepafin.tendermanagement.service; + +import jakarta.servlet.http.HttpServletRequest; + + +public interface PdfService { + + public byte[] generatePdf(HttpServletRequest request, Long applicationId); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/PdfServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/PdfServiceImpl.java new file mode 100644 index 00000000..3e6951f1 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/PdfServiceImpl.java @@ -0,0 +1,25 @@ +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) { + UserEntity userEntity = validator.validateUser(request); + return pdfDao.generatePdf(userEntity,applicationId); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/PdfApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/PdfApi.java new file mode 100644 index 00000000..a8f7ea48 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/PdfApi.java @@ -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 generateApplicationPdf( + HttpServletRequest request, + @Parameter(description = "The application id", required = true) + @PathVariable(value = "applicationId", required = true) Long applicationId); +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/PdfController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/PdfController.java new file mode 100644 index 00000000..f14451ed --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/PdfController.java @@ -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 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); + } +} + From 4fa213823300a611578748840b6ead006ffed6a7 Mon Sep 17 00:00:00 2001 From: nisha Date: Sat, 12 Oct 2024 16:00:21 +0530 Subject: [PATCH 43/50] Updated code --- .../web/rest/api/ApplicationApi.java | 18 +++++- .../api/impl/ApplicationApiController.java | 61 +++++++++++++------ 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java index 1869655c..bfefce4f 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java @@ -130,7 +130,23 @@ public interface ApplicationApi { ResponseEntity> updateApplicationStatus(HttpServletRequest request, @Parameter(description = "The application id", required = true) @PathVariable("applicationId") Long applicationId, @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 generateApplicationPdf( + HttpServletRequest request, + @Parameter(description = "The application id", required = true) + @PathVariable(value = "applicationId", required = true) Long applicationId); } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java index bcbf8e80..4de81e0b 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java @@ -13,11 +13,14 @@ import net.gepafin.tendermanagement.model.response.ApplicationResponseBean; import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse; import net.gepafin.tendermanagement.model.util.Response; 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.errors.Status; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -35,17 +38,21 @@ public class ApplicationApiController implements ApplicationApi { @Autowired private ApplicationService applicationService; + @Autowired + private PdfService pdfService; + @Override - public ResponseEntity> createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean,Long applicationId, Long formId) { - ApplicationResponseBean applicationResponseBean= applicationService.createApplication(request,applicationRequestBean,applicationId,formId); + public ResponseEntity> createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long applicationId, Long formId) { + ApplicationResponseBean applicationResponseBean = applicationService.createApplication(request, applicationRequestBean, applicationId, formId); 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 public ResponseEntity> getApplicationByFormId(HttpServletRequest request - , Long applicationId,Long formId) { + , Long applicationId, Long formId) { 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) .body(new Response<>(application, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG))); } @@ -54,39 +61,55 @@ public class ApplicationApiController implements ApplicationApi { public ResponseEntity> deleteApplication(HttpServletRequest request, Long applicationId) { log.info("Delete Application - Application ID: {}", applicationId); - applicationService.deleteApplication(request,applicationId); + applicationService.deleteApplication(request, applicationId); return ResponseEntity.status(HttpStatus.OK) .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELETE_APPLICATION_SUCCESS_MSG))); } @Override public ResponseEntity> 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) .body(new Response<>(applicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_CREATED_SUCCESS_MSG))); } + @Override - public ResponseEntity>> getAllApplications(HttpServletRequest request,Long callId,Long companyId) { - List applications = applicationService.getAllApplications(request,callId,companyId); + public ResponseEntity>> getAllApplications(HttpServletRequest request, Long callId, Long companyId) { + List applications = applicationService.getAllApplications(request, callId, companyId); log.info("Get All Applications"); return ResponseEntity.status(HttpStatus.OK) .body(new Response<>(applications, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG))); } - + @Override - public ResponseEntity> getNextOrPreviousForm(HttpServletRequest request,Long applicationId, - Long formId, FormActionEnum action) { - NextOrPreviousFormResponse data = applicationService.getNextOrPreviousForm(request, applicationId, formId, action); - log.info("Get Next Or Previous Form "); + public ResponseEntity> getNextOrPreviousForm(HttpServletRequest request, Long applicationId, + Long formId, FormActionEnum action) { + NextOrPreviousFormResponse data = applicationService.getNextOrPreviousForm(request, applicationId, formId, action); + log.info("Get Next Or Previous Form "); return ResponseEntity.status(HttpStatus.OK) .body(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG))); } - + @Override public ResponseEntity> updateApplicationStatus(HttpServletRequest request, Long applicationId, - ApplicationStatusTypeEnum status) { + ApplicationStatusTypeEnum status) { ApplicationResponse applicationResponse = applicationService.updateApplicationStatus(request, applicationId, status); - return ResponseEntity.status(HttpStatus.OK) - .body(new Response<>(applicationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_STATUS_UPDATED_SUCCESSFULLY))); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(applicationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_STATUS_UPDATED_SUCCESSFULLY))); } -} + + @Override + public ResponseEntity 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); + } +} \ No newline at end of file From 95251f82dde8601468af27a3b0b27a0a26187865 Mon Sep 17 00:00:00 2001 From: rajesh Date: Sat, 12 Oct 2024 16:44:35 +0530 Subject: [PATCH 44/50] updated code --- .../web/rest/api/impl/ApplicationApiController.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java index 34920076..f6e6d1e5 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java @@ -11,7 +11,6 @@ import net.gepafin.tendermanagement.model.response.ApplicationGetResponseBean; import net.gepafin.tendermanagement.model.response.ApplicationResponse; 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.util.Response; import net.gepafin.tendermanagement.service.ApplicationService; @@ -115,7 +114,6 @@ public class ApplicationApiController implements ApplicationApi { .contentType(MediaType.APPLICATION_PDF) .body(pdfBytes); } -} @Override public ResponseEntity> uploadSignedDocument(HttpServletRequest request, From 1227632681d50cbc6e068e02ed9ed24f55876524 Mon Sep 17 00:00:00 2001 From: rajesh Date: Sat, 12 Oct 2024 17:59:19 +0530 Subject: [PATCH 45/50] updated docker script --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index ceacf16e..18ed6c1a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,5 @@ FROM amazoncorretto:17.0.8-alpine3.17 +ENV TZ="Europe/Rome" EXPOSE 8080 ADD /target/tendermanagement-0.0.1-SNAPSHOT.jar tendermanagement-0.0.1-SNAPSHOT.jar ENTRYPOINT ["java", "-jar","tendermanagement-0.0.1-SNAPSHOT.jar"] From f0d1af18421d54db9a93e14afecbb0c03a65fe7e Mon Sep 17 00:00:00 2001 From: rajesh Date: Sat, 12 Oct 2024 18:41:05 +0530 Subject: [PATCH 46/50] updated code for pdf --- .../gepafin/tendermanagement/dao/PdfDao.java | 52 ++++++++++++++----- .../service/impl/PdfServiceImpl.java | 3 +- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java index 11e39dc4..30e10fe8 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java @@ -1,5 +1,7 @@ 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; @@ -12,6 +14,8 @@ 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.*; @@ -20,6 +24,7 @@ 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; @@ -38,26 +43,21 @@ import java.util.stream.Collectors; @Component public class PdfDao { - @Autowired - private ApplicationRepository applicationRepository; - @Autowired private CallService callService; @Autowired private ApplicationDao applicationDao; + + @Autowired + private Validator validator; - public byte[] generatePdf(UserEntity userEntity,Long applicationId) { + public byte[] generatePdf(HttpServletRequest request,Long applicationId) { try { - ApplicationEntity applicationEntity = applicationRepository - .findByIdAndUserIdAndIsDeletedFalse(applicationId, userEntity.getId()) - .orElseThrow(() -> new ResourceNotFoundException( - Status.NOT_FOUND, - Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG) - )); - - CompanyEntity companyEntity=applicationEntity.getCompany(); + 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 @@ -127,7 +127,7 @@ public class PdfDao { // addLabelValuePair(document, "Con il titolo di", "Rappresentante legale", regularFont); document.add(new Paragraph(" ")); - ApplicationGetResponseBean applicationGetResponseBean=applicationDao.getApplicationByFormId(applicationId,null,userEntity); + 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 @@ -534,6 +534,7 @@ public class PdfDao { 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)); } } @@ -541,6 +542,31 @@ public class PdfDao { return labelValuePairs; } + + public static Object findLabelInOptions(List 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 diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/PdfServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/PdfServiceImpl.java index 3e6951f1..b075584d 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/PdfServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/PdfServiceImpl.java @@ -19,7 +19,6 @@ public class PdfServiceImpl implements PdfService { @Override public byte[] generatePdf(HttpServletRequest request, Long applicationId) { - UserEntity userEntity = validator.validateUser(request); - return pdfDao.generatePdf(userEntity,applicationId); + return pdfDao.generatePdf(request, applicationId); } } From 7fd5a4cb27ac493d3f144fcec9374de6f69ca9dc Mon Sep 17 00:00:00 2001 From: nisha Date: Sun, 13 Oct 2024 04:39:24 +0530 Subject: [PATCH 47/50] Corrected code for page number in pdf --- .../gepafin/tendermanagement/dao/PdfDao.java | 49 +++++++++++++------ .../dao/PdfPageNumberInserter.java | 45 +++++++++++++++++ 2 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/PdfPageNumberInserter.java diff --git a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java index 30e10fe8..f12941bf 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java @@ -36,6 +36,8 @@ import com.itextpdf.layout.element.Cell; import java.awt.*; import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.*; import java.util.List; import java.util.stream.Collectors; @@ -66,10 +68,10 @@ public class PdfDao { 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); +// CustomPageEvent pageEvent = new CustomPageEvent(call.getName(), 0); +// writer.setPageEvent(pageEvent); document.open(); - pageEvent.setTotalPages(writer.getPageNumber()); +// pageEvent.setTotalPages(writer.getPageNumber()); addLogo(document, "https://mementoresources.s3.eu-west-1.amazonaws.com/gepafin/logo.jpg"); // Add your image path here @@ -91,7 +93,7 @@ public class PdfDao { document.add(new Paragraph(" ")); // Application ID section (Centered) - pageEvent.setTotalPages(writer.getPageNumber()); +// pageEvent.setTotalPages(writer.getPageNumber()); Paragraph appId = new Paragraph("ID domanda :" +"XX00"); appId.setAlignment(Element.ALIGN_RIGHT); document.add(appId); @@ -138,7 +140,7 @@ public class PdfDao { Integer pages=0; pages=addLabelValuePair(writer,document, label, value, labelFont,valueFont,call.getName(),pages); if(pages !=0 ){ - pageEvent.setTotalPages(writer.getPageNumber()); +// pageEvent.setTotalPages(writer.getPageNumber()); } } addColoredLines(writer,document,greenColor); @@ -150,8 +152,9 @@ public class PdfDao { // Adding the "Documenti Allegati" section title document.add(new Paragraph(" ")); - pageEvent.setTotalPages(writer.getPageNumber()); +// pageEvent.setTotalPages(writer.getPageNumber()); document.newPage(); +// pageEvent.setTotalPages(writer.getPageNumber()); document.add(new Paragraph("Documenti Allegati", sectionFont)); document.add(new Paragraph(" ")); @@ -215,11 +218,20 @@ public class PdfDao { addColoredLines(writer,document,greenColor); +// System.out.println(writer.getPageSize()); +// System.out.println(document.getPageSize()); +// System.out.println(document.getPageNumber()); +// System.out.println(writer.getPageNumber()); +// document.setPageCount(100); +// document.setPageCount(writer.getPageNumber()); +// System.out.println(document.getPageNumber()); + // Close the document document.close(); // Convert to byte array for response - byte[] pdfBytes = out.toByteArray(); + byte[] pdfBytes =PdfPageNumberInserter.addPageNumbers(out.toByteArray()); + return pdfBytes; } catch (Exception e) { e.printStackTrace(); @@ -308,7 +320,7 @@ public class PdfDao { 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 + String combinedValue = number + "; " + description + "; " + amount; // Concatenate them as a single value extractedMap.put("combined", combinedValue); // Store as a single entry, key as "combined" } @@ -380,14 +392,14 @@ public class PdfDao { } // Split the value for "combined" into separate parts - String[] combinedValues = value.split(", "); + 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 number = combinedValues[0]; // 1st part (number) + String description = combinedValues[1]; // 2nd part (description) String amount = ""; if (combinedValues.length == 3) { - amount = combinedValues[2].trim(); // 3rd part (amount) + amount = combinedValues[2]; // 3rd part (amount) } // Create PDF cells using the split values @@ -401,9 +413,14 @@ public class PdfDao { cellAmount.setBackgroundColor(new BaseColor(239, 243, 248)); // Set cell height and add rounded borders - cellNumber.setFixedHeight(rowHeight); - cellDescription.setFixedHeight(rowHeight); - cellAmount.setFixedHeight(rowHeight); +// cellNumber.setFixedHeight(rowHeight); +// cellDescription.setFixedHeight(rowHeight); +// cellAmount.setFixedHeight(rowHeight); + + cellNumber.setMinimumHeight(20f); // Set minimum height for better appearance + cellDescription.setMinimumHeight(20f); // Set minimum height for better appearance + cellAmount.setMinimumHeight(20f); // Set minimum height for better appearance + cellNumber.setPadding(7f); cellDescription.setPadding(7f); cellAmount.setPadding(7f); @@ -441,6 +458,8 @@ public class PdfDao { cellKey.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for other rows cellValue.setBackgroundColor(new BaseColor(239, 243, 248)); + cellKey.setPadding(7f); + cellValue.setPadding(7f); // Set cell height and add rounded borders cellKey.setFixedHeight(rowHeight); cellValue.setFixedHeight(rowHeight); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/PdfPageNumberInserter.java b/src/main/java/net/gepafin/tendermanagement/dao/PdfPageNumberInserter.java new file mode 100644 index 00000000..0ac9ce20 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/PdfPageNumberInserter.java @@ -0,0 +1,45 @@ +package net.gepafin.tendermanagement.dao; +import com.itextpdf.text.BaseColor; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.Font; +import com.itextpdf.text.FontFactory; +import com.itextpdf.text.pdf.BaseFont; +import com.itextpdf.text.pdf.PdfReader; +import com.itextpdf.text.pdf.PdfStamper; +import com.itextpdf.text.pdf.PdfContentByte; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class PdfPageNumberInserter { + + public static byte[] addPageNumbers(byte[] pdfData) throws IOException, DocumentException { + PdfReader reader = new PdfReader(pdfData); // Read the generated PDF + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BaseColor darkGreenColor = new BaseColor(1, 50, 32); // Adjust RGB values as needed + Font baseFont = FontFactory.getFont(FontFactory.HELVETICA, 4,darkGreenColor); + BaseFont font = baseFont.getBaseFont(); + + // PdfStamper allows us to modify the existing PDF + PdfStamper stamper = new PdfStamper(reader, outputStream); + int totalPages = reader.getNumberOfPages(); + + // Set the font for page numbers + + for (int i = 1; i <= totalPages; i++) { + // Get the content of the current page + PdfContentByte over = stamper.getOverContent(i); + over.beginText(); + over.setFontAndSize(font, 12); + + // Add the page number at the bottom center of the page + over.showTextAligned(PdfContentByte.ALIGN_CENTER, "Page " + i + " of " + totalPages, 300, 30, 0); + + over.endText(); + } + + stamper.close(); + reader.close(); + + return outputStream.toByteArray(); // Return the modified PDF with page numbers + } +} From 115614329c0aab69e8aa84567bb37277d7c5c0fd Mon Sep 17 00:00:00 2001 From: rajesh Date: Sun, 13 Oct 2024 14:00:47 +0530 Subject: [PATCH 48/50] Fixed upload Signed Document issue --- .../java/net/gepafin/tendermanagement/dao/ApplicationDao.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 879c12b2..6963f3e0 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -94,7 +94,6 @@ public class ApplicationDao { private ProtocolRepository protocolRepository; @Autowired - private SystemEmailTemplatesService systemEmailTemplatesService; @Autowired @@ -112,6 +111,7 @@ public class ApplicationDao { @Value("${carlo_email}") private String carloEmail; + @Autowired private AmazonS3Service amazonS3Service; @Autowired From 34a2803c4afa10ca0bbb8552abd4426d6a824eb5 Mon Sep 17 00:00:00 2001 From: rajesh Date: Sun, 13 Oct 2024 15:25:18 +0530 Subject: [PATCH 49/50] Fixed issue related to creating multiple applications per user based on their company --- .../net/gepafin/tendermanagement/dao/ApplicationDao.java | 6 +++--- .../repositories/ApplicationRepository.java | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 6963f3e0..6d7619d6 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -560,15 +560,15 @@ public class ApplicationDao { ApplicationRequest applicationRequest, Long callId, UserEntity userEntity) { CallEntity call = callService.validateCall(callId); // call = callService.validatePublishedCall(call.getId()); - checkIfApplicationExists(call, companyEntity); + checkIfApplicationExists(call, companyEntity, userEntity); ApplicationEntity applicationEntity = createApplicationEntity(userEntity, call, companyEntity); applicationEntity.setComments(applicationRequest.getComments()); applicationEntity = saveApplicationEntity(applicationEntity); ApplicationResponse applicationResponse = getApplicationResponse(applicationEntity); return applicationResponse; } - public void checkIfApplicationExists(CallEntity call, CompanyEntity companyEntity){ - Optional applicationEntity=applicationRepository.findByCompanyIdAndCallIdAndIsDeletedFalse(companyEntity.getId(),call.getId()); + public void checkIfApplicationExists(CallEntity call, CompanyEntity companyEntity, UserEntity userEntity){ + Optional applicationEntity=applicationRepository.findByUserIdAndCompanyIdAndCallIdAndIsDeletedFalse(userEntity.getId(), companyEntity.getId(),call.getId()); if(applicationEntity.isPresent()){ throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_EXISTS)); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java index 567c8198..a1c3a474 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java @@ -1,7 +1,6 @@ package net.gepafin.tendermanagement.repositories; import net.gepafin.tendermanagement.entities.ApplicationEntity; -import net.gepafin.tendermanagement.entities.FaqEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; @@ -25,7 +24,7 @@ public interface ApplicationRepository extends JpaRepository findByIdAndUserIdAndIsDeletedFalse(Long id,Long userId); - Optional findByCompanyIdAndCallIdAndIsDeletedFalse(Long companyId, Long callId); + Optional findByUserIdAndCompanyIdAndCallIdAndIsDeletedFalse(Long userId, Long companyId, Long callId); public Optional findByIdAndUserIdAndCallIdAndIsDeletedFalse(Long applicationId, Long userId, Long callId); From daaac744cf74739df1ee45145911c2846c10b8b7 Mon Sep 17 00:00:00 2001 From: rajesh Date: Sun, 13 Oct 2024 15:48:13 +0530 Subject: [PATCH 50/50] updated form_filed for table --- src/main/resources/db/changelog/db.changelog-1.0.0.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 86f1097e..0f6aeeb2 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -1019,7 +1019,13 @@ referencedColumnNames="ID" constraintName="fk_application_signed_document_application"/> - + + + + + name='table' + +