diff --git a/scripts/native/file/rec-legal-customer-product-directory-1.0-native-quarkus-jdk17-runner b/scripts/native/file/rec-legal-customer-product-directory-1.0-native-quarkus-jdk17-runner index a766473..30048d9 100644 Binary files a/scripts/native/file/rec-legal-customer-product-directory-1.0-native-quarkus-jdk17-runner and b/scripts/native/file/rec-legal-customer-product-directory-1.0-native-quarkus-jdk17-runner differ diff --git a/src/main/java/com/banesco/common/application/helper/MessageResponseHelper.java b/src/main/java/com/banesco/common/application/helper/MessageHelper.java similarity index 70% rename from src/main/java/com/banesco/common/application/helper/MessageResponseHelper.java rename to src/main/java/com/banesco/common/application/helper/MessageHelper.java index cd61fa9..ee26bf0 100644 --- a/src/main/java/com/banesco/common/application/helper/MessageResponseHelper.java +++ b/src/main/java/com/banesco/common/application/helper/MessageHelper.java @@ -1,18 +1,18 @@ package com.banesco.common.application.helper; -import com.banesco.common.domain.exception.InternalServerException; -import com.banesco.common.domain.model.ErrorMapping; -import com.banesco.common.infrastructure.config.MessagesConfig; -import com.banesco.common.domain.exception.BaseApiException; +import com.banesco.common.domain.exception.HttpStatusCodeException; import com.banesco.common.domain.model.ApiResponse; +import com.banesco.common.domain.model.ErrorMapping; import com.banesco.common.domain.model.StatusResponse; +import com.banesco.common.infrastructure.config.MessagesConfig; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import io.quarkus.runtime.annotations.RegisterForReflection; -import lombok.extern.slf4j.Slf4j; -import jakarta.ws.rs.core.Response; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import jakarta.ws.rs.core.Response; +import lombok.extern.slf4j.Slf4j; + import java.io.InputStream; import java.util.List; import java.util.Map; @@ -21,7 +21,7 @@ import java.util.concurrent.ConcurrentHashMap; @Slf4j @ApplicationScoped @RegisterForReflection -public class MessageResponseHelper { +public class MessageHelper { private final MessagesConfig messagesConfig; private final Map errorMappings; @@ -31,7 +31,7 @@ public class MessageResponseHelper { private final ObjectMapper objectMapper; @Inject - public MessageResponseHelper( + public MessageHelper( ObjectMapper objectMapper, MessagesConfig messagesConfig ) { @@ -40,31 +40,32 @@ public class MessageResponseHelper { this.errorMappings = initializeErrorMappings(); } - // Ya no es una clase interna, ahora usa la clase del dominio - // Solo necesitas mantener la referencia al tipo - // Si ErrorMapping está en otro paquete, asegúrate de importarlo - - public Response handleException(BaseApiException exception) { + public Response handleException(HttpStatusCodeException exception) { + log.error( + "Error interno controlado: {} -> {}", + exception.getStatusCode(), + exception.getErrorCode() + ); return buildErrorResponse(exception); } public Response handleGenericException(Exception exception) { - log.error("Error interno no controlado: {}", exception.getMessage(), exception); - return buildErrorResponse(new InternalServerException("500", null)); + log.error("Error interno no controlado: {}", exception.getMessage()); + return buildErrorResponse(HttpStatusCodeException.internalServer("500")); } - public StatusResponse createSuccessResponse(String code) { + public StatusResponse createStatusResponse(String code) { ErrorMapping successMapping = getError(code); return StatusResponse.builder() - .statusCode(successMapping.getStatusCode()) - .message(successMapping.getDescription()) - .build(); + .statusCode(successMapping.getStatusCode()) + .message(successMapping.getDescription()) + .build(); } - public StatusResponse createErrorResponse( - ErrorMapping mapping, - String fieldPath + public StatusResponse createError( + ErrorMapping mapping, + String fieldPath ) { String message = mapping.getDescription(); @@ -73,39 +74,39 @@ public class MessageResponseHelper { } return StatusResponse.builder() - .statusCode(mapping.getStatusCode()) - .message(message) - .build(); + .statusCode(mapping.getStatusCode()) + .message(message) + .build(); } public ApiResponse buildServiceUnavailableResponse() { - return new ApiResponse<>(null, createSuccessResponse("503")); + return new ApiResponse<>(createStatusResponse("503")); } private ErrorMapping getError(String errorCode) { return errorMappings.getOrDefault( - errorCode, errorMappings.getOrDefault(ERROR_DEFAULT, createDefaultMapping()) + errorCode, errorMappings.getOrDefault(ERROR_DEFAULT, createDefaultMapping()) ); } - private Response buildErrorResponse(BaseApiException exception) { + private Response buildErrorResponse(HttpStatusCodeException exception) { ErrorMapping mapping = errorMappings.getOrDefault( - exception.getErrorCode(), - errorMappings.getOrDefault(ERROR_DEFAULT, createDefaultMapping()) - ); - StatusResponse status = createErrorResponse( - mapping, exception.getFieldPath() + exception.getErrorCode(), errorMappings.getOrDefault( + String.valueOf(exception.getStatusCode()), + createDefaultMapping() + ) ); + StatusResponse status = createError(mapping, exception.getFieldPath()); log.error( - "[{}] Message {} -> {}", - exception.getExceptionType(), - exception.getErrorCode(), - status.getMessage() + "[{}] Message {} -> {}", + exception.getExceptionType(), + exception.getErrorCode(), + status.getMessage() ); return Response.status(mapping.getHttpCode()) - .entity(new ApiResponse<>(null, status)) + .entity(new ApiResponse<>(status)) .build(); } @@ -150,7 +151,7 @@ public class MessageResponseHelper { } private String loadFromJsonFile() { - try (InputStream is = MessageResponseHelper.class.getClassLoader().getResourceAsStream(ERROR_FILE_PATH)) { + try (InputStream is = MessageHelper.class.getClassLoader().getResourceAsStream(ERROR_FILE_PATH)) { if (is == null) { log.warn("No se encontró el archivo de errores: {}", ERROR_FILE_PATH); return ""; @@ -172,9 +173,9 @@ public class MessageResponseHelper { private ErrorMapping createDefaultMapping() { ErrorMapping mapping = new ErrorMapping(); mapping.setBackendCode(ERROR_DEFAULT); - mapping.setHttpCode(500); - mapping.setStatusCode("500"); - mapping.setDescription("Error interno del servidor"); + mapping.setHttpCode(409); + mapping.setStatusCode("409"); + mapping.setDescription("Conflicto"); return mapping; } @@ -182,7 +183,7 @@ public class MessageResponseHelper { ErrorMapping mapping = new ErrorMapping(); mapping.setBackendCode(SUCCESS_DEFAULT); mapping.setHttpCode(200); - mapping.setStatusCode("000"); + mapping.setStatusCode("200"); mapping.setDescription("Operación exitosa"); return mapping; } @@ -190,4 +191,17 @@ public class MessageResponseHelper { public boolean isReadingFromProps() { return messagesConfig.isReadFromProps(); } + + public boolean isSuccessStatusCode(StatusResponse statusResponse) { + if (statusResponse == null || statusResponse.getStatusCode() == null) { + return false; + } + + try { + int statusCode = Integer.parseInt(statusResponse.getStatusCode()); + return statusCode >= 200 && statusCode < 300; + } catch (NumberFormatException e) { + return false; + } + } } \ No newline at end of file diff --git a/src/main/java/com/banesco/common/application/helper/RequestValidatorHelper.java b/src/main/java/com/banesco/common/application/helper/RequestValidatorHelper.java index cd127c7..77bf199 100644 --- a/src/main/java/com/banesco/common/application/helper/RequestValidatorHelper.java +++ b/src/main/java/com/banesco/common/application/helper/RequestValidatorHelper.java @@ -1,17 +1,21 @@ package com.banesco.common.application.helper; -import com.banesco.common.domain.exception.BadRequestException; +import com.banesco.common.domain.exception.HttpStatusCodeException; import com.banesco.common.infrastructure.config.RequestValidationConfig; import com.banesco.module.legal_customer_product_directory.domain.dto.request.LegalCustomerProductDirectoryRequest; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import lombok.extern.slf4j.Slf4j; +@Slf4j @ApplicationScoped public class RequestValidatorHelper { private final RequestValidationConfig config; @Inject - public RequestValidatorHelper(RequestValidationConfig config) { + public RequestValidatorHelper( + RequestValidationConfig config + ) { this.config = config; } @@ -35,13 +39,13 @@ public class RequestValidatorHelper { private void required(String value, String fieldName) { if (value == null || value.trim().isEmpty()) { - throw new BadRequestException("VDE01", fieldName); + throw HttpStatusCodeException.badRequest("VDE01", fieldName); } } private void validate(String value, String regex, String fieldName) { if (value != null && !value.isEmpty() && !value.matches(regex)) { - throw new BadRequestException("VDE02", fieldName); + throw HttpStatusCodeException.badRequest("VDE02", fieldName); } } } diff --git a/src/main/java/com/banesco/common/application/service/HttpClientService.java b/src/main/java/com/banesco/common/application/service/HttpClientService.java index c772de9..f51607b 100644 --- a/src/main/java/com/banesco/common/application/service/HttpClientService.java +++ b/src/main/java/com/banesco/common/application/service/HttpClientService.java @@ -1,37 +1,37 @@ package com.banesco.common.application.service; import com.banesco.common.application.usecase.HttpClientUseCase; +import com.banesco.common.domain.exception.HttpApiResponseException; +import com.banesco.common.domain.exception.HttpStatusCodeException; +import com.banesco.common.domain.model.ApiResponse; import com.banesco.common.domain.model.HttpRequest; -import jakarta.ws.rs.core.MediaType; -import lombok.extern.slf4j.Slf4j; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.enterprise.context.ApplicationScoped; -import jakarta.ws.rs.client.Client; -import jakarta.ws.rs.client.ClientBuilder; -import jakarta.ws.rs.client.Entity; -import jakarta.ws.rs.client.Invocation; -import jakarta.ws.rs.client.WebTarget; +import jakarta.inject.Inject; +import jakarta.ws.rs.client.*; +import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +import lombok.extern.slf4j.Slf4j; -import java.util.concurrent.TimeUnit; import java.util.Map; +import java.util.concurrent.TimeUnit; @Slf4j @ApplicationScoped public class HttpClientService implements HttpClientUseCase { + private final ObjectMapper objectMapper; + + @Inject + public HttpClientService(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + @Override public T execute(HttpRequest request) { - String finalUrl = request.getUrl(); - - if (request.getPathParams() != null && !request.getPathParams().isEmpty()) { - log.debug("PathParams antes de reemplazar: {}", request.getPathParams()); - log.debug("URL original: {}", finalUrl); - - for (Map.Entry entry : request.getPathParams().entrySet()) { - String placeholder = "{" + entry.getKey() + "}"; - finalUrl = finalUrl.replace(placeholder, entry.getValue()); - } - } + String finalUrl = buildFinalUrl(request); log.info("URL final: {}", finalUrl); @@ -50,24 +50,80 @@ public class HttpClientService implements HttpClientUseCase { try (Client client = createClient(request.getConnectTimeout(), request.getReadTimeout())) { WebTarget target = client.target(finalUrl); - if (request.getQueryParams() != null && !request.getQueryParams().isEmpty()) { - request.getQueryParams().forEach(target::queryParam); - } - Invocation.Builder builder = target.request(MediaType.APPLICATION_JSON); if (request.getHeaders() != null && !request.getHeaders().isEmpty()) { - request.getHeaders().forEach(builder::header); + for (Map.Entry entry : request.getHeaders().entrySet()) { + builder.header(entry.getKey(), entry.getValue()); + } } Response response = buildRequest(builder, request); - return handleResponse(response, request); + return handleResponse(request, response); + } catch (HttpStatusCodeException | HttpApiResponseException e) { + throw e; + } catch (Exception e) { + log.error("Error de conexión {}: {}", request.getMethod(), e.getMessage()); + throw HttpStatusCodeException.serviceUnavailable( + "503", + "Error de conexión con el servicio externo: " + e.getMessage() + ); } } - private Response buildRequest(Invocation.Builder builder, HttpRequest request) { - log.info("Método HTTP: {}, Headers enviados: {}", request.getMethod(), builder); + private String buildFinalUrl(HttpRequest request) { + String finalUrl = request.getUrl(); + + if (request.getPathParams() != null && !request.getPathParams().isEmpty()) { + log.debug("PathParams antes de reemplazar: {}", request.getPathParams()); + log.debug("URL original: {}", finalUrl); + + for (Map.Entry entry : request.getPathParams().entrySet()) { + String placeholder = "{" + entry.getKey() + "}"; + finalUrl = finalUrl.replace(placeholder, entry.getValue()); + } + } + + finalUrl = appendQueryParams(finalUrl, request.getQueryParams()); + + return finalUrl; + } + + private String appendQueryParams(String url, Map queryParams) { + if (queryParams == null || queryParams.isEmpty()) { + return url; + } + + StringBuilder urlBuilder = new StringBuilder(url); + + boolean firstParam = !url.contains("?"); + + for (Map.Entry entry : queryParams.entrySet()) { + if (firstParam) { + urlBuilder.append("?"); + firstParam = false; + } else { + urlBuilder.append("&"); + } + + urlBuilder.append(entry.getKey()) + .append("=") + .append(entry.getValue() != null ? entry.getValue() : ""); + } + + return urlBuilder.toString(); + } + + private Response buildRequest( + Invocation.Builder builder, + HttpRequest request + ) { + log.info( + "Método HTTP: {}, Headers enviados: {}", + request.getMethod().name(), + request.getHeaders() + ); return switch (request.getMethod()) { case GET -> builder.get(); @@ -81,44 +137,148 @@ public class HttpClientService implements HttpClientUseCase { }; } - private Client createClient(int connectTimeout, int readTimeout) { + private Client createClient( + int connectTimeout, + int readTimeout + ) { return ClientBuilder.newBuilder() - .connectTimeout(connectTimeout, TimeUnit.MILLISECONDS) - .readTimeout(readTimeout, TimeUnit.MILLISECONDS) - .build(); + .connectTimeout(connectTimeout, TimeUnit.MILLISECONDS) + .readTimeout(readTimeout, TimeUnit.MILLISECONDS) + .build(); } - @SuppressWarnings("unchecked") - private T handleResponse(Response response, HttpRequest request) { - log.info("Respuesta {} {} - Status: {}", request.getMethod(), request.getUrl(), response.getStatus()); + private T handleResponse( + HttpRequest request, + Response response + ) { + int statusCode = response.getStatus(); + log.info("Respuesta {} - Status: {}", request.getMethod(), statusCode); - if (response.getStatus() >= 200 && response.getStatus() < 300) { - try { + try (response) { + String responseBody = response.readEntity(String.class); + + if (statusCode >= 200 && statusCode < 300) { if (request.getResponseType() == Void.class || request.getResponseType() == void.class) { return null; } - T result = (T) response.readEntity(request.getResponseType()); + T result; + + if (request.getResponseType() == ApiResponse.class) { + result = deserializeApiResponse(responseBody, request); + } else { + result = objectMapper.readValue( + responseBody, + objectMapper.getTypeFactory().constructType(request.getResponseType()) + ); + } + log.debug("Respuesta exitosa {} {}: {}", request.getMethod(), request.getUrl(), result); return result; - } catch (Exception e) { - log.error("Error parseando respuesta {} {}: {}", request.getMethod(), request.getUrl(), e.getMessage()); - throw new HttpClientException("Error parseando respuesta", e); + } else { + log.error( + "Error HTTP {} {} - Status: {} - Body: {}", + request.getMethod(), + request.getUrl(), + statusCode, + responseBody + ); + + if (isApiResponseFormat(responseBody)) { + ApiResponse apiResponse = deserializeApiResponse(responseBody, request); + throw new HttpApiResponseException(statusCode, apiResponse); + } else { + throw mapHttpStatusToException(statusCode, responseBody); + } } - } else { - String errorBody = response.readEntity(String.class); - log.error("Error HTTP {} {} - Status: {} - Body: {}", request.getMethod(), request.getUrl(), response.getStatus(), errorBody); - throw new HttpClientException("HTTP Error " + response.getStatus() + ": " + errorBody); + } catch (HttpStatusCodeException | HttpApiResponseException e) { + throw e; + } catch (Exception e) { + log.error( + "Error procesando respuesta {} {}: {}", + request.getMethod(), + request.getUrl(), + e.getMessage() + ); + throw HttpStatusCodeException.internalServer( + "500", + "Error procesando respuesta del servicio externo: " + e.getMessage() + ); } } - public static class HttpClientException extends RuntimeException { - public HttpClientException(String message) { - super(message); + @SuppressWarnings("unchecked") + private T deserializeApiResponse( + String responseBody, + HttpRequest request + ) { + try { + if (request.getGenericType() != null) { + JavaType javaType = objectMapper.getTypeFactory().constructParametricType( + ApiResponse.class, + objectMapper.getTypeFactory().constructType(request.getGenericType()) + ); + return objectMapper.readValue(responseBody, javaType); + } else { + return (T) objectMapper.readValue(responseBody, ApiResponse.class); + } + } catch (JsonProcessingException e) { + throw HttpStatusCodeException.internalServer( + "500", + "Error deserializando respuesta JSON: " + e.getMessage() + ); + } catch (Exception e) { + throw HttpStatusCodeException.internalServer( + "500", + "Error desconocido al deserializar respuesta: " + e.getMessage() + ); } + } - public HttpClientException(String message, Throwable cause) { - super(message, cause); + private boolean isApiResponseFormat(String responseBody) { + try { + if (responseBody == null || responseBody.trim().isEmpty()) { + return false; + } + + return responseBody.contains("\"data\"") && + responseBody.contains("\"statusResponse\"") && + responseBody.contains("\"statusCode\"") && + responseBody.contains("\"message\""); + } catch (Exception e) { + return false; } } + + private HttpStatusCodeException mapHttpStatusToException( + int statusCode, + String errorBody + ) { + String errorCode = "HTTP_" + statusCode; + String defaultMessage = "Error en servicio externo: HTTP " + statusCode; + String message = errorBody != null && !errorBody.isEmpty() + ? errorBody + : defaultMessage; + + return switch (statusCode) { + case 400 -> HttpStatusCodeException.badRequest(errorCode, message); + case 401 -> HttpStatusCodeException.unauthorized(errorCode, message); + case 403 -> HttpStatusCodeException.forbidden(errorCode, message); + case 404 -> HttpStatusCodeException.notFound(errorCode, message); + case 405 -> HttpStatusCodeException.methodNotAllowed(errorCode, message); + case 408 -> HttpStatusCodeException.fromStatusCode(408, errorCode, message); + case 409 -> HttpStatusCodeException.conflict(errorCode, message); + case 410 -> HttpStatusCodeException.gone(errorCode, message); + case 412 -> HttpStatusCodeException.preconditionFailed(errorCode, message); + case 415 -> HttpStatusCodeException.unsupportedMediaType(errorCode, message); + case 422 -> HttpStatusCodeException.unprocessableEntity(errorCode, message); + case 429 -> HttpStatusCodeException.tooManyRequests(errorCode, message); + case 500 -> HttpStatusCodeException.internalServer(errorCode, message); + case 501 -> HttpStatusCodeException.notImplemented(errorCode, message); + case 502 -> HttpStatusCodeException.badGateway(errorCode, message); + case 503 -> HttpStatusCodeException.serviceUnavailable(errorCode, message); + case 504 -> HttpStatusCodeException.gatewayTimeout(errorCode, message); + default -> HttpStatusCodeException.fromStatusCode(statusCode, errorCode, message); + }; + } } \ No newline at end of file diff --git a/src/main/java/com/banesco/common/domain/exception/BadRequestException.java b/src/main/java/com/banesco/common/domain/exception/BadRequestException.java deleted file mode 100644 index 8c7630a..0000000 --- a/src/main/java/com/banesco/common/domain/exception/BadRequestException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.banesco.common.domain.exception; - -public class BadRequestException extends BaseApiException { - public BadRequestException(String errorCode, String message, String fieldPath) { - super(errorCode, message, fieldPath, "bad-request"); - } - - public BadRequestException(String errorCode, String fieldPath) { - super(errorCode, fieldPath, "bad-request"); - } -} diff --git a/src/main/java/com/banesco/common/domain/exception/HttpApiResponseException.java b/src/main/java/com/banesco/common/domain/exception/HttpApiResponseException.java new file mode 100644 index 0000000..399bdd9 --- /dev/null +++ b/src/main/java/com/banesco/common/domain/exception/HttpApiResponseException.java @@ -0,0 +1,20 @@ +package com.banesco.common.domain.exception; + +import com.banesco.common.domain.model.ApiResponse; +import lombok.Getter; + +@Getter +public class HttpApiResponseException extends RuntimeException { + private final int statusCode; + private final transient ApiResponse apiResponse; + + public HttpApiResponseException(int statusCode, ApiResponse apiResponse) { + super(String.format( + "HTTP %d: %s", statusCode, + apiResponse.getStatusResponse() != null ? + apiResponse.getStatusResponse().getMessage() : "Error sin mensaje" + )); + this.statusCode = statusCode; + this.apiResponse = apiResponse; + } +} \ No newline at end of file diff --git a/src/main/java/com/banesco/common/domain/exception/HttpClientException.java b/src/main/java/com/banesco/common/domain/exception/HttpClientException.java new file mode 100644 index 0000000..04f4f03 --- /dev/null +++ b/src/main/java/com/banesco/common/domain/exception/HttpClientException.java @@ -0,0 +1,11 @@ +package com.banesco.common.domain.exception; + +public class HttpClientException extends RuntimeException { + public HttpClientException(String message) { + super(message); + } + + public HttpClientException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/banesco/common/domain/exception/HttpStatusCodeException.java b/src/main/java/com/banesco/common/domain/exception/HttpStatusCodeException.java new file mode 100644 index 0000000..d93d532 --- /dev/null +++ b/src/main/java/com/banesco/common/domain/exception/HttpStatusCodeException.java @@ -0,0 +1,322 @@ +package com.banesco.common.domain.exception; + +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +import java.util.HashMap; +import java.util.Map; + +@Getter +@ToString +@Builder +public class HttpStatusCodeException extends BaseApiException { + private final int statusCode; + + private static final Map STATUS_CATEGORIES = new HashMap<>(); + + static { + STATUS_CATEGORIES.put(100, "continue"); + STATUS_CATEGORIES.put(101, "switching-protocols"); + STATUS_CATEGORIES.put(102, "processing"); + STATUS_CATEGORIES.put(103, "early-hints"); + STATUS_CATEGORIES.put(200, "ok"); + STATUS_CATEGORIES.put(201, "created"); + STATUS_CATEGORIES.put(202, "accepted"); + STATUS_CATEGORIES.put(203, "non-authoritative-information"); + STATUS_CATEGORIES.put(204, "no-content"); + STATUS_CATEGORIES.put(205, "reset-content"); + STATUS_CATEGORIES.put(206, "partial-content"); + STATUS_CATEGORIES.put(207, "multi-status"); + STATUS_CATEGORIES.put(208, "already-reported"); + STATUS_CATEGORIES.put(226, "im-used"); + STATUS_CATEGORIES.put(300, "multiple-choices"); + STATUS_CATEGORIES.put(301, "moved-permanently"); + STATUS_CATEGORIES.put(302, "found"); + STATUS_CATEGORIES.put(303, "see-other"); + STATUS_CATEGORIES.put(304, "not-modified"); + STATUS_CATEGORIES.put(305, "use-proxy"); + STATUS_CATEGORIES.put(307, "temporary-redirect"); + STATUS_CATEGORIES.put(308, "permanent-redirect"); + STATUS_CATEGORIES.put(400, "bad-request"); + STATUS_CATEGORIES.put(401, "unauthorized"); + STATUS_CATEGORIES.put(402, "payment-required"); + STATUS_CATEGORIES.put(403, "forbidden"); + STATUS_CATEGORIES.put(404, "not-found"); + STATUS_CATEGORIES.put(405, "method-not-allowed"); + STATUS_CATEGORIES.put(406, "not-acceptable"); + STATUS_CATEGORIES.put(407, "proxy-authentication-required"); + STATUS_CATEGORIES.put(408, "request-timeout"); + STATUS_CATEGORIES.put(409, "conflict"); + STATUS_CATEGORIES.put(410, "gone"); + STATUS_CATEGORIES.put(411, "length-required"); + STATUS_CATEGORIES.put(412, "precondition-failed"); + STATUS_CATEGORIES.put(413, "payload-too-large"); + STATUS_CATEGORIES.put(414, "uri-too-long"); + STATUS_CATEGORIES.put(415, "unsupported-media-type"); + STATUS_CATEGORIES.put(416, "range-not-satisfiable"); + STATUS_CATEGORIES.put(417, "expectation-failed"); + STATUS_CATEGORIES.put(418, "im-a-teapot"); + STATUS_CATEGORIES.put(421, "misdirected-request"); + STATUS_CATEGORIES.put(422, "unprocessable-entity"); + STATUS_CATEGORIES.put(423, "locked"); + STATUS_CATEGORIES.put(424, "failed-dependency"); + STATUS_CATEGORIES.put(425, "too-early"); + STATUS_CATEGORIES.put(426, "upgrade-required"); + STATUS_CATEGORIES.put(428, "precondition-required"); + STATUS_CATEGORIES.put(429, "too-many-requests"); + STATUS_CATEGORIES.put(431, "request-header-fields-too-large"); + STATUS_CATEGORIES.put(451, "unavailable-for-legal-reasons"); + STATUS_CATEGORIES.put(500, "internal-server-error"); + STATUS_CATEGORIES.put(501, "not-implemented"); + STATUS_CATEGORIES.put(502, "bad-gateway"); + STATUS_CATEGORIES.put(503, "service-unavailable"); + STATUS_CATEGORIES.put(504, "gateway-timeout"); + STATUS_CATEGORIES.put(505, "http-version-not-supported"); + STATUS_CATEGORIES.put(506, "variant-also-negotiates"); + STATUS_CATEGORIES.put(507, "insufficient-storage"); + STATUS_CATEGORIES.put(508, "loop-detected"); + STATUS_CATEGORIES.put(510, "not-extended"); + STATUS_CATEGORIES.put(511, "network-authentication-required"); + } + + public HttpStatusCodeException(int statusCode, String errorCode, String message, String fieldPath) { + super(errorCode, message, fieldPath, getHttpStatusCategory(statusCode)); + this.statusCode = statusCode; + } + + public HttpStatusCodeException(int statusCode, String errorCode, String message) { + this(statusCode, errorCode, message, null); + } + + public HttpStatusCodeException(int statusCode, String errorCode) { + this(statusCode, errorCode, getDefaultMessage(statusCode), null); + } + + public HttpStatusCodeException(int statusCode) { + this(statusCode, "HTTP_" + statusCode); + } + + private static String getHttpStatusCategory(int statusCode) { + String category = STATUS_CATEGORIES.get(statusCode); + + if (category != null) { + return category; + } + + if (statusCode >= 100 && statusCode < 200) return "informational"; + if (statusCode >= 200 && statusCode < 300) return "success"; + if (statusCode >= 300 && statusCode < 400) return "redirection"; + if (statusCode >= 400 && statusCode < 500) return "client-error"; + if (statusCode >= 500 && statusCode < 600) return "server-error"; + return "unknown"; + } + + private static String getDefaultMessage(int statusCode) { + return switch (statusCode) { + case 200 -> "OK"; + case 201 -> "Created"; + case 202 -> "Accepted"; + case 204 -> "No Content"; + case 400 -> "Bad Request"; + case 401 -> "Unauthorized"; + case 403 -> "Forbidden"; + case 404 -> "Not Found"; + case 405 -> "Method Not Allowed"; + case 408 -> "Request Timeout"; + case 409 -> "Conflict"; + case 410 -> "Gone"; + case 422 -> "Unprocessable Entity"; + case 429 -> "Too Many Requests"; + case 500 -> "Internal Server Error"; + case 502 -> "Bad Gateway"; + case 503 -> "Service Unavailable"; + case 504 -> "Gateway Timeout"; + default -> "HTTP " + statusCode; + }; + } + + public static HttpStatusCodeException badRequest(String errorCode) { + return new HttpStatusCodeException(400, errorCode); + } + + public static HttpStatusCodeException badRequest(String errorCode, String fieldPath) { + return new HttpStatusCodeException(400, errorCode, getDefaultMessage(400), fieldPath); + } + + public static HttpStatusCodeException unauthorized(String errorCode) { + return new HttpStatusCodeException(401, errorCode); + } + + public static HttpStatusCodeException unauthorized(String errorCode, String fieldPath) { + return new HttpStatusCodeException(401, errorCode, getDefaultMessage(401), fieldPath); + } + + public static HttpStatusCodeException forbidden(String errorCode) { + return new HttpStatusCodeException(403, errorCode); + } + + public static HttpStatusCodeException forbidden(String errorCode, String fieldPath) { + return new HttpStatusCodeException(403, errorCode, getDefaultMessage(403), fieldPath); + } + + public static HttpStatusCodeException notFound(String errorCode) { + return new HttpStatusCodeException(404, errorCode); + } + + public static HttpStatusCodeException notFound(String errorCode, String fieldPath) { + return new HttpStatusCodeException(404, errorCode, getDefaultMessage(404), fieldPath); + } + + public static HttpStatusCodeException methodNotAllowed(String errorCode) { + return new HttpStatusCodeException(405, errorCode); + } + + public static HttpStatusCodeException methodNotAllowed(String errorCode, String fieldPath) { + return new HttpStatusCodeException(405, errorCode, getDefaultMessage(405), fieldPath); + } + + public static HttpStatusCodeException conflict(String errorCode) { + return new HttpStatusCodeException(409, errorCode); + } + + public static HttpStatusCodeException conflict(String errorCode, String fieldPath) { + return new HttpStatusCodeException(409, errorCode, getDefaultMessage(409), fieldPath); + } + + public static HttpStatusCodeException unprocessableEntity(String errorCode) { + return new HttpStatusCodeException(422, errorCode); + } + + public static HttpStatusCodeException unprocessableEntity(String errorCode, String fieldPath) { + return new HttpStatusCodeException(422, errorCode, getDefaultMessage(422), fieldPath); + } + + public static HttpStatusCodeException tooManyRequests(String errorCode) { + return new HttpStatusCodeException(429, errorCode); + } + + public static HttpStatusCodeException tooManyRequests(String errorCode, String fieldPath) { + return new HttpStatusCodeException(429, errorCode, getDefaultMessage(429), fieldPath); + } + + public static HttpStatusCodeException internalServer(String errorCode) { + return new HttpStatusCodeException(500, errorCode); + } + + public static HttpStatusCodeException internalServer(String errorCode, String fieldPath) { + return new HttpStatusCodeException(500, errorCode, getDefaultMessage(500), fieldPath); + } + + public static HttpStatusCodeException badGateway(String errorCode) { + return new HttpStatusCodeException(502, errorCode); + } + + public static HttpStatusCodeException badGateway(String errorCode, String fieldPath) { + return new HttpStatusCodeException(502, errorCode, getDefaultMessage(502), fieldPath); + } + + public static HttpStatusCodeException serviceUnavailable(String errorCode) { + return new HttpStatusCodeException(503, errorCode); + } + + public static HttpStatusCodeException serviceUnavailable(String errorCode, String fieldPath) { + return new HttpStatusCodeException(503, errorCode, getDefaultMessage(503), fieldPath); + } + + public static HttpStatusCodeException gatewayTimeout(String errorCode) { + return new HttpStatusCodeException(504, errorCode); + } + + public static HttpStatusCodeException gatewayTimeout(String errorCode, String fieldPath) { + return new HttpStatusCodeException(504, errorCode, getDefaultMessage(504), fieldPath); + } + + public static HttpStatusCodeException paymentRequired(String errorCode) { + return new HttpStatusCodeException(402, errorCode); + } + + public static HttpStatusCodeException paymentRequired(String errorCode, String fieldPath) { + return new HttpStatusCodeException(402, errorCode, getDefaultMessage(402), fieldPath); + } + + public static HttpStatusCodeException gone(String errorCode) { + return new HttpStatusCodeException(410, errorCode); + } + + public static HttpStatusCodeException gone(String errorCode, String fieldPath) { + return new HttpStatusCodeException(410, errorCode, getDefaultMessage(410), fieldPath); + } + + public static HttpStatusCodeException preconditionFailed(String errorCode) { + return new HttpStatusCodeException(412, errorCode); + } + + public static HttpStatusCodeException preconditionFailed(String errorCode, String fieldPath) { + return new HttpStatusCodeException(412, errorCode, getDefaultMessage(412), fieldPath); + } + + public static HttpStatusCodeException unsupportedMediaType(String errorCode) { + return new HttpStatusCodeException(415, errorCode); + } + + public static HttpStatusCodeException unsupportedMediaType(String errorCode, String fieldPath) { + return new HttpStatusCodeException(415, errorCode, getDefaultMessage(415), fieldPath); + } + + public static HttpStatusCodeException notImplemented(String errorCode) { + return new HttpStatusCodeException(501, errorCode); + } + + public static HttpStatusCodeException notImplemented(String errorCode, String fieldPath) { + return new HttpStatusCodeException(501, errorCode, getDefaultMessage(501), fieldPath); + } + + public static HttpStatusCodeException ok(String errorCode) { + return new HttpStatusCodeException(200, errorCode); + } + + public static HttpStatusCodeException ok(String errorCode, String fieldPath) { + return new HttpStatusCodeException(200, errorCode, getDefaultMessage(200), fieldPath); + } + + public static HttpStatusCodeException created(String errorCode) { + return new HttpStatusCodeException(201, errorCode); + } + + public static HttpStatusCodeException created(String errorCode, String fieldPath) { + return new HttpStatusCodeException(201, errorCode, getDefaultMessage(201), fieldPath); + } + + public static HttpStatusCodeException accepted(String errorCode) { + return new HttpStatusCodeException(202, errorCode); + } + + public static HttpStatusCodeException accepted(String errorCode, String fieldPath) { + return new HttpStatusCodeException(202, errorCode, getDefaultMessage(202), fieldPath); + } + + public static HttpStatusCodeException noContent(String errorCode) { + return new HttpStatusCodeException(204, errorCode); + } + + public static HttpStatusCodeException noContent(String errorCode, String fieldPath) { + return new HttpStatusCodeException(204, errorCode, getDefaultMessage(204), fieldPath); + } + + public static HttpStatusCodeException requestTimeout(String errorCode) { + return new HttpStatusCodeException(408, errorCode); + } + + public static HttpStatusCodeException requestTimeout(String errorCode, String fieldPath) { + return new HttpStatusCodeException(408, errorCode, getDefaultMessage(408), fieldPath); + } + + public static HttpStatusCodeException fromStatusCode(int statusCode, String errorCode) { + return new HttpStatusCodeException(statusCode, errorCode); + } + + public static HttpStatusCodeException fromStatusCode(int statusCode, String errorCode, String fieldPath) { + return new HttpStatusCodeException(statusCode, errorCode, getDefaultMessage(statusCode), fieldPath); + } +} \ No newline at end of file diff --git a/src/main/java/com/banesco/common/domain/exception/InternalServerException.java b/src/main/java/com/banesco/common/domain/exception/InternalServerException.java deleted file mode 100644 index c96d30d..0000000 --- a/src/main/java/com/banesco/common/domain/exception/InternalServerException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.banesco.common.domain.exception; - -public class InternalServerException extends BaseApiException { - public InternalServerException(String errorCode, String message, String fieldPath) { - super(errorCode, message, fieldPath, "internal-server"); - } - - public InternalServerException(String errorCode, String fieldPath) { - super(errorCode, fieldPath, "internal-server"); - } -} diff --git a/src/main/java/com/banesco/common/domain/exception/NotFoundException.java b/src/main/java/com/banesco/common/domain/exception/NotFoundException.java deleted file mode 100644 index 3593fb3..0000000 --- a/src/main/java/com/banesco/common/domain/exception/NotFoundException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.banesco.common.domain.exception; - -public class NotFoundException extends BaseApiException { - public NotFoundException(String errorCode, String message, String fieldPath) { - super(errorCode, message, fieldPath, "not-found"); - } - - public NotFoundException(String errorCode, String fieldPath) { - super(errorCode, fieldPath, "not-found"); - } -} diff --git a/src/main/java/com/banesco/common/domain/exception/ServiceUnavailableException.java b/src/main/java/com/banesco/common/domain/exception/ServiceUnavailableException.java deleted file mode 100644 index f5195ad..0000000 --- a/src/main/java/com/banesco/common/domain/exception/ServiceUnavailableException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.banesco.common.domain.exception; - -public class ServiceUnavailableException extends BaseApiException { - public ServiceUnavailableException(String errorCode, String message, String fieldPath) { - super(errorCode, message, fieldPath, "service-unavailable"); - } - - public ServiceUnavailableException(String errorCode, String fieldPath) { - super(errorCode, fieldPath, "service-unavailable"); - } -} diff --git a/src/main/java/com/banesco/common/domain/exception/SuccessException.java b/src/main/java/com/banesco/common/domain/exception/SuccessException.java deleted file mode 100644 index 141c661..0000000 --- a/src/main/java/com/banesco/common/domain/exception/SuccessException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.banesco.common.domain.exception; - -public class SuccessException extends BaseApiException { - public SuccessException(String code, String message, String fieldPath) { - super(code, message, fieldPath, "ok"); - } - - public SuccessException(String code, String fieldPath) { - super(code, fieldPath, "ok"); - } -} diff --git a/src/main/java/com/banesco/common/domain/exception/UnauthorizedException.java b/src/main/java/com/banesco/common/domain/exception/UnauthorizedException.java deleted file mode 100644 index e8994d4..0000000 --- a/src/main/java/com/banesco/common/domain/exception/UnauthorizedException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.banesco.common.domain.exception; - -public class UnauthorizedException extends BaseApiException { - public UnauthorizedException(String errorCode, String message, String fieldPath) { - super(errorCode, message, fieldPath, "unauthorized"); - } - - public UnauthorizedException(String errorCode, String fieldPath) { - super(errorCode, fieldPath, "unauthorized"); - } -} diff --git a/src/main/java/com/banesco/common/domain/model/ApiResponse.java b/src/main/java/com/banesco/common/domain/model/ApiResponse.java index 3c3a8f9..a5e4845 100644 --- a/src/main/java/com/banesco/common/domain/model/ApiResponse.java +++ b/src/main/java/com/banesco/common/domain/model/ApiResponse.java @@ -10,4 +10,9 @@ import lombok.*; public class ApiResponse { private T data; private StatusResponse statusResponse; -} + + public ApiResponse(StatusResponse statusResponse) { + this.statusResponse = statusResponse; + this.data = null; + } +} \ No newline at end of file diff --git a/src/main/java/com/banesco/common/domain/model/HttpRequest.java b/src/main/java/com/banesco/common/domain/model/HttpRequest.java index 4c8b082..a14d04a 100644 --- a/src/main/java/com/banesco/common/domain/model/HttpRequest.java +++ b/src/main/java/com/banesco/common/domain/model/HttpRequest.java @@ -1,25 +1,38 @@ package com.banesco.common.domain.model; -import lombok.Builder; -import lombok.Getter; -import lombok.ToString; +import lombok.*; + import java.util.Map; @Getter -@Builder +@Setter @ToString +@NoArgsConstructor +@AllArgsConstructor +@Builder public class HttpRequest { private String url; private HttpMethod method; private Object body; - private Map pathParams; - private Map queryParams; private Map headers; - private Class responseType; - private int connectTimeout; - private int readTimeout; + private Map queryParams; + private Map pathParams; + + @Builder.Default + private Class responseType = Object.class; + + private Class genericType; + + @Builder.Default + private int connectTimeout = 5000; + + @Builder.Default + private int readTimeout = 10000; + + @Builder.Default + private boolean returnFullResponse = false; public enum HttpMethod { GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS } -} +} \ No newline at end of file diff --git a/src/main/java/com/banesco/common/infrastructure/config/MessagesConfig.java b/src/main/java/com/banesco/common/infrastructure/config/MessagesConfig.java index 82a42d0..51f4d02 100644 --- a/src/main/java/com/banesco/common/infrastructure/config/MessagesConfig.java +++ b/src/main/java/com/banesco/common/infrastructure/config/MessagesConfig.java @@ -13,7 +13,7 @@ public class MessagesConfig { private final String errorMessagesJson; private final String messagesKey; - private static final String KEY = "recLogalCustomerProductDirectory"; + private static final String KEY = "rec-legal-customer-product-directory"; @Inject public MessagesConfig(Config config) { diff --git a/src/main/java/com/banesco/common/infrastructure/config/RestClientConfig.java b/src/main/java/com/banesco/common/infrastructure/config/RestClientConfig.java index 4060e7d..53af552 100644 --- a/src/main/java/com/banesco/common/infrastructure/config/RestClientConfig.java +++ b/src/main/java/com/banesco/common/infrastructure/config/RestClientConfig.java @@ -2,13 +2,13 @@ package com.banesco.common.infrastructure.config; import com.banesco.common.domain.model.BusinessConfig; import com.fasterxml.jackson.core.JsonProcessingException; -import io.quarkus.runtime.annotations.RegisterForReflection; -import lombok.extern.slf4j.Slf4j; -import jakarta.enterprise.context.ApplicationScoped; -import org.eclipse.microprofile.config.Config; -import jakarta.inject.Inject; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import io.quarkus.runtime.annotations.RegisterForReflection; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.microprofile.config.Config; import java.util.Map; @@ -20,27 +20,34 @@ public class RestClientConfig { private final Config config; private final ObjectMapper objectMapper; + private static final String API_BASE = "api.rest-client."; + private static final String API_DOMAIN_NAME = "bus-legal-customer-product-directory"; + @Inject - public RestClientConfig(Config config, ObjectMapper objectMapper) { + public RestClientConfig( + Config config, + ObjectMapper objectMapper + ) { this.config = config; this.objectMapper = objectMapper; } public BusinessConfig getBusLegalCustomerConfig() { try { - String json = config.getValue("api.rest-client.bus-legal-customer-product-directory", String.class); - log.info("Configurando bus-legal-customer-product-directory: {}", json); + String fullConfigName = API_BASE + API_DOMAIN_NAME; + String json = config.getValue(fullConfigName, String.class); + log.info("Configurando {}: {}", fullConfigName, json); if (json == null || json.trim().isEmpty()) { - throw new IllegalStateException("Configuración requerida no encontrada para: api.rest-client.bus-legal-customer-product-directory"); + throw new IllegalStateException("Configuración no encontrada para: " + fullConfigName); } Map configMap = objectMapper.readValue(json, new TypeReference<>() {}); return objectMapper.convertValue(configMap, BusinessConfig.class); } catch (JsonProcessingException e) { - throw new IllegalArgumentException("Formato JSON inválido en la configuración: api.rest-client.bus-legal-customer-product-directory", e); + throw new IllegalArgumentException("Formato JSON inválido para " + API_DOMAIN_NAME + ": " + e.getMessage(), e); } catch (Exception e) { - throw new IllegalStateException("Error cargando configuración del servicio", e); + throw new IllegalStateException("Error cargando configuración del servicio " + API_DOMAIN_NAME + ": " + e.getMessage(), e); } } -} +} \ No newline at end of file diff --git a/src/main/java/com/banesco/module/legal_customer_product_directory/application/service/LegalCustomerProductDirectoryService.java b/src/main/java/com/banesco/module/legal_customer_product_directory/application/service/LegalCustomerProductDirectoryService.java index 1fc7249..2895586 100644 --- a/src/main/java/com/banesco/module/legal_customer_product_directory/application/service/LegalCustomerProductDirectoryService.java +++ b/src/main/java/com/banesco/module/legal_customer_product_directory/application/service/LegalCustomerProductDirectoryService.java @@ -1,46 +1,35 @@ package com.banesco.module.legal_customer_product_directory.application.service; -import com.banesco.common.application.helper.MessageResponseHelper; +import com.banesco.common.application.helper.MessageHelper; import com.banesco.common.application.helper.RequestValidatorHelper; -import com.banesco.common.domain.exception.BaseApiException; -import com.banesco.common.domain.exception.ServiceUnavailableException; +import com.banesco.common.domain.exception.HttpStatusCodeException; import com.banesco.common.domain.model.*; import com.banesco.module.account.domain.model.*; -import com.banesco.common.domain.model.Agreement; -import com.banesco.common.domain.model.Arrangement; -import com.banesco.common.domain.model.ArrangementType; import com.banesco.module.legal_customer_product_directory.application.usecase.BusinessUseCase; import com.banesco.module.legal_customer_product_directory.application.usecase.LegalCustomerProductDirectoryUseCase; import com.banesco.module.legal_customer_product_directory.domain.dto.request.LegalCustomerProductDirectoryRequest; import com.banesco.module.legal_customer_product_directory.domain.dto.response.LegalCustomerProductDirectoryResponse; -import com.banesco.module.legal_customer_product_directory.domain.model.CustomerProductAndServiceDirectory; -import com.banesco.module.party.domain.model.Party; -import com.banesco.module.party.domain.model.PartyIdentification; -import com.banesco.module.party.domain.model.PartyIdentificationType; -import com.banesco.module.party.domain.model.PartyType; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import lombok.extern.slf4j.Slf4j; -import java.math.BigDecimal; -import java.util.List; import java.util.Objects; @Slf4j @ApplicationScoped public class LegalCustomerProductDirectoryService implements LegalCustomerProductDirectoryUseCase { - private final MessageResponseHelper messageResponseHelper; + private final MessageHelper messageHelper; private final RequestValidatorHelper requestValidatorHelper; private final BusinessUseCase businessUseCase; @Inject public LegalCustomerProductDirectoryService( - MessageResponseHelper messageResponseHelper, + MessageHelper messageHelper, RequestValidatorHelper requestValidatorHelper, BusinessUseCase businessUseCase ) { - this.messageResponseHelper = messageResponseHelper; + this.messageHelper = messageHelper; this.requestValidatorHelper = requestValidatorHelper; this.businessUseCase = businessUseCase; } @@ -54,18 +43,24 @@ public class LegalCustomerProductDirectoryService implements LegalCustomerProduc validate(request); try { - return business(request); - } catch (BaseApiException e) { - log.warn("Excepción controlada del api de negocio: {} -> {}", e.getErrorCode(), e.getMessage()); + ApiResponse response = business(request); - if(Objects.equals(e.getErrorCode(), "200")) { - return createSuccessMock(); + if ( + !Objects.isNull(response.getData()) && + messageHelper.isSuccessStatusCode(response.getStatusResponse()) + ) { + return new ApiResponse<>(response.getData(), messageHelper.createStatusResponse( + response.getStatusResponse().getStatusCode() + )); } + throw HttpStatusCodeException.serviceUnavailable("503"); + } catch (HttpStatusCodeException e) { + log.error("Excepción HTTP del api de negocio: {} - {}", e.getStatusCode(), e.getErrorCode()); throw e; } catch (Exception e) { - log.warn("Excepción generica del api de negocio: {}", e.getMessage()); - throw new ServiceUnavailableException("503", e.getMessage(), null); + log.error("Excepción genérica del api de negocio: {}", e.getMessage()); + throw e; } } @@ -78,134 +73,7 @@ public class LegalCustomerProductDirectoryService implements LegalCustomerProduc private ApiResponse business( LegalCustomerProductDirectoryRequest request ) { - log.info("Calling business service for client: {}", request.getCustomerIbsNumber()); - + log.info("Ejecutando llamada al api de negocio: {}", request.getCustomerIbsNumber()); return businessUseCase.execute(request, LegalCustomerProductDirectoryResponse.class); } - - private ApiResponse createSuccessMock() { - return new ApiResponse<>( - LegalCustomerProductDirectoryResponse.builder() - .customerProductAndServiceDirectory( - CustomerProductAndServiceDirectory.builder() - .accounts(List.of(getAccount())) - .build() - ) - .build(), - messageResponseHelper.createSuccessResponse("200") - ); - } - - private Account getAccount() { - return Account.builder() - .accountStatus(AccountStatus.builder() - .status("A") - .statusType(AccountStatusType.ENABLED) - .build()) - .accountType(AccountType.CURRENT_ACCOUNT) - .accountIdentification(List.of( - AccountIdentification.builder() - .accountIdentificationType(AccountIdentificationType.ACCOUNT_NUMBER) - .accountIdentification(Identifier.builder() - .identifierValue("01340025330253093528") - .build()) - .build(), - AccountIdentification.builder() - .accountIdentificationType(AccountIdentificationType.BANK_NUMBER) - .accountIdentification(Identifier.builder() - .identifierValue("01") - .build()) - .build(), - AccountIdentification.builder() - .accountIdentificationType(AccountIdentificationType.PRODUCT_CODE) - .accountIdentification(Identifier.builder() - .identifierValue("3980") - .build()) - .build(), - AccountIdentification.builder() - .accountIdentificationType(AccountIdentificationType.ACCOUNT_CLASS) - .accountIdentification(Identifier.builder() - .identifierValue("80") - .build()) - .build() - )) - .accountBalance(List.of( - AccountBalance.builder() - .balanceAmount(BigDecimal.valueOf(390417.36)) - .balanceType(BalanceType.AVAILABLE_BALANCE) - .build(), - AccountBalance.builder() - .balanceAmount(BigDecimal.valueOf(100000.00)) - .balanceType(BalanceType.DAILY_MAXIMUM) - .build(), - AccountBalance.builder() - .balanceAmount(BigDecimal.valueOf(3000000.00)) - .balanceType(BalanceType.MONTHLY_MAXIMUM) - .build(), - AccountBalance.builder() - .balanceAmount(BigDecimal.valueOf(0.01)) - .balanceType(BalanceType.TRANSACTION_MINIMUM) - .build(), - AccountBalance.builder() - .balanceAmount(BigDecimal.valueOf(100000.00)) - .balanceType(BalanceType.TRANSACTION_MAXIMUM) - .build() - )) - .accountCurrency(List.of( - AccountCurrency.builder() - .currencyCode("BS") - .currencyType(CurrencyType.BASE) - .build() - )) - .accountInvolvement(List.of( - AccountInvolvement.builder() - .accountInvolvementType(AccountInvolvementType.PARTY_IS_OWNER_OF_ACCOUNT) - .partyReference( - Party.builder() - .partyName(List.of( - Name.builder() - .fullName("TASCA RESTAURANT GOOD WORLD CEN, C.A.") - .build() - )) - .partyType(PartyType.ORGANISATION) - .partyIdentification(List.of( - PartyIdentification.builder() - .partyIdentificationType(PartyIdentificationType.TAX_IDENTIFICATION_NUMBER) - .partyIdentification(Identifier.builder() - .identifierValue("J000000001") - .build()) - .build(), - PartyIdentification.builder() - .partyIdentificationType(PartyIdentificationType.TELEPHONE_NUMBER) - .partyIdentification(Identifier.builder() - .identifierValue("04122710660") - .build()) - .build(), - PartyIdentification.builder() - .partyIdentificationType(PartyIdentificationType.TELEPHONE_OPERATOR) - .partyIdentification(Identifier.builder() - .identifierValue("0412") - .build()) - .build() - )) - .build() - ) - .build() - )) - .accountRelationship(List.of( - AccountRelationship.builder() - .accountRelationshipType(AccountRelationshipType.ACCOUNT_IS_SUB_ACCOUNT_FOR_ACCOUNT) - .build() - )) - .agreement(List.of( - Agreement.builder() - .arrangement(List.of( - Arrangement.builder() - .arrangementType(ArrangementType.INTEREST_ARRANGEMENT) - .build() - )) - .build() - )) - .build(); - } } \ No newline at end of file diff --git a/src/main/java/com/banesco/module/legal_customer_product_directory/infrastructure/client/BusLegalCustomerDirectoryClient.java b/src/main/java/com/banesco/module/legal_customer_product_directory/infrastructure/client/BusLegalCustomerDirectoryClient.java index d6c115c..4bb4c13 100644 --- a/src/main/java/com/banesco/module/legal_customer_product_directory/infrastructure/client/BusLegalCustomerDirectoryClient.java +++ b/src/main/java/com/banesco/module/legal_customer_product_directory/infrastructure/client/BusLegalCustomerDirectoryClient.java @@ -1,16 +1,17 @@ package com.banesco.module.legal_customer_product_directory.infrastructure.client; import com.banesco.common.application.usecase.HttpClientUseCase; -import com.banesco.common.domain.exception.ServiceUnavailableException; +import com.banesco.common.domain.exception.HttpApiResponseException; +import com.banesco.common.domain.exception.HttpStatusCodeException; import com.banesco.common.domain.model.ApiResponse; import com.banesco.common.domain.model.BusinessConfig; import com.banesco.common.domain.model.HttpRequest; import com.banesco.common.infrastructure.config.RestClientConfig; import com.banesco.module.legal_customer_product_directory.application.usecase.BusinessUseCase; import com.banesco.module.legal_customer_product_directory.domain.dto.request.LegalCustomerProductDirectoryRequest; -import lombok.extern.slf4j.Slf4j; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import lombok.extern.slf4j.Slf4j; import java.util.Map; @@ -36,26 +37,51 @@ public class BusLegalCustomerDirectoryClient implements BusinessUseCase { Class responseType ) { String customerIbsNumber = params.getCustomerIbsNumber(); + HttpRequest request = HttpRequest.builder() + .url(businessConfig.getUrl()) + .method(HttpRequest.HttpMethod.GET) + .pathParams(Map.of("customerIbsNumber", customerIbsNumber)) + .queryParams(params.toQueryString()) + .responseType(ApiResponse.class) + .genericType(responseType) + .connectTimeout(businessConfig.getTimeout().getConnect()) + .readTimeout(businessConfig.getTimeout().getResponse()) + .build(); - log.info("Consultando información del cliente: {}", customerIbsNumber); + log.debug("Request configurado: {}", request); try { - HttpRequest request = HttpRequest.builder() - .url(businessConfig.getUrl()) - .method(HttpRequest.HttpMethod.GET) - .pathParams(Map.of("customerIbsNumber", customerIbsNumber)) - .queryParams(params.toQueryString()) - .responseType(responseType) - .connectTimeout(businessConfig.getTimeout().getConnect()) - .readTimeout(businessConfig.getTimeout().getResponse()) - .build(); + ApiResponse response = httpClientUseCase.execute(request); - log.debug("Request configurado: {}", request); + log.info( + "Solicitud del api de dominio exitoso: {}", + response.getStatusResponse() + ); - return httpClientUseCase.execute(request); + return response; + } catch (HttpApiResponseException e) { + log.error( + "Error HTTP con ApiResponse consultando cliente {}: {}", + customerIbsNumber, + e.getApiResponse() + ); + + throw new HttpStatusCodeException( + e.getStatusCode(), + e.getApiResponse().getStatusResponse().getStatusCode() + ); + } catch (HttpStatusCodeException e) { + log.error( + "Error HTTP consultando cliente {}: {} - {}", + customerIbsNumber, + e.getStatusCode(), + e.getMessage() + ); + + throw e; } catch (Exception e) { log.error("Error consultando cliente {}: {}", customerIbsNumber, e.getMessage()); - throw new ServiceUnavailableException("503", e.getMessage(), null); + throw HttpStatusCodeException.serviceUnavailable("503"); } } } \ No newline at end of file diff --git a/src/main/java/com/banesco/module/legal_customer_product_directory/infrastructure/resource/LegalCustomerProductDirectoryResource.java b/src/main/java/com/banesco/module/legal_customer_product_directory/infrastructure/resource/LegalCustomerProductDirectoryResource.java index 4960613..ceef899 100644 --- a/src/main/java/com/banesco/module/legal_customer_product_directory/infrastructure/resource/LegalCustomerProductDirectoryResource.java +++ b/src/main/java/com/banesco/module/legal_customer_product_directory/infrastructure/resource/LegalCustomerProductDirectoryResource.java @@ -1,7 +1,7 @@ package com.banesco.module.legal_customer_product_directory.infrastructure.resource; -import com.banesco.common.application.helper.MessageResponseHelper; -import com.banesco.common.domain.exception.BaseApiException; +import com.banesco.common.application.helper.MessageHelper; +import com.banesco.common.domain.exception.HttpStatusCodeException; import com.banesco.common.domain.model.ApiResponse; import com.banesco.common.domain.model.StatusResponse; import com.banesco.module.legal_customer_product_directory.application.usecase.LegalCustomerProductDirectoryUseCase; @@ -30,15 +30,15 @@ import java.util.Objects; public class LegalCustomerProductDirectoryResource { private final LegalCustomerProductDirectoryUseCase useCase; - private final MessageResponseHelper messageResponseHelper; + private final MessageHelper messageHelper; @Inject public LegalCustomerProductDirectoryResource( LegalCustomerProductDirectoryUseCase useCase, - MessageResponseHelper messageResponseHelper + MessageHelper messageHelper ) { this.useCase = useCase; - this.messageResponseHelper = messageResponseHelper; + this.messageHelper = messageHelper; } @GET @@ -343,10 +343,10 @@ public class LegalCustomerProductDirectoryResource { .appId(appId) .build() )).build(); - } catch (BaseApiException e) { - return messageResponseHelper.handleException(e); + } catch (HttpStatusCodeException e) { + return messageHelper.handleException(e); } catch (Exception e) { - return messageResponseHelper.handleGenericException(e); + return messageHelper.handleGenericException(e); } } } \ No newline at end of file diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 116897f..86e669f 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -15,11 +15,12 @@ api: product-cv-code: '^(CV|CVFL)$' limit-type: '^(PAG|REC)$' cachea-indicator: '^(SI|NO)$' + app-id: DANIAPP read-messages: from-props: true - recLogalCustomerProductDirectory: + rec-legal-customer-product-directory: messages: - key: 'recLogalCustomerProductDirectory' - content: '[{"backendCode":"200","httpCode":200,"statusCode":"200","description":"Operacion exitosa"},{"backendCode":"R404","httpCode":404,"statusCode":"404","description":"Datos de validación no encontrado."},{"backendCode":"503","httpCode":503,"statusCode":"503","description":"Uso interno"},{"backendCode":"422","httpCode":422,"statusCode":"422","description":"Uso interno"},{"backendCode":"500","httpCode":500,"statusCode":"500","description":"Uso interno"},{"backendCode":"100","httpCode":503,"statusCode":"503","description":"VDR13 - OSB Disponible"},{"backendCode":"OSB-382505","httpCode":503,"statusCode":"503","description":"VDR13 - OSB Disponible"},{"backendCode":"OSB-380002","httpCode":503,"statusCode":"503","description":"VDR13 - OSB Disponible"},{"backendCode":"ERROR","httpCode":400,"statusCode":"400","description":"Uso interno"},{"backendCode":"400","httpCode":400,"statusCode":"400","description":"Uso interno"},{"backendCode":"401","httpCode":401,"statusCode":"401","description":"Uso interno"},{"backendCode":"403","httpCode":403,"statusCode":"403","description":"Uso interno"},{"backendCode":"404","httpCode":404,"statusCode":"404","description":"Uso interno"},{"backendCode":"default","httpCode":409,"statusCode":"409","description":"Conflicto"},{"backendCode":"424","httpCode":424,"statusCode":"424","description":"Error de dependencia"},{"backendCode":"VDE01","httpCode":400,"statusCode":"VDE01","description":"VDE01 - Error en dato de entrada obligatorio: %s"},{"backendCode":"VDE02","httpCode":400,"statusCode":"VDE02","description":"VDE02 - Error en valor permitido para campo: %s"}]' + key: 'rec-legal-customer-product-directory' + content: '[{"backendCode":"200","httpCode":200,"statusCode":"200","description":"Operacion exitosa"},{"backendCode":"R404","httpCode":404,"statusCode":"404","description":"Datos de validación no encontrado."},{"backendCode":"503","httpCode":503,"statusCode":"503","description":"Uso interno"},{"backendCode":"422","httpCode":422,"statusCode":"422","description":"Uso interno"},{"backendCode":"500","httpCode":500,"statusCode":"500","description":"Uso interno"},{"backendCode":"100","httpCode":503,"statusCode":"503","description":"VDR13 - OSB Disponible"},{"backendCode":"OSB-382505","httpCode":503,"statusCode":"503","description":"VDR13 - OSB Disponible"},{"backendCode":"OSB-380002","httpCode":503,"statusCode":"503","description":"VDR13 - OSB Disponible"},{"backendCode":"ERROR","httpCode":400,"statusCode":"400","description":"Uso interno"},{"backendCode":"400","httpCode":400,"statusCode":"400","description":"Uso interno"},{"backendCode":"401","httpCode":401,"statusCode":"401","description":"Uso interno"},{"backendCode":"403","httpCode":403,"statusCode":"403","description":"Uso interno"},{"backendCode":"404","httpCode":404,"statusCode":"404","description":"Uso interno"},{"backendCode":"default","httpCode":409,"statusCode":"409","description":"Conflicto"},{"backendCode":"424","httpCode":424,"statusCode":"424","description":"Error de dependencia"},{"backendCode":"VDE01","httpCode":400,"statusCode":"VDE01","description":"VDE01 - Error en dato de entrada obligatorio: %s"},{"backendCode":"VDE02","httpCode":400,"statusCode":"VDE02","description":"VDE02 - Error en valor permitido para campo: %s"},{"backendCode":"VRN04","httpCode":"503","statusCode":"VRN04","description":"Servicio en horario de mantenimiento","status":"error"},{"backendCode":"204","httpCode":"200","statusCode":"200","description":"Cliente sin productos","status":"ok"}]' rest-client: - bus-legal-customer-product-directory: '{"url":"http://localhost:8082/bus-legal-customer-product-directory/retrieve/{customerIbsNumber}/{appId}/{customerReferenceFintechId}","timeout":{"connect":20000,"response":20000},"config":{}}' \ No newline at end of file + bus-legal-customer-product-directory: '{"url":"http://localhost:8082/bus-legal-customer-product-directory/retrieve/{customerIbsNumber}","timeout":{"connect":15000,"response":15000},"config":{}}' \ No newline at end of file