diff --git a/README.md b/README.md
index c72b2bb..c211769 100644
--- a/README.md
+++ b/README.md
@@ -183,3 +183,5 @@ For further questions or contributions, feel free to open an issue or submit a p
---
+(link jira)[https://bouananisfn.atlassian.net/jira/software/projects/PIG/boards/39]
+
diff --git a/pom.xml b/pom.xml
index cb74529..69caf20 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,35 +6,22 @@
org.springframework.boot
spring-boot-starter-parent
3.3.5
-
+
ma.yc
PigeonSkyRace
0.0.1-SNAPSHOT
PigeonSkyRace
saas project foodeals
-
-
-
-
-
-
-
-
-
-
-
-
-
21
1.2.4
21
21
-
1.6.2
+
org.springframework.boot
spring-boot-starter-data-mongodb
@@ -47,15 +34,6 @@
org.springframework.boot
spring-boot-starter-web
-
- org.springframework.modulith
- spring-modulith-starter-core
-
-
- org.springframework.modulith
- spring-modulith-starter-mongodb
-
-
org.springframework.boot
spring-boot-devtools
@@ -68,34 +46,36 @@
true
- org.projectlombok
- lombok
- true
+ org.springframework.boot
+ spring-boot-starter-test
+ test
org.springframework.boot
- spring-boot-starter-test
+ spring-boot-testcontainers
test
+
+
org.springframework.modulith
- spring-modulith-starter-test
- test
+ spring-modulith-starter-core
- org.springframework.boot
- spring-boot-testcontainers
- test
+ org.springframework.modulith
+ spring-modulith-starter-mongodb
- org.testcontainers
- junit-jupiter
+ org.springframework.modulith
+ spring-modulith-starter-test
test
+
+
- org.testcontainers
- mongodb
- test
+ org.projectlombok
+ lombok
+ true
org.mapstruct
@@ -107,6 +87,8 @@
spring-security-crypto
6.3.4
+
+
org.springdoc
springdoc-openapi-starter-webmvc-ui
@@ -128,6 +110,17 @@
1.76
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+ org.testcontainers
+ mongodb
+ test
+
@@ -140,7 +133,6 @@
-
@@ -155,7 +147,6 @@
-
org.apache.maven.plugins
maven-compiler-plugin
@@ -182,8 +173,6 @@
go-offline-maven-plugin
1.2.8
-
-
-
+
\ No newline at end of file
diff --git a/src/main/java/ma/yc/PigeonSkyRace/common/infrastructure/web/GlobalExceptionHandler.java b/src/main/java/ma/yc/PigeonSkyRace/common/infrastructure/web/GlobalExceptionHandler.java
index daa7eb9..9557ef6 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/common/infrastructure/web/GlobalExceptionHandler.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/common/infrastructure/web/GlobalExceptionHandler.java
@@ -1,5 +1,7 @@
package ma.yc.PigeonSkyRace.common.infrastructure.web;
+import ma.yc.PigeonSkyRace.common.domain.exception.NotFoundException;
+import ma.yc.PigeonSkyRace.competition.domain.Exception.FailedToRegister;
import ma.yc.PigeonSkyRace.piegon.domain.exception.InvalidLoftException;
import ma.yc.PigeonSkyRace.piegon.domain.exception.InvalidLoftIdFormatException;
import ma.yc.PigeonSkyRace.user.domain.exception.InvalidCredentialsException;
@@ -17,6 +19,13 @@
@RestControllerAdvice
public class GlobalExceptionHandler {
+
+ @ExceptionHandler(NotFoundException.class)
+ public ResponseEntityhandleNotFoundException(NotFoundException e) {
+ ErrorResponse errorResponse = new ErrorResponse(LocalDateTime.now(),HttpStatus.BAD_REQUEST.value(), "Not Found",e.getMessage() );
+ return new ResponseEntity(errorResponse, HttpStatus.BAD_REQUEST);
+ }
+
@ExceptionHandler(InvalidLoftIdFormatException.class)
public ResponseEntity handleInvalidLoftIdFormatException ( InvalidLoftIdFormatException ex ) {
return ResponseEntity
@@ -37,6 +46,7 @@ public ResponseEntity handleUserRegistrationException ( UserRegis
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
+
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleValidationExceptions ( MethodArgumentNotValidException ex ) {
@@ -56,6 +66,12 @@ public ResponseEntity handleInvalidCredentialsException ( Invalid
ErrorResponse error = new ErrorResponse(LocalDateTime.now(), HttpStatus.UNAUTHORIZED.value(), "Authentication Error", e.getMessage());
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(error);
}
+ @ExceptionHandler(FailedToRegister.class)
+ public ResponseEntity handleRegisterFailed ( FailedToRegister e ) {
+ ErrorResponse error = new ErrorResponse(LocalDateTime.now(), HttpStatus.UNAUTHORIZED.value(), "register Error", e.getMessage());
+ return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(error);
+ }
+
}
record ErrorResponse(LocalDateTime timestamp, int status, String error, String message) {
diff --git a/src/main/java/ma/yc/PigeonSkyRace/competition/application/dto/request/CompetitionRequestDto.java b/src/main/java/ma/yc/PigeonSkyRace/competition/application/dto/request/CompetitionRequestDto.java
index a47de21..0b55232 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/competition/application/dto/request/CompetitionRequestDto.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/competition/application/dto/request/CompetitionRequestDto.java
@@ -1,11 +1,12 @@
package ma.yc.PigeonSkyRace.competition.application.dto.request;
+import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import ma.yc.PigeonSkyRace.competition.domain.ValueObject.AdmissionPercentage;
-import ma.yc.PigeonSkyRace.competition.domain.ValueObject.Coordinate;
import ma.yc.PigeonSkyRace.competition.domain.ValueObject.SeasonId;
+import ma.yc.PigeonSkyRace.piegon.application.dto.request.CoordinateRequestDTO;
import java.time.LocalDateTime;
@@ -13,7 +14,10 @@ public record CompetitionRequestDto(
@NotBlank String name,
@NotBlank String description,
@Positive Integer maxPigeons,
- @NotNull Coordinate coordinate,
+ @Valid
+ @NotNull(message = "coordinate cannot be null" )
+ CoordinateRequestDTO coordinate,
+ @Valid
@NotNull AdmissionPercentage admissionPercentage,
@NotNull LocalDateTime dateStart,
@NotNull LocalDateTime dateEnd,
diff --git a/src/main/java/ma/yc/PigeonSkyRace/competition/application/service/CompetitionPigeonApplicationService.java b/src/main/java/ma/yc/PigeonSkyRace/competition/application/service/CompetitionPigeonApplicationService.java
index a093c43..f908426 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/competition/application/service/CompetitionPigeonApplicationService.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/competition/application/service/CompetitionPigeonApplicationService.java
@@ -6,10 +6,12 @@
import ma.yc.PigeonSkyRace.competition.domain.entity.SeasonPigeon;
import javax.swing.text.html.Option;
+import java.util.List;
import java.util.Optional;
public interface CompetitionPigeonApplicationService {
CompetitionPigeon findBySeasonPigeonAndCompetition(SeasonPigeon seasonPigeon, Competition competition);
CompetitionPigeon findById(CompetitionPigeonId id);
+ List findByCompetition(Competition competition);
}
diff --git a/src/main/java/ma/yc/PigeonSkyRace/competition/domain/ValueObject/Coordinate.java b/src/main/java/ma/yc/PigeonSkyRace/competition/domain/ValueObject/Coordinate.java
index ee6e44e..e4f9945 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/competition/domain/ValueObject/Coordinate.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/competition/domain/ValueObject/Coordinate.java
@@ -3,7 +3,9 @@
import jakarta.validation.constraints.NotNull;
-public record Coordinate( Double latitude, Double longitude) {
+import java.io.Serializable;
+
+public record Coordinate(@NotNull Double latitude, @NotNull Double longitude) implements Serializable {
public Coordinate {
if (latitude < -90 || latitude > 90) {
throw new IllegalArgumentException("Latitude must be between -90 and 90 degrees.");
diff --git a/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/CompetitionPigeonDomainService.java b/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/CompetitionPigeonDomainService.java
index 1bfc5c6..6e8449f 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/CompetitionPigeonDomainService.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/CompetitionPigeonDomainService.java
@@ -77,4 +77,8 @@ public CompetitionPigeon findById(CompetitionPigeonId id){
return repository.findById(id).orElseThrow(() -> new NotFoundException("competitionPigeon", id));
}
+ @Override
+ public List findByCompetition(Competition competition) {
+ return repository.findByCompetition(competition);
+ }
}
diff --git a/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/CompetitionServiceImpl.java b/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/CompetitionServiceImpl.java
index d7466a8..17a4dc3 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/CompetitionServiceImpl.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/CompetitionServiceImpl.java
@@ -15,12 +15,14 @@
import static ma.yc.PigeonSkyRace.common.application.service.Helper.calculateDistance;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
@Service
+@Validated
@RequiredArgsConstructor
public class CompetitionServiceImpl implements CompetitionService, CompetitionApplicationService {
diff --git a/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/SeasonPigeonDomainService.java b/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/SeasonPigeonDomainService.java
index 3d3249f..6e8466c 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/SeasonPigeonDomainService.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/competition/domain/service/Impl/SeasonPigeonDomainService.java
@@ -29,6 +29,9 @@ public SeasonPigeonResponseDto RegisterToSeason(SeasonPigeonRequestDto seasonPig
).ifPresent(existing -> {
throw new FailedToRegister("This pigeon is already registered in the season.");
});
+ if(!seasonPigeonRequestDto.season().getIsActive()){
+ throw new FailedToRegister("This pigeon is not active.");
+ }
SeasonPigeon savedSeasonPigeon = repository.save(mapper.toEntity(seasonPigeonRequestDto));
diff --git a/src/main/java/ma/yc/PigeonSkyRace/competition/infrastructure/repository/CompetitionPigeonRepository.java b/src/main/java/ma/yc/PigeonSkyRace/competition/infrastructure/repository/CompetitionPigeonRepository.java
index ac6020f..5d9a2e2 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/competition/infrastructure/repository/CompetitionPigeonRepository.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/competition/infrastructure/repository/CompetitionPigeonRepository.java
@@ -4,6 +4,7 @@
import ma.yc.PigeonSkyRace.competition.domain.entity.Competition;
import ma.yc.PigeonSkyRace.competition.domain.entity.CompetitionPigeon;
+import ma.yc.PigeonSkyRace.competition.domain.entity.Season;
import ma.yc.PigeonSkyRace.competition.domain.entity.SeasonPigeon;
import ma.yc.PigeonSkyRace.piegon.domain.model.aggregate.Pigeon;
import org.springframework.data.mongodb.repository.MongoRepository;
diff --git a/src/main/java/ma/yc/PigeonSkyRace/piegon/application/dto/request/LoftRequestDTO.java b/src/main/java/ma/yc/PigeonSkyRace/piegon/application/dto/request/LoftRequestDTO.java
index a7e42ae..150486f 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/piegon/application/dto/request/LoftRequestDTO.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/piegon/application/dto/request/LoftRequestDTO.java
@@ -11,5 +11,6 @@ public record LoftRequestDTO(
CoordinateRequestDTO coordinate,
@EntityExists(entity = User.class, message = "The specified breeder does not exist")
- @NotNull String userId) {
+ @NotNull
+ String userId) {
}
\ No newline at end of file
diff --git a/src/main/java/ma/yc/PigeonSkyRace/result/api/ResultController.java b/src/main/java/ma/yc/PigeonSkyRace/result/api/ResultController.java
index 7179882..547abd0 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/result/api/ResultController.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/result/api/ResultController.java
@@ -30,28 +30,37 @@ public class ResultController {
@PostMapping("/{competitionId}")
- public ResponseEntity> createResult ( @PathVariable String competitionId, @RequestBody ResultRequestDto resultRequestDto ) {
+ public ResponseEntity> createResult(
+ @PathVariable String competitionId,
+ @RequestBody ResultRequestDto resultRequestDto) {
CompetitionResponseDto competitionResponseDto = competitionApplicationService.getCompetition(CompetitionId.fromString(competitionId));
- ResultResponseDto responseDto = resultService.createResult(resultRequestDto, competitionResponseDto);
+ ResultResponseDto responseDto = resultService.createResult(resultRequestDto, competitionResponseDto);
- ResponseApi response = new ResponseApi<>(responseDto, "The information stored with success for competition ", HttpStatus.CREATED);
+ ResponseApi response = new ResponseApi<>(
+ responseDto,
+ "The information stored with success for competition ",
+ HttpStatus.CREATED
+ );
return new ResponseEntity<>(response, HttpStatus.CREATED);
}
- @GetMapping("/{id}")
- public ResponseEntity> getResult ( @PathVariable String id ) {
- List resultsResponseDto = resultService.calculatePoint(CompetitionPigeonId.fromString(id));
+ @GetMapping("/{competitionId}")
+ public ResponseEntity> getResult(@PathVariable String competitionId){
+ CompetitionResponseDto competitionResponseDto = competitionApplicationService.getCompetition(CompetitionId.fromString(competitionId));
+ List resultsResponseDto = resultService.calculatePoint(competitionResponseDto);
return new ResponseEntity<>(resultsResponseDto, HttpStatus.CREATED);
}
- @GetMapping("/{id}/pdf")
- public ResponseEntity downloadResultPdf ( @PathVariable String id ) {
+ @GetMapping("/{competitionId}/pdf")
+ public ResponseEntity downloadResultPdf ( @PathVariable String competitionId ) {
try {
- List results = resultService.calculatePoint(CompetitionPigeonId.fromString(id));
+ CompetitionResponseDto competitionResponseDto = competitionApplicationService.getCompetition(CompetitionId.fromString(competitionId));
+
+ List results = resultService.calculatePoint(competitionResponseDto);
byte[] pdfBytes = pdfGenerationService.generateResultsPdf(results);
diff --git a/src/main/java/ma/yc/PigeonSkyRace/result/application/mapping/ResultMapper.java b/src/main/java/ma/yc/PigeonSkyRace/result/application/mapping/ResultMapper.java
index c9bf36d..5e3ea24 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/result/application/mapping/ResultMapper.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/result/application/mapping/ResultMapper.java
@@ -19,6 +19,7 @@ public abstract class ResultMapper {
@Mapping(target = "bandNumber", expression = "java(result.getCompetitionPigeon().getSeasonPigeon().getPigeon().getBandNumber())")
@Mapping(target = "loft", expression = "java(getLoftName(result.getCompetitionPigeon().getSeasonPigeon().getPigeon().getLoft()))")
+ @Mapping(target = "createdDate", expression = "java(java.time.LocalDateTime.now())")
public abstract ResultResponseDto toDto(Result result);
protected String getLoftName(LoftId loftId) {
diff --git a/src/main/java/ma/yc/PigeonSkyRace/result/domain/service/ResultService.java b/src/main/java/ma/yc/PigeonSkyRace/result/domain/service/ResultService.java
index 9078763..6e78e46 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/result/domain/service/ResultService.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/result/domain/service/ResultService.java
@@ -12,5 +12,5 @@
public interface ResultService {
ResultResponseDto createResult(ResultRequestDto requestDto, CompetitionResponseDto competition);
- List calculatePoint(CompetitionPigeonId id);
+ List calculatePoint(CompetitionResponseDto competition);
}
diff --git a/src/main/java/ma/yc/PigeonSkyRace/result/domain/service/impl/ResultDomainService.java b/src/main/java/ma/yc/PigeonSkyRace/result/domain/service/impl/ResultDomainService.java
index 7939dda..7d61a44 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/result/domain/service/impl/ResultDomainService.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/result/domain/service/impl/ResultDomainService.java
@@ -10,6 +10,7 @@
import ma.yc.PigeonSkyRace.competition.domain.ValueObject.CompetitionId;
import ma.yc.PigeonSkyRace.competition.domain.ValueObject.CompetitionPigeonId;
import ma.yc.PigeonSkyRace.competition.domain.ValueObject.Coordinate;
+import ma.yc.PigeonSkyRace.competition.domain.entity.Competition;
import ma.yc.PigeonSkyRace.competition.domain.entity.CompetitionPigeon;
import ma.yc.PigeonSkyRace.competition.domain.entity.SeasonPigeon;
import ma.yc.PigeonSkyRace.piegon.application.service.LoftApplicationService;
@@ -24,6 +25,7 @@
import org.springframework.stereotype.Service;
import java.time.Duration;
+import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -66,20 +68,21 @@ private double calculateSpeed(double distance, Duration flightTime) {
@Override
- public List calculatePoint(CompetitionPigeonId id) {
- List results = repository.findAllByCompetitionPigeonOrderBySpeed(competitionPigeonApplicationService.findById(id));
- results.getFirst().setPoints(100.0);
-
- for (int i = 1; i < results.size(); i++) {
- Double point = 100.0 - (i * 100.0 / results.get(i).getCompetitionPigeon().getCompetition().getMaxPigeons());
- results.get(i).setPoints(point);
- repository.save(results.get(i));
+ public List calculatePoint(CompetitionResponseDto competition) {
+ List competitionPigeon = competitionPigeonApplicationService.findByCompetition(competitionMapper.toEntity(competition));
+ List results = new ArrayList<>();
+ for (CompetitionPigeon cp : competitionPigeon) {
+ results.add(repository.findByCompetitionPigeon(cp));
}
- return results.stream()
- .map(mapper::toDto)
- .sorted((curr, next) -> Double.compare(next.points(), curr.points()))
- .collect(Collectors.toList());
+ List sortedResults = results.stream().sorted((curr, next) -> Double.compare(next.getSpeed(), curr.getSpeed())).toList();
+ sortedResults.getFirst().setPoints(100.0);
+ for (int i = 1; i < sortedResults.size(); i++) {
+ Double point = 100.0 - (i * 100.0 / sortedResults.get(i).getCompetitionPigeon().getCompetition().getMaxPigeons());
+ sortedResults.get(i).setPoints(point);
+ repository.save(sortedResults.get(i));
+ }
+ return sortedResults.stream().map(mapper::toDto).sorted((curr, next) -> Double.compare(next.points(), curr.points())).toList();
}
diff --git a/src/main/java/ma/yc/PigeonSkyRace/result/infrastructure/repository/ResultRepository.java b/src/main/java/ma/yc/PigeonSkyRace/result/infrastructure/repository/ResultRepository.java
index 7d4e74b..9b6d033 100644
--- a/src/main/java/ma/yc/PigeonSkyRace/result/infrastructure/repository/ResultRepository.java
+++ b/src/main/java/ma/yc/PigeonSkyRace/result/infrastructure/repository/ResultRepository.java
@@ -8,6 +8,6 @@
import java.util.List;
public interface ResultRepository extends MongoRepository {
- List findAllByCompetitionPigeonOrderBySpeed ( CompetitionPigeon competitionPigeon );
+ Result findByCompetitionPigeon(CompetitionPigeon competitionPigeon);
}
diff --git a/src/test/java/ma/yc/PigeonSkyRace/serviceTest/CompetitionServiceImplTest.java b/src/test/java/ma/yc/PigeonSkyRace/serviceTest/CompetitionServiceImplTest.java
index b9b7c80..2ea5197 100644
--- a/src/test/java/ma/yc/PigeonSkyRace/serviceTest/CompetitionServiceImplTest.java
+++ b/src/test/java/ma/yc/PigeonSkyRace/serviceTest/CompetitionServiceImplTest.java
@@ -12,6 +12,7 @@
import ma.yc.PigeonSkyRace.competition.domain.entity.Competition;
import ma.yc.PigeonSkyRace.competition.infrastructure.repository.CompetitionRepository;
import ma.yc.PigeonSkyRace.competition.domain.service.Impl.CompetitionServiceImpl;
+import ma.yc.PigeonSkyRace.piegon.application.dto.request.CoordinateRequestDTO;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
@@ -56,7 +57,7 @@ void setUp() {
competition.setCoordinate(new Coordinate(34.05, -118.25));
SeasonId seasonId = new SeasonId();
AdmissionPercentage num = new AdmissionPercentage(12.3);
- competitionRequestDto = new CompetitionRequestDto("Spring Competition", "A fun competition", 100,new Coordinate(32.2949,-8.1755), num, LocalDateTime.now(), LocalDateTime.now(), seasonId);
+ competitionRequestDto = new CompetitionRequestDto("Spring Competition", "A fun competition", 100,new CoordinateRequestDTO(32.2949,-8.1755), num, LocalDateTime.now(), LocalDateTime.now(), seasonId);
coordinate = new Coordinate(35.68, 139.69);
competitionResponseDto = new CompetitionResponseDto(competitionId, "Spring Competition", "A fun competition", coordinate, 100,100.0, num,seasonId, LocalDateTime.now(), LocalDateTime.now(), null);
}
diff --git a/src/test/java/ma/yc/PigeonSkyRace/serviceTest/ResultDomainServiceTest.java b/src/test/java/ma/yc/PigeonSkyRace/serviceTest/ResultDomainServiceTest.java
new file mode 100644
index 0000000..0f6f015
--- /dev/null
+++ b/src/test/java/ma/yc/PigeonSkyRace/serviceTest/ResultDomainServiceTest.java
@@ -0,0 +1,138 @@
+package ma.yc.PigeonSkyRace.serviceTest;
+
+import ma.yc.PigeonSkyRace.competition.application.dto.response.CompetitionResponseDto;
+import ma.yc.PigeonSkyRace.competition.application.mapping.CompetitionMapper;
+import ma.yc.PigeonSkyRace.competition.application.service.CompetitionPigeonApplicationService;
+import ma.yc.PigeonSkyRace.competition.application.service.SeasonApplicationService;
+import ma.yc.PigeonSkyRace.competition.application.service.SeasonPigeonApplicationService;
+import ma.yc.PigeonSkyRace.competition.domain.ValueObject.AdmissionPercentage;
+import ma.yc.PigeonSkyRace.competition.domain.ValueObject.Coordinate;
+import ma.yc.PigeonSkyRace.competition.domain.ValueObject.SeasonId;
+import ma.yc.PigeonSkyRace.competition.domain.entity.CompetitionPigeon;
+import ma.yc.PigeonSkyRace.competition.domain.entity.SeasonPigeon;
+import ma.yc.PigeonSkyRace.piegon.application.service.LoftApplicationService;
+import ma.yc.PigeonSkyRace.piegon.application.service.PigeonApplicationService;
+import ma.yc.PigeonSkyRace.piegon.domain.model.aggregate.Pigeon;
+import ma.yc.PigeonSkyRace.piegon.domain.model.valueObject.BandNumber;
+import ma.yc.PigeonSkyRace.result.application.dto.request.ResultRequestDto;
+import ma.yc.PigeonSkyRace.result.application.dto.response.ResultResponseDto;
+import ma.yc.PigeonSkyRace.result.application.mapping.ResultMapper;
+import ma.yc.PigeonSkyRace.result.domain.entity.Result;
+import ma.yc.PigeonSkyRace.result.domain.service.impl.ResultDomainService;
+import ma.yc.PigeonSkyRace.result.domain.valueObject.ResultId;
+import ma.yc.PigeonSkyRace.result.infrastructure.repository.ResultRepository;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+@DisplayName("Result Domain Service Test")
+public class ResultDomainServiceTest {
+
+ @Mock
+ private ResultRepository resultRepository;
+ @Mock
+ private PigeonApplicationService pigeonApplicationService;
+ @Mock
+ private ResultMapper resultMapper;
+ @Mock
+ private SeasonPigeonApplicationService seasonPigeonApplicationService;
+ @Mock
+ private SeasonApplicationService seasonApplicationService;
+ @Mock
+ private CompetitionPigeonApplicationService competitionPigeonApplicationService;
+ @Mock
+ private LoftApplicationService loftApplicationService;
+ @Mock
+ private CompetitionMapper competitionMapper;
+
+ @InjectMocks
+ private ResultDomainService resultService;
+
+ @Nested
+ @DisplayName("createResult() method tests")
+ class CreateResult {
+
+ @Test
+ @DisplayName("should create and return result successfully")
+ void shouldCreateResult() {
+ ResultRequestDto request = new ResultRequestDto(
+ new BandNumber("AU 2023 XYZ 3234534"),
+ LocalDateTime.now()
+ );
+
+ CompetitionResponseDto competition = new CompetitionResponseDto(
+ null, "Race1", "Description", new Coordinate(1.21332, 2.11232),
+ 100, 500.0, new AdmissionPercentage(12.2), new SeasonId(),
+ LocalDateTime.now(), LocalDateTime.now().plusHours(1), LocalDateTime.now()
+ );
+
+ Result result = new Result();
+ ResultResponseDto response = new ResultResponseDto(
+ new ResultId(), 500.0, 1200.0, 100.0,
+ new BandNumber("AU 2021 XYZ 3234534"),
+ "Loft A", LocalDateTime.now(), LocalDateTime.now().plusHours(2)
+ );
+
+ when(pigeonApplicationService.findPigeonByBandNumber(request.bandNumber()))
+ .thenReturn(mock(Pigeon.class));
+ when(seasonPigeonApplicationService.findSeasonPigeonPigeonAndSeason(any(), any()))
+ .thenReturn(mock(SeasonPigeon.class));
+ when(competitionPigeonApplicationService.findBySeasonPigeonAndCompetition(any(), any()))
+ .thenReturn(mock(CompetitionPigeon.class));
+ when(resultMapper.toEntity(request)).thenReturn(result);
+ when(loftApplicationService.geLoftCoordinate(any())).thenReturn(mock(Coordinate.class));
+ when(resultMapper.toDto(any(Result.class))).thenReturn(response);
+ when(resultRepository.save(any(Result.class))).thenReturn(result);
+
+ ResultResponseDto resultResponse = resultService.createResult(request, competition);
+
+ assertNotNull(resultResponse);
+ assertEquals(response.distance(), resultResponse.distance());
+ verify(resultRepository).save(any(Result.class));
+ }
+ }
+
+ @Nested
+ @DisplayName("calculatePoint() method tests")
+ class CalculatePoint {
+
+ @Test
+ @DisplayName("should calculate and assign points successfully")
+ void shouldCalculatePoints() {
+ CompetitionResponseDto competition = new CompetitionResponseDto(
+ null, "Race1", "Description", null,
+ 100, 500.0, null, null,
+ LocalDateTime.now(), LocalDateTime.now().plusHours(1), LocalDateTime.now()
+ );
+
+ CompetitionPigeon cp1 = mock(CompetitionPigeon.class);
+ CompetitionPigeon cp2 = mock(CompetitionPigeon.class);
+ Result result1 = new Result();
+ Result result2 = new Result();
+
+ result1.setSpeed(1200.0);
+ result2.setSpeed(1100.0);
+
+ when(competitionPigeonApplicationService.findByCompetition(any()))
+ .thenReturn(List.of(cp1, cp2));
+ when(resultRepository.findByCompetitionPigeon(cp1)).thenReturn(result1);
+ when(resultRepository.findByCompetitionPigeon(cp2)).thenReturn(result2);
+
+ List results = resultService.calculatePoint(competition);
+
+ assertEquals(2, results.size());
+ verify(resultRepository, times(2)).save(any(Result.class));
+ }
+ }
+}