Implemented spreadsheet logic

This commit is contained in:
rajesh
2026-04-02 16:11:23 +05:30
parent 6ae1963c47
commit ed856947b5
3 changed files with 135 additions and 0 deletions

View File

@@ -141,6 +141,9 @@ public class GepafinConstant {
public static final String UPDATING_FORM_VALUE_IMPACT_ON_FLOW = "updating.form.value.impact.on.flow";
public static final String APPLICATION_IS_INCOMPLETE_MSG = "application.is.incomplete";
public static final String AUTHORIZATION = "Authorization";
public static final String BEARER_PREFIX = "Bearer ";
public static final String SPREADSHEET = "spreadsheet";
public static final String TEMPLATE = "template";
public static final String CHECK_VATNUMBER_URL_V1 = "https://imprese.openapi.it/advance";
public static final String CHECK_VATNUMBER_URL_V2 = "https://company.openapi.com/IT-advanced";
public static final String VAT_CHECK_API_VERSION = "VAT_CHECK_API_VERSION";

View File

@@ -20,8 +20,14 @@ import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal;
@@ -157,6 +163,12 @@ public class ApplicationEvaluationDao {
@Value("${default.hub.uuid}")
private String defaultHubUuid;
@Value("${excel.fill.api.url}")
private String excelFillApiUrl;
@Value("${excel.fill.api.token:}")
private String excelFillApiToken;
@Autowired
private ApplicationSignedDocumentRepository applicationSignedDocumentRepository;
@@ -762,6 +774,11 @@ public class ApplicationEvaluationDao {
// Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.EVALUATION_CREATION);
// V2 only, idempotent: runs on every create/update of application evaluation (e.g. evaluation created at
// instructor assignment). External fill API is called only for spreadsheet fields that still have no stored
// value. If APPLICATION_EVALUATION_FORM / spreadsheet rows were created here earlier, later
// createApplicationEvaluation and plain updates skip re-fill and leave existing flow unchanged.
populateSpreadsheetEvaluationFormFieldsForV2(application, entity);
Map<String, String> placeHolders = new HashMap<>();
placeHolders.put("{{call_name}}", application.getCall().getName());
String protocolNumber=application.getProtocol().getExternalProtocolNumber();
@@ -2190,6 +2207,118 @@ public class ApplicationEvaluationDao {
return response;
}
/**
* Evaluation V2 only ({@link ApplicationEntity#getEvaluationVersion()}).
* <p>
* Ensures {@link ApplicationEvaluationFormEntity} exists for the call's evaluation form, then for each
* {@code spreadsheet} field calls the external fill API and saves {@code APPLICATION_EVALUATION_FORM_FIELD}
* only when that field has no stored value yet. Safe when this runs at assignment-time (first evaluation create)
* and on later {@code createOrUpdateApplicationEvaluation} updates: no second API call and no overwrite once a
* value is present. {@link #createApplicationEvaluation} continues to work: it reuses the same form row via
* {@link #getApplicationEvaluationFormOrCreate}.
*/
private void populateSpreadsheetEvaluationFormFieldsForV2(ApplicationEntity application, ApplicationEvaluationEntity entity) {
if (!EvaluationVersionEnum.V2.getValue().equals(application.getEvaluationVersion())) {
return;
}
EvaluationFormEntity evaluationFormEntity = evaluationFormRepository.findByCallIdAndIsDeletedFalse(application.getCall().getId());
if (evaluationFormEntity == null) {
return;
}
ApplicationEvaluationFormEntity applicationEvaluationFormEntity = getApplicationEvaluationFormOrCreate(evaluationFormEntity, entity);
List<ContentResponseBean> contentResponseBeans = evaluationFormDao
.convertEvaluationFormEntityToEvaluationFormResponseBean(evaluationFormEntity)
.getContent();
if (CollectionUtils.isEmpty(contentResponseBeans)) {
return;
}
List<ApplicationFormFieldRequestBean> spreadsheetUpdates = new ArrayList<>();
for (ContentResponseBean contentResponseBean : contentResponseBeans) {
if (!GepafinConstant.SPREADSHEET.equals(contentResponseBean.getName())) {
continue;
}
String fieldId = contentResponseBean.getId();
Optional<ApplicationEvaluationFormFieldEntity> existingSpreadsheetField = applicationEvaluationFormFieldRepository
.findByApplicationEvaluationFormIdAndFieldIdAndIsDeletedFalse(applicationEvaluationFormEntity.getId(), fieldId);
if (existingSpreadsheetField.isPresent()
&& StringUtils.isNotBlank(existingSpreadsheetField.get().getFieldValue())) {
continue;
}
Object populatedSpreadsheetValue = fetchSpreadsheetValueFromExternalApi(
application.getCall().getId(),
application.getId(),
contentResponseBean
);
if (populatedSpreadsheetValue == null) {
log.warn("Skipping spreadsheet field {}: external API did not return a template workbook value", fieldId);
continue;
}
ApplicationFormFieldRequestBean spreadsheetFieldRequest = new ApplicationFormFieldRequestBean();
spreadsheetFieldRequest.setFieldId(fieldId);
spreadsheetFieldRequest.setFieldValue(populatedSpreadsheetValue);
spreadsheetUpdates.add(spreadsheetFieldRequest);
}
if (!spreadsheetUpdates.isEmpty()) {
createOrUpdateMultipleFormFields(spreadsheetUpdates, applicationEvaluationFormEntity, evaluationFormEntity);
}
}
private Object fetchSpreadsheetValueFromExternalApi(Long callId, Long applicationId, ContentResponseBean spreadsheetField) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
if (StringUtils.isNotBlank(excelFillApiToken)) {
headers.set(GepafinConstant.AUTHORIZATION, GepafinConstant.BEARER_PREFIX + excelFillApiToken);
}
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("call_id", callId);
requestBody.put("application_id", applicationId);
requestBody.put(GepafinConstant.TEMPLATE, spreadsheetField);
try {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Object> response = restTemplate.postForEntity(
excelFillApiUrl,
new HttpEntity<>(requestBody, headers),
Object.class
);
return resolveSpreadsheetFieldValueFromApiResponse(response.getBody());
} catch (RestClientException exception) {
log.error("Failed to populate spreadsheet field {} from external API", spreadsheetField.getId(), exception);
throw new CustomValidationException(Status.BAD_REQUEST,
"Failed to populate spreadsheet field from external API for fieldId: " + spreadsheetField.getId());
}
}
/**
* External fill API returns a spreadsheet field-shaped JSON (id, name, settings, …). Persist only the
* workbook object: {@code settings[name=template].value}. If the response is already a bare workbook
* ({@code sheets} / {@code sheetOrder}), it is stored as-is.
*/
private Object resolveSpreadsheetFieldValueFromApiResponse(Object apiResponseBody) {
if (apiResponseBody == null) {
return null;
}
if (!(apiResponseBody instanceof Map<?, ?> map)) {
return apiResponseBody;
}
Object settingsObj = map.get("settings");
if (settingsObj instanceof List<?> settingsList) {
for (Object setting : settingsList) {
if (!(setting instanceof Map<?, ?> settingMap)) {
continue;
}
Object name = settingMap.get("name");
if (GepafinConstant.TEMPLATE.equals(name != null ? name.toString() : null)) {
return settingMap.get("value");
}
}
log.warn("External spreadsheet API returned settings[] without a template entry");
return null;
}
return apiResponseBody;
}
private ApplicationEvaluationFormEntity getApplicationEvaluationFormOrCreate(EvaluationFormEntity evaluationFormEntity, ApplicationEvaluationEntity applicationEvaluationEntity) {
ApplicationEvaluationFormEntity applicationEvaluationFormEntity = applicationEvaluationFormRepository.findByEvaluationIdAndEvaluationFormId(applicationEvaluationEntity.getId(), evaluationFormEntity.getId());

View File

@@ -77,6 +77,9 @@ spring.rabbitmq.connection-timeout=120000
app.bandi.login.url.suffix=/loginadmin
app.confidi.login.url.suffix=/confidi
excel.fill.api.url=https://excel-gepafin-dev-be.bflows.ai/excel/fill
excel.fill.api.token=a3f8c2d1e4b5a6f7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1
#sviluppumbria protocol
codAoo=SVILUMBRIA-01
sviluppumbria.username=protocollatoresvilumbria