Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -652,13 +652,13 @@ components:
gender:
name: gender
in: query
description: preferred gender of the dancers
description: required preferred gender of the dancers
schema:
type: string
range:
name: range
in: query
description: Range [km] in which the search for dancers should be done
description: Range [km] in which the search for dancers should be done, defaults to 20 km
schema:
type: string
schemas:
Expand Down
15 changes: 0 additions & 15 deletions src/main/java/net/dancier/dancer/core/DancerRepository.java

This file was deleted.

39 changes: 0 additions & 39 deletions src/main/java/net/dancier/dancer/core/DancerService.java

This file was deleted.

1 change: 1 addition & 0 deletions src/main/java/net/dancier/dancer/core/ProfileService.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import net.dancier.dancer.core.model.DanceProfile;
import net.dancier.dancer.core.model.Dancer;
import net.dancier.dancer.core.util.ModelMapper;
import net.dancier.dancer.dancers.DancerRepository;
import net.dancier.dancer.location.ZipCode;
import net.dancier.dancer.location.ZipCodeRepository;
import org.slf4j.Logger;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package net.dancier.dancer.chat;
package net.dancier.dancer.dancers;

import lombok.RequiredArgsConstructor;
import net.dancier.dancer.chat.dto.DancerDto;
import net.dancier.dancer.chat.dto.DancerIdsDto;
import net.dancier.dancer.core.DancerService;
import net.dancier.dancer.core.dto.PublicProfileDto;
import net.dancier.dancer.core.model.Gender;
import net.dancier.dancer.security.AuthenticatedUser;
import net.dancier.dancer.security.CurrentUser;
import org.slf4j.Logger;
Expand All @@ -12,8 +13,7 @@
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.UUID;
import java.util.*;

import static net.dancier.dancer.authentication.Constants.ROLE_USER;

Expand All @@ -25,6 +25,17 @@ public class DancerController {

private final DancerService dancerService;

@GetMapping("")
@Secured(ROLE_USER)
public ResponseEntity<List<PublicProfileDto>> get(
@CurrentUser AuthenticatedUser authenticatedUser,
@RequestParam Gender gender,
@RequestParam(defaultValue = "20") int range
) {
log.info("Fetching list of dancers in {} km range with gender {} for user {}", range, gender, authenticatedUser.getUserId());
return ResponseEntity.ok(dancerService.getDancerList(authenticatedUser, gender, range));
}

@PostMapping("")
@Secured(ROLE_USER)
public ResponseEntity<HashMap<UUID, DancerDto>> post(
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/net/dancier/dancer/dancers/DancerRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package net.dancier.dancer.dancers;

import net.dancier.dancer.core.model.Dancer;
import net.dancier.dancer.core.model.Gender;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

public interface DancerRepository extends JpaRepository<Dancer, UUID> {

Optional<Dancer> findByUserId(UUID userid);

Boolean existsByDancerName(String dancerName);

List<Dancer> findFirst500ByGenderAndLongitudeBetweenAndLatitudeBetween(
Gender gender,
double lowerLongitude,
double upperLongitude,
double lowerLatitude,
double upperLatitude
);

}
65 changes: 65 additions & 0 deletions src/main/java/net/dancier/dancer/dancers/DancerService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package net.dancier.dancer.dancers;

import net.dancier.dancer.chat.dto.DancerDto;
import net.dancier.dancer.chat.dto.DancerIdsDto;
import net.dancier.dancer.core.dto.PublicProfileDto;
import net.dancier.dancer.core.exception.NotFoundException;
import net.dancier.dancer.core.model.Dancer;
import net.dancier.dancer.core.model.Gender;
import net.dancier.dancer.security.AuthenticatedUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.UUID;

@Service
public class DancerService {

@Autowired
DancerRepository dancerRepository;

public Dancer loadByUserId(UUID userId) {
return dancerRepository.findByUserId(userId).orElseThrow(() -> new NotFoundException("No Profile found for given user."));
}

public List<Dancer> getAllDancer() {
return dancerRepository.findAll();
}

public HashMap<UUID, DancerDto> getDancerMap(DancerIdsDto dancerIdsDto) {

HashMap<UUID, DancerDto> dancers = new HashMap<>();

dancerRepository.findAllById(dancerIdsDto.getDancerIds())
.stream()
.map(DancerDto::fromDancer)
.forEach(dancerDto -> dancers.put(dancerDto.getId(), dancerDto));

return dancers;
}

public List<PublicProfileDto> getDancerList(AuthenticatedUser authenticatedUser, Gender gender, int range) {

Dancer dancer = loadByUserId(authenticatedUser.getUserId());

// 1° in longitude in Germany (latitude 47) are 75,78 km
double longitudeRange = range/75.78;
// 1° in longitude are 112,12 km
double latitudeRange = range/112.12;

double upperLatitude = dancer.getLatitude() + latitudeRange;
double lowerLatitude = dancer.getLatitude() - latitudeRange;
double upperLongitude = dancer.getLongitude() + longitudeRange;
double lowerLongitude = dancer.getLongitude() - longitudeRange;

List<Dancer> resultList = dancerRepository.findFirst500ByGenderAndLongitudeBetweenAndLatitudeBetween(
gender, lowerLongitude, upperLongitude, lowerLatitude, upperLatitude);

return resultList.stream()
.map(PublicProfileDto::of)
.filter(d -> d.getId() != dancer.getId())
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.dancier.dancer.recommendation;

import lombok.RequiredArgsConstructor;
import net.dancier.dancer.core.DancerRepository;
import net.dancier.dancer.dancers.DancerRepository;
import net.dancier.dancer.core.model.Dancer;
import net.dancier.dancer.recommendation.model.BaseRecommendation;
import net.dancier.dancer.recommendation.model.RecommendationWrapper;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import lombok.RequiredArgsConstructor;
import net.dancier.dancer.authentication.model.User;
import net.dancier.dancer.authentication.repository.UserRepository;
import net.dancier.dancer.core.DancerRepository;
import net.dancier.dancer.dancers.DancerRepository;
import net.dancier.dancer.core.model.Dancer;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,17 @@
import net.dancier.dancer.AbstractPostgreSQLEnabledTest;
import net.dancier.dancer.chat.client.ChatServiceClient;
import net.dancier.dancer.chat.dto.*;
import net.dancier.dancer.core.DancerRepository;
import net.dancier.dancer.dancers.DancerRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.test.context.support.WithUserDetails;
import org.springframework.test.web.servlet.ResultActions;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
Expand Down
69 changes: 69 additions & 0 deletions src/test/java/net/dancier/dancer/dancers/DancerControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package net.dancier.dancer.dancers;

import net.dancier.dancer.AbstractPostgreSQLEnabledTest;
import org.junit.jupiter.api.Test;
import org.springframework.security.test.context.support.WithUserDetails;
import org.springframework.test.context.jdbc.Sql;
import java.util.List;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.isA;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@Sql(value = {"/dancers/data.sql"})
public class DancerControllerTest extends AbstractPostgreSQLEnabledTest {

@Test
@WithUserDetails("user-with-a-profile@dancier.net")
void getDancersShouldReturnFilteredProfiles() throws Exception {

mockMvc
.perform(get("/dancers")
.param("range", "20")
.param("gender", "FEMALE")
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.*", isA(List.class)))
.andExpect(jsonPath("$.*", hasSize(1)))
.andExpect(jsonPath("$[0].id").value("503ffad4-148b-4af1-8365-62315ff89b9f"))
.andExpect(jsonPath("$[0].gender").value("FEMALE"))
.andExpect(jsonPath("$[0].dancerName").value("perfect_dancer"))
.andExpect(jsonPath("$[0].aboutMe").value("Hi"))
.andExpect(jsonPath("$[0].age").isNotEmpty())
.andExpect(jsonPath("$[0].size").value("178"))
.andExpect(jsonPath("$[0].city").value("Dortmund"))
.andExpect(jsonPath("$[0].country").value("GER"));

}

@Test
@WithUserDetails("user-with-a-profile@dancier.net")
void getDancersUsingDefaultRange() throws Exception {

mockMvc
.perform(get("/dancers")
.param("gender", "FEMALE")
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.*", isA(List.class)))
.andExpect(jsonPath("$.*", hasSize(1)))
.andExpect(jsonPath("$[0].id").value("503ffad4-148b-4af1-8365-62315ff89b9f"))
.andExpect(jsonPath("$[0].gender").value("FEMALE"))
.andExpect(jsonPath("$[0].dancerName").value("perfect_dancer"))
.andExpect(jsonPath("$[0].aboutMe").value("Hi"))
.andExpect(jsonPath("$[0].age").isNotEmpty())
.andExpect(jsonPath("$[0].size").value("178"))
.andExpect(jsonPath("$[0].city").value("Dortmund"))
.andExpect(jsonPath("$[0].country").value("GER"));

}

@Test
@WithUserDetails("user-with-a-profile@dancier.net")
void shouldFailIfGenderIsNotSet() throws Exception {
mockMvc .perform(get("/dancers")
.param("range", "20")
).andExpect(status().isBadRequest());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.dancier.dancer.recommendation;

import net.dancier.dancer.AbstractPostgreSQLEnabledTest;
import net.dancier.dancer.core.DancerRepository;
import net.dancier.dancer.dancers.DancerRepository;
import net.dancier.dancer.core.model.Dancer;
import net.dancier.dancer.recommendation.dto.RecommendationDto;
import org.junit.jupiter.api.BeforeEach;
Expand Down
Loading
Loading