diff --git a/pom.xml b/pom.xml
index 20b332e..78a069d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,6 +62,10 @@
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
org.springframework.cloud
spring-cloud-starter-bootstrap
diff --git a/src/main/java/com/classes/MsvcClassesApplication.java b/src/main/java/com/classes/MsvcClassesApplication.java
index fd1f000..cef39cd 100644
--- a/src/main/java/com/classes/MsvcClassesApplication.java
+++ b/src/main/java/com/classes/MsvcClassesApplication.java
@@ -2,8 +2,10 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
+@EnableFeignClients
public class MsvcClassesApplication {
public static void main(String[] args) {
diff --git a/src/main/java/com/classes/config/RestTemplateConfig.java b/src/main/java/com/classes/config/RestTemplateConfig.java
deleted file mode 100644
index a376e58..0000000
--- a/src/main/java/com/classes/config/RestTemplateConfig.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.classes.config;
-
-import org.springframework.cloud.client.loadbalancer.LoadBalanced;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.client.RestTemplate;
-
-@Configuration
-public class RestTemplateConfig {
-
- @Bean
- @LoadBalanced
- public RestTemplate restTemplate() {
- return new RestTemplate();
- }
-}
diff --git a/src/main/java/com/classes/dtos/external/MemberInfoDTO.java b/src/main/java/com/classes/dtos/external/MemberInfoDTO.java
index 32fbed5..80eec96 100644
--- a/src/main/java/com/classes/dtos/external/MemberInfoDTO.java
+++ b/src/main/java/com/classes/dtos/external/MemberInfoDTO.java
@@ -1,5 +1,6 @@
package com.classes.dtos.external;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -10,17 +11,28 @@
/**
* DTO para recibir información del microservicio de Members
+ * Mapea la respuesta de msvc-members con los nombres correctos de campos
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class MemberInfoDTO {
+ @JsonProperty("userId") // msvc-members usa "userId"
private UUID id;
+
private String firstName;
private String lastName;
private String email;
+ private String dni;
+ private String phone;
+ private String initials;
+ private String profileImageUrl;
+
private String status; // "ACTIVO", "INACTIVO", "SUSPENDIDO"
- private String membershipType; // "MENSUAL", "ANUAL", "PREMIUM"
+
+ @JsonProperty("membership") // msvc-members usa "membership"
+ private MembershipDTO membershipType;
+
private LocalDateTime lastAccess;
}
diff --git a/src/main/java/com/classes/entities/TrainerEntity.java b/src/main/java/com/classes/entities/TrainerEntity.java
index af4dcd9..e2c8d00 100644
--- a/src/main/java/com/classes/entities/TrainerEntity.java
+++ b/src/main/java/com/classes/entities/TrainerEntity.java
@@ -24,8 +24,7 @@
@EntityListeners(AuditListener.class)
public class TrainerEntity {
@Id
- @GeneratedValue(strategy = GenerationType.UUID)
- private UUID id;
+ private UUID id; // ID del usuario desde msvc-security (no se genera automáticamente)
private String firstName;
private String lastName;
private String dni;
diff --git a/src/main/java/com/classes/services/Impl/ClassStatsServiceImpl.java b/src/main/java/com/classes/services/Impl/ClassStatsServiceImpl.java
index dcccf39..7aa2ab2 100644
--- a/src/main/java/com/classes/services/Impl/ClassStatsServiceImpl.java
+++ b/src/main/java/com/classes/services/Impl/ClassStatsServiceImpl.java
@@ -64,7 +64,15 @@ public ClassDetailResponse getClassDetail(UUID classId) {
.map(ClassReservation::getMemberId)
.distinct()
.collect(Collectors.toList());
+
+ log.info("📋 Consultando información de {} miembros: {}", memberIds.size(), memberIds);
List membersInfo = memberClientService.getMembersInfo(memberIds);
+ log.info("📊 Información obtenida de {} miembros", membersInfo.size());
+
+ if (membersInfo.isEmpty() && !memberIds.isEmpty()) {
+ log.warn("⚠️ No se pudo obtener información de ningún miembro. Usando datos por defecto.");
+ }
+
List students = reservations.stream()
.map(reservation -> buildStudentDTO(reservation, membersInfo))
.collect(Collectors.toList());
@@ -115,14 +123,20 @@ private StudentInClassDTO buildStudentDTO(ClassReservation reservation, List reservations = reservationRepository.findByMemberId(memberId);
+ List reservations = reservationRepository.findByMemberId(memberId);
List activeReservations = reservations.stream()
.filter(r -> r.getStatus() == ReservationStatus.RESERVADO || Boolean.TRUE.equals(r.getAttended()))
.toList();
-
LocalDateTime now = LocalDateTime.now();
-
boolean inClass = activeReservations.stream()
.anyMatch(r -> {
LocalDateTime start = LocalDateTime.of(LocalDate.now(), r.getClassEntity().getStartTime());
@@ -38,7 +36,6 @@ public MemberDashboardDTO getDashboardForMember(UUID memberId) {
return !now.isBefore(start) && !now.isAfter(end)
&& r.getStatus() == ReservationStatus.RESERVADO;
});
-
Optional nextClassOpt = activeReservations.stream()
.filter(r -> {
LocalDateTime start = LocalDateTime.of(LocalDate.now(), r.getClassEntity().getStartTime());
@@ -46,19 +43,14 @@ public MemberDashboardDTO getDashboardForMember(UUID memberId) {
})
.sorted(Comparator.comparing(r -> r.getClassEntity().getStartTime()))
.findFirst();
-
int totalReserved = (int) activeReservations.stream()
- .filter(r -> r.getStatus() == ReservationStatus.RESERVADO)
- .count();
-
+ .filter(r -> r.getStatus() == ReservationStatus.RESERVADO).count();
int attended = (int) activeReservations.stream()
.filter(r -> Boolean.TRUE.equals(r.getAttended()))
.count();
-
int remaining = Math.max(totalReserved - attended, 0);
int consecutiveDays = calcularDiasConsecutivos(activeReservations);
List weeklyActivity = calcularActividadSemanal(activeReservations);
-
List upcoming = activeReservations.stream()
.filter(r -> {
LocalDateTime start = LocalDateTime.of(LocalDate.now(), r.getClassEntity().getStartTime());
@@ -75,7 +67,6 @@ public MemberDashboardDTO getDashboardForMember(UUID memberId) {
.location(r.getClassEntity().getLocation().getName())
.build())
.toList();
-
return MemberDashboardDTO.builder()
.inClass(inClass)
.remainingClasses(remaining)
diff --git a/src/main/java/com/classes/services/Impl/MemberClientServiceImpl.java b/src/main/java/com/classes/services/Impl/MemberClientServiceImpl.java
index 22cd230..fb3b2e6 100644
--- a/src/main/java/com/classes/services/Impl/MemberClientServiceImpl.java
+++ b/src/main/java/com/classes/services/Impl/MemberClientServiceImpl.java
@@ -1,15 +1,12 @@
package com.classes.services.Impl;
+import com.classes.clients.MemberFeignClient;
import com.classes.dtos.external.MemberInfoDTO;
import com.classes.services.MemberClientService;
+import feign.FeignException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.core.ParameterizedTypeReference;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
-import org.springframework.web.client.HttpClientErrorException;
-import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
@@ -20,28 +17,26 @@
@Slf4j
public class MemberClientServiceImpl implements MemberClientService {
- private final RestTemplate restTemplate;
- private static final String MEMBERS_SERVICE_URL = "http://msvc-members";
+ private final MemberFeignClient memberFeignClient;
@Override
public MemberInfoDTO getMemberInfo(UUID memberId) {
try {
- String url = MEMBERS_SERVICE_URL + "/members/" + memberId;
- log.debug("🔗 Llamando al microservicio de members: {}", url);
-
- ResponseEntity response = restTemplate.exchange(
- url,
- HttpMethod.GET,
- null,
- MemberInfoDTO.class
- );
- return response.getBody();
- } catch (HttpClientErrorException.NotFound e) {
- log.warn("❌ Miembro {} no encontrado en el microservicio de members", memberId);
+ log.info("🔗 Consultando información del miembro {} usando Feign", memberId);
+ MemberInfoDTO result = memberFeignClient.getMemberInfo(memberId);
+ log.info("✅ Información recibida: {} {}", result.getFirstName(), result.getLastName());
+ return result;
+ } catch (FeignException.NotFound e) {
+ log.error("❌ Miembro {} no encontrado en msvc-members (404)", memberId);
+ return null;
+ } catch (FeignException e) {
+ log.error("❌ Error Feign al consultar miembro {}: {} - {}",
+ memberId, e.status(), e.getMessage());
+ log.error("❌ Response body: {}", e.contentUTF8());
return null;
} catch (Exception e) {
- log.error("❌ Error al consultar el microservicio de members para el miembro {}: {}",
- memberId, e.getMessage());
+ log.error("❌ Error inesperado al consultar miembro {}: {}",
+ memberId, e.getMessage(), e);
return null;
}
}
diff --git a/src/main/resources/bootstrap.yml b/src/main/resources/bootstrap.yml
index 3381ebb..5746442 100644
--- a/src/main/resources/bootstrap.yml
+++ b/src/main/resources/bootstrap.yml
@@ -9,4 +9,10 @@ spring:
servlet:
multipart:
max-file-size: 10MB
- max-request-size: 20MB
\ No newline at end of file
+ max-request-size: 20MB
+
+# Logging para debuggear Feign
+logging:
+ level:
+ com.classes.clients: DEBUG
+ feign: DEBUG
\ No newline at end of file