Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package fr.parisnanterre.greentrip.backend.controller;

import fr.parisnanterre.greentrip.backend.entity.Hotel;
import fr.parisnanterre.greentrip.backend.entity.HotelReview;
import fr.parisnanterre.greentrip.backend.service.HotelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/hotels")
@CrossOrigin(origins = "*")
public class HotelController {

@Autowired
private HotelService hotelService;

@GetMapping("/favorites/{userId}")
public ResponseEntity<List<Hotel>> getUserFavorites(@PathVariable Long userId) {
return ResponseEntity.ok(hotelService.getUserFavorites(userId));
}

@PostMapping("/favorites/{userId}/{hotelId}")
public ResponseEntity<Void> addToFavorites(
@PathVariable Long userId,
@PathVariable Long hotelId) {
hotelService.addToFavorites(userId, hotelId);
return ResponseEntity.ok().build();
}

@DeleteMapping("/favorites/{userId}/{hotelId}")
public ResponseEntity<Void> removeFromFavorites(
@PathVariable Long userId,
@PathVariable Long hotelId) {
hotelService.removeFromFavorites(userId, hotelId);
return ResponseEntity.ok().build();
}

@PostMapping("/{hotelId}/reviews")
public ResponseEntity<HotelReview> addReview(
@PathVariable Long hotelId,
@RequestBody HotelReview review) {
return ResponseEntity.ok(hotelService.addReview(hotelId, review));
}

@GetMapping("/{hotelId}/reviews")
public ResponseEntity<List<HotelReview>> getHotelReviews(@PathVariable Long hotelId) {
return ResponseEntity.ok(hotelService.getHotelReviews(hotelId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package fr.parisnanterre.greentrip.backend.entity;

import jakarta.persistence.*;
import lombok.Data;
import java.util.List;

@Entity
@Data
public class Hotel {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

// Référence à l'API externe
private String externalId;
private String externalSource; // ex: "booking", "hotels.com", etc.

// Informations de base
private String name;
private String city;
private String country;

// Relations
@ManyToMany(mappedBy = "favoriteHotels")
private List<User> favoritedBy;

@OneToMany(mappedBy = "hotel", cascade = CascadeType.ALL)
private List<HotelReview> reviews;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package fr.parisnanterre.greentrip.backend.entity;

import jakarta.persistence.*;
import lombok.Data;
import java.time.LocalDateTime;

@Entity
@Data
@Table(name = "hotel_review")
public class HotelReview {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "hotel_id", nullable = false)
private Hotel hotel;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;

@Column(nullable = false)
private String comment;

@Column(nullable = false)
private Integer ecoRating; // Note sur 10 pour l'aspect écologique

@Column(nullable = false)
private LocalDateTime createdAt;

@Column(nullable = false)
private LocalDateTime updatedAt;

@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now();
updatedAt = LocalDateTime.now();
}

@PreUpdate
protected void onUpdate() {
updatedAt = LocalDateTime.now();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

Expand All @@ -31,6 +32,14 @@ public class User implements UserDetails {
@Enumerated(EnumType.STRING)
private Role role;

@ManyToMany
@JoinTable(
name = "user_favorite_hotels",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "hotel_id")
)
private List<Hotel> favoriteHotels = new ArrayList<>();

public User(Long id, String firstName, String lastName, String email, String password, Role role) {
this.id = id;
this.firstName = firstName;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fr.parisnanterre.greentrip.backend.repository;

import fr.parisnanterre.greentrip.backend.entity.Hotel;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

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

@Repository
public interface HotelRepository extends JpaRepository<Hotel, Long> {

Optional<Hotel> findByExternalIdAndExternalSource(String externalId, String externalSource);

@Query("SELECT h FROM Hotel h JOIN h.favoritedBy u WHERE u.id = :userId")
List<Hotel> findFavoritesByUserId(@Param("userId") Long userId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package fr.parisnanterre.greentrip.backend.service;

import fr.parisnanterre.greentrip.backend.entity.Hotel;
import fr.parisnanterre.greentrip.backend.entity.HotelReview;
import fr.parisnanterre.greentrip.backend.entity.User;
import fr.parisnanterre.greentrip.backend.repository.HotelRepository;
import fr.parisnanterre.greentrip.backend.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class HotelService {

@Autowired
private HotelRepository hotelRepository;

@Autowired
private UserRepository userRepository;

public List<Hotel> getUserFavorites(Long userId) {
return hotelRepository.findFavoritesByUserId(userId);
}

public void addToFavorites(Long userId, Long hotelId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("User not found"));

Hotel hotel = hotelRepository.findById(hotelId)
.orElseThrow(() -> new RuntimeException("Hotel not found"));

if (user.getFavoriteHotels() == null) {
user.setFavoriteHotels(new ArrayList<>());
}

user.getFavoriteHotels().add(hotel);
userRepository.save(user);
}

public void removeFromFavorites(Long userId, Long hotelId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("User not found"));

Hotel hotel = hotelRepository.findById(hotelId)
.orElseThrow(() -> new RuntimeException("Hotel not found"));

if (user.getFavoriteHotels() != null) {
user.getFavoriteHotels().remove(hotel);
userRepository.save(user);
}
}

public HotelReview addReview(Long hotelId, HotelReview review) {
Hotel hotel = hotelRepository.findById(hotelId)
.orElseThrow(() -> new RuntimeException("Hotel not found"));

if (hotel.getReviews() == null) {
hotel.setReviews(new ArrayList<>());
}

review.setHotel(hotel);
hotel.getReviews().add(review);
hotelRepository.save(hotel);

return review;
}

public List<HotelReview> getHotelReviews(Long hotelId) {
Hotel hotel = hotelRepository.findById(hotelId)
.orElseThrow(() -> new RuntimeException("Hotel not found"));

return hotel.getReviews() != null ? hotel.getReviews() : new ArrayList<>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package fr.parisnanterre.greentrip.backend.controller;

import fr.parisnanterre.greentrip.backend.entity.Hotel;
import fr.parisnanterre.greentrip.backend.entity.HotelReview;
import fr.parisnanterre.greentrip.backend.service.HotelService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.http.ResponseEntity;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

class HotelControllerTest {

@Mock
private HotelService hotelService;

@InjectMocks
private HotelController hotelController;

private Hotel hotel;
private HotelReview review;
private List<Hotel> hotels;
private List<HotelReview> reviews;

@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);

// Création d'un hôtel de test
hotel = new Hotel();
hotel.setId(1L);
hotel.setName("Test Hotel");
hotel.setCity("Paris");
hotel.setCountry("France");

// Création d'un avis de test
review = new HotelReview();
review.setId(1L);
review.setComment("Great hotel!");
review.setEcoRating(8);

// Création des listes de test
hotels = new ArrayList<>();
hotels.add(hotel);

reviews = new ArrayList<>();
reviews.add(review);
}

@Test
void getUserFavorites_ShouldReturnFavorites() {
// Arrange
when(hotelService.getUserFavorites(1L)).thenReturn(hotels);

// Act
ResponseEntity<List<Hotel>> response = hotelController.getUserFavorites(1L);

// Assert
assertEquals(200, response.getStatusCodeValue());
assertEquals(hotels, response.getBody());
verify(hotelService).getUserFavorites(1L);
}

@Test
void addToFavorites_ShouldAddHotelToFavorites() {
// Act
ResponseEntity<Void> response = hotelController.addToFavorites(1L, 1L);

// Assert
assertEquals(200, response.getStatusCodeValue());
verify(hotelService).addToFavorites(1L, 1L);
}

@Test
void removeFromFavorites_ShouldRemoveHotelFromFavorites() {
// Act
ResponseEntity<Void> response = hotelController.removeFromFavorites(1L, 1L);

// Assert
assertEquals(200, response.getStatusCodeValue());
verify(hotelService).removeFromFavorites(1L, 1L);
}

@Test
void addReview_ShouldAddReviewToHotel() {
// Arrange
when(hotelService.addReview(1L, review)).thenReturn(review);

// Act
ResponseEntity<HotelReview> response = hotelController.addReview(1L, review);

// Assert
assertEquals(200, response.getStatusCodeValue());
assertEquals(review, response.getBody());
verify(hotelService).addReview(1L, review);
}

@Test
void getHotelReviews_ShouldReturnReviews() {
// Arrange
when(hotelService.getHotelReviews(1L)).thenReturn(reviews);

// Act
ResponseEntity<List<HotelReview>> response = hotelController.getHotelReviews(1L);

// Assert
assertEquals(200, response.getStatusCodeValue());
assertEquals(reviews, response.getBody());
verify(hotelService).getHotelReviews(1L);
}
}
Loading
Loading