Resolved Conflicts
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package net.gepafin.tendermanagement.dao;
|
||||
|
||||
import com.amazonaws.services.s3.AmazonS3Client;
|
||||
import com.amazonaws.services.s3.model.GetObjectRequest;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -13,12 +12,14 @@ import net.gepafin.tendermanagement.config.Translator;
|
||||
import net.gepafin.tendermanagement.config.jwt.TokenProvider;
|
||||
import net.gepafin.tendermanagement.constants.AppointmentApiConstant;
|
||||
import net.gepafin.tendermanagement.constants.GepafinConstant;
|
||||
import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity;
|
||||
import net.gepafin.tendermanagement.entities.ApplicationEntity;
|
||||
import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity;
|
||||
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.NotificationTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.VersionActionTypeEnum;
|
||||
import net.gepafin.tendermanagement.model.request.AppointmentCreationRequest;
|
||||
@@ -37,6 +38,7 @@ import net.gepafin.tendermanagement.repositories.CompanyRepository;
|
||||
import net.gepafin.tendermanagement.repositories.DocumentRepository;
|
||||
import net.gepafin.tendermanagement.repositories.HubRepository;
|
||||
import net.gepafin.tendermanagement.repositories.UserRepository;
|
||||
import net.gepafin.tendermanagement.service.AmazonS3Service;
|
||||
import net.gepafin.tendermanagement.service.ApplicationService;
|
||||
import net.gepafin.tendermanagement.service.CompanyService;
|
||||
import net.gepafin.tendermanagement.service.feignClient.AppointmentApiService;
|
||||
@@ -60,12 +62,7 @@ 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.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -141,6 +138,18 @@ public class AppointmentDao {
|
||||
@Autowired
|
||||
private ApplicationEvaluationServiceImpl applicationEvaluationService;
|
||||
|
||||
@Autowired
|
||||
private AmazonS3Service amazonS3Service;
|
||||
|
||||
@Autowired
|
||||
private ApplicationDao applicationDao;
|
||||
|
||||
@Autowired
|
||||
private ApplicationAmendmentRequestDao applicationAmendmentRequestDao;
|
||||
|
||||
@Autowired
|
||||
private ApplicationEvaluationDao applicationEvaluationDao;
|
||||
|
||||
private final Map<Long, ExecutorService> executorMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final ConcurrentHashMap<Long, ExecutorService> threadForDocumentMap = new ConcurrentHashMap<>();
|
||||
@@ -174,10 +183,182 @@ public class AppointmentDao {
|
||||
return ndgResponse;
|
||||
}
|
||||
|
||||
private HubEntity loginToOdessa(HubEntity hub, ApplicationEntity application) {
|
||||
// private HubEntity loginToOdessa(HubEntity hub, ApplicationEntity application) {
|
||||
//
|
||||
// int maxRetries = 3;
|
||||
// int attempt = 0;
|
||||
// boolean success = false;
|
||||
// while (attempt < maxRetries && !success) {
|
||||
// attempt++;
|
||||
// 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);
|
||||
// Map<String, Object> body = Collections.emptyMap();
|
||||
// ResponseEntity<Object> responseLogin = appointmentApiService.loginWithOdessa(authJwtToken, source, context, user, password, body);
|
||||
// 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);
|
||||
// log.info("Saved new authToken and areaCode for Hub.");
|
||||
// success = true;
|
||||
// return hub;
|
||||
// } else {
|
||||
// throw new RuntimeException("Login response is missing a valid tokenId for login to odessa system, please try again.");
|
||||
// }
|
||||
// }
|
||||
// throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_IN_GENERATING_NDG_TRY_AGAIN));
|
||||
// } catch (FeignException.Forbidden forbiddenException) {
|
||||
// log.error("Failed to login to odessa due to some error");
|
||||
//
|
||||
// // Extract raw response body
|
||||
// String responseBody = forbiddenException.contentUTF8(); // Extract raw JSON response
|
||||
//
|
||||
// // Parse JSON to check for "PasswordExpired"
|
||||
// try {
|
||||
// ObjectMapper objectMapper = new ObjectMapper();
|
||||
// JsonNode rootNode = objectMapper.readTree(responseBody);
|
||||
// JsonNode errorsNode = rootNode.path("errors");
|
||||
//
|
||||
// if (errorsNode.isArray()) {
|
||||
// for (JsonNode error : errorsNode) {
|
||||
// // Check the main errorCode
|
||||
// if (GepafinConstant.PASSWORD_EXPIRED.equals(error.path("errorCode").asText())) {
|
||||
// application.setNdgStatus(GepafinConstant.NDG_FAILED);
|
||||
// applicationRepository.save(application);
|
||||
// throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA));
|
||||
// }
|
||||
//
|
||||
// // Check inside "subErrors"
|
||||
// JsonNode subErrorsNode = error.path("subErrors");
|
||||
// if (subErrorsNode.isArray()) {
|
||||
// for (JsonNode subError : subErrorsNode) {
|
||||
// if (GepafinConstant.PASSWORD_EXPIRED.equals(subError.path("errorCode").asText())) {
|
||||
// application.setNdgStatus(GepafinConstant.NDG_FAILED);
|
||||
// applicationRepository.save(application);
|
||||
// throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// log.error("Error parsing JSON response: {}", e.getMessage());
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// log.error("Failed to authenticate user on Odessa : {}", e.getMessage(), e);
|
||||
// throw new RuntimeException("Authentication failed on Odessa. try again", e);
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// private HubEntity authenticateAndSaveToken(HubEntity hub) {
|
||||
//
|
||||
// int maxRetries = 3;
|
||||
// int attempt = 0;
|
||||
// boolean success = false;
|
||||
// while (attempt < maxRetries && !success) {
|
||||
// attempt++;
|
||||
// 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);
|
||||
// // 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);
|
||||
//
|
||||
// log.info("Saved new authToken and areaCode for Hub.");
|
||||
// success = true;
|
||||
// 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 (FeignException.Forbidden forbiddenException) {
|
||||
// log.error("Failed to login to odessa due to some error occurred.");
|
||||
//
|
||||
// // Extract raw response body
|
||||
// String responseBody = forbiddenException.contentUTF8(); // Extract raw JSON response
|
||||
//
|
||||
// // Parse JSON to check for "PasswordExpired"
|
||||
// try {
|
||||
// ObjectMapper objectMapper = new ObjectMapper();
|
||||
// JsonNode rootNode = objectMapper.readTree(responseBody);
|
||||
// JsonNode errorsNode = rootNode.path("errors");
|
||||
//
|
||||
// if (errorsNode.isArray()) {
|
||||
// for (JsonNode error : errorsNode) {
|
||||
// // Check the main errorCode
|
||||
// if (GepafinConstant.PASSWORD_EXPIRED.equals(error.path("errorCode").asText())) {
|
||||
// throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA));
|
||||
// }
|
||||
//
|
||||
// // Check inside "subErrors"
|
||||
// JsonNode subErrorsNode = error.path("subErrors");
|
||||
// if (subErrorsNode.isArray()) {
|
||||
// for (JsonNode subError : subErrorsNode) {
|
||||
// if (GepafinConstant.PASSWORD_EXPIRED.equals(subError.path("errorCode").asText())) {
|
||||
// throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// log.error("Error parsing JSON response: {}", e.getMessage());
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// log.error("Failed to authenticate user on Odessa : {}", e.getMessage(), e);
|
||||
// throw new RuntimeException("Authentication failed on Odessa. try again", e);
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
private void loginToOdessa(HubEntity hub, ApplicationEntity application) {
|
||||
log.info("Starting login to Odessa. HubId: {}, ApplicationId: {}", hub.getId(), application.getId());
|
||||
performOdessaLogin(hub, application);
|
||||
}
|
||||
|
||||
private HubEntity authenticateAndSaveToken(HubEntity hub, ApplicationEntity application) {
|
||||
|
||||
return performOdessaLogin(hub, application);
|
||||
}
|
||||
|
||||
private HubEntity performOdessaLogin(HubEntity hub, ApplicationEntity application) {
|
||||
|
||||
int maxRetries = 3;
|
||||
int attempt = 0;
|
||||
while (attempt < maxRetries) {
|
||||
attempt++;
|
||||
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);
|
||||
@@ -189,7 +370,6 @@ public class AppointmentDao {
|
||||
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());
|
||||
@@ -202,55 +382,53 @@ public class AppointmentDao {
|
||||
}
|
||||
}
|
||||
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_IN_GENERATING_NDG_TRY_AGAIN));
|
||||
} catch (FeignException.Forbidden forbiddenException) {
|
||||
log.error("Failed to login to odessa due to forbidden error.");
|
||||
|
||||
CheckPasswordExpiredOrErrorInResponse(application, forbiddenException);
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to authenticate user on Odessa (Attempt {}): {}", attempt, e.getMessage(), e);
|
||||
}
|
||||
catch (FeignException.Forbidden forbiddenException) {
|
||||
log.warn("Received 403 Forbidden from Odessa. Attempting to parse error response.");
|
||||
logForbiddenError();
|
||||
}
|
||||
throw new RuntimeException("Max retries exceeded. Failed to login to Odessa.");
|
||||
}
|
||||
private void CheckPasswordExpiredOrErrorInResponse(ApplicationEntity application, FeignException.Forbidden forbiddenException) {
|
||||
|
||||
// Extract raw response body
|
||||
String responseBody = forbiddenException.contentUTF8(); // Extract raw JSON response
|
||||
String responseBody = forbiddenException.contentUTF8();
|
||||
|
||||
// Parse JSON to check for "PasswordExpired"
|
||||
try {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonNode rootNode = objectMapper.readTree(responseBody);
|
||||
JsonNode errorsNode = rootNode.path("errors");
|
||||
try {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonNode rootNode = objectMapper.readTree(responseBody);
|
||||
JsonNode errorsNode = rootNode.path("errors");
|
||||
|
||||
if (errorsNode.isArray()) {
|
||||
for (JsonNode error : errorsNode) {
|
||||
// Check the main errorCode
|
||||
if (GepafinConstant.PASSWORD_EXPIRED.equals(error.path("errorCode").asText())) {
|
||||
application.setNdgStatus(GepafinConstant.NDG_FAILED);
|
||||
applicationRepository.save(application);
|
||||
log.warn("Detected PASSWORD_EXPIRED error during Odessa login. ApplicationId: {}", application.getId());
|
||||
throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA));
|
||||
}
|
||||
if (errorsNode.isArray()) {
|
||||
for (JsonNode error : errorsNode) {
|
||||
if (GepafinConstant.PASSWORD_EXPIRED.equals(error.path("errorCode").asText())) {
|
||||
if (application != null) {
|
||||
application.setNdgStatus(GepafinConstant.NDG_FAILED);
|
||||
applicationRepository.save(application);
|
||||
}
|
||||
log.warn("Detected PASSWORD_EXPIRED error during Odessa login. ApplicationId: {}", application.getId());
|
||||
throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA));
|
||||
}
|
||||
|
||||
// Check inside "subErrors"
|
||||
JsonNode subErrorsNode = error.path("subErrors");
|
||||
if (subErrorsNode.isArray()) {
|
||||
for (JsonNode subError : subErrorsNode) {
|
||||
if (GepafinConstant.PASSWORD_EXPIRED.equals(subError.path("errorCode").asText())) {
|
||||
application.setNdgStatus(GepafinConstant.NDG_FAILED);
|
||||
applicationRepository.save(application);
|
||||
throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA));
|
||||
}
|
||||
JsonNode subErrorsNode = error.path("subErrors");
|
||||
if (subErrorsNode.isArray()) {
|
||||
for (JsonNode subError : subErrorsNode) {
|
||||
if (GepafinConstant.PASSWORD_EXPIRED.equals(subError.path("errorCode").asText())) {
|
||||
if (application != null) {
|
||||
application.setNdgStatus(GepafinConstant.NDG_FAILED);
|
||||
applicationRepository.save(application);
|
||||
}
|
||||
throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Error parsing JSON response: {}", e.getMessage());
|
||||
}
|
||||
|
||||
// Regenerate the token and retry
|
||||
loginToOdessa(hub, application);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Unexpected exception during Odessa login. HubId: {}, Error: {}", hub.getId(), e.getMessage(), e);
|
||||
throw new RuntimeException("Authentication failed on Odessa. try again", e);
|
||||
}
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
log.error("Unexpected exception during Odessa login.Error: {}",e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void startAsyncNdgProcessing(Long applicationId) {
|
||||
@@ -300,7 +478,7 @@ public class AppointmentDao {
|
||||
try {
|
||||
// Authenticate and fetch token if required
|
||||
if (hub.getAppointmentAuthTokenId() == null || hub.getAreaCode() == null) {
|
||||
authenticateAndSaveToken(hub);
|
||||
authenticateAndSaveToken(hub, application);
|
||||
}
|
||||
|
||||
String authorizationToken = getBearerToken(hub);
|
||||
@@ -349,9 +527,13 @@ public class AppointmentDao {
|
||||
applicationRepository.save(application);
|
||||
companyRepository.save(company);
|
||||
ApplicationEvaluationEntity applicationEvaluationEntity = applicationEvaluationService.validateApplicationEvaluation(application.getApplicationEvaluationId());
|
||||
Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.NDG_GENERATION);
|
||||
// Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.NDG_GENERATION);
|
||||
|
||||
Map<String, String> placeHolders = new HashMap<>();
|
||||
placeHolders.put("{{call_name}}", application.getCall().getName());
|
||||
placeHolders.put("{{protocol_number}}", String.valueOf(application.getProtocol().getProtocolNumber()));
|
||||
notificationDao.sendNotificationToInstructor(placeHolders, applicationEvaluationEntity, NotificationTypeEnum.NDG_GENERATION);
|
||||
notificationDao.sendNotificationToSuperUser(application,placeHolders,NotificationTypeEnum.NDG_GENERATION);
|
||||
notificationDao.sendNotificationToSuperUser(application, placeHolders, NotificationTypeEnum.NDG_GENERATION);
|
||||
log.info("NDG saved successfully for applicationId: {}", application.getId());
|
||||
break;
|
||||
}
|
||||
@@ -399,9 +581,12 @@ public class AppointmentDao {
|
||||
companyRepository.save(company);
|
||||
applicationRepository.save(application);
|
||||
ApplicationEvaluationEntity applicationEvaluationEntity = applicationEvaluationService.validateApplicationEvaluation(application.getApplicationEvaluationId());
|
||||
Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.NDG_GENERATION);
|
||||
// Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.NDG_GENERATION);
|
||||
Map<String, String> placeHolders = new HashMap<>();
|
||||
placeHolders.put("{{call_name}}", application.getCall().getName());
|
||||
placeHolders.put("{{protocol_number}}", String.valueOf(application.getProtocol().getProtocolNumber()));
|
||||
notificationDao.sendNotificationToInstructor(placeHolders, applicationEvaluationEntity, NotificationTypeEnum.NDG_GENERATION);
|
||||
notificationDao.sendNotificationToSuperUser(application,placeHolders,NotificationTypeEnum.NDG_GENERATION);
|
||||
notificationDao.sendNotificationToSuperUser(application, placeHolders, NotificationTypeEnum.NDG_GENERATION);
|
||||
log.info("NDG saved for applicationId: {}, {}", application.getId(), application.getNdg());
|
||||
}
|
||||
|
||||
@@ -420,7 +605,7 @@ public class AppointmentDao {
|
||||
} catch (FeignException.Forbidden forbiddenException) {
|
||||
log.warn("403 Forbidden while fetching Visura list. Attempting token regeneration | ApplicationId: {}, HubId: {}", application.getId(), hub.getId());
|
||||
// Regenerate the token and retry
|
||||
String newAuthorizationToken = regenerateTokenAndSave(hub);
|
||||
String newAuthorizationToken = regenerateTokenAndSave(hub, application);
|
||||
return getVisuraList(idVisura, newAuthorizationToken, application, hub);
|
||||
} catch (Exception e) {
|
||||
log.error("Error while fetching Visura list | ApplicationId: {}, HubId: {}, Error: {}", application.getId(), hub.getId(), e.getMessage(), e);
|
||||
@@ -428,86 +613,6 @@ public class AppointmentDao {
|
||||
}
|
||||
}
|
||||
|
||||
private HubEntity authenticateAndSaveToken(HubEntity hub) {
|
||||
|
||||
try {
|
||||
log.info("Starting authentication to Odessa | HubId: {}", hub.getId());
|
||||
//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);
|
||||
// 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);
|
||||
|
||||
log.info("Saved new authToken and areaCode for Hub.");
|
||||
return hub;
|
||||
} else {
|
||||
log.error("Login response missing tokenId | HubId: {}", hub.getId());
|
||||
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 (FeignException.Forbidden forbiddenException) {
|
||||
log.error("403 Forbidden during Odessa login | HubId: {}", hub.getId());
|
||||
logForbiddenError();
|
||||
|
||||
// Extract raw response body
|
||||
String responseBody = forbiddenException.contentUTF8(); // Extract raw JSON response
|
||||
|
||||
// Parse JSON to check for "PasswordExpired"
|
||||
try {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonNode rootNode = objectMapper.readTree(responseBody);
|
||||
JsonNode errorsNode = rootNode.path("errors");
|
||||
|
||||
if (errorsNode.isArray()) {
|
||||
for (JsonNode error : errorsNode) {
|
||||
// Check the main errorCode
|
||||
if (GepafinConstant.PASSWORD_EXPIRED.equals(error.path("errorCode").asText())) {
|
||||
log.warn("Odessa password expired detected in login response | HubId: {}", hub.getId());
|
||||
throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA));
|
||||
}
|
||||
|
||||
// Check inside "subErrors"
|
||||
JsonNode subErrorsNode = error.path("subErrors");
|
||||
if (subErrorsNode.isArray()) {
|
||||
for (JsonNode subError : subErrorsNode) {
|
||||
if (GepafinConstant.PASSWORD_EXPIRED.equals(subError.path("errorCode").asText())) {
|
||||
throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Error parsing forbidden JSON response | HubId: {}, Error: {}", hub.getId(), e.getMessage(), e);
|
||||
}
|
||||
|
||||
// Regenerate the token and retry
|
||||
regenerateTokenAndSave(hub);
|
||||
} catch (Exception e) {
|
||||
log.error("Unexpected error during Odessa authentication | HubId: {}, Error: {}", hub.getId(), e.getMessage(), e);
|
||||
throw new RuntimeException("Authentication failed on Odessa. try again", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private AppointmentLoginResponse retrieveNdgByVatNumber(String vatNumber, String authorizationToken, HubEntity hub, ApplicationEntity application) {
|
||||
|
||||
try {
|
||||
@@ -523,7 +628,7 @@ public class AppointmentDao {
|
||||
log.error("403 Forbidden during NDG retrieval | ApplicationId: {}, HubId: {}", application.getId(), hub.getId());
|
||||
logForbiddenError();
|
||||
// Regenerate the token and retry
|
||||
String newAuthorizationToken = regenerateTokenAndSave(hub);
|
||||
String newAuthorizationToken = regenerateTokenAndSave(hub, application);
|
||||
return retrieveNdgByVatNumber(vatNumber, newAuthorizationToken, hub, application);
|
||||
} catch (Exception e) {
|
||||
log.error("Error during NDG retrieval | ApplicationId: {}, HubId: {}, Message: {}", application.getId(), hub.getId(), e.getMessage(), e);
|
||||
@@ -531,9 +636,10 @@ public class AppointmentDao {
|
||||
}
|
||||
}
|
||||
|
||||
private String regenerateTokenAndSave(HubEntity hub) {
|
||||
hub = authenticateAndSaveToken(hub);
|
||||
return "Bearer " + hub.getAppointmentAuthTokenId();
|
||||
private String regenerateTokenAndSave(HubEntity hub, ApplicationEntity application) {
|
||||
|
||||
hub = authenticateAndSaveToken(hub, application);
|
||||
return "Bearer " + hub.getAppointmentAuthTokenId();
|
||||
}
|
||||
|
||||
private AppointmentLoginResponse createVisura(CompanyEntity company, String authorizationToken, HubEntity hub) {
|
||||
@@ -546,7 +652,7 @@ public class AppointmentDao {
|
||||
} catch (FeignException.Forbidden forbiddenException) {
|
||||
logForbiddenError();
|
||||
// Regenerate the token and retry
|
||||
String newAuthorizationToken = regenerateTokenAndSave(hub);
|
||||
String newAuthorizationToken = regenerateTokenAndSave(hub, null);
|
||||
return createVisura(company, newAuthorizationToken, hub);
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to create Visura for Ndg : {}", e.getMessage());
|
||||
@@ -719,9 +825,8 @@ public class AppointmentDao {
|
||||
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NDG_NOT_FOUND_FOR_APPLICATION));
|
||||
}
|
||||
|
||||
hub = authenticateAndSaveToken(hub);
|
||||
// Generate authorization token and fetch template data
|
||||
String authorizationToken = getBearerToken(hub);
|
||||
String authorizationToken = regenerateTokenAndSave(hub, application);
|
||||
Long appointmentTemplateId = application.getCall().getAppointmentTemplateId();
|
||||
if (appointmentTemplateId == null) {
|
||||
log.error("Missing appointment template ID for applicationId: {}", applicationId);
|
||||
@@ -741,9 +846,11 @@ public class AppointmentDao {
|
||||
// Build the appointment request body
|
||||
AppointmentCreationRequest appointmentCreationRequest = buildAppointmentCreationRequest(applicationId, createAppointmentRequest, appointmentTemplateId,
|
||||
templateRichiestaData);
|
||||
log.info("AppointmentCreationRequest : {}", appointmentCreationRequest);
|
||||
String appointmentRequestBody = Utils.convertObjectToJson(appointmentCreationRequest);
|
||||
|
||||
// Make API call to create the appointment
|
||||
log.info("Context:{}, Authorization Token : {}, RequestBody : {}", context, authorizationToken, appointmentRequestBody);
|
||||
ResponseEntity<Object> appointmentResponse = appointmentApiService.createAppointment(authorizationToken, context, appointmentRequestBody);
|
||||
String appointmentId = extractAppointmentIdFromResponse(appointmentResponse);
|
||||
|
||||
@@ -764,8 +871,8 @@ public class AppointmentDao {
|
||||
return appointmentCreationResponse;
|
||||
|
||||
} catch (FeignException.Forbidden forbiddenException) {
|
||||
log.error("403 Forbidden received while retrieving template. Attempting to regenerate token and retry. Application ID: {}", applicationId);
|
||||
regenerateTokenAndSave(hub);
|
||||
log.error("403 Forbidden received while retrieving template. Attempting to regenerate token and retry. Application ID: {}", applicationId);
|
||||
regenerateTokenAndSave(hub, application);
|
||||
return createAppointment(applicationId, createAppointmentRequest);
|
||||
}
|
||||
}
|
||||
@@ -773,12 +880,32 @@ public class AppointmentDao {
|
||||
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();
|
||||
log.info("Appointment API Response : {}", appointmentResponse.getBody());
|
||||
try {
|
||||
Map<String, Object> responseBody = (Map<String, Object>) appointmentResponse.getBody();
|
||||
// 1. Try to get appointment ID from data.id
|
||||
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();
|
||||
}
|
||||
}
|
||||
// 2. If ID not present, check errors[0].cause.errorDescription
|
||||
if (responseBody.containsKey(GepafinConstant.ERROR_STRING)) {
|
||||
List<Map<String, Object>> errors = (List<Map<String, Object>>) responseBody.get(GepafinConstant.ERROR_STRING);
|
||||
if (errors != null && !errors.isEmpty()) {
|
||||
Map<String, Object> firstError = errors.get(0);
|
||||
if (firstError.containsKey(GepafinConstant.CAUSE_STRING)) {
|
||||
Map<String, Object> cause = (Map<String, Object>) firstError.get(GepafinConstant.CAUSE_STRING);
|
||||
if (cause != null && cause.containsKey(GepafinConstant.ERROR_DESCRIPTION_STRING)) {
|
||||
String errorDescription = cause.get(GepafinConstant.ERROR_DESCRIPTION_STRING).toString();
|
||||
log.warn("Appointment creation failed: {}", errorDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error while extracting appointment ID or parsing error message", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -808,20 +935,20 @@ public class AppointmentDao {
|
||||
JsonNode prodottoNode = richiestaNode.path(AppointmentApiConstant.PRODOTTO);
|
||||
String prodottoCode = prodottoNode.path(AppointmentApiConstant.PRODOTTO_CODE).asText();
|
||||
|
||||
richiestaCliente.setCodProdotto(prodottoCode);
|
||||
richiestaCliente.setIdMotivazione(getIntValue(richiestaNode));
|
||||
richiestaCliente.setCodAbi(getTextValue(richiestaNode, AppointmentApiConstant.COD_ABI));
|
||||
richiestaCliente.setCodCab(getTextValue(richiestaNode, AppointmentApiConstant.COD_CAB));
|
||||
richiestaCliente.setIdNota(getTextValue(richiestaNode, AppointmentApiConstant.ID_NOTA));
|
||||
richiestaCliente.setImportoAgevolato(getTextValue(richiestaNode, AppointmentApiConstant.IMPORTO_AGEVOLATO));
|
||||
richiestaCliente.setImportoMedioLungoTermine(getTextValue(richiestaNode, AppointmentApiConstant.IMPORTO_MEDIOLUNGO_TERMINE));
|
||||
richiestaCliente.setCodTipoProdotto(getTextValue(richiestaNode, AppointmentApiConstant.COD_TIPO_PRODOTTO));
|
||||
richiestaCliente.setCodCategoriaProdotto(getTextValue(richiestaNode, AppointmentApiConstant.COD_CATEGORIA_PRODOTTO));
|
||||
richiestaCliente.setCodFormaTecnica(getTextValue(richiestaNode, AppointmentApiConstant.COD_FORMATECNICA));
|
||||
richiestaCliente.setCodOperazione(getTextValue(richiestaNode, AppointmentApiConstant.COD_OPERAZIONE));
|
||||
richiestaCliente.setCodProdotto(prodottoCode);
|
||||
richiestaCliente.setIdMotivazione(getIntValue(richiestaNode));
|
||||
richiestaCliente.setCodAbi(getTextValue(richiestaNode, AppointmentApiConstant.COD_ABI));
|
||||
richiestaCliente.setCodCab(getTextValue(richiestaNode, AppointmentApiConstant.COD_CAB));
|
||||
richiestaCliente.setIdNota(getTextValue(richiestaNode, AppointmentApiConstant.ID_NOTA));
|
||||
richiestaCliente.setImportoAgevolato(getTextValue(richiestaNode, AppointmentApiConstant.IMPORTO_AGEVOLATO));
|
||||
richiestaCliente.setImportoMedioLungoTermine(getTextValue(richiestaNode, AppointmentApiConstant.IMPORTO_MEDIOLUNGO_TERMINE));
|
||||
richiestaCliente.setCodTipoProdotto(getTextValue(richiestaNode, AppointmentApiConstant.COD_TIPO_PRODOTTO));
|
||||
richiestaCliente.setCodCategoriaProdotto(getTextValue(richiestaNode, AppointmentApiConstant.COD_CATEGORIA_PRODOTTO));
|
||||
richiestaCliente.setCodFormaTecnica(getTextValue(richiestaNode, AppointmentApiConstant.COD_FORMATECNICA));
|
||||
richiestaCliente.setCodOperazione(getTextValue(richiestaNode, AppointmentApiConstant.COD_OPERAZIONE));
|
||||
|
||||
richiestaClienteList.add(richiestaCliente);
|
||||
}
|
||||
richiestaClienteList.add(richiestaCliente);
|
||||
}
|
||||
|
||||
input.setRichiestaCliente(richiestaClienteList);
|
||||
appointmentCreationRequest.setInput(input);
|
||||
@@ -883,13 +1010,40 @@ public class AppointmentDao {
|
||||
// Check if the document is already being processed
|
||||
DocumentEntity systemDoc = documentDao.validateDocument(documentId);
|
||||
|
||||
ApplicationEntity application = null;
|
||||
|
||||
if (systemDoc != null) {
|
||||
DocumentSourceTypeEnum sourceType = DocumentSourceTypeEnum.valueOf(systemDoc.getSource());
|
||||
|
||||
switch (sourceType) {
|
||||
case APPLICATION:
|
||||
application = applicationDao.validateApplication(systemDoc.getSourceId());
|
||||
break;
|
||||
case AMENDMENT:
|
||||
ApplicationAmendmentRequestEntity applicationAmendmentEntity = applicationAmendmentRequestDao.validateApplicationAmendmentRequest(systemDoc.getSourceId());
|
||||
application = applicationDao.validateApplication(applicationAmendmentEntity.getApplicationId());
|
||||
break;
|
||||
case EVALUATION:
|
||||
ApplicationEvaluationEntity applicationEvaluationEntity = applicationEvaluationDao.validateApplicationEvaluation(systemDoc.getSourceId());
|
||||
application = applicationDao.validateApplication(applicationEvaluationEntity.getApplicationId());
|
||||
break;
|
||||
|
||||
case CALL:
|
||||
break;
|
||||
|
||||
default:
|
||||
log.warn("Unhandled document source type: {}", sourceType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Claims claims = tokenProvider.getClaimsFromToken(tokenProvider.extractTokenFromRequest(request));
|
||||
Long hubId = Utils.extractHubIdFromPayload(claims.getSubject());
|
||||
|
||||
// Authenticate the hub before proceeding
|
||||
HubEntity hub = hubRepository.findByHubId(hubId);
|
||||
authenticateAndSaveToken(hub);
|
||||
if (systemDoc.getDocumentAttachmentId() != null) {
|
||||
authenticateAndSaveToken(hub, application);
|
||||
if (systemDoc != null && systemDoc.getDocumentAttachmentId() != null) {
|
||||
// If the documentAttachmentId is already set, return the response
|
||||
log.info("Document already uploaded with documentAttachmentId: {}", systemDoc.getDocumentAttachmentId());
|
||||
DocumentUploadResponse response = new DocumentUploadResponse();
|
||||
@@ -909,11 +1063,12 @@ public class AppointmentDao {
|
||||
});
|
||||
threadForDocumentMap.put(documentId, executor);
|
||||
|
||||
ApplicationEntity finalApplication = application;
|
||||
executor.submit(() -> {
|
||||
threadLocalHubId.set(hubId);
|
||||
try {
|
||||
log.info("Starting async document upload for documentId: {}", documentId);
|
||||
uploadDocumentToExternalSystemSync(documentId, docToExternalSystemRequest);
|
||||
uploadDocumentToExternalSystemSync(documentId, docToExternalSystemRequest, finalApplication);
|
||||
} catch (Exception e) {
|
||||
log.error("Error in async document upload for documentId: {}", documentId, e);
|
||||
} finally {
|
||||
@@ -929,8 +1084,8 @@ public class AppointmentDao {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void uploadDocumentToExternalSystemSync(Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest) {
|
||||
log.info("Starting sync document upload for documentId: {}", documentId);
|
||||
private void uploadDocumentToExternalSystemSync(Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest, ApplicationEntity application) {
|
||||
log.info("Starting sync document upload for documentId: {}", documentId);
|
||||
// Synchronous upload logic
|
||||
DocumentEntity systemDoc = documentDao.validateDocument(documentId);
|
||||
|
||||
@@ -971,9 +1126,9 @@ public class AppointmentDao {
|
||||
|
||||
log.info("Document uploaded successfully to external system: {}", parsedResponse);
|
||||
} catch (FeignException.Forbidden forbiddenException) {
|
||||
log.error("403 Forbidden from external system during upload for documentId: {}. Retrying with new token...", documentId);
|
||||
regenerateTokenAndSave(hub);
|
||||
uploadDocumentToExternalSystemSync(documentId, docToExternalSystemRequest);
|
||||
log.error("403 Forbidden from external system during upload for documentId: {}. Retrying with new token...", documentId);
|
||||
regenerateTokenAndSave(hub, application);
|
||||
uploadDocumentToExternalSystemSync(documentId, docToExternalSystemRequest, application);
|
||||
} catch (Exception e) {
|
||||
log.error("Exception during document upload: {}", e.getMessage(), e);
|
||||
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.EXTERNAL_DOCUMENT_UPLOAD_FAILURE_MSG));
|
||||
@@ -1004,12 +1159,12 @@ public class AppointmentDao {
|
||||
|
||||
private File downloadFileFromS3(String fileUrl) throws Exception {
|
||||
|
||||
String key = extractS3KeyFromUrl(fileUrl);
|
||||
File localFile = new File(GepafinConstant.TEMP_FILE_PATH + extractFileName(key));
|
||||
String key = amazonS3Service.extractS3KeyFromUrl(fileUrl);
|
||||
String fileName = extractFileName(key);
|
||||
String folderPath = key.substring(0, key.lastIndexOf("/"));
|
||||
File localFile = new File(GepafinConstant.TEMP_FILE_PATH + fileName);
|
||||
|
||||
GetObjectRequest getObjectRequest = new GetObjectRequest(OLD_BUCKET, key);
|
||||
|
||||
try (InputStream s3Stream = s3Client.getObject(getObjectRequest).getObjectContent(); FileOutputStream outputStream = new FileOutputStream(localFile)) {
|
||||
try (InputStream s3Stream = amazonS3Service.getFile(folderPath, key); FileOutputStream outputStream = new FileOutputStream(localFile)) {
|
||||
s3Stream.transferTo(outputStream);
|
||||
}
|
||||
|
||||
@@ -1017,11 +1172,6 @@ public class AppointmentDao {
|
||||
return localFile;
|
||||
}
|
||||
|
||||
private String extractS3KeyFromUrl(String url) {
|
||||
|
||||
return url.replace(s3Url, "");
|
||||
}
|
||||
|
||||
private String extractFileName(String filePath) {
|
||||
|
||||
String[] parts = filePath.split("/");
|
||||
|
||||
Reference in New Issue
Block a user