Merge branch 'develop' into feature/SUPPORT-8974_messaging

This commit is contained in:
ivanov.denis 2025-03-06 11:34:43 +03:00
commit f78f3ea446
7 changed files with 164 additions and 68 deletions

View file

@ -96,7 +96,7 @@ public class ApiController {
@PostMapping("/downloadCSV")
public ResponseEntity<Resource> downloadCSV(@RequestBody RequestParameters request) throws IOException {
public ResponseEntity<Resource> downloadCSV(@RequestBody RequestParameters request) throws IOException, SQLException {
logger.debug("Starting downloadCSV process for request: {}", request.getType());
File csvFile = apiService.download(ConfigType.DOWNLOAD_CSV, request);

View file

@ -109,6 +109,15 @@ public class GlobalExceptionHandler {
));
}
@ExceptionHandler(NoDownloadReportRecordsException.class)
public ResponseEntity<?> handleNoDownloadReportRecordsException(NoDownloadReportRecordsException e) {
logger.error("Unexpected error occurred: {}", e.getMessage(), e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of(
"message", e.getMessage(),
"details", e.getMessage()
));
}
}

View file

@ -0,0 +1,14 @@
package org.micord.exceptions;
import java.io.Serial;
public class NoDownloadReportRecordsException extends RuntimeException {
@Serial
private static final long serialVersionUID = 1L;
public NoDownloadReportRecordsException(String message) {
super(message);
}
}

View file

@ -14,11 +14,11 @@ import lombok.Setter;
public class RequestValidationRules {
@XmlAttribute(name = "isEmptyIdsAllowed")
private Boolean isEmptyIdsAllowed;
private Boolean isEmptyIdsAllowed = false;
@XmlAttribute(name = "isEmptyDatesAllowed")
private Boolean isEmptyDatesAllowed;
private Boolean isEmptyDatesAllowed = false;
@XmlAttribute(name = "isIdsFormatted")
private Boolean isIdsFormatted;
private Boolean isIdsFormatted = true;
}

View file

@ -47,7 +47,7 @@ public class ApiService {
sqlAndAqlService.processSqlAndAqlRequests(config, parameters);
}
public File download(ConfigType methodName, RequestParameters downloadRequest) throws IOException {
public File download(ConfigType methodName, RequestParameters downloadRequest) throws IOException, SQLException {
Requests config = configService.getConfig(methodName, Requests.class);
String type = downloadRequest.getType();

View file

@ -6,6 +6,7 @@ import com.arangodb.ArangoDatabase;
import com.arangodb.model.AqlQueryOptions;
import org.micord.config.ArangoDBConnection;
import org.micord.config.DatabaseConnection;
import org.micord.exceptions.NoDownloadReportRecordsException;
import org.micord.models.requests.RequestParameters;
import org.micord.models.requests.downloads.AQLDownloadRequest;
import org.micord.models.requests.downloads.BaseDownloadRequest;
@ -30,7 +31,7 @@ public class DownloadService {
private static final Logger logger = LoggerFactory.getLogger(DownloadService.class);
public File download(BaseDownloadRequest selectedRequest, List<String> ids, RequestParameters parameters, Map<String, Boolean> validationResults) {
public File download(BaseDownloadRequest selectedRequest, List<String> ids, RequestParameters parameters, Map<String, Boolean> validationResults) throws SQLException {
LocalDate startDate = parameters.getStartDate();
LocalDate endDate = parameters.getEndDate();
if (selectedRequest instanceof SQLDownloadRequest) {
@ -41,43 +42,65 @@ public class DownloadService {
throw new IllegalArgumentException("Unsupported request type: " + selectedRequest.getClass().getSimpleName());
}
private File processAqlDownloadRequest(AQLDownloadRequest request, List<String> ids, LocalDate startDate, LocalDate endDate, Map<String, Boolean> validationResults) {
ArangoDatabase arangoDb = ArangoDBConnection.getConnection(request.getAqlConnectionParams());
private File processAqlDownloadRequest(AQLDownloadRequest request, List<String> ids, LocalDate startDate, LocalDate endDate, Map<String, Boolean> validationResults) throws SQLException {
try {
ArangoDatabase arangoDb = ArangoDBConnection.getConnection(request.getAqlConnectionParams());
Boolean emptyIdsAllowed = validationResults.getOrDefault(ValidationService.IS_EMPTY_IDS_ALLOWED, false);
Boolean emptyDatesAllowed = validationResults.getOrDefault(ValidationService.IS_EMPTY_DATES_ALLOWED, false);
Boolean emptyIdsAllowed = validationResults.get(ValidationService.IS_EMPTY_IDS_ALLOWED);
Boolean emptyDatesAllowed = validationResults.get(ValidationService.IS_EMPTY_DATES_ALLOWED);
List<Map<String, Object>> entities = executeSelectAqlRequest(
arangoDb,
request.getDownloadRequestEntitySelectorQuery(),
ids,
startDate,
endDate,
emptyIdsAllowed,
emptyDatesAllowed
);
Map<String, Object> entities = executeSelectAqlRequest(arangoDb, request.getDownloadRequestEntitySelectorQuery(), ids, emptyIdsAllowed);
if (entities.isEmpty()) {
logger.warn("No entities found for main AQL request.");
throw new NoDownloadReportRecordsException(
"Отчет не может быть сгенерирован. Нет записей в базе для успешной генерации."
);
}
if (entities.isEmpty()) {
logger.warn("No entities found for main AQL request.");
return null;
return writeResultsToCsv(entities);
} catch (ArangoDBException e) {
logger.error("Error connecting to ArangoDB or executing AQL query: {}", e.getMessage(), e);
throw new SQLException("Ошибка работы с базой данных. Попробуйте позже.", e);
} catch (NoDownloadReportRecordsException e) {
logger.warn("No records available for report generation: {}", e.getMessage());
throw e;
} catch (Exception e) {
logger.error("Unexpected error occurred during report generation: {}", e.getMessage(), e);
throw new RuntimeException("Произошла непредвиденная ошибка при генерации отчета.", e);
}
List<Map<String, Object>> results = new ArrayList<>();
request.getAqlRequestCollections().forEach(collection -> {
String type = collection.getCollectionUrl();
String entityType;
// request.getAqlRequestCollections().forEach(collection -> {
// String type = collection.getCollectionUrl();
// String entityType;
//
// if (Objects.equals(type, "applications")) {
// entityType = "applicationId";
// } else {
// entityType = type + "Id";
// }
//
// Object entityIds = entities.get(entityType);
//
// if (entityIds instanceof String) {
// entityIds = Collections.singletonList((String) entityIds);
// }
//
// String aqlQuery = buildAqlQuery(type, ids, collection.getDateAttribute(), startDate, endDate, emptyIdsAllowed, emptyDatesAllowed);
//
// results.addAll(executeAqlQuery(arangoDb, aqlQuery, (List<String>) entityIds, startDate, endDate, emptyIdsAllowed, emptyDatesAllowed));
// });
if (Objects.equals(type, "applications")) {
entityType = "applicationId";
} else {
entityType = type + "Id";
}
Object entityIds = entities.get(entityType);
if (entityIds instanceof String) {
entityIds = Collections.singletonList((String) entityIds);
}
String aqlQuery = buildAqlQuery(type, ids, collection.getDateAttribute(), startDate, endDate, emptyIdsAllowed, emptyDatesAllowed);
results.addAll(executeAqlQuery(arangoDb, aqlQuery, (List<String>) entityIds, startDate, endDate, emptyIdsAllowed, emptyDatesAllowed));
});
return writeResultsToCsv(results);
// return writeResultsToCsv(results);
}
private File processSqlDownloadRequest(SQLDownloadRequest request, List<String> ids, LocalDate startDate, LocalDate endDate, Map<String, Boolean> validationResults) {
@ -113,35 +136,77 @@ public class DownloadService {
return null;
}
private Map<String, Object> executeSelectAqlRequest(ArangoDatabase arangoDb,
private List<Map<String, Object>> executeSelectAqlRequest(ArangoDatabase arangoDb,
String downloadRequestEntitySelectorQuery,
List<String> ids, Boolean emptyIdsAllowed) {
Map<String, Object> entities = new HashMap<>();
List<String> ids, LocalDate startDate, LocalDate endDate, Boolean emptyIdsAllowed, Boolean emptyDatesAllowed) {
List<Map<String, Object>> results = new ArrayList<>();
Map<String, Object> bindVars = new HashMap<>();
if (!emptyIdsAllowed) bindVars.put("ids", ids);
AqlQueryOptions aqlQueryOptions = new AqlQueryOptions();
try (ArangoCursor<Map> cursor = arangoDb.query(downloadRequestEntitySelectorQuery, Map.class, bindVars, aqlQueryOptions)) {
while (cursor.hasNext()) {
Map<String, Object> result = cursor.next();
for (Map.Entry<String, Object> entry : result.entrySet()) {
String key = entry.getKey();
Object entityValue = entry.getValue();
entities.put(key, entityValue);
try {
Map<String, Object> bindVars = new HashMap<>();
if (!emptyIdsAllowed && ids != null && !ids.isEmpty()) {
bindVars.put("ids", ids);
}
if (!emptyDatesAllowed) {
if (startDate != null) {
bindVars.put("startDate", startDate.toString());
}
if (endDate != null) {
bindVars.put("endDate", endDate.toString());
}
}
}
catch (Exception e) {
logger.error("Failed to execute AQL url", e);
}
return entities;
logger.info("Executing AQL query: {}\nWith bindVars: {}", downloadRequestEntitySelectorQuery, bindVars);
AqlQueryOptions aqlQueryOptions = new AqlQueryOptions();
try (ArangoCursor<Map> cursor = arangoDb.query(downloadRequestEntitySelectorQuery, Map.class, bindVars, aqlQueryOptions)) {
while (cursor.hasNext()) {
results.add(cursor.next());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
} catch (ArangoDBException e) {
logger.error("AQL query execution failed: {}\nError: {}", downloadRequestEntitySelectorQuery, e.getMessage(), e);
}
return results;
// Map<String, Object> entities = new HashMap<>();
//
// Map<String, Object> bindVars = new HashMap<>();
// if (!emptyIdsAllowed && ids != null && !ids.isEmpty()) {
// bindVars.put("ids", ids);
// }
// if (!emptyDatesAllowed) {
// if (startDate != null) {
// bindVars.put("startDate", startDate.toString());
// }
// if (endDate != null) {
// bindVars.put("endDate", endDate.toString());
// }
// }
//
// logger.info("Executing AQL query: {}\nWith bindVars: {}", aqlQuery, bindVars);
//
// AqlQueryOptions aqlQueryOptions = new AqlQueryOptions();
//
// try (ArangoCursor<Map> cursor = arangoDb.query(downloadRequestEntitySelectorQuery, Map.class, bindVars, aqlQueryOptions)) {
// while (cursor.hasNext()) {
// Map<String, Object> result = cursor.next();
//
// for (Map.Entry<String, Object> entry : result.entrySet()) {
// String key = entry.getKey();
// Object entityValue = entry.getValue();
//
// entities.put(key, entityValue);
// }
// }
// }
// catch (Exception e) {
// logger.error("Failed to execute AQL url", e);
// }
//
// return entities;
}
private String buildAqlQuery(String collectionName, List<String> ids, String dateAttribute, LocalDate startDate, LocalDate endDate, Boolean emptyIdsAllowed, Boolean emptyDatesAllowed) {
@ -265,8 +330,8 @@ public class DownloadService {
}
private Map<String, Object> buildSqlQuery(SQLDownloadRequest request, List<String> ids, LocalDate startDate, LocalDate endDate, Map<String, Boolean> validationResults) {
Boolean emptyIdsAllowed = validationResults.getOrDefault(ValidationService.IS_EMPTY_IDS_ALLOWED, false);
Boolean emptyDatesAllowed = validationResults.getOrDefault(ValidationService.IS_EMPTY_DATES_ALLOWED, false);
Boolean emptyIdsAllowed = validationResults.get(ValidationService.IS_EMPTY_IDS_ALLOWED);
Boolean emptyDatesAllowed = validationResults.get(ValidationService.IS_EMPTY_DATES_ALLOWED);
Map<String, Object> resultMap = new HashMap<>();

View file

@ -6,6 +6,7 @@ import org.micord.exceptions.IllegalRequestParametersException;
import org.micord.exceptions.ValidationException;
import org.micord.models.requests.BaseRequest;
import org.micord.models.requests.RequestParameters;
import org.micord.models.requests.RequestValidationRules;
import org.micord.models.requests.downloads.BaseDownloadRequest;
import org.micord.models.validations.ValidationRule;
import org.micord.models.validations.ValidationRules;
@ -76,24 +77,31 @@ public class ValidationService {
}
public Map<String, Boolean> validateRequest(BaseRequest request, List<String> ids) throws ValidationException, SQLException, FileNotFoundException {
Map<String, Boolean> validationResults = validateIds(request, ids);
RequestValidationRules requestValidationRules = new RequestValidationRules();
Map<String, Boolean> validationResults = validateIds(request, ids, requestValidationRules);
if (isRequestValidatedByValidationConfig) validateByValidationConfig(ids, BaseRequest.class);
return validationResults;
}
public Map<String, Boolean> validateMilitaryNoticeRequest(BaseRequest request, RequestParameters parameters) throws ValidationException, SQLException, FileNotFoundException {
RequestValidationRules requestValidationRules = new RequestValidationRules();
List<String> ids = parameters.getIds();
validateIds(request, ids);
Map<String, Boolean> validation = validateDates(request, parameters);
Map<String, Boolean> validateIds = validateIds(request, ids, requestValidationRules);
Map<String, Boolean> validateDates = validateDates(request, parameters);
if (isMilitaryNoticeRequestValidatedByValidationConfig) validateByValidationConfig(ids, RequestParameters.class);
return validation;
Map<String, Boolean> merged = new HashMap<>();
merged.putAll(validateIds);
merged.putAll(validateDates);
return merged;
}
public Map<String, Boolean> validateDownloadRequest(BaseDownloadRequest request, RequestParameters downloadRequest, List<String> ids) throws ValidationException {
Map<String, Boolean> validateIds = validateIds(request, ids);
RequestValidationRules requestValidationRules = new RequestValidationRules();
Map<String, Boolean> validateIds = validateIds(request, ids, requestValidationRules);
Map<String, Boolean> validateDates = validateDates(request, downloadRequest);
Map<String, Boolean> merged = new HashMap<>();
@ -103,10 +111,10 @@ public class ValidationService {
return merged;
}
private static Map<String, Boolean> validateIds(BaseRequest request, List<String> ids) {
private static Map<String, Boolean> validateIds(BaseRequest request, List<String> ids, RequestValidationRules requestValidationRules) {
if (request.getRequestValidationRules() == null) {
return Map.of();
return Map.of(ValidationService.IS_EMPTY_IDS_ALLOWED, requestValidationRules.getIsEmptyIdsAllowed());
}
Boolean emptyIdsAllowed = request.getRequestValidationRules().getIsEmptyIdsAllowed();
if (emptyIdsAllowed) {