diff --git a/requests.http b/requests.http index 7e78e46efff37a1bdc7147e29b6198566e22b12d..88e0fc53498af6a2dd287adb7b724f9f044220a1 100644 --- a/requests.http +++ b/requests.http @@ -25,3 +25,18 @@ content-type: application/json "email": "lukas.karsch@gmx.de", "password": "myPassword123" } + +### Get all plants from wishlist +GET http://localhost:8080/api/v1/wishlist + +### Get amount of plants in wishlist +GET http://localhost:8080/api/v1/wishlist/count + +### Add plant to wishlist +POST http://localhost:8080/api/v1/wishlist/add/1 + +### Remove plant from wishlist +DELETE http://localhost:8080/api/v1/wishlist/remove/1 + +### Remove all plants from wishlist +DELETE http://localhost:8080/api/v1/wishlist/remove/all \ No newline at end of file diff --git a/src/main/java/hdm/mi/growbros/controllers/WishListController.java b/src/main/java/hdm/mi/growbros/controllers/WishListController.java new file mode 100644 index 0000000000000000000000000000000000000000..54f406664c88b466a67f1b1936bfb821def8c055 --- /dev/null +++ b/src/main/java/hdm/mi/growbros/controllers/WishListController.java @@ -0,0 +1,53 @@ +package hdm.mi.growbros.controllers; + +import hdm.mi.growbros.models.plant.Plant; +import hdm.mi.growbros.models.user.User; +import hdm.mi.growbros.service.WishListService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import java.util.Collection; + +@RestController +@CrossOrigin +@RequestMapping("/api/v1/wishlist") +@RequiredArgsConstructor +public class WishListController { + + private final WishListService wishListService; + + @GetMapping + public Collection<Plant> getAllPlantsInWishList(@RequestParam(value = "sort", required = false) String sort, + @AuthenticationPrincipal User user) { + return wishListService.getWishedPlants(user, sort); + } + + @GetMapping("/count") + public int getWishListSize( + @AuthenticationPrincipal User user) { + return wishListService.countByUser(user); + } + + + @PostMapping("/add/{plantId}") + public ResponseEntity<Integer> addPlantToWishlist(@PathVariable Long plantId, + @AuthenticationPrincipal User user) { + wishListService.addPlantToWishList(plantId, user); + return ResponseEntity.status(201).build(); + } + + @DeleteMapping("/remove/{entryId}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void removePlantFromWishlist(@PathVariable Long entryId, + @AuthenticationPrincipal User user) { + wishListService.removeFromWishList(entryId, user); + } + + @DeleteMapping("/remove/all") + public int removeAllPlantsFromWishlist(@AuthenticationPrincipal User user) { + return wishListService.clearWishList(user); + } +} \ No newline at end of file diff --git a/src/main/java/hdm/mi/growbros/models/WishListEntry.java b/src/main/java/hdm/mi/growbros/models/WishListEntry.java new file mode 100644 index 0000000000000000000000000000000000000000..90e8ae4e6a7b9d25dbc7788e8968c407067610d8 --- /dev/null +++ b/src/main/java/hdm/mi/growbros/models/WishListEntry.java @@ -0,0 +1,33 @@ +package hdm.mi.growbros.models; + +import hdm.mi.growbros.models.plant.Plant; +import hdm.mi.growbros.models.user.User; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; + +import java.util.Date; + +@Entity +@Data +@AllArgsConstructor +@NoArgsConstructor +public class WishListEntry { + + @ManyToOne + @CreatedBy + private User user; + + @ManyToOne + private Plant plant; + + @CreatedDate + private Date createdAt; + + @Id + @GeneratedValue + private Long id; +} \ No newline at end of file diff --git a/src/main/java/hdm/mi/growbros/repositories/WishListRepository.java b/src/main/java/hdm/mi/growbros/repositories/WishListRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..f1c8d560b25478583f2844f4643b697dac68565d --- /dev/null +++ b/src/main/java/hdm/mi/growbros/repositories/WishListRepository.java @@ -0,0 +1,51 @@ +package hdm.mi.growbros.repositories; + +import hdm.mi.growbros.models.plant.Plant; +import hdm.mi.growbros.models.WishListEntry; +import hdm.mi.growbros.models.user.User; +import org.springframework.data.domain.Sort; +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; + + +@Repository +public interface WishListRepository extends JpaRepository<WishListEntry, Long> { + + List<WishListEntry> findByUser(User user); + + List<WishListEntry> findByUser(User user, Sort sort); + + int countByUser(User user); + + int deleteAllByUser(User user); + + void deleteByIdAndUser(long entryId, User user); + + @Query(""" + SELECT ge FROM WishListEntry ge + WHERE ge.user = :user + ORDER BY + CASE + WHEN :week <= ge.plant.plantWeekStart + THEN ABS(:week - ge.plant.plantWeekStart) + ELSE ABS(52 + :week - ge.plant.plantWeekStart) + END, + ge.plant.name + ASC + """) + List<WishListEntry> findAllByNearestPlantingWeek(@Param("user") User user, @Param("week") int currentWeek); + + @Query(""" + SELECT ge FROM WishListEntry ge + WHERE ge.user = :user + AND ge.plant.plantWeekStart <= :week + AND ge.plant.plantWeekEnd >= :week + """) + List<WishListEntry> findByCurrentPlantingWeek(@Param("user") User user, @Param("week") int currentWeek); + + boolean existsByUserAndPlant(User user, Plant plant); +} \ No newline at end of file diff --git a/src/main/java/hdm/mi/growbros/service/WishListService.java b/src/main/java/hdm/mi/growbros/service/WishListService.java new file mode 100644 index 0000000000000000000000000000000000000000..0d832d672cd617de3053b346178779ed0c847c68 --- /dev/null +++ b/src/main/java/hdm/mi/growbros/service/WishListService.java @@ -0,0 +1,90 @@ +package hdm.mi.growbros.service; + +import hdm.mi.growbros.exceptions.PlantNotFoundException; +import hdm.mi.growbros.models.WishListEntry; +import hdm.mi.growbros.models.plant.Plant; +import hdm.mi.growbros.models.user.User; +import hdm.mi.growbros.repositories.PlantRepository; +import hdm.mi.growbros.repositories.WishListRepository; +import hdm.mi.growbros.util.DateTimeUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; + + +@Service +@RequiredArgsConstructor +public class WishListService { + + private final WishListRepository wishListRepository; + private final PlantRepository plantRepository; + + public List<Plant> getWishedPlants(User user, String sort) { + if (sort == null) return getAllPlantsOrderedByName(user); + return switch (sort) { + case "createdAt" -> getAllPlantsOrderedByCreatedDate(user); + case "plantDate" -> getAllPlantsOrderedByNextPossiblePlantDate(user); + case "currentPlantable" -> getCurrentPlantablePlants(user); + default -> getAllPlantsOrderedByName(user); + }; + } + + public void addPlantToWishList(Long plantId, User user) { + Plant plant = plantRepository.findById(plantId).orElseThrow(() -> new PlantNotFoundException(plantId)); + + if (wishListRepository.existsByUserAndPlant(user, plant)) { + return; + } + + WishListEntry wishListEntry = new WishListEntry(); + wishListEntry.setPlant(plant); + wishListEntry.setUser(user); + wishListRepository.save(wishListEntry); + } + + public void removeFromWishList(Long entryId, User user) { + wishListRepository.deleteByIdAndUser(entryId, user); + } + + public int clearWishList(User user) { + return wishListRepository.deleteAllByUser(user); + } + + private List<Plant> getAllPlantsOrderedByName(User user) { + return mapWishListEntriesToPlants( + wishListRepository.findByUser(user, Sort.by("plant.name")) + ); + } + + private List<Plant> getAllPlantsOrderedByCreatedDate(User user) { + return mapWishListEntriesToPlants( + wishListRepository.findByUser(user, Sort.by("createdAt")) + ); + } + + private List<Plant> getAllPlantsOrderedByNextPossiblePlantDate(User user) { + return mapWishListEntriesToPlants( + wishListRepository.findAllByNearestPlantingWeek(user, DateTimeUtils.getCurrentWeekForToday()) + ); + } + + private List<Plant> getCurrentPlantablePlants(User user) { + return mapWishListEntriesToPlants( + wishListRepository.findByCurrentPlantingWeek(user, DateTimeUtils.getCurrentWeekForToday()) + ); + } + + private List<Plant> mapWishListEntriesToPlants(Collection<WishListEntry> entries) { + return entries + .stream() + .map(WishListEntry::getPlant) + .toList(); + } + + public int countByUser(User user) { + return wishListRepository.countByUser(user); + } +} \ No newline at end of file