Merge pull request #120 from Kitzanos/feature/GEPAFINBE-106
GEPAFINBE-106 (Create Appointments (Only for Hub Gepafin))
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -88,8 +88,8 @@
|
|||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.amazonaws</groupId>
|
<groupId>com.amazonaws</groupId>
|
||||||
<artifactId>aws-java-sdk-s3</artifactId>
|
<artifactId>aws-java-sdk</artifactId>
|
||||||
<version>1.12.312</version>
|
<version>1.12.563</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package net.gepafin.tendermanagement.constants;
|
||||||
|
|
||||||
|
public class AppointmentApiConstant {
|
||||||
|
|
||||||
|
public static final String ODESSA_LOGIN = "/WSGatewayLogin.apiLogin";
|
||||||
|
public static final String GET_NDG_BY_VAT_NUMBER = "/WSAnagrafica.getListaNdg";
|
||||||
|
public static final String CREATE_VISURA = "/WSAnagrafica.createVisura";
|
||||||
|
public static final String GET_VISURA_LIST = "/WSAnagrafica.getVisuraList";
|
||||||
|
public static final String GET_APPOINTMENT_TEMPLATE = "/WSCrmConsulenza.getAppuntamentoTemplate?idAppuntamentoTemplate=7";
|
||||||
|
public static final String CREATE_APPOINTMENT_FROM_TEMPLATE = "/WSCrmConsulenza.createAppointmentFromTemplate";
|
||||||
|
public static final String UPLOAD_APOOINTMENT_DOCUMENT = "/WSDocumentDetail.createStream";
|
||||||
|
|
||||||
|
//get ndg number
|
||||||
|
public static final int TARGET_PAGE_SIZE = 1;
|
||||||
|
public static final int RECORD_PER_PAGE_SIZE = 10;
|
||||||
|
|
||||||
|
//create visura request Body constant
|
||||||
|
public static final boolean CREA_ANAGRAFICA = Boolean.TRUE;
|
||||||
|
public static final boolean SALVA_DOCUMENTI = Boolean.TRUE;
|
||||||
|
public static final String VISURA_PROVIDER = "cerved";
|
||||||
|
public static final String VISURA_TYPE = "StandardReport";
|
||||||
|
public static final String VISURA_MODE = "visure";
|
||||||
|
public static final String COD_AGENTE = "UtenzaAPIPortal";
|
||||||
|
public static final boolean IS_FROM_RATING = Boolean.FALSE;
|
||||||
|
public static final boolean IS_ANAGRAFICA_LEGAME = Boolean.FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -306,5 +306,37 @@ public class GepafinConstant {
|
|||||||
public static final String LOGIN_ATTEMPT_ID = "loginAttemptId";
|
public static final String LOGIN_ATTEMPT_ID = "loginAttemptId";
|
||||||
public static final String USER_ACTION_ID = "userActionId";
|
public static final String USER_ACTION_ID = "userActionId";
|
||||||
public static final String ATLEAST_ONE_ID_REQUIRED="atleast.one.id.required";
|
public static final String ATLEAST_ONE_ID_REQUIRED="atleast.one.id.required";
|
||||||
|
|
||||||
|
//Appointment
|
||||||
|
public static final String NDG_IN_PROGRESS = "IN_PROGRESS";
|
||||||
|
public static final String NDG_AVAILABLE = "ndg.available";
|
||||||
|
public static final String NDG_GENERATION_IS_IN_PROGRESS = "ndg.generation.in.progress";
|
||||||
|
public static final String NDG_GENERATED = "NDG_GENERATED";
|
||||||
|
public static final String NDG_NOT_FOUND_FOR_APPLICATION = "ndg.not.found.for.this.application.or.invalid";
|
||||||
|
public static final String APPOINTMENT_ALREADY_CREATED = "appointment.already.created";
|
||||||
|
public static final String EXTERNAL_DOCUMENT_UPLOAD_FAILURE_MSG = "document.not.uploaded.to.external.system.please.try.again";
|
||||||
|
public static final String PROVIDE_VALID_APPLICATION_DOC_ID = "provide.valid.application.document.id";
|
||||||
|
public static final String DOCUMENT_UPLOADED_SUCCESSFULLY_TO_EXTERNAL_SYSTEM = "document.uploaded.successfully.to.external.system";
|
||||||
|
public static final String ERROR_UPLOADING_DOCUMENT = "error.in.uploading.document.check.input";
|
||||||
|
public static final String DOCUMENT_ALREADY_UPLOADED = "document.already.uploaded";
|
||||||
|
public static final String NDG_NOT_MATCHED_OR_NOT_FOUND = "ndg.not.found.or.not.matched";
|
||||||
|
public static final String NO_NDG_FOR_ANOTHER_HUB = "ndg.generation.is.only.for.gepafin";
|
||||||
|
public static final String NO_APPOINTMENT_FOR_ANOTHER_HUB = "appointment.creation.is.only.for.gepafin";
|
||||||
|
public static final String NO_DOCUMENT_UPLOAD_FOR_ANOTHER_HUB = "upload.document.is.only.for.gepafin";
|
||||||
|
public static final String APPOINTMENT_CREATED = "appointment.created.successfully";
|
||||||
|
public static final String DATA_STRING = "data";
|
||||||
|
public static final String DOCUMENT_ATTACHMENT_ID_STRING = "documentAttachmentId";
|
||||||
|
public static final String TEMP_FILE_PATH = "/tmp/";
|
||||||
|
public static final String RICHIESTA_CLIENTE_STRING = "richiestaCliente";
|
||||||
|
public static final String ID_STRING = "id";
|
||||||
|
public static final String NULL_STRING = "null";
|
||||||
|
public static final String NDG_STRING = "ndg";
|
||||||
|
public static final String ID_VISURA_STRING = "idVisura";
|
||||||
|
public static final String NDG_FETCH_SUCCESSFULLY = "ndg.fetch.successfully";
|
||||||
|
public static final String AUTH_JWT_SECRET_KEY = "hTa5qe$af/4',BFs";
|
||||||
|
public static final String JWT_ALGO_HEADER = "{\"alg\":\"HS256\",\"typ\":\"JWT\"}";
|
||||||
|
public static final String HMAC_ALGO = "HmacSHA256";
|
||||||
|
public static final String ERROR_IN_GENERATING_NDG_TRY_AGAIN = "error.try.again";
|
||||||
|
public static final String POLLING_THREAD_NAME = "Ndg-Polling-Thread-";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -830,6 +830,9 @@ public class ApplicationDao {
|
|||||||
if (status.equals(ApplicationStatusTypeEnum.DRAFT) && Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.AWAITING.getValue()))) {
|
if (status.equals(ApplicationStatusTypeEnum.DRAFT) && Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.AWAITING.getValue()))) {
|
||||||
applicationEntity.setStatus(status.getValue());
|
applicationEntity.setStatus(status.getValue());
|
||||||
}
|
}
|
||||||
|
if(status.equals(ApplicationStatusTypeEnum.ADMISSIBLE) && Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.APPOINTMENT.getValue()))){
|
||||||
|
applicationEntity.setStatus(status.getValue());
|
||||||
|
}
|
||||||
applicationEntity = applicationRepository.save(applicationEntity);
|
applicationEntity = applicationRepository.save(applicationEntity);
|
||||||
|
|
||||||
if (!status.equals(ApplicationStatusTypeEnum.SUBMIT)) {
|
if (!status.equals(ApplicationStatusTypeEnum.SUBMIT)) {
|
||||||
|
|||||||
@@ -0,0 +1,889 @@
|
|||||||
|
package net.gepafin.tendermanagement.dao;
|
||||||
|
|
||||||
|
import com.amazonaws.services.s3.AmazonS3Client;
|
||||||
|
import com.amazonaws.services.s3.model.GetObjectRequest;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import feign.FeignException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.gepafin.tendermanagement.config.Translator;
|
||||||
|
import net.gepafin.tendermanagement.constants.AppointmentApiConstant;
|
||||||
|
import net.gepafin.tendermanagement.constants.GepafinConstant;
|
||||||
|
import net.gepafin.tendermanagement.entities.ApplicationEntity;
|
||||||
|
import net.gepafin.tendermanagement.entities.CompanyEntity;
|
||||||
|
import net.gepafin.tendermanagement.entities.DocumentEntity;
|
||||||
|
import net.gepafin.tendermanagement.entities.HubEntity;
|
||||||
|
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
|
||||||
|
import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum;
|
||||||
|
import net.gepafin.tendermanagement.enums.VersionActionTypeEnum;
|
||||||
|
import net.gepafin.tendermanagement.model.request.AppointmentCreationRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.AppointmentNdgRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.AppointmentVisuraListRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.AppointmentVisuraRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.CreateAppointmentRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.UploadDocToExternalSystemRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.VersionHistoryRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.response.AppointmentCreationResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.response.AppointmentLoginResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.response.DocumentUploadResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.response.NdgResponse;
|
||||||
|
import net.gepafin.tendermanagement.repositories.ApplicationRepository;
|
||||||
|
import net.gepafin.tendermanagement.repositories.CompanyRepository;
|
||||||
|
import net.gepafin.tendermanagement.repositories.DocumentRepository;
|
||||||
|
import net.gepafin.tendermanagement.repositories.HubRepository;
|
||||||
|
import net.gepafin.tendermanagement.service.ApplicationService;
|
||||||
|
import net.gepafin.tendermanagement.service.CompanyService;
|
||||||
|
import net.gepafin.tendermanagement.service.feignClient.AppointmentApiService;
|
||||||
|
import net.gepafin.tendermanagement.util.LoggingUtil;
|
||||||
|
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.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.mock.web.MockMultipartFile;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class AppointmentDao {
|
||||||
|
|
||||||
|
@Value("${appointment.portal.user}")
|
||||||
|
private String user;
|
||||||
|
|
||||||
|
@Value("${appointment.portal.password}")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Value("${appointment.portal.source}")
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
@Value("${appointment.portal.context}")
|
||||||
|
private String context;
|
||||||
|
|
||||||
|
@Value("${default.hub.uuid}")
|
||||||
|
private String defaultHubUuid;
|
||||||
|
|
||||||
|
@Value("${aws.s3.url}")
|
||||||
|
private String s3Url;
|
||||||
|
|
||||||
|
@Value("${aws.s3.bucket.name}")
|
||||||
|
private String OLD_BUCKET;
|
||||||
|
|
||||||
|
@Value("${flagDaFirmare}")
|
||||||
|
private Boolean flagDaFirmare;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private HubRepository hubRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AppointmentApiService appointmentApiService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationService applicationService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CompanyService companyService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationRepository applicationRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CompanyRepository companyRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DocumentDao documentDao;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AmazonS3Client s3Client;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DocumentRepository documentRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private HttpServletRequest request;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoggingUtil loggingUtil;
|
||||||
|
|
||||||
|
private final Map<Long, ExecutorService> executorMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public NdgResponse checkNdgForAppointment(Long applicationId) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
NdgResponse ndgResponseToReturn = new NdgResponse();
|
||||||
|
// Validate application, company, and hub
|
||||||
|
ApplicationEntity application = applicationService.validateApplication(applicationId);
|
||||||
|
if (application.getNdgStatus() != null && application.getNdgStatus().equalsIgnoreCase(GepafinConstant.NDG_IN_PROGRESS)) {
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NDG_GENERATION_IS_IN_PROGRESS));
|
||||||
|
}
|
||||||
|
//cloned for old application data
|
||||||
|
ApplicationEntity oldApplicationData = Utils.getClonedEntityForData(application);
|
||||||
|
|
||||||
|
CompanyEntity company = companyService.validateCompany(application.getCompanyId());
|
||||||
|
HubEntity hub = hubRepository.findByHubId(application.getHubId());
|
||||||
|
|
||||||
|
if (!hub.getUniqueUuid().equals(defaultHubUuid)) {
|
||||||
|
log.info("Ndg cannot be created for another Hub, it is default for Gepafin.");
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NO_NDG_FOR_ANOTHER_HUB));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if NDG and idVisura are already present
|
||||||
|
if (isNdgAndIdVisuraPresent(application)) {
|
||||||
|
log.info("NDG already exist for applicationId: {}", applicationId);
|
||||||
|
ndgResponseToReturn.setNdg(application.getNdg());
|
||||||
|
return ndgResponseToReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authenticate and fetch token if required
|
||||||
|
if (hub.getAppointmentAuthTokenId() == null && hub.getAreaCode() == null) {
|
||||||
|
hub = authenticateAndSaveToken(hub);
|
||||||
|
}
|
||||||
|
|
||||||
|
String authorizationToken = getBearerToken(hub);
|
||||||
|
|
||||||
|
// Try retrieving NDG by VAT number
|
||||||
|
AppointmentLoginResponse ndgResponse = retrieveNdgByVatNumber(company.getVatNumber(), authorizationToken, hub, application);
|
||||||
|
//For testing purpose Commenting it
|
||||||
|
if (isNdgValid(ndgResponse.getNdg())) {
|
||||||
|
saveNdgAndIdVisura(application, company, ndgResponse.getNdg(), null);
|
||||||
|
ndgResponseToReturn.setNdg(application.getNdg());
|
||||||
|
return ndgResponseToReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getNdgResponse(company, authorizationToken, hub, application, ndgResponseToReturn, oldApplicationData);
|
||||||
|
} catch (FeignException e) {
|
||||||
|
log.error("Error in feign client call during NDG handling: {}", e.getMessage(), e);
|
||||||
|
Utils.callException(e.status(), e);
|
||||||
|
} catch (CustomValidationException e) {
|
||||||
|
log.info("Custom validation exception: {}", e.getMessage());
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error during NDG handling: {}", e.getMessage(), e);
|
||||||
|
throw new RuntimeException("Error during fetching NDG.");
|
||||||
|
}
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_IN_GENERATING_NDG_TRY_AGAIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
private NdgResponse getNdgResponse(CompanyEntity company, String authorizationToken, HubEntity hub, ApplicationEntity application, NdgResponse ndgResponseToReturn,
|
||||||
|
ApplicationEntity oldApplicationData) {
|
||||||
|
// Create Visura if NDG is not found
|
||||||
|
AppointmentLoginResponse visuraResponse = createVisura(company, authorizationToken, hub);
|
||||||
|
if (isNdgValid(visuraResponse.getNdg())) {
|
||||||
|
saveNdgAndIdVisura(application, company, visuraResponse.getNdg(), visuraResponse.getIdVisura());
|
||||||
|
ndgResponseToReturn.setNdg(application.getNdg());
|
||||||
|
} else if (visuraResponse.getIdVisura() != null) {
|
||||||
|
application.setNdgStatus(GepafinConstant.NDG_IN_PROGRESS);
|
||||||
|
application.setStatus(ApplicationStatusTypeEnum.NDG.getValue());
|
||||||
|
applicationRepository.save(application);
|
||||||
|
|
||||||
|
/** This code is responsible for adding a version history log for the "Updating ndg status in application" operation. **/
|
||||||
|
loggingUtil.addVersionHistory(
|
||||||
|
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationData).newData(application).build());
|
||||||
|
|
||||||
|
startNdgPollingTask(application, company, hub);
|
||||||
|
throw new CustomValidationException(Status.SUCCESS, Translator.toLocale(GepafinConstant.NDG_GENERATION_IS_IN_PROGRESS));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndgResponseToReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getBearerToken(HubEntity hub) {
|
||||||
|
|
||||||
|
return "Bearer " + hub.getAppointmentAuthTokenId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startNdgPollingTask(ApplicationEntity application, CompanyEntity company, HubEntity hub) {
|
||||||
|
//cloned for all data
|
||||||
|
ApplicationEntity oldApplicationData = Utils.getClonedEntityForData(application);
|
||||||
|
CompanyEntity oldCompanyData = Utils.getClonedEntityForData(company);
|
||||||
|
|
||||||
|
// Check if a thread is already running for this application
|
||||||
|
if (executorMap.containsKey(application.getId())) {
|
||||||
|
log.warn("Polling task already running for applicationId: {}", application.getId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a dedicated thread (single-threaded executor) for this application
|
||||||
|
ExecutorService executor = Executors.newSingleThreadExecutor(runnable -> {
|
||||||
|
Thread thread = new Thread(runnable);
|
||||||
|
thread.setName(GepafinConstant.POLLING_THREAD_NAME + application.getId());
|
||||||
|
return thread;
|
||||||
|
});
|
||||||
|
executorMap.put(application.getId(), executor);
|
||||||
|
|
||||||
|
// Submit polling task to this thread
|
||||||
|
executor.submit(() -> {
|
||||||
|
try {
|
||||||
|
log.info("Polling task started for applicationId: {} on thread: {}", application.getId(), Thread.currentThread().getName());
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (application.getNdg() != null)
|
||||||
|
break;
|
||||||
|
try {
|
||||||
|
String visuraListJson = getVisuraList(application.getIdVisura(), hub.getAppointmentAuthTokenId(), application, hub);
|
||||||
|
String ndg = parseNdgFromVisuraListResponse(visuraListJson);
|
||||||
|
|
||||||
|
if (isNdgValid(ndg)) {
|
||||||
|
company.setNdg(ndg);
|
||||||
|
application.setNdgStatus(GepafinConstant.NDG_GENERATED);
|
||||||
|
application.setStatus(ApplicationStatusTypeEnum.NDG.getValue());
|
||||||
|
application.setNdg(ndg);
|
||||||
|
applicationRepository.save(application);
|
||||||
|
companyRepository.save(company);
|
||||||
|
|
||||||
|
log.info("NDG obtained for applicationId: {} and saved successfully.", application.getId());
|
||||||
|
break; // Exit the loop after successful NDG retrieval
|
||||||
|
} else {
|
||||||
|
log.warn("NDG not found for applicationId: {} in Visura List API response.", application.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if polling time has exceeded the limit
|
||||||
|
if (System.currentTimeMillis() - startTime > TimeUnit.HOURS.toMillis(2)) {
|
||||||
|
log.warn("Polling timed out for applicationId: {}", application.getId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait before the next polling attempt
|
||||||
|
Thread.sleep(TimeUnit.MINUTES.toMillis(15));
|
||||||
|
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.warn("Polling task interrupted for applicationId: {}", application.getId());
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
break;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error during NDG polling for applicationId: {}", application.getId(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
// Cleanup: Shut down the thread for this application
|
||||||
|
executor.shutdown();
|
||||||
|
executorMap.remove(application.getId());
|
||||||
|
log.info("Polling task completed and thread shut down for applicationId: {}", application.getId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
/** This code is responsible for adding a version history log for the "Update application ndgCode and ndgStatus" operation. **/
|
||||||
|
loggingUtil.addVersionHistory(
|
||||||
|
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationData).newData(application).build());
|
||||||
|
|
||||||
|
/** This code is responsible for adding a version history log for the "Update company ndgCode" operation. **/
|
||||||
|
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldCompanyData).newData(company).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isNdgAndIdVisuraPresent(ApplicationEntity application) {
|
||||||
|
|
||||||
|
String ndg = application.getNdg();
|
||||||
|
String idVisura = application.getIdVisura();
|
||||||
|
|
||||||
|
if (ndg != null && idVisura == null) {
|
||||||
|
return true;
|
||||||
|
} else if (ndg == null && idVisura != null) {
|
||||||
|
return false;
|
||||||
|
} else
|
||||||
|
return ndg != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isNdgValid(String ndg) {
|
||||||
|
|
||||||
|
return ndg != null && !ndg.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveNdgAndIdVisura(ApplicationEntity application, CompanyEntity company, String ndg, String idVisura) {
|
||||||
|
|
||||||
|
//cloned for old application and company data
|
||||||
|
ApplicationEntity oldApplicationData = Utils.getClonedEntityForData(application);
|
||||||
|
CompanyEntity oldCompanyData = Utils.getClonedEntityForData(company);
|
||||||
|
|
||||||
|
application.setNdg(ndg);
|
||||||
|
application.setIdVisura(idVisura);
|
||||||
|
application.setNdgStatus(GepafinConstant.NDG_GENERATED);
|
||||||
|
application.setStatus(ApplicationStatusTypeEnum.NDG.getValue());
|
||||||
|
company.setNdg(ndg);
|
||||||
|
companyRepository.save(company);
|
||||||
|
applicationRepository.save(application);
|
||||||
|
|
||||||
|
/** This code is responsible for adding a version history log for the "update application ndg code, status, and Id visura" operation. **/
|
||||||
|
loggingUtil.addVersionHistory(
|
||||||
|
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationData).newData(application).build());
|
||||||
|
|
||||||
|
/** This code is responsible for adding a version history log for the "update company ndg code" operation. **/
|
||||||
|
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldCompanyData).newData(company).build());
|
||||||
|
|
||||||
|
log.info("NDG saved for applicationId: {}, {}", application.getId(), application.getNdg());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getVisuraList(String idVisura, String authorizationToken, ApplicationEntity application, HubEntity hub) {
|
||||||
|
|
||||||
|
AppointmentVisuraListRequest visuraListRequest = new AppointmentVisuraListRequest();
|
||||||
|
AppointmentVisuraListRequest.VisuraFilter filter = new AppointmentVisuraListRequest.VisuraFilter();
|
||||||
|
filter.setIdVisura(idVisura);
|
||||||
|
visuraListRequest.setFilter(filter);
|
||||||
|
|
||||||
|
try {
|
||||||
|
String requestJson = Utils.convertObjectToJson(visuraListRequest);
|
||||||
|
ResponseEntity<Object> response = appointmentApiService.getVisuraList(requestJson, authorizationToken);
|
||||||
|
return Utils.convertObjectToJson(response.getBody());
|
||||||
|
} catch (FeignException.Forbidden forbiddenException) {
|
||||||
|
log.error("403 Forbidden received while getting visuraList for Ndg code. Regenerating token...");
|
||||||
|
// Regenerate the token and retry
|
||||||
|
String newAuthorizationToken = regenerateTokenAndSave(hub);
|
||||||
|
return getVisuraList(idVisura, newAuthorizationToken, application, hub);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to fetch Ndg code: {}", e.getMessage(), e);
|
||||||
|
throw new RuntimeException("Error fetching Ndg List", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HubEntity authenticateAndSaveToken(HubEntity hub) {
|
||||||
|
|
||||||
|
HubEntity oldHubData = Utils.getClonedEntityForData(hub);
|
||||||
|
try {
|
||||||
|
//code to generate token with payload having "iat" epoch timestamp and secret key with no expiry and send in below method call
|
||||||
|
String authJwtToken = Utils.generateAuthTokenForLoginToOdessa();
|
||||||
|
log.info("Got the auth for login to odessa {}", authJwtToken);
|
||||||
|
hub.setAuthToken(authJwtToken);
|
||||||
|
hubRepository.save(hub);
|
||||||
|
|
||||||
|
/** This code is responsible for adding a version history log for the "Updating auth token for login api in hub" operation. **/
|
||||||
|
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldHubData).newData(hub).build());
|
||||||
|
|
||||||
|
// Prepare the request body (adjust if necessary for login API)
|
||||||
|
Map<String, Object> body = Collections.emptyMap();
|
||||||
|
// Perform login API call
|
||||||
|
ResponseEntity<Object> responseLogin = appointmentApiService.loginWithOdessa(authJwtToken, source, context, user, password, body);
|
||||||
|
|
||||||
|
// Handle successful login
|
||||||
|
if (responseLogin.getStatusCode() == HttpStatus.OK) {
|
||||||
|
log.info("Login successful to odessa. Parsing response.");
|
||||||
|
String loginResponseJson = Utils.convertObjectToJson(responseLogin.getBody());
|
||||||
|
AppointmentLoginResponse parsedResponse = parseLoginResponse(loginResponseJson);
|
||||||
|
|
||||||
|
// Validate and save token
|
||||||
|
if (parsedResponse.getTokenId() != null) {
|
||||||
|
hub.setAppointmentAuthTokenId(parsedResponse.getTokenId());
|
||||||
|
hub.setAreaCode(parsedResponse.getAreaCode());
|
||||||
|
hubRepository.save(hub);
|
||||||
|
|
||||||
|
/** This code is responsible for adding a version history log for the "inserting token and areaCode from login odessa response for appointment flow api's"
|
||||||
|
* operation. **/
|
||||||
|
loggingUtil.addVersionHistory(
|
||||||
|
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldHubData).newData(hub).build());
|
||||||
|
|
||||||
|
log.info("Saved new authToken and areaCode for Hub.");
|
||||||
|
return hub;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Login response is missing a valid tokenId for login to odessa system, please try again.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle non-OK response
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_IN_GENERATING_NDG_TRY_AGAIN));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to authenticate user on Odessa : {}", e.getMessage(), e);
|
||||||
|
throw new RuntimeException("Authentication failed on Odessa. try again", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AppointmentLoginResponse retrieveNdgByVatNumber(String vatNumber, String authorizationToken, HubEntity hub, ApplicationEntity application) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Prepare the NDG request
|
||||||
|
AppointmentNdgRequest ndgRequest = getAppointmentNdgRequest(vatNumber);
|
||||||
|
// Call the API to retrieve NDG
|
||||||
|
ResponseEntity<Object> response = appointmentApiService.getNdgByVatNumber(ndgRequest, authorizationToken);
|
||||||
|
String responseJson = Utils.convertObjectToJson(response.getBody());
|
||||||
|
// Parse and return the NDG response
|
||||||
|
return parseNdgResponse(responseJson);
|
||||||
|
} catch (FeignException.Forbidden forbiddenException) {
|
||||||
|
log.error("403 Forbidden received while retrieving NDG. Regenerating token...");
|
||||||
|
// Regenerate the token and retry
|
||||||
|
String newAuthorizationToken = regenerateTokenAndSave(hub);
|
||||||
|
return retrieveNdgByVatNumber(vatNumber, newAuthorizationToken, hub, application);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to retrieve NDG by VAT number: {}", e.getMessage(), e);
|
||||||
|
throw new RuntimeException("NDG retrieval failed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String regenerateTokenAndSave(HubEntity hub) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
hub = authenticateAndSaveToken(hub);
|
||||||
|
return "Bearer " + hub.getAppointmentAuthTokenId();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to regenerate token from Odessa: {}", e.getMessage());
|
||||||
|
throw new RuntimeException("Token regeneration failed from Odessa.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AppointmentLoginResponse createVisura(CompanyEntity company, String authorizationToken, HubEntity hub) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
String visuraRequest = getAppointmentVisuraRequest(company, hub.getAreaCode());
|
||||||
|
ResponseEntity<Object> response = appointmentApiService.createVisura(visuraRequest, authorizationToken);
|
||||||
|
String responseJson = Utils.convertObjectToJson(response.getBody());
|
||||||
|
return parseVisuraResponse(responseJson);
|
||||||
|
} catch (FeignException.Forbidden forbiddenException) {
|
||||||
|
log.error("403 Forbidden received while retrieving NDG. Regenerating token...");
|
||||||
|
// Regenerate the token and retry
|
||||||
|
String newAuthorizationToken = regenerateTokenAndSave(hub);
|
||||||
|
return createVisura(company, newAuthorizationToken, hub);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to create Visura for Ndg : {}", e.getMessage());
|
||||||
|
throw new RuntimeException("Visura creation failed for Ndg.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AppointmentNdgRequest getAppointmentNdgRequest(String vatNumber) {
|
||||||
|
|
||||||
|
AppointmentNdgRequest request = new AppointmentNdgRequest();
|
||||||
|
AppointmentNdgRequest.Filter filter = new AppointmentNdgRequest.Filter();
|
||||||
|
filter.setPartitaIva(vatNumber);
|
||||||
|
|
||||||
|
AppointmentNdgRequest.Pagination pagination = new AppointmentNdgRequest.Pagination();
|
||||||
|
pagination.setTargetPage(AppointmentApiConstant.TARGET_PAGE_SIZE);
|
||||||
|
pagination.setRecordsPerPage(AppointmentApiConstant.RECORD_PER_PAGE_SIZE);
|
||||||
|
|
||||||
|
request.setFilter(filter);
|
||||||
|
request.setPagination(pagination);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getAppointmentVisuraRequest(CompanyEntity company, String areaCode) {
|
||||||
|
|
||||||
|
AppointmentVisuraRequest visuraRequest = new AppointmentVisuraRequest();
|
||||||
|
AppointmentVisuraRequest.VisuraInput input = new AppointmentVisuraRequest.VisuraInput();
|
||||||
|
input.setPartitaIva(company.getVatNumber());
|
||||||
|
input.setCodiceFiscale(company.getCodiceFiscale());
|
||||||
|
input.setCodArea(areaCode);
|
||||||
|
input.setVisuraMode(AppointmentApiConstant.VISURA_MODE);
|
||||||
|
input.setVisuraProvider(AppointmentApiConstant.VISURA_PROVIDER);
|
||||||
|
input.setCodAgente(AppointmentApiConstant.COD_AGENTE);
|
||||||
|
input.setAnagraficaLegame(AppointmentApiConstant.IS_ANAGRAFICA_LEGAME);
|
||||||
|
input.setCreaAnagrafica(AppointmentApiConstant.CREA_ANAGRAFICA);
|
||||||
|
input.setFromRating(AppointmentApiConstant.IS_FROM_RATING);
|
||||||
|
input.setSalvaDocumenti(AppointmentApiConstant.SALVA_DOCUMENTI);
|
||||||
|
input.setVisuraType(AppointmentApiConstant.VISURA_TYPE);
|
||||||
|
visuraRequest.setInput(input);
|
||||||
|
return Utils.convertObjectToJson(visuraRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseNdgFromVisuraListResponse(String jsonResponse) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = objectMapper.readTree(jsonResponse);
|
||||||
|
JsonNode dataNode = rootNode.get(GepafinConstant.DATA_STRING);
|
||||||
|
|
||||||
|
if (dataNode != null && dataNode.isArray() && dataNode.size() > 0) {
|
||||||
|
JsonNode firstEntry = dataNode.get(0);
|
||||||
|
JsonNode ndgClienteNode = firstEntry.get("ndgCliente");
|
||||||
|
if (ndgClienteNode != null && ndgClienteNode.get("code") != null) {
|
||||||
|
String code = ndgClienteNode.get("code").asText();
|
||||||
|
return normalizeNullValue(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.warn("NDG not found in Visura List API response.");
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to parse NDG from Visura List API response: {}", e.getMessage(), e);
|
||||||
|
throw new RuntimeException("Error parsing NDG from Visura List API response", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppointmentLoginResponse parseLoginResponse(String jsonResponse) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = objectMapper.readTree(jsonResponse);
|
||||||
|
JsonNode dataNode = rootNode.get(GepafinConstant.DATA_STRING);
|
||||||
|
|
||||||
|
if (dataNode != null) {
|
||||||
|
AppointmentLoginResponse response = new AppointmentLoginResponse();
|
||||||
|
response.setTokenId(dataNode.get("tokenId").asText());
|
||||||
|
JsonNode areasNode = dataNode.get("areas");
|
||||||
|
if (areasNode != null && areasNode.isArray() && areasNode.size() > 0) {
|
||||||
|
response.setAreaCode(areasNode.get(0).get("code").asText());
|
||||||
|
}
|
||||||
|
response.setCompanyId(dataNode.get("companyId").asLong());
|
||||||
|
return response;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Invalid JSON structure: Missing 'data' node.");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to parse response from loginApi for odessa: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppointmentLoginResponse parseVisuraResponse(String jsonResponse) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = objectMapper.readTree(jsonResponse);
|
||||||
|
JsonNode dataNode = rootNode.get(GepafinConstant.DATA_STRING);
|
||||||
|
|
||||||
|
if (dataNode != null) {
|
||||||
|
AppointmentLoginResponse response = new AppointmentLoginResponse();
|
||||||
|
response.setIdVisura(normalizeNullValue(dataNode.get(GepafinConstant.ID_VISURA_STRING).asText()));
|
||||||
|
response.setNdg(normalizeNullValue(dataNode.get(GepafinConstant.NDG_STRING).asText()));
|
||||||
|
return response;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Invalid JSON structure: Missing 'data' node.");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to parse response: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppointmentLoginResponse parseNdgResponse(String jsonResponse) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = objectMapper.readTree(jsonResponse);
|
||||||
|
JsonNode dataArray = rootNode.get(GepafinConstant.DATA_STRING);
|
||||||
|
if (dataArray == null || !dataArray.isArray() || dataArray.isEmpty()) {
|
||||||
|
log.info("NDG data is empty or missing in the response.");
|
||||||
|
AppointmentLoginResponse emptyResponse = new AppointmentLoginResponse();
|
||||||
|
emptyResponse.setNdg(null);
|
||||||
|
return emptyResponse;
|
||||||
|
}
|
||||||
|
JsonNode firstDataEntry = dataArray.get(0);
|
||||||
|
AppointmentLoginResponse response = new AppointmentLoginResponse();
|
||||||
|
if (firstDataEntry.has(GepafinConstant.NDG_STRING)) {
|
||||||
|
response.setNdg(normalizeNullValue(firstDataEntry.get(GepafinConstant.NDG_STRING).asText()));
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to parse response: {}", e.getMessage(), e);
|
||||||
|
throw new RuntimeException("Failed to parse NDG response.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeNullValue(String value) {
|
||||||
|
|
||||||
|
return (value == null || GepafinConstant.NULL_STRING.equalsIgnoreCase(value.trim())) ? null : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppointmentCreationResponse createAppointment(Long applicationId, CreateAppointmentRequest createAppointmentRequest) {
|
||||||
|
// Validate the application
|
||||||
|
ApplicationEntity application = applicationService.validateApplication(applicationId);
|
||||||
|
|
||||||
|
AppointmentCreationResponse appointmentCreationResponse = new AppointmentCreationResponse();
|
||||||
|
|
||||||
|
ApplicationEntity oldApplicationData = Utils.getClonedEntityForData(application);
|
||||||
|
HubEntity hub = hubRepository.findByHubId(application.getHubId());
|
||||||
|
|
||||||
|
// Check hub UUID and enforce constraints
|
||||||
|
if (!hub.getUniqueUuid().equals(defaultHubUuid)) {
|
||||||
|
log.info("Appointment cannot be created for another Hub; default is required for Gepafin.");
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NO_APPOINTMENT_FOR_ANOTHER_HUB));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Pre-check conditions for appointment creation
|
||||||
|
if (application.getNdg() != null && !Objects.equals(application.getNdgStatus(), GepafinConstant.NDG_IN_PROGRESS) && application.getAppointmentId() != null) {
|
||||||
|
appointmentCreationResponse.setAppointmentId(application.getAppointmentId());
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPOINTMENT_ALREADY_CREATED));
|
||||||
|
// return appointmentCreationResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (application.getNdg() == null && Objects.equals(application.getNdgStatus(), GepafinConstant.NDG_IN_PROGRESS)) {
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NDG_NOT_FOUND_FOR_APPLICATION));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate authorization token and fetch template data
|
||||||
|
String authorizationToken = getBearerToken(hub);
|
||||||
|
ResponseEntity<Object> response = appointmentApiService.getAppointmentTemplateForTemplateCreation(authorizationToken);
|
||||||
|
|
||||||
|
if (response.getStatusCode() != HttpStatus.OK) {
|
||||||
|
log.error("Failed to retrieve appointment template for appointment creation. Status: {}", response.getStatusCode());
|
||||||
|
throw new IllegalStateException("Failed to retrieve appointment template for appointment creation");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse template data
|
||||||
|
String responseDataForTemplate = Utils.convertObjectToJson(response.getBody());
|
||||||
|
AppointmentCreationRequest templateRichiestaData = parseTemplateResponseData(responseDataForTemplate);
|
||||||
|
|
||||||
|
// Build the appointment request body
|
||||||
|
AppointmentCreationRequest appointmentCreationRequest = buildAppointmentCreationRequest(applicationId, createAppointmentRequest, hub.getAreaCode(),
|
||||||
|
templateRichiestaData);
|
||||||
|
String appointmentRequestBody = Utils.convertObjectToJson(appointmentCreationRequest);
|
||||||
|
|
||||||
|
// Make API call to create the appointment
|
||||||
|
ResponseEntity<Object> appointmentResponse = appointmentApiService.createAppointment(authorizationToken, context, appointmentRequestBody);
|
||||||
|
String appointmentId = extractAppointmentIdFromResponse(appointmentResponse);
|
||||||
|
|
||||||
|
if (appointmentId != null) {
|
||||||
|
// Update application with the appointment ID
|
||||||
|
application.setAppointmentId(appointmentId);
|
||||||
|
application.setStatus(ApplicationStatusTypeEnum.APPOINTMENT.getValue());
|
||||||
|
applicationRepository.save(application);
|
||||||
|
|
||||||
|
// Log version history
|
||||||
|
loggingUtil.addVersionHistory(
|
||||||
|
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationData).newData(application).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
appointmentCreationResponse.setAppointmentId(appointmentId);
|
||||||
|
return appointmentCreationResponse;
|
||||||
|
|
||||||
|
} catch (FeignException.Forbidden forbiddenException) {
|
||||||
|
log.error("403 Forbidden received while retrieving template. Regenerating token...");
|
||||||
|
regenerateTokenAndSave(hub);
|
||||||
|
return createAppointment(applicationId, createAppointmentRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractAppointmentIdFromResponse(ResponseEntity<Object> appointmentResponse) {
|
||||||
|
|
||||||
|
if (appointmentResponse.getBody() != null) {
|
||||||
|
Map<String, Object> responseBody = (Map<String, Object>) appointmentResponse.getBody();
|
||||||
|
if (responseBody.containsKey(GepafinConstant.DATA_STRING)) {
|
||||||
|
Map<String, Object> data = (Map<String, Object>) responseBody.get(GepafinConstant.DATA_STRING);
|
||||||
|
if (data != null && data.containsKey(GepafinConstant.ID_STRING)) {
|
||||||
|
return data.get(GepafinConstant.ID_STRING).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppointmentCreationRequest parseTemplateResponseData(String jsonResponse) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = objectMapper.readTree(jsonResponse);
|
||||||
|
JsonNode richiestaClienteArray = rootNode.path(GepafinConstant.DATA_STRING).path(GepafinConstant.RICHIESTA_CLIENTE_STRING);
|
||||||
|
|
||||||
|
AppointmentCreationRequest appointmentCreationRequest = new AppointmentCreationRequest();
|
||||||
|
AppointmentCreationRequest.Input input = new AppointmentCreationRequest.Input();
|
||||||
|
|
||||||
|
// Map `richiestaCliente` array
|
||||||
|
List<AppointmentCreationRequest.RichiestaCliente> richiestaClienteList = new ArrayList<>();
|
||||||
|
if (richiestaClienteArray.isArray()) {
|
||||||
|
for (JsonNode richiestaNode : richiestaClienteArray) {
|
||||||
|
richiestaClienteList.add(objectMapper.treeToValue(richiestaNode, AppointmentCreationRequest.RichiestaCliente.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input.setRichiestaCliente(richiestaClienteList);
|
||||||
|
appointmentCreationRequest.setInput(input);
|
||||||
|
return appointmentCreationRequest;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error parsing template response: {}", e.getMessage(), e);
|
||||||
|
throw new IllegalStateException("Failed to parse template response", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppointmentCreationRequest buildAppointmentCreationRequest(Long applicationId, CreateAppointmentRequest createAppointmentRequest, String areaCode,
|
||||||
|
AppointmentCreationRequest templateRichiestaData) {
|
||||||
|
|
||||||
|
ApplicationEntity application = applicationService.validateApplication(applicationId);
|
||||||
|
CreateAppointmentRequest.Nota nota = createAppointmentRequest.getNota();
|
||||||
|
|
||||||
|
AppointmentCreationRequest appointmentCreationRequest = new AppointmentCreationRequest();
|
||||||
|
AppointmentCreationRequest.Input input = new AppointmentCreationRequest.Input();
|
||||||
|
|
||||||
|
// Set Input Fields
|
||||||
|
input.setId(areaCode);
|
||||||
|
input.setNdg(application.getNdg());
|
||||||
|
|
||||||
|
// Populate richiestaCliente from template data
|
||||||
|
List<AppointmentCreationRequest.RichiestaCliente> richiestaClienteList = new ArrayList<>();
|
||||||
|
for (AppointmentCreationRequest.RichiestaCliente templateRichiesta : templateRichiestaData.getInput().getRichiestaCliente()) {
|
||||||
|
AppointmentCreationRequest.RichiestaCliente richiestaCliente = new AppointmentCreationRequest.RichiestaCliente();
|
||||||
|
BeanUtils.copyProperties(templateRichiesta, richiestaCliente);
|
||||||
|
|
||||||
|
// Add specific `nota`
|
||||||
|
AppointmentCreationRequest.Nota requestNota = new AppointmentCreationRequest.Nota();
|
||||||
|
requestNota.setTitolo(nota.getTitolo());
|
||||||
|
requestNota.setTesto(nota.getTesto());
|
||||||
|
richiestaCliente.setNota(requestNota);
|
||||||
|
|
||||||
|
richiestaClienteList.add(richiestaCliente);
|
||||||
|
}
|
||||||
|
|
||||||
|
input.setRichiestaCliente(richiestaClienteList);
|
||||||
|
appointmentCreationRequest.setInput(input);
|
||||||
|
return appointmentCreationRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DocumentUploadResponse uploadDocumentToExternalSystem(Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest, Long applicationId) {
|
||||||
|
|
||||||
|
DocumentUploadResponse response = new DocumentUploadResponse();
|
||||||
|
DocumentEntity systemDoc = documentDao.validateDocument(documentId);
|
||||||
|
|
||||||
|
ApplicationEntity application = getApplicationEntityForDocument(applicationId, systemDoc);
|
||||||
|
|
||||||
|
//cloned for old document data
|
||||||
|
DocumentEntity oldDocumentEntity = Utils.getClonedEntityForData(systemDoc);
|
||||||
|
|
||||||
|
if (!docToExternalSystemRequest.getInput().getAttributes().getNdg().equalsIgnoreCase(application.getNdg())) {
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NDG_NOT_MATCHED_OR_NOT_FOUND));
|
||||||
|
}
|
||||||
|
|
||||||
|
Long hubId = application.getHubId();
|
||||||
|
HubEntity hub = hubRepository.findByHubId(hubId);
|
||||||
|
|
||||||
|
if (!hub.getUniqueUuid().equals(defaultHubUuid)) {
|
||||||
|
log.info("Document cannot be uploaded for another Hub, it is default for Gepafin.");
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NO_DOCUMENT_UPLOAD_FOR_ANOTHER_HUB));
|
||||||
|
}
|
||||||
|
log.info("Got Document in system {}", systemDoc);
|
||||||
|
|
||||||
|
String oldUrl = systemDoc.getFilePath();
|
||||||
|
log.info("Processing {}", oldUrl);
|
||||||
|
|
||||||
|
String authorizationToken = getBearerToken(hub);
|
||||||
|
try {
|
||||||
|
File localFile = downloadFileFromS3(oldUrl);
|
||||||
|
MultipartFile multipartFile = convertFileToMultipartFile(localFile);
|
||||||
|
|
||||||
|
UploadDocToExternalSystemRequest externalSystemRequest = new UploadDocToExternalSystemRequest();
|
||||||
|
|
||||||
|
UploadDocToExternalSystemRequest.Input input = getUploadDocumentInput(docToExternalSystemRequest);
|
||||||
|
externalSystemRequest.setInput(input);
|
||||||
|
|
||||||
|
String uploadDocRequest = Utils.convertObjectToJson(externalSystemRequest);
|
||||||
|
ResponseEntity<Object> uploadedDocumentData = appointmentApiService.uploadDocumentToExternalSystemForAppointment(authorizationToken, context, uploadDocRequest,
|
||||||
|
multipartFile);
|
||||||
|
String responseData = Utils.convertObjectToJson(uploadedDocumentData.getBody());
|
||||||
|
DocumentUploadResponse parsedDocumentUploadResponse = parseDocumentUploadResponse(responseData);
|
||||||
|
|
||||||
|
if (parsedDocumentUploadResponse == null) {
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_UPLOADING_DOCUMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
systemDoc.setDocumentAttachmentId(parsedDocumentUploadResponse.getDocumentAttachmentId());
|
||||||
|
documentRepository.save(systemDoc);
|
||||||
|
|
||||||
|
/** This code is responsible for adding a version history log for the "Update document with document attachment id" operation. **/
|
||||||
|
loggingUtil.addVersionHistory(
|
||||||
|
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldDocumentEntity).newData(systemDoc).build());
|
||||||
|
|
||||||
|
log.info("Document uploaded successfully to external system : {}", parsedDocumentUploadResponse);
|
||||||
|
response.setDocumentAttachmentId(systemDoc.getDocumentAttachmentId());
|
||||||
|
return response;
|
||||||
|
} catch (FeignException.Forbidden forbiddenException) {
|
||||||
|
log.error("403 Forbidden received while uploading document to external system. Regenerating token...");
|
||||||
|
|
||||||
|
regenerateTokenAndSave(hub);
|
||||||
|
return uploadDocumentToExternalSystem(systemDoc.getSourceId(), docToExternalSystemRequest, applicationId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Exception in uploading document to external system {}", e.getMessage());
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.EXTERNAL_DOCUMENT_UPLOAD_FAILURE_MSG));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private ApplicationEntity getApplicationEntityForDocument(Long applicationId, DocumentEntity systemDoc) {
|
||||||
|
|
||||||
|
if (systemDoc.getDocumentAttachmentId() != null) {
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.DOCUMENT_ALREADY_UPLOADED));
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationEntity application;
|
||||||
|
|
||||||
|
if (systemDoc.getSource().equalsIgnoreCase(DocumentSourceTypeEnum.APPLICATION.getValue()) && Objects.equals(systemDoc.getSourceId(), applicationId)) {
|
||||||
|
application = applicationService.validateApplication(systemDoc.getSourceId());
|
||||||
|
} else {
|
||||||
|
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.PROVIDE_VALID_APPLICATION_DOC_ID));
|
||||||
|
}
|
||||||
|
return application;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UploadDocToExternalSystemRequest.Input getUploadDocumentInput(UploadDocToExternalSystemRequest docToExternalSystemRequest) {
|
||||||
|
|
||||||
|
UploadDocToExternalSystemRequest.Input input = new UploadDocToExternalSystemRequest.Input();
|
||||||
|
input.setIdTipoProtocollo(docToExternalSystemRequest.getInput().getIdTipoProtocollo());
|
||||||
|
input.setIdClassificazione(docToExternalSystemRequest.getInput().getIdClassificazione());
|
||||||
|
input.setFlagDaFirmare(flagDaFirmare);
|
||||||
|
input.setDescrizione(docToExternalSystemRequest.getInput().getDescrizione());
|
||||||
|
|
||||||
|
UploadDocToExternalSystemRequest.Input.Attributes attributes = new UploadDocToExternalSystemRequest.Input.Attributes();
|
||||||
|
attributes.setNdg(docToExternalSystemRequest.getInput().getAttributes().getNdg());
|
||||||
|
attributes.setEmail(docToExternalSystemRequest.getInput().getAttributes().getEmail());
|
||||||
|
|
||||||
|
input.setAttributes(attributes);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MultipartFile convertFileToMultipartFile(File file) throws IOException {
|
||||||
|
|
||||||
|
FileInputStream input = new FileInputStream(file);
|
||||||
|
return new MockMultipartFile(file.getName(), file.getName(), MediaType.APPLICATION_OCTET_STREAM_VALUE, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File downloadFileFromS3(String fileUrl) throws Exception {
|
||||||
|
|
||||||
|
String key = extractS3KeyFromUrl(fileUrl);
|
||||||
|
File localFile = new File(GepafinConstant.TEMP_FILE_PATH + extractFileName(key));
|
||||||
|
|
||||||
|
GetObjectRequest getObjectRequest = new GetObjectRequest(OLD_BUCKET, key);
|
||||||
|
|
||||||
|
try (InputStream s3Stream = s3Client.getObject(getObjectRequest).getObjectContent(); FileOutputStream outputStream = new FileOutputStream(localFile)) {
|
||||||
|
s3Stream.transferTo(outputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Downloaded file from old S3 bucket: {}", key);
|
||||||
|
return localFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractS3KeyFromUrl(String url) {
|
||||||
|
|
||||||
|
return url.replace(s3Url, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractFileName(String filePath) {
|
||||||
|
|
||||||
|
String[] parts = filePath.split("/");
|
||||||
|
return parts[parts.length - 1];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DocumentUploadResponse parseDocumentUploadResponse(String jsonResponse) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = objectMapper.readTree(jsonResponse);
|
||||||
|
|
||||||
|
// Navigate to the "data" node
|
||||||
|
JsonNode dataNode = rootNode.get(GepafinConstant.DATA_STRING);
|
||||||
|
if (dataNode != null) {
|
||||||
|
DocumentUploadResponse response = new DocumentUploadResponse();
|
||||||
|
|
||||||
|
// Extract "documentAttachmentId"
|
||||||
|
JsonNode documentAttachmentIdNode = dataNode.get(GepafinConstant.DOCUMENT_ATTACHMENT_ID_STRING);
|
||||||
|
if (documentAttachmentIdNode != null) {
|
||||||
|
response.setDocumentAttachmentId(documentAttachmentIdNode.asText());
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Invalid JSON structure: Missing 'documentAttachmentId' node.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to parse response: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,4 +42,17 @@ public class ApplicationEntity extends BaseEntity {
|
|||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "USER_WITH_COMPANY_ID")
|
@JoinColumn(name = "USER_WITH_COMPANY_ID")
|
||||||
private UserWithCompanyEntity userWithCompany;
|
private UserWithCompanyEntity userWithCompany;
|
||||||
|
|
||||||
|
@Column(name = "NDG")
|
||||||
|
private String ndg;
|
||||||
|
|
||||||
|
@Column(name = "ID_VISURA")
|
||||||
|
private String idVisura;
|
||||||
|
|
||||||
|
@Column(name = "NDG_STATUS")
|
||||||
|
private String ndgStatus;
|
||||||
|
|
||||||
|
@Column(name = "APPOINTMENT_ID")
|
||||||
|
private String appointmentId;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -63,4 +63,6 @@ public class CompanyEntity extends BaseEntity{
|
|||||||
@JoinColumn(name = "HUB_ID")
|
@JoinColumn(name = "HUB_ID")
|
||||||
private HubEntity hub;
|
private HubEntity hub;
|
||||||
|
|
||||||
|
@Column(name = "NDG")
|
||||||
|
private String ndg;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,4 +29,7 @@ public class DocumentEntity extends BaseEntity{
|
|||||||
@Column(name ="IS_DELETED", nullable = false)
|
@Column(name ="IS_DELETED", nullable = false)
|
||||||
private Boolean isDeleted = false;
|
private Boolean isDeleted = false;
|
||||||
|
|
||||||
|
@Column(name="DOCUMENT_ATTACHMENT_ID")
|
||||||
|
private String documentAttachmentId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,13 @@ public class HubEntity extends BaseEntity{
|
|||||||
|
|
||||||
@Column(name = "EMAIL_SERVICE_CONFIG")
|
@Column(name = "EMAIL_SERVICE_CONFIG")
|
||||||
private String emailServiceConfig;
|
private String emailServiceConfig;
|
||||||
|
|
||||||
|
@Column(name = "AUTH_TOKEN")
|
||||||
|
private String authToken;
|
||||||
|
|
||||||
|
@Column(name = "APPOINTMENT_AUTH_TOKEN_ID")
|
||||||
|
private String appointmentAuthTokenId;
|
||||||
|
|
||||||
|
@Column(name = "AREA_CODE")
|
||||||
|
private String areaCode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ public enum ApplicationStatusTypeEnum {
|
|||||||
SOCCORSO("SOCCORSO"),
|
SOCCORSO("SOCCORSO"),
|
||||||
APPROVED("APPROVED"),
|
APPROVED("APPROVED"),
|
||||||
REJECTED("REJECTED"),
|
REJECTED("REJECTED"),
|
||||||
EVALUATION("EVALUATION");
|
EVALUATION("EVALUATION"),
|
||||||
|
APPOINTMENT("APPOINTMENT"),
|
||||||
|
NDG("NDG"),
|
||||||
|
ADMISSIBLE("ADMISSIBLE");
|
||||||
|
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,12 @@ public enum UserActionContextEnum {
|
|||||||
|
|
||||||
/** scheduler action context **/
|
/** scheduler action context **/
|
||||||
AMENDMENT_EXPIRATION_SCHEDULER("AMENDMENT_EXPIRATION_SCHEDULER"),
|
AMENDMENT_EXPIRATION_SCHEDULER("AMENDMENT_EXPIRATION_SCHEDULER"),
|
||||||
EVALUATION_EXPIRATION_SCHEDULER("EVALUATION_EXPIRATION_SCHEDULER");
|
EVALUATION_EXPIRATION_SCHEDULER("EVALUATION_EXPIRATION_SCHEDULER"),
|
||||||
|
|
||||||
|
/** appointment action context **/
|
||||||
|
CHECK_OR_CREATE_NDG_CODE("CHECK_OR_CREATE_NDG_CODE"),
|
||||||
|
CREATE_APPOINTMENT("CREATE_APPOINTMENT"),
|
||||||
|
UPLOAD_DOCUMENT_TO_EXTERNAL_SYSTEM("UPLOAD_DOCUMENT_TO_EXTERNAL_SYSTEM");
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package net.gepafin.tendermanagement.model.request;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AppointmentCreationRequest {
|
||||||
|
|
||||||
|
private Input input;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Input {
|
||||||
|
private String id;
|
||||||
|
private String ndg;
|
||||||
|
private List<RichiestaCliente> richiestaCliente;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class RichiestaCliente {
|
||||||
|
private String codAbi;
|
||||||
|
private String codCab;
|
||||||
|
private Integer durataMesiFinanziamento;
|
||||||
|
private Integer idMotivazione;
|
||||||
|
private String idNota;
|
||||||
|
private String importoAgevolato;
|
||||||
|
private Double importoBreveTermine;
|
||||||
|
private String importoMedioLungoTermine;
|
||||||
|
private String codTipoProdotto;
|
||||||
|
private String codCategoriaProdotto;
|
||||||
|
private String codFormaTecnica;
|
||||||
|
private String codProdotto;
|
||||||
|
private String codOperazione;
|
||||||
|
private Nota nota;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Nota {
|
||||||
|
private String titolo;
|
||||||
|
private String testo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package net.gepafin.tendermanagement.model.request;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AppointmentNdgRequest {
|
||||||
|
private Filter filter;
|
||||||
|
private Pagination pagination;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Filter {
|
||||||
|
private String partitaIva;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Pagination {
|
||||||
|
private int targetPage;
|
||||||
|
private int recordsPerPage;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package net.gepafin.tendermanagement.model.request;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AppointmentVisuraListRequest {
|
||||||
|
|
||||||
|
private AppointmentVisuraListRequest.VisuraFilter filter;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class VisuraFilter {
|
||||||
|
private String idVisura;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package net.gepafin.tendermanagement.model.request;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AppointmentVisuraRequest {
|
||||||
|
private VisuraInput input;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class VisuraInput {
|
||||||
|
private String codiceFiscale;
|
||||||
|
private String partitaIva;
|
||||||
|
private boolean creaAnagrafica;
|
||||||
|
private boolean salvaDocumenti;
|
||||||
|
private String visuraProvider;
|
||||||
|
private String visuraType;
|
||||||
|
private String visuraMode;
|
||||||
|
private String codArea;
|
||||||
|
private String codAgente;
|
||||||
|
@JsonProperty("isFromRating")
|
||||||
|
private boolean isFromRating;
|
||||||
|
@JsonProperty("isAnagraficaLegame")
|
||||||
|
private boolean isAnagraficaLegame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package net.gepafin.tendermanagement.model.request;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CreateAppointmentRequest {
|
||||||
|
private Double importoBreveTermine;
|
||||||
|
private Integer durataMesiFinanziamento;
|
||||||
|
private Nota nota;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Nota {
|
||||||
|
private String titolo;
|
||||||
|
|
||||||
|
private String testo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package net.gepafin.tendermanagement.model.request;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class UploadDocToExternalSystemRequest {
|
||||||
|
private Input input;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Input {
|
||||||
|
private Long idTipoProtocollo;
|
||||||
|
private Long idClassificazione;
|
||||||
|
private Boolean flagDaFirmare;
|
||||||
|
private String descrizione;
|
||||||
|
private Attributes attributes;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Attributes {
|
||||||
|
private String ndg;
|
||||||
|
private String email;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package net.gepafin.tendermanagement.model.response;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AppointmentCreationResponse {
|
||||||
|
private String appointmentId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package net.gepafin.tendermanagement.model.response;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AppointmentLoginResponse {
|
||||||
|
|
||||||
|
private String tokenId;
|
||||||
|
private String areaCode;
|
||||||
|
private Long companyId;
|
||||||
|
private String codecFiscale;
|
||||||
|
private String vatNumber;
|
||||||
|
private String ndg;
|
||||||
|
private String message;
|
||||||
|
private String idVisura;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package net.gepafin.tendermanagement.model.response;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DocumentUploadResponse {
|
||||||
|
private String documentAttachmentId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package net.gepafin.tendermanagement.model.response;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class NdgResponse {
|
||||||
|
private String ndg;
|
||||||
|
}
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
package net.gepafin.tendermanagement.repositories;
|
package net.gepafin.tendermanagement.repositories;
|
||||||
|
|
||||||
import net.gepafin.tendermanagement.entities.HubEntity;
|
import net.gepafin.tendermanagement.entities.HubEntity;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface HubRepository extends JpaRepository<HubEntity, Long> {
|
public interface HubRepository extends JpaRepository<HubEntity, Long> {
|
||||||
|
|
||||||
Optional<HubEntity> findByUniqueUuid(String hubUuid);
|
Optional<HubEntity> findByUniqueUuid(String hubUuid);
|
||||||
|
|
||||||
|
@Query("SELECT h FROM HubEntity h WHERE h.id = :hubId")
|
||||||
|
HubEntity findByHubId(@Param("hubId") Long hubId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package net.gepafin.tendermanagement.service;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.CreateAppointmentRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.UploadDocToExternalSystemRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.response.AppointmentCreationResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.response.DocumentUploadResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.response.NdgResponse;
|
||||||
|
|
||||||
|
public interface AppointmentService {
|
||||||
|
NdgResponse checkNdgForAppointment(HttpServletRequest request, Long applicationId);
|
||||||
|
|
||||||
|
AppointmentCreationResponse createAppointmentForApplication(HttpServletRequest request, Long applicationId, CreateAppointmentRequest createAppointmentRequest);
|
||||||
|
|
||||||
|
DocumentUploadResponse uploadDocToExternalSystem(HttpServletRequest request, Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest, Long applicationId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package net.gepafin.tendermanagement.service.feignClient;
|
||||||
|
|
||||||
|
import net.gepafin.tendermanagement.constants.AppointmentApiConstant;
|
||||||
|
import net.gepafin.tendermanagement.model.request.AppointmentNdgRequest;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestHeader;
|
||||||
|
import org.springframework.web.bind.annotation.RequestPart;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@FeignClient(value = "appointment-api-service", url = "${appointment.base.url}")
|
||||||
|
public interface AppointmentApiService {
|
||||||
|
|
||||||
|
@PostMapping(value = AppointmentApiConstant.ODESSA_LOGIN, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
ResponseEntity<Object> loginWithOdessa(@RequestHeader("auth") String authToken, @RequestHeader("source") String source, @RequestHeader("context") String context,
|
||||||
|
@RequestHeader("user") String user, @RequestHeader("password") String password, @RequestBody(required = false) Map<String, Object> body);
|
||||||
|
|
||||||
|
@PostMapping(value = AppointmentApiConstant.GET_NDG_BY_VAT_NUMBER, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
ResponseEntity<Object> getNdgByVatNumber(@RequestBody AppointmentNdgRequest ndgRequest, @RequestHeader("Authorization") String token);
|
||||||
|
|
||||||
|
@PostMapping(value = AppointmentApiConstant.CREATE_VISURA, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
ResponseEntity<Object> createVisura(@RequestBody String visuraRequest, @RequestHeader("Authorization") String token);
|
||||||
|
|
||||||
|
@GetMapping(value = AppointmentApiConstant.GET_VISURA_LIST, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
ResponseEntity<Object> getVisuraList(@RequestBody String visuraRequest, @RequestHeader("Authorization") String token);
|
||||||
|
|
||||||
|
@GetMapping(value = AppointmentApiConstant.GET_APPOINTMENT_TEMPLATE, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
ResponseEntity<Object> getAppointmentTemplateForTemplateCreation(@RequestHeader("Authorization") String token);
|
||||||
|
|
||||||
|
@PostMapping(value = AppointmentApiConstant.CREATE_APPOINTMENT_FROM_TEMPLATE, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
ResponseEntity<Object> createAppointment(@RequestHeader("Authorization") String token, @RequestHeader("context") String context, String appointmentCreationRequest);
|
||||||
|
|
||||||
|
@PostMapping(value = AppointmentApiConstant.UPLOAD_APOOINTMENT_DOCUMENT, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||||
|
ResponseEntity<Object> uploadDocumentToExternalSystemForAppointment(@RequestHeader("Authorization") String token, @RequestHeader("context") String context,
|
||||||
|
@RequestPart("input") String uploadDocumentRequest, @RequestPart("file") MultipartFile file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package net.gepafin.tendermanagement.service.impl;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import net.gepafin.tendermanagement.dao.AppointmentDao;
|
||||||
|
import net.gepafin.tendermanagement.model.request.CreateAppointmentRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.UploadDocToExternalSystemRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.response.AppointmentCreationResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.response.DocumentUploadResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.response.NdgResponse;
|
||||||
|
import net.gepafin.tendermanagement.service.AppointmentService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class AppointmentServiceImpl implements AppointmentService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AppointmentDao appointmentDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NdgResponse checkNdgForAppointment(HttpServletRequest request, Long applicationId) {
|
||||||
|
|
||||||
|
return appointmentDao.checkNdgForAppointment(applicationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppointmentCreationResponse createAppointmentForApplication(HttpServletRequest request, Long applicationId, CreateAppointmentRequest createAppointmentRequest) {
|
||||||
|
|
||||||
|
return appointmentDao.createAppointment(applicationId, createAppointmentRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DocumentUploadResponse uploadDocToExternalSystem(HttpServletRequest request, Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest,
|
||||||
|
Long applicationId) {
|
||||||
|
|
||||||
|
return appointmentDao.uploadDocumentToExternalSystem(documentId, docToExternalSystemRequest, applicationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,6 +51,7 @@ import org.springframework.web.context.request.RequestContextHolder;
|
|||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
@@ -580,4 +581,35 @@ public class Utils {
|
|||||||
// Clear the RequestContextHolder after task execution
|
// Clear the RequestContextHolder after task execution
|
||||||
RequestContextHolder.resetRequestAttributes();
|
RequestContextHolder.resetRequestAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String generateAuthTokenForLoginToOdessa() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Your weak secret key
|
||||||
|
String secretKey = GepafinConstant.AUTH_JWT_SECRET_KEY;
|
||||||
|
|
||||||
|
// Header
|
||||||
|
String header = GepafinConstant.JWT_ALGO_HEADER;
|
||||||
|
String encodedHeader = Base64.getUrlEncoder().withoutPadding().encodeToString(header.getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
// Payload
|
||||||
|
String payload = "{\"iat\":" + (System.currentTimeMillis() / 1000) + "}";
|
||||||
|
String encodedPayload = Base64.getUrlEncoder().withoutPadding().encodeToString(payload.getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
// Combine header and payload
|
||||||
|
String dataToSign = encodedHeader + "." + encodedPayload;
|
||||||
|
|
||||||
|
// Sign the token manually
|
||||||
|
Mac mac = Mac.getInstance(GepafinConstant.HMAC_ALGO);
|
||||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), GepafinConstant.HMAC_ALGO);
|
||||||
|
mac.init(secretKeySpec);
|
||||||
|
byte[] signatureBytes = mac.doFinal(dataToSign.getBytes(StandardCharsets.UTF_8));
|
||||||
|
String signature = Base64.getUrlEncoder().withoutPadding().encodeToString(signatureBytes);
|
||||||
|
|
||||||
|
// Return the final JWT
|
||||||
|
return dataToSign + "." + signature;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to generate JWT token", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
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.model.request.CreateAppointmentRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.UploadDocToExternalSystemRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.response.AppointmentCreationResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.response.DocumentUploadResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.response.NdgResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.util.Response;
|
||||||
|
import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
|
public interface AppointmentApi {
|
||||||
|
|
||||||
|
@Operation(summary = "API to check or create ndg.", 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 = "/application/{applicationId}/check-ndg", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
ResponseEntity<Response<NdgResponse>> checkNdgForAppointment(HttpServletRequest request,
|
||||||
|
@Parameter(description = "The application id", required = true) @PathVariable(value = "applicationId", required = true) Long applicationId);
|
||||||
|
|
||||||
|
@Operation(summary = "API to create appointment.", 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 = "/application/{applicationId}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
ResponseEntity<Response<AppointmentCreationResponse>> createAppointment(HttpServletRequest request,
|
||||||
|
@Parameter(description = "The application id", required = true) @PathVariable(value = "applicationId", required = true) Long applicationId,
|
||||||
|
@RequestBody CreateAppointmentRequest createAppointmentRequest);
|
||||||
|
|
||||||
|
@Operation(summary = "API to Upload document to external system.", 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 = "/application/{applicationId}/document/{documentId}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
ResponseEntity<Response<DocumentUploadResponse>> uploadDocumentToExternalSystem(HttpServletRequest request,
|
||||||
|
@Parameter(description = "The document id", required = true) @PathVariable(value = "documentId", required = true) Long documentId,
|
||||||
|
@Parameter(description = "The application id", required = true) @PathVariable(value = "applicationId", required = true) Long applicationId,
|
||||||
|
@RequestBody UploadDocToExternalSystemRequest docToExternalSystemRequest);
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package net.gepafin.tendermanagement.web.rest.api.impl;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.gepafin.tendermanagement.config.Translator;
|
||||||
|
import net.gepafin.tendermanagement.constants.GepafinConstant;
|
||||||
|
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
|
||||||
|
import net.gepafin.tendermanagement.enums.UserActionLogsEnum;
|
||||||
|
import net.gepafin.tendermanagement.model.request.CreateAppointmentRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.UploadDocToExternalSystemRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.request.UserActionRequest;
|
||||||
|
import net.gepafin.tendermanagement.model.response.AppointmentCreationResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.response.DocumentUploadResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.response.NdgResponse;
|
||||||
|
import net.gepafin.tendermanagement.model.util.Response;
|
||||||
|
import net.gepafin.tendermanagement.service.AppointmentService;
|
||||||
|
import net.gepafin.tendermanagement.util.LoggingUtil;
|
||||||
|
import net.gepafin.tendermanagement.web.rest.api.AppointmentApi;
|
||||||
|
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("${openapi.gepafin.base-path:/v1/appointment}")
|
||||||
|
@Slf4j
|
||||||
|
public class AppointmentController implements AppointmentApi {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AppointmentService appointmentService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoggingUtil loggingUtil;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Response<NdgResponse>> checkNdgForAppointment(HttpServletRequest request, Long applicationId) {
|
||||||
|
|
||||||
|
/** This code is responsible for creating user action logs for the "checking or creating ndg" operation. **/
|
||||||
|
loggingUtil.logUserAction(
|
||||||
|
UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.INSERT).actionContext(UserActionContextEnum.CHECK_OR_CREATE_NDG_CODE).build());
|
||||||
|
|
||||||
|
NdgResponse appointmentLoginResponse = appointmentService.checkNdgForAppointment(request, applicationId);
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.OK).body(new Response<>(appointmentLoginResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.NDG_FETCH_SUCCESSFULLY)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Response<AppointmentCreationResponse>> createAppointment(HttpServletRequest request, Long applicationId,
|
||||||
|
CreateAppointmentRequest createAppointmentRequest) {
|
||||||
|
|
||||||
|
/** This code is responsible for creating user action logs for the "create appointment" operation. **/
|
||||||
|
loggingUtil.logUserAction(
|
||||||
|
UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.INSERT).actionContext(UserActionContextEnum.CREATE_APPOINTMENT).build());
|
||||||
|
|
||||||
|
AppointmentCreationResponse appointmentCreationResponse = appointmentService.createAppointmentForApplication(request, applicationId, createAppointmentRequest);
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.CREATED)
|
||||||
|
.body(new Response<>(appointmentCreationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPOINTMENT_CREATED)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Response<DocumentUploadResponse>> uploadDocumentToExternalSystem(HttpServletRequest request, Long documentId, Long applicationId,
|
||||||
|
UploadDocToExternalSystemRequest docToExternalSystemRequest) {
|
||||||
|
|
||||||
|
/** This code is responsible for creating user action logs for the "Upload document to external system" operation. **/
|
||||||
|
loggingUtil.logUserAction(
|
||||||
|
UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.UPLOAD).actionContext(UserActionContextEnum.UPLOAD_DOCUMENT_TO_EXTERNAL_SYSTEM).build());
|
||||||
|
|
||||||
|
DocumentUploadResponse documentUploadResponse = appointmentService.uploadDocToExternalSystem(request, documentId, docToExternalSystemRequest, applicationId);
|
||||||
|
return ResponseEntity.status(HttpStatus.OK)
|
||||||
|
.body(new Response<>(documentUploadResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.DOCUMENT_UPLOADED_SUCCESSFULLY_TO_EXTERNAL_SYSTEM)));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,3 +15,11 @@ gepafin_email=rinaldo.bonazzo@bflows.net
|
|||||||
rinaldo_email=rinaldo.bonazzo@bflows.net
|
rinaldo_email=rinaldo.bonazzo@bflows.net
|
||||||
carlo_email=test@test.test
|
carlo_email=test@test.test
|
||||||
default.hub.uuid=p4lk3bcx1RStqTaIVVbXs
|
default.hub.uuid=p4lk3bcx1RStqTaIVVbXs
|
||||||
|
|
||||||
|
#Login to Odessa, Appointment Creation, Upload document Configuration
|
||||||
|
appointment.base.url=https://demo.galileonetwork.it/gateway/rest
|
||||||
|
appointment.portal.user=UtenzaAPIPortal@621
|
||||||
|
appointment.portal.password=u13nzaAP1P0rtal
|
||||||
|
appointment.portal.source=GEPAFINPORTAL
|
||||||
|
appointment.portal.context=GEPAFINPORTAL
|
||||||
|
flagDaFirmare=false
|
||||||
@@ -14,3 +14,10 @@ gepafin_email=test@test.test
|
|||||||
rinaldo_email=test@test.test
|
rinaldo_email=test@test.test
|
||||||
carlo_email=test@test.test
|
carlo_email=test@test.test
|
||||||
default.hub.uuid=p4lk3bcx1RStqTaIVVbXs
|
default.hub.uuid=p4lk3bcx1RStqTaIVVbXs
|
||||||
|
|
||||||
|
appointment.base.url=https://demo.galileonetwork.it/gateway/rest
|
||||||
|
appointment.portal.user=UtenzaAPIPortal@621
|
||||||
|
appointment.portal.password=u13nzaAP1P0rtal
|
||||||
|
appointment.portal.source=GEPAFINPORTAL
|
||||||
|
appointment.portal.context=GEPAFINPORTAL
|
||||||
|
flagDaFirmare=false
|
||||||
@@ -22,3 +22,11 @@ rinaldo_email=rinaldo.bonazzo@bflows.net
|
|||||||
carlo_email=carlo.mancosu@bflows.net
|
carlo_email=carlo.mancosu@bflows.net
|
||||||
default.hub.uuid=p4lk3bcx1RStqTaIVVbXs
|
default.hub.uuid=p4lk3bcx1RStqTaIVVbXs
|
||||||
# TEST DEPLOY Configuration
|
# TEST DEPLOY Configuration
|
||||||
|
|
||||||
|
#Login to Odessa, Appointment Creation, Upload document Configuration
|
||||||
|
appointment.base.url=https://demo.galileonetwork.it/gateway/rest
|
||||||
|
appointment.portal.user=UtenzaAPIPortal@621
|
||||||
|
appointment.portal.password=u13nzaAP1P0rtal
|
||||||
|
appointment.portal.source=GEPAFINPORTAL
|
||||||
|
appointment.portal.context=GEPAFINPORTAL
|
||||||
|
flagDaFirmare=true
|
||||||
@@ -65,3 +65,6 @@ default.email.signature=Gepafin S.p.a
|
|||||||
|
|
||||||
default.hub.pdf.banner=https://mementoresources.s3.amazonaws.com/gepafin/staging/template/gepafin-logo.jpg
|
default.hub.pdf.banner=https://mementoresources.s3.amazonaws.com/gepafin/staging/template/gepafin-logo.jpg
|
||||||
|
|
||||||
|
#feign client config
|
||||||
|
spring.cloud.openfeign.client.config.default.connectTimeout=300000
|
||||||
|
spring.cloud.openfeign.client.config.default.readTimeout=300000
|
||||||
@@ -1972,5 +1972,24 @@
|
|||||||
path="db/dump/update_system_email_template_for_updating_amendment_mail_notification_mail_04_12_2024_1.sql"/>
|
path="db/dump/update_system_email_template_for_updating_amendment_mail_notification_mail_04_12_2024_1.sql"/>
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
|
<changeSet id="04-12-2024_3" author="Piyush">
|
||||||
|
<addColumn tableName="hub">
|
||||||
|
<column name="auth_token" type="TEXT"/>
|
||||||
|
<column name="appointment_auth_token_id" type="TEXT"/>
|
||||||
|
<column name="area_code" type="TEXT"/>
|
||||||
|
</addColumn>
|
||||||
|
<addColumn tableName="company">
|
||||||
|
<column name="ndg" type="TEXT"/>
|
||||||
|
</addColumn>
|
||||||
|
<addColumn tableName="application">
|
||||||
|
<column name="ndg" type="TEXT"/>
|
||||||
|
<column name="id_visura" type="TEXT"/>
|
||||||
|
<column name="ndg_status" type="TEXT"/>
|
||||||
|
<column name="appointment_id" type="TEXT"/>
|
||||||
|
</addColumn>
|
||||||
|
<addColumn tableName="document">
|
||||||
|
<column name="document_attachment_id" type="TEXT"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|||||||
@@ -315,3 +315,22 @@ response.days.not.null=Response days should not be null and greater than zero.
|
|||||||
application.cannot.approved.or.rejected=Application cannot be approved and rejected because amendment is active.
|
application.cannot.approved.or.rejected=Application cannot be approved and rejected because amendment is active.
|
||||||
|
|
||||||
atleast.one.id.required=At least one of companyId or applicationId must be provided
|
atleast.one.id.required=At least one of companyId or applicationId must be provided
|
||||||
|
|
||||||
|
#Appointment flow messages
|
||||||
|
ndg.generated = NDG Generated.
|
||||||
|
ndg.available = NDG Available.
|
||||||
|
ndg.generation.in.progress = NDG generation is in progress.
|
||||||
|
ndg.fetch.successfully = NDG fetch successfully.
|
||||||
|
appointment.already.created = Appointment Already Created.
|
||||||
|
ndg.not.found.for.this.application.or.invalid = Ndg not found for this application or invalid.
|
||||||
|
provide.valid.application.document.id = Provide valid application document id.
|
||||||
|
document.uploaded.successfully.to.external.system = Document uploaded successfully to external system.
|
||||||
|
error.in.uploading.document.check.input = Error in uploading document check input data or try again.
|
||||||
|
document.already.uploaded = Document already uploaded.
|
||||||
|
document.not.uploaded.to.external.system.please.try.again = Document not uploaded to external system, please try again.
|
||||||
|
ndg.not.found.or.not.matched = The provided NDG does not match the application NDG, or the NDG has not been generated.
|
||||||
|
ndg.generation.is.only.for.gepafin = NDG generation is only available for GEPAFIN Hub.
|
||||||
|
appointment.creation.is.only.for.gepafin = Appointment creation is only allowed for GEPAFIN Hub.
|
||||||
|
upload.document.is.only.for.gepafin = Document cant be uploaded, this is only available for GEPAFIN Hub.
|
||||||
|
appointment.created.successfully = Appointment created successfully.
|
||||||
|
error.try.again = Service call error while performing the operation. Please try again.
|
||||||
|
|||||||
@@ -197,8 +197,6 @@ invalid.vatnumber=Numero di partita IVA non valido.
|
|||||||
vatnumber.mandatory=Il numero di partita IVA � obbligatorio.
|
vatnumber.mandatory=Il numero di partita IVA � obbligatorio.
|
||||||
vatnumber.already.exists=Il numero di partita IVA esiste gi�.
|
vatnumber.already.exists=Il numero di partita IVA esiste gi�.
|
||||||
invalid.email=Email non valida.
|
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.firstName=Il nome � obbligatorio.
|
||||||
validation.error.missing.lastName=Il cognome � obbligatorio.
|
validation.error.missing.lastName=Il cognome � obbligatorio.
|
||||||
validation.error.missing.codiceFiscale=Il Codice Fiscale � obbligatorio.
|
validation.error.missing.codiceFiscale=Il Codice Fiscale � obbligatorio.
|
||||||
@@ -308,3 +306,21 @@ company.id.required.for.preferred.call=ID azienda obbligatorio quando si richied
|
|||||||
response.days.not.null=I giorni di risposta non devono essere nulli e maggiori di zero.
|
response.days.not.null=I giorni di risposta non devono essere nulli e maggiori di zero.
|
||||||
application.cannot.approved.or.rejected=La domanda non può essere approvata o rifiutata perché l'emendamento è attivo.
|
application.cannot.approved.or.rejected=La domanda non può essere approvata o rifiutata perché l'emendamento è attivo.
|
||||||
atleast.one.id.required=Almeno uno tra companyId o applicationId deve essere fornito.
|
atleast.one.id.required=Almeno uno tra companyId o applicationId deve essere fornito.
|
||||||
|
|
||||||
|
#Appointment flow messages
|
||||||
|
ndg.available = NDG disponibile.
|
||||||
|
ndg.generation.in.progress = La generazione NDG ? in corso.
|
||||||
|
ndg.fetch.successfully = Recupero NDG riuscito.
|
||||||
|
appointment.already.created = Appuntamento gi? creato.
|
||||||
|
ndg.not.found.for.this.application.or.invalid = NDG non trovato per questa applicazione o non valido.
|
||||||
|
provide.valid.application.document.id = Fornisci un ID documento applicativo valido.
|
||||||
|
document.uploaded.successfully.to.external.system = Documento caricato con successo nel sistema esterno.
|
||||||
|
error.in.uploading.document.check.input = Errore nel caricamento del documento. Controlla i dati inseriti o riprova.
|
||||||
|
document.already.uploaded = Documento gi? caricato.
|
||||||
|
document.not.uploaded.to.external.system.please.try.again = Documento non caricato nel sistema esterno, riprova.
|
||||||
|
ndg.not.found.or.not.matched = L'NDG fornito non corrisponde all'NDG dell'applicazione o non ? stato generato.
|
||||||
|
ndg.generation.is.only.for.gepafin = La generazione dell'NDG ? disponibile solo per GEPAFIN.
|
||||||
|
appointment.creation.is.only.for.gepafin = La creazione degli appuntamenti ? consentita solo per GEPAFIN.
|
||||||
|
upload.document.is.only.for.gepafin = Il documento non pu? essere caricato, questa operazione ? disponibile solo per il Hub GEPAFIN.
|
||||||
|
appointment.created.successfully = Appuntamento creato con successo.
|
||||||
|
error.try.again = Errore di chiamata di servizio durante l'esecuzione dell'operazione. Riprovare.
|
||||||
|
|||||||
Reference in New Issue
Block a user