Merge pull request #310 from Kitzanos/feature/GEPAFINBE-229
GEPAFINBE-229 (Refactor NDG handling)
This commit is contained in:
@@ -18,7 +18,7 @@ public class AppointmentApiConstant {
|
||||
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_TYPE = "FullReport";
|
||||
public static final String VISURA_MODE = "visure";
|
||||
public static final String COD_AGENTE = "UtenzaAPIPortal";
|
||||
public static final boolean IS_FROM_RATING = Boolean.FALSE;
|
||||
@@ -38,4 +38,7 @@ public class AppointmentApiConstant {
|
||||
public static final String COD_OPERAZIONE = "codOperazione";
|
||||
public static final String MOTIVAZIONE_ID = "id";
|
||||
public static final String PRODOTTO_CODE = "code";
|
||||
|
||||
public static final String WS_ANAGRAFICA_URL= "/WSAnagrafica.getList";
|
||||
|
||||
}
|
||||
|
||||
@@ -12,12 +12,7 @@ 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.entities.*;
|
||||
import net.gepafin.tendermanagement.enums.*;
|
||||
import net.gepafin.tendermanagement.model.request.AppointmentCreationRequest;
|
||||
import net.gepafin.tendermanagement.model.request.AppointmentNdgRequest;
|
||||
@@ -30,11 +25,7 @@ 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.repositories.UserRepository;
|
||||
import net.gepafin.tendermanagement.repositories.*;
|
||||
import net.gepafin.tendermanagement.service.AmazonS3Service;
|
||||
import net.gepafin.tendermanagement.service.ApplicationService;
|
||||
import net.gepafin.tendermanagement.service.CompanyService;
|
||||
@@ -62,13 +53,8 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@@ -177,7 +163,7 @@ public class AppointmentDao {
|
||||
|
||||
// Update application status
|
||||
log.info("Updating NDG status to IN_PROGRESS. applicationId: {}", applicationId);
|
||||
application.setNdgStatus(GepafinConstant.NDG_IN_PROGRESS);
|
||||
application.setNdgStatus(NdgStatusEnum.NDG_INITITATED.getValue());
|
||||
applicationRepository.save(application);
|
||||
|
||||
loggingUtil.addVersionHistory(
|
||||
@@ -401,6 +387,7 @@ public class AppointmentDao {
|
||||
}
|
||||
throw new RuntimeException("Max retries exceeded. Failed to login to Odessa.");
|
||||
}
|
||||
|
||||
private void CheckPasswordExpiredOrErrorInResponse(ApplicationEntity application, FeignException.Forbidden forbiddenException) {
|
||||
|
||||
String responseBody = forbiddenException.contentUTF8();
|
||||
@@ -436,89 +423,89 @@ public class AppointmentDao {
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Unexpected exception during Odessa login.Error: {}",e.getMessage(), e);
|
||||
log.error("Unexpected exception during Odessa login.Error: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void startAsyncNdgProcessing(Long applicationId) {
|
||||
// If already polling for this applicationId, do nothing:
|
||||
if (executorMap.containsKey(applicationId)) {
|
||||
log.warn("Async processing already running for applicationId: {}", applicationId);
|
||||
return;
|
||||
}
|
||||
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
|
||||
|
||||
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> {
|
||||
Thread t = new Thread(runnable);
|
||||
t.setName("AsyncNdgProcessing-" + applicationId);
|
||||
return t;
|
||||
});
|
||||
executorMap.put(applicationId, scheduler);
|
||||
|
||||
// Record the start time so we can stop after 2 hours:
|
||||
long startTime = System.currentTimeMillis();
|
||||
long twoHoursMs = TimeUnit.HOURS.toMillis(2);
|
||||
long fifteenMin = 15; // in MINUTES
|
||||
|
||||
// We need a reference to cancel the scheduled task from inside itself when we're done:
|
||||
AtomicReference<ScheduledFuture<?>> futureRef = new AtomicReference<>();
|
||||
|
||||
Runnable pollingTask = () -> {
|
||||
RequestContextHolder.setRequestAttributes(requestAttributes, true);
|
||||
Utils.setHttpServletRequestForThread(request,HttpMethodEnum.POST.getValue(),GepafinConstant.CREATE_NDG, (Long) request.getAttribute(GepafinConstant.USER_ACTION_ID));
|
||||
try {
|
||||
// 1) If 2 hours have already passed, mark as FAILED and shut down:
|
||||
if (System.currentTimeMillis() - startTime > twoHoursMs) {
|
||||
ApplicationEntity app = applicationService.validateApplication(applicationId);
|
||||
log.warn("2-hour timeout reached for applicationId {}. Marking NDG_FAILED.", applicationId);
|
||||
app.setNdgStatus(GepafinConstant.NDG_FAILED);
|
||||
applicationRepository.save(app);
|
||||
|
||||
futureRef.get().cancel(false);
|
||||
shutdownScheduler(applicationId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2) Otherwise, call processNdgGeneration once:
|
||||
processNdgGeneration(applicationId);
|
||||
|
||||
// 3) After return, check if NDG is now set or timed out. If so, cancel & shut down:
|
||||
ApplicationEntity updated = applicationService.validateApplication(applicationId);
|
||||
if (isNdgValid(updated.getNdg())) {
|
||||
log.info("NDG found for applicationId {}. Shutting down scheduler.", applicationId);
|
||||
futureRef.get().cancel(false);
|
||||
shutdownScheduler(applicationId);
|
||||
} else if (updated.getNdgStatus() != null && updated.getNdgStatus().equals(GepafinConstant.NDG_FAILED)) {
|
||||
log.info("NDG status is NDG_FAILED for applicationId {}. Shutting down scheduler.", applicationId);
|
||||
futureRef.get().cancel(false);
|
||||
shutdownScheduler(applicationId);
|
||||
}
|
||||
// Otherwise: no NDG yet, not timed out → next run happens in 15 minutes automatically.
|
||||
} catch (Exception ex) {
|
||||
log.error("Unexpected error during scheduled polling for applicationId {}: {}", applicationId, ex.getMessage(), ex);
|
||||
try {
|
||||
ApplicationEntity checkApp = applicationService.validateApplication(applicationId);
|
||||
if (System.currentTimeMillis() - startTime > twoHoursMs) {
|
||||
log.warn("After exception, 2-hour window passed for applicationId {}. Marking NDG_FAILED.", applicationId);
|
||||
checkApp.setNdgStatus(GepafinConstant.NDG_FAILED);
|
||||
applicationRepository.save(checkApp);
|
||||
|
||||
futureRef.get().cancel(false);
|
||||
shutdownScheduler(applicationId);
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
futureRef.get().cancel(false);
|
||||
shutdownScheduler(applicationId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Schedule pollingTask: run now (delay=0), then every fifteen minutes:
|
||||
ScheduledFuture<?> future = scheduler.scheduleWithFixedDelay(pollingTask, 0, // initial delay = 0 min → run immediately
|
||||
fifteenMin, // subsequent runs every 15 minutes
|
||||
TimeUnit.MINUTES);
|
||||
futureRef.set(future);
|
||||
}
|
||||
// private void startAsyncNdgProcessing(Long applicationId) {
|
||||
// // If already polling for this applicationId, do nothing:
|
||||
// if (executorMap.containsKey(applicationId)) {
|
||||
// log.warn("Async processing already running for applicationId: {}", applicationId);
|
||||
// return;
|
||||
// }
|
||||
// ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
|
||||
//
|
||||
// ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> {
|
||||
// Thread t = new Thread(runnable);
|
||||
// t.setName("AsyncNdgProcessing-" + applicationId);
|
||||
// return t;
|
||||
// });
|
||||
// executorMap.put(applicationId, scheduler);
|
||||
//
|
||||
// // Record the start time so we can stop after 2 hours:
|
||||
// long startTime = System.currentTimeMillis();
|
||||
// long twoHoursMs = TimeUnit.HOURS.toMillis(2);
|
||||
// long fifteenMin = 15; // in MINUTES
|
||||
//
|
||||
// // We need a reference to cancel the scheduled task from inside itself when we're done:
|
||||
// AtomicReference<ScheduledFuture<?>> futureRef = new AtomicReference<>();
|
||||
//
|
||||
// Runnable pollingTask = () -> {
|
||||
// RequestContextHolder.setRequestAttributes(requestAttributes, true);
|
||||
// Utils.setHttpServletRequestForThread(request,HttpMethodEnum.POST.getValue(),GepafinConstant.CREATE_NDG, (Long) request.getAttribute(GepafinConstant.USER_ACTION_ID));
|
||||
// try {
|
||||
// // 1) If 2 hours have already passed, mark as FAILED and shut down:
|
||||
// if (System.currentTimeMillis() - startTime > twoHoursMs) {
|
||||
// ApplicationEntity app = applicationService.validateApplication(applicationId);
|
||||
// log.warn("2-hour timeout reached for applicationId {}. Marking NDG_FAILED.", applicationId);
|
||||
// app.setNdgStatus(GepafinConstant.NDG_FAILED);
|
||||
// applicationRepository.save(app);
|
||||
//
|
||||
// futureRef.get().cancel(false);
|
||||
// shutdownScheduler(applicationId);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 2) Otherwise, call processNdgGeneration once:
|
||||
// processNdgGeneration(applicationId);
|
||||
//
|
||||
// // 3) After return, check if NDG is now set or timed out. If so, cancel & shut down:
|
||||
// ApplicationEntity updated = applicationService.validateApplication(applicationId);
|
||||
// if (isNdgValid(updated.getNdg())) {
|
||||
// log.info("NDG found for applicationId {}. Shutting down scheduler.", applicationId);
|
||||
// futureRef.get().cancel(false);
|
||||
// shutdownScheduler(applicationId);
|
||||
// } else if (updated.getNdgStatus() != null && updated.getNdgStatus().equals(GepafinConstant.NDG_FAILED)) {
|
||||
// log.info("NDG status is NDG_FAILED for applicationId {}. Shutting down scheduler.", applicationId);
|
||||
// futureRef.get().cancel(false);
|
||||
// shutdownScheduler(applicationId);
|
||||
// }
|
||||
// // Otherwise: no NDG yet, not timed out → next run happens in 15 minutes automatically.
|
||||
// } catch (Exception ex) {
|
||||
// log.error("Unexpected error during scheduled polling for applicationId {}: {}", applicationId, ex.getMessage(), ex);
|
||||
// try {
|
||||
// ApplicationEntity checkApp = applicationService.validateApplication(applicationId);
|
||||
// if (System.currentTimeMillis() - startTime > twoHoursMs) {
|
||||
// log.warn("After exception, 2-hour window passed for applicationId {}. Marking NDG_FAILED.", applicationId);
|
||||
// checkApp.setNdgStatus(GepafinConstant.NDG_FAILED);
|
||||
// applicationRepository.save(checkApp);
|
||||
//
|
||||
// futureRef.get().cancel(false);
|
||||
// shutdownScheduler(applicationId);
|
||||
// }
|
||||
// } catch (Exception ignore) {
|
||||
// futureRef.get().cancel(false);
|
||||
// shutdownScheduler(applicationId);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// // Schedule pollingTask: run now (delay=0), then every fifteen minutes:
|
||||
// ScheduledFuture<?> future = scheduler.scheduleWithFixedDelay(pollingTask, 0, // initial delay = 0 min → run immediately
|
||||
// fifteenMin, // subsequent runs every 15 minutes
|
||||
// TimeUnit.MINUTES);
|
||||
// futureRef.set(future);
|
||||
// }
|
||||
|
||||
private void shutdownScheduler(Long applicationId) {
|
||||
|
||||
@@ -529,12 +516,10 @@ public class AppointmentDao {
|
||||
log.info("Scheduler shut down for applicationId: {}", applicationId);
|
||||
}
|
||||
|
||||
private void processNdgGeneration(Long applicationId) {
|
||||
private void processNdgGeneration(ApplicationEntity application, CompanyEntity company, HubEntity hub) {
|
||||
// Validate application, company, and hub
|
||||
Long applicationId = application.getId();
|
||||
log.info("Starting NDG generation process for applicationId: {}", applicationId);
|
||||
ApplicationEntity application = applicationService.validateApplication(applicationId);
|
||||
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.");
|
||||
@@ -552,7 +537,7 @@ public class AppointmentDao {
|
||||
// Try retrieving NDG by VAT number
|
||||
AppointmentLoginResponse ndgResponse = retrieveNdgByVatNumber(company.getVatNumber(), authorizationToken, hub, application);
|
||||
if (isNdgValid(ndgResponse.getNdg())) {
|
||||
saveNdgAndIdVisura(application, company, ndgResponse.getNdg());
|
||||
saveNdg(application, company, ndgResponse.getNdg());
|
||||
log.info("NDG successfully generated for applicationId: {}", applicationId);
|
||||
} else {
|
||||
log.info("Polling for NDG for applicationId: {}", applicationId);
|
||||
@@ -568,7 +553,7 @@ public class AppointmentDao {
|
||||
|
||||
log.info("Starting single‐shot NDG polling attempt for applicationId: {}, CompanyId: {}, HubId: {}", application.getId(), company.getId(), hub.getId());
|
||||
ApplicationEntity oldApplication = Utils.getClonedEntityForData(application);
|
||||
CompanyEntity oldCompanyEntity=Utils.getClonedEntityForData(company);
|
||||
CompanyEntity oldCompanyEntity = Utils.getClonedEntityForData(company);
|
||||
long startTime = System.currentTimeMillis();
|
||||
long twoHoursMs = TimeUnit.HOURS.toMillis(2);
|
||||
|
||||
@@ -589,7 +574,7 @@ public class AppointmentDao {
|
||||
|
||||
company.setNdg(fetchedNdg);
|
||||
application.setNdg(fetchedNdg);
|
||||
application.setNdgStatus(GepafinConstant.NDG_GENERATED);
|
||||
application.setNdgStatus(NdgStatusEnum.NDG_GENERATED.getValue());
|
||||
application.setStatus(ApplicationStatusTypeEnum.NDG.getValue());
|
||||
application.setIdVisura(visuraResponse.getIdVisura());
|
||||
|
||||
@@ -678,10 +663,10 @@ public class AppointmentDao {
|
||||
return ndg != null && !ndg.isEmpty();
|
||||
}
|
||||
|
||||
private void saveNdgAndIdVisura(ApplicationEntity application, CompanyEntity company, String ndg) {
|
||||
private void saveNdg(ApplicationEntity application, CompanyEntity company, String ndg) {
|
||||
|
||||
ApplicationEntity oldApplication = Utils.getClonedEntityForData(application);
|
||||
CompanyEntity oldCompanyEntity=Utils.getClonedEntityForData(company);
|
||||
CompanyEntity oldCompanyEntity = Utils.getClonedEntityForData(company);
|
||||
application.setNdg(ndg);
|
||||
application.setNdgStatus(GepafinConstant.NDG_GENERATED);
|
||||
application.setStatus(ApplicationStatusTypeEnum.NDG.getValue());
|
||||
@@ -1328,4 +1313,107 @@ public class AppointmentDao {
|
||||
throw new RuntimeException("Failed to parse response: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void startAsyncNdgProcessing(Long applicationId) {
|
||||
if (executorMap.containsKey(applicationId)) {
|
||||
log.warn("Async processing already running for applicationId: {}", applicationId);
|
||||
return;
|
||||
}
|
||||
ApplicationEntity application = applicationService.validateApplication(applicationId);
|
||||
CompanyEntity company = companyService.validateCompany(application.getCompanyId());
|
||||
ApplicationEntity oldApplication = Utils.getClonedEntityForData(application);
|
||||
CompanyEntity oldCompanyEntity = Utils.getClonedEntityForData(company);
|
||||
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
|
||||
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(r -> {
|
||||
Thread t = new Thread(r);
|
||||
t.setName("AsyncNdgPolling-" + applicationId);
|
||||
return t;
|
||||
});
|
||||
|
||||
executorMap.put(applicationId, scheduler);
|
||||
application.setNdgStatus(NdgStatusEnum.NDG_IN_PROGRESS.getValue());
|
||||
applicationRepository.save(application);
|
||||
loggingUtil.addVersionHistory(
|
||||
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplication).newData(application).build());
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
long twoHoursMs = TimeUnit.HOURS.toMillis(2);
|
||||
long fifteenMin = 15;
|
||||
|
||||
HubEntity hub = hubRepository.findByHubId(application.getHubId());
|
||||
|
||||
// 1. Run full NDG generation logic once upfront
|
||||
processNdgGeneration(application, company, hub);
|
||||
|
||||
AtomicReference<ScheduledFuture<?>> futureRef = new AtomicReference<>();
|
||||
|
||||
// 2. Now define the polling logic ONLY
|
||||
Runnable pollingTask = () -> {
|
||||
RequestContextHolder.setRequestAttributes(requestAttributes, true);
|
||||
Utils.setHttpServletRequestForThread(request, HttpMethodEnum.POST.getValue(),
|
||||
GepafinConstant.CREATE_NDG, (Long) request.getAttribute(GepafinConstant.USER_ACTION_ID));
|
||||
try {
|
||||
|
||||
// Stop if timeout
|
||||
if (System.currentTimeMillis() - startTime > twoHoursMs) {
|
||||
log.warn("Polling timed out for applicationId {}. Marking NDG_FAILED.", applicationId);
|
||||
application.setNdgStatus(GepafinConstant.NDG_FAILED);
|
||||
applicationRepository.save(application);
|
||||
loggingUtil.addVersionHistory(
|
||||
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplication).newData(application).build());
|
||||
|
||||
futureRef.get().cancel(false);
|
||||
shutdownScheduler(applicationId);
|
||||
return;
|
||||
}
|
||||
|
||||
// If NDG already present or marked failed
|
||||
if (isNdgValid(application.getNdg()) || GepafinConstant.NDG_FAILED.equals(application.getNdgStatus())) {
|
||||
log.info("NDG already present or failed for applicationId {}. Stopping polling.", applicationId);
|
||||
futureRef.get().cancel(false);
|
||||
shutdownScheduler(applicationId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only Visura polling here:
|
||||
String visuraListJson = getVisuraList(application.getIdVisura(), hub.getAppointmentAuthTokenId(), application, hub);
|
||||
String parsedNdg = parseNdgFromVisuraListResponse(visuraListJson);
|
||||
|
||||
if (isNdgValid(parsedNdg)) {
|
||||
log.info("Valid NDG parsed from VisuraList: {} | applicationId: {}", parsedNdg, application.getId());
|
||||
|
||||
company.setNdg(parsedNdg);
|
||||
application.setNdg(parsedNdg);
|
||||
application.setNdgStatus(GepafinConstant.NDG_GENERATED);
|
||||
application.setStatus(ApplicationStatusTypeEnum.NDG.getValue());
|
||||
// application.setIdVisura(visuraResponse.getIdVisura());
|
||||
|
||||
companyRepository.save(company);
|
||||
applicationRepository.save(application);
|
||||
loggingUtil.addVersionHistory(
|
||||
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplication).newData(application).build());
|
||||
loggingUtil.addVersionHistory(
|
||||
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldCompanyEntity).newData(company).build());
|
||||
|
||||
ApplicationEvaluationEntity eval = applicationEvaluationService.validateApplicationEvaluation(application.getApplicationEvaluationId());
|
||||
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, eval, NotificationTypeEnum.NDG_GENERATION);
|
||||
notificationDao.sendNotificationToSuperUser(application, placeholders, NotificationTypeEnum.NDG_GENERATION);
|
||||
|
||||
log.info("NDG saved successfully for applicationId: {}", application.getId());
|
||||
return;
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
log.error("Error during NDG polling: {}", ex.getMessage(), ex);
|
||||
}
|
||||
};
|
||||
|
||||
ScheduledFuture<?> future = scheduler.scheduleWithFixedDelay(pollingTask, fifteenMin, fifteenMin, TimeUnit.MINUTES);
|
||||
futureRef.set(future);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package net.gepafin.tendermanagement.enums;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
public enum NdgStatusEnum {
|
||||
|
||||
NDG_INITITATED("NDG_INITITATED"),
|
||||
NDG_GENERATED("NDG_GENERATED"),
|
||||
NDG_IN_PROGRESS("NDG_IN_PROGRESS");
|
||||
|
||||
private String value;
|
||||
|
||||
NdgStatusEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user