From d26439ed9a45c42d3f3519813472e55c8146736b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kinga=20=C5=BBmuda?= <66728641+kingazm@users.noreply.github.com> Date: Wed, 27 May 2026 12:46:26 +0200 Subject: [PATCH] Revert "feat: add recommendations" --- .../controllers/RestaurantController.java | 18 -- .../backend/controllers/TagController.java | 40 ---- .../backend/controllers/UserController.java | 19 -- .../backend/model/MenuProcessingListener.java | 1 + .../com/backend/model/dtos/AIDishDTO.java | 14 +- .../java/com/backend/model/dtos/DishDTO.java | 5 +- .../backend/model/dtos/LocalizedDishDTO.java | 2 - .../backend/model/dtos/PreferenceRequest.java | 11 -- .../model/dtos/RankedRestaurantDTO.java | 8 - .../java/com/backend/model/dtos/TagDTO.java | 21 -- .../model/dtos/UpdatePreferencesRequest.java | 10 - .../backend/model/dtos/UserPreferenceDTO.java | 18 -- .../java/com/backend/model/entities/Dish.java | 19 +- .../backend/model/entities/Restaurant.java | 7 +- .../java/com/backend/model/entities/Tag.java | 88 --------- .../java/com/backend/model/entities/User.java | 19 -- .../model/entities/UserPreference.java | 54 ------ .../backend/repositories/DishRepository.java | 1 + .../repositories/RestaurantRepository.java | 11 -- .../backend/repositories/TagRepository.java | 17 -- .../com/backend/services/MenuService.java | 22 +-- .../com/backend/services/ProdAIService.java | 108 +---------- .../services/RecommendationService.java | 153 --------------- .../java/com/backend/services/TagService.java | 34 ---- .../com/backend/services/UserService.java | 70 +------ src/main/resources/data.sql | 92 ++++----- .../resources/db/migration/V4__tag_chema.sql | 23 --- .../resources/db/migration/V5__seed_tags.sql | 16 -- .../migration/V6__remove_dish_allergens.sql | 2 - .../db/migration/V7__add_sesame_tag.sql | 3 - .../RestaurantControllerTest.java | 4 - .../model/MenuProcessingListenerTest.java | 2 +- .../servicesTests/MenuServiceTest.java | 16 +- .../RecommendationServiceTest.java | 181 ------------------ .../servicesTests/RestaurantServiceTest.java | 2 +- 35 files changed, 79 insertions(+), 1032 deletions(-) delete mode 100644 src/main/java/com/backend/controllers/TagController.java delete mode 100644 src/main/java/com/backend/model/dtos/PreferenceRequest.java delete mode 100644 src/main/java/com/backend/model/dtos/RankedRestaurantDTO.java delete mode 100644 src/main/java/com/backend/model/dtos/TagDTO.java delete mode 100644 src/main/java/com/backend/model/dtos/UpdatePreferencesRequest.java delete mode 100644 src/main/java/com/backend/model/dtos/UserPreferenceDTO.java delete mode 100644 src/main/java/com/backend/model/entities/Tag.java delete mode 100644 src/main/java/com/backend/model/entities/UserPreference.java delete mode 100644 src/main/java/com/backend/repositories/TagRepository.java delete mode 100644 src/main/java/com/backend/services/RecommendationService.java delete mode 100644 src/main/java/com/backend/services/TagService.java delete mode 100644 src/main/resources/db/migration/V4__tag_chema.sql delete mode 100644 src/main/resources/db/migration/V5__seed_tags.sql delete mode 100644 src/main/resources/db/migration/V6__remove_dish_allergens.sql delete mode 100644 src/main/resources/db/migration/V7__add_sesame_tag.sql delete mode 100644 src/test/java/com/backend/servicesTests/RecommendationServiceTest.java diff --git a/src/main/java/com/backend/controllers/RestaurantController.java b/src/main/java/com/backend/controllers/RestaurantController.java index 4babd9d..ec296ca 100644 --- a/src/main/java/com/backend/controllers/RestaurantController.java +++ b/src/main/java/com/backend/controllers/RestaurantController.java @@ -1,12 +1,10 @@ package com.backend.controllers; import com.backend.model.dtos.CreateRestaurantRequest; -import com.backend.model.dtos.RankedRestaurantDTO; import com.backend.model.dtos.RestaurantDetailsDTO; import com.backend.model.dtos.RestaurantListDTO; import com.backend.model.dtos.UpdateRestaurantRequest; import com.backend.model.entities.Restaurant; -import com.backend.services.RecommendationService; import com.backend.services.RestaurantService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -44,7 +42,6 @@ public class RestaurantController { private final RestaurantService restaurantService; - private final RecommendationService recommendationService; @Operation( summary = "Get all restaurants", @@ -59,21 +56,6 @@ public ResponseEntity> getAllRestaurants() { return ResponseEntity.ok(restaurants); } - @Operation( - summary = "Get all restaurants with ranks", - description = "Retrieves a list of all available restaurants in the system including user based ranking." - ) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Successfully retrieved the list of restaurants") - }) - @GetMapping("/recommendation") - public ResponseEntity> getAllRestaurantsWithRecommendations( - @AuthenticationPrincipal Jwt jwt) { - String userId = jwt != null ? jwt.getSubject() : null; - List restaurants = recommendationService.getRankedRestaurants(userId); - return ResponseEntity.ok(restaurants); - } - @Operation( summary = "Get restaurant details by ID", description = "Retrieves detailed information about a specific restaurant, including location, opening hours, and today's menu." diff --git a/src/main/java/com/backend/controllers/TagController.java b/src/main/java/com/backend/controllers/TagController.java deleted file mode 100644 index 40ce9ca..0000000 --- a/src/main/java/com/backend/controllers/TagController.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.backend.controllers; - -import com.backend.model.dtos.TagDTO; -import com.backend.model.entities.DishTranslation; -import com.backend.model.entities.Tag; -import com.backend.services.TagService; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import java.util.List; -import java.util.Map; - -@RestController -@RequestMapping("/api/tags") -@RequiredArgsConstructor -@io.swagger.v3.oas.annotations.tags.Tag(name = "Tags", description = "Endpoints for retrieving tags") -@CrossOrigin(origins = "http://localhost:3000") -public class TagController { - private final TagService tagService; - @GetMapping - public ResponseEntity> getAllTags( - @Parameter(description = "Language code (PL or EN)", required = false) - @RequestParam(value = "language", defaultValue = "EN") DishTranslation.Language language) { - return ResponseEntity.ok(tagService.getAllTags(language)); - } - - @GetMapping("/grouped") - public ResponseEntity>> getAllTagsGrouped( - @Parameter(description = "Language code (PL or EN)", required = false) - @RequestParam(value = "language", defaultValue = "EN") DishTranslation.Language language) { - return ResponseEntity.ok(tagService.getAllTagsGrouped(language)); - } - -} diff --git a/src/main/java/com/backend/controllers/UserController.java b/src/main/java/com/backend/controllers/UserController.java index 4f27664..9f4881f 100644 --- a/src/main/java/com/backend/controllers/UserController.java +++ b/src/main/java/com/backend/controllers/UserController.java @@ -1,15 +1,11 @@ package com.backend.controllers; -import com.backend.model.dtos.PreferenceRequest; -import com.backend.model.dtos.UpdatePreferencesRequest; -import com.backend.model.dtos.UserPreferenceDTO; import com.backend.model.dtos.UserProfileDTO; import com.backend.services.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ -18,12 +14,10 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.CrossOrigin; -import java.util.List; import java.util.UUID; @RestController @@ -93,17 +87,4 @@ public ResponseEntity removeFromFavourites( return ResponseEntity.ok().build(); } - @GetMapping - public ResponseEntity> getPreferences(@AuthenticationPrincipal Jwt jwt) { - return ResponseEntity.ok(userService.getPreferences(jwt)); - } - - - @PostMapping("/preferences") - public void addPreference( - @AuthenticationPrincipal Jwt jwt, - @RequestBody @Valid UpdatePreferencesRequest request) { - userService.updatePreferences(jwt, request); - } - } diff --git a/src/main/java/com/backend/model/MenuProcessingListener.java b/src/main/java/com/backend/model/MenuProcessingListener.java index 4dae48d..bbfa85f 100644 --- a/src/main/java/com/backend/model/MenuProcessingListener.java +++ b/src/main/java/com/backend/model/MenuProcessingListener.java @@ -47,6 +47,7 @@ public void processMenu(MessageDTO message) { throw new RuntimeException("No items parsed from image"); } + parsedItems.forEach(dish -> dish.setRestaurant(menu.getRestaurant())); menu.setDishes(new ArrayList<>(parsedItems)); menu.setStatus(DailyMenu.Status.DRAFT); //menu.setProcessedAt(LocalDateTime.now()); do audit logów? diff --git a/src/main/java/com/backend/model/dtos/AIDishDTO.java b/src/main/java/com/backend/model/dtos/AIDishDTO.java index ea870dc..07c0e48 100644 --- a/src/main/java/com/backend/model/dtos/AIDishDTO.java +++ b/src/main/java/com/backend/model/dtos/AIDishDTO.java @@ -1,8 +1,6 @@ package com.backend.model.dtos; import com.backend.model.entities.Dish; -import com.backend.model.entities.Tag; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -14,12 +12,16 @@ @Getter @Setter @NoArgsConstructor -@AllArgsConstructor public class AIDishDTO { private String name; private String category; private BigDecimal price; - private Set allergens; - private Set cuisines; - private Set dietary; + private Set allergens; + + public AIDishDTO(Dish dish) { + this.name = dish.getName(); + this.category = dish.getCategory().name(); + this.price = dish.getPrice().getAmount(); + this.allergens = dish.getAllergens(); + } } diff --git a/src/main/java/com/backend/model/dtos/DishDTO.java b/src/main/java/com/backend/model/dtos/DishDTO.java index 11f6b2f..2b8d14f 100644 --- a/src/main/java/com/backend/model/dtos/DishDTO.java +++ b/src/main/java/com/backend/model/dtos/DishDTO.java @@ -1,7 +1,6 @@ package com.backend.model.dtos; import com.backend.model.entities.Dish; -import com.backend.model.entities.Tag; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -18,13 +17,13 @@ public class DishDTO { private String name; private String category; private BigDecimal price; - private Set tags; + private Set allergens; public DishDTO(Dish dish) { this.id = dish.getId(); this.name = dish.getName(); this.category = dish.getCategory().name(); this.price = dish.getPrice().getAmount(); - this.tags = dish.getTags(); + this.allergens = dish.getAllergens(); } } diff --git a/src/main/java/com/backend/model/dtos/LocalizedDishDTO.java b/src/main/java/com/backend/model/dtos/LocalizedDishDTO.java index afb11e6..73c2824 100644 --- a/src/main/java/com/backend/model/dtos/LocalizedDishDTO.java +++ b/src/main/java/com/backend/model/dtos/LocalizedDishDTO.java @@ -4,7 +4,6 @@ import lombok.Getter; import java.math.BigDecimal; -import java.util.Set; @Getter @AllArgsConstructor @@ -12,5 +11,4 @@ public class LocalizedDishDTO { private DishDTO dish; private String displayName; private BigDecimal price; - private Set tags; } diff --git a/src/main/java/com/backend/model/dtos/PreferenceRequest.java b/src/main/java/com/backend/model/dtos/PreferenceRequest.java deleted file mode 100644 index cfd69c0..0000000 --- a/src/main/java/com/backend/model/dtos/PreferenceRequest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.backend.model.dtos; - -import com.backend.model.entities.Tag; -import com.backend.model.entities.UserPreference; -import jakarta.validation.constraints.NotNull; - -public record PreferenceRequest( - @NotNull Tag.TagValue tagValue, - @NotNull UserPreference.PreferenceType preferenceType -) {} - diff --git a/src/main/java/com/backend/model/dtos/RankedRestaurantDTO.java b/src/main/java/com/backend/model/dtos/RankedRestaurantDTO.java deleted file mode 100644 index 0d5d97f..0000000 --- a/src/main/java/com/backend/model/dtos/RankedRestaurantDTO.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.backend.model.dtos; - -import java.util.List; - -public record RankedRestaurantDTO ( - RestaurantListDTO restaurant, - double score){ -} diff --git a/src/main/java/com/backend/model/dtos/TagDTO.java b/src/main/java/com/backend/model/dtos/TagDTO.java deleted file mode 100644 index 3d22227..0000000 --- a/src/main/java/com/backend/model/dtos/TagDTO.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.backend.model.dtos; - -import com.backend.model.entities.DishTranslation; -import com.backend.model.entities.Tag; -import com.backend.model.entities.Tag.TagType; -import com.backend.model.entities.Tag.TagValue; - -public record TagDTO( - TagValue value, - TagType tagType, - String label -) { - public static TagDTO from(Tag tag, DishTranslation.Language language) { - return new TagDTO( - tag.getValue(), - tag.getTagType(), - tag.getValue().getLabel(language) - ); - } -} - diff --git a/src/main/java/com/backend/model/dtos/UpdatePreferencesRequest.java b/src/main/java/com/backend/model/dtos/UpdatePreferencesRequest.java deleted file mode 100644 index c8385bb..0000000 --- a/src/main/java/com/backend/model/dtos/UpdatePreferencesRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.backend.model.dtos; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotNull; - -import java.util.List; - -public record UpdatePreferencesRequest( - @NotNull @Valid List preferences -) {} diff --git a/src/main/java/com/backend/model/dtos/UserPreferenceDTO.java b/src/main/java/com/backend/model/dtos/UserPreferenceDTO.java deleted file mode 100644 index 2e479fa..0000000 --- a/src/main/java/com/backend/model/dtos/UserPreferenceDTO.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.backend.model.dtos; - -import com.backend.model.entities.Tag; -import com.backend.model.entities.UserPreference; - -public record UserPreferenceDTO( - Tag.TagValue tagValue, - Tag.TagType tagType, - UserPreference.PreferenceType preferenceType -) { - public static UserPreferenceDTO from(UserPreference preference) { - return new UserPreferenceDTO( - preference.getTag().getValue(), - preference.getTag().getTagType(), - preference.getPreferenceType() - ); - } -} diff --git a/src/main/java/com/backend/model/entities/Dish.java b/src/main/java/com/backend/model/entities/Dish.java index f759b55..5cce490 100644 --- a/src/main/java/com/backend/model/entities/Dish.java +++ b/src/main/java/com/backend/model/entities/Dish.java @@ -11,8 +11,6 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.JoinTable; import jakarta.persistence.ManyToMany; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; @@ -21,7 +19,6 @@ import lombok.Setter; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; @@ -42,13 +39,11 @@ public class Dish { private Price price; - @ManyToMany - @JoinTable( - name = "dish_tags", - joinColumns = @JoinColumn(name = "dish_id"), - inverseJoinColumns = @JoinColumn(name = "tag_id") - ) - private Set tags = new HashSet<>(); + @ElementCollection(targetClass = Allergens.class) + @Enumerated(EnumType.STRING) + @CollectionTable(name = "dish_allergens") + @Column(name = "allergen") + private Set allergens; @ManyToOne private Restaurant restaurant; @@ -59,4 +54,8 @@ public class Dish { public enum Category { SOUP, MAIN_COURSE } + + public enum Allergens { + NUTS, GLUTEN, MEAT, LACTOSE, SESAME + } } diff --git a/src/main/java/com/backend/model/entities/Restaurant.java b/src/main/java/com/backend/model/entities/Restaurant.java index 6c168cc..c0a7022 100644 --- a/src/main/java/com/backend/model/entities/Restaurant.java +++ b/src/main/java/com/backend/model/entities/Restaurant.java @@ -33,10 +33,11 @@ public class Restaurant extends Facility { private String name; @OneToMany(mappedBy = "restaurant", cascade = CascadeType.ALL, orphanRemoval = true) - private List openingHours = new ArrayList<>(); - + private List openingHours; + @OneToMany(mappedBy = "restaurant", cascade = CascadeType.ALL) + private List dishes = new ArrayList<>(); @OneToMany(mappedBy = "restaurant", cascade = CascadeType.ALL) - private Set dailyMenus = new HashSet<>(); + private List dailyMenus = new ArrayList<>(); @ManyToMany @JoinTable( name = "restaurant_owners", diff --git a/src/main/java/com/backend/model/entities/Tag.java b/src/main/java/com/backend/model/entities/Tag.java deleted file mode 100644 index d80024c..0000000 --- a/src/main/java/com/backend/model/entities/Tag.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.backend.model.entities; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import jakarta.persistence.UniqueConstraint; -import lombok.AllArgsConstructor; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.util.UUID; - -@Entity -@Table(name = "tags") -@Getter -@Setter -@NoArgsConstructor -@AllArgsConstructor -//@EqualsAndHashCode(of = "id") -public class Tag { - - @Id - @GeneratedValue(strategy = GenerationType.UUID) - private UUID id; - - @Enumerated(EnumType.STRING) - @Column(name = "tag_value", columnDefinition = "varchar(50)") - private TagValue value; - - public TagType getTagType() { - return value.getType(); - } - - public String getName() { - return value.name(); - } - - - @Getter - public enum TagValue { - // Cuisine - ITALIAN(TagType.CUISINE, "Włoska", "Italian"), - POLISH(TagType.CUISINE, "Polska", "Polish"), - ASIAN(TagType.CUISINE, "Azjatycka", "Asian"), - FAST_FOOD(TagType.CUISINE, "Fast food", "Fast food"), - - // Allergen - NUTS(TagType.ALLERGEN, "Orzechy", "Nuts"), - GLUTEN(TagType.ALLERGEN, "Gluten", "Gluten"), - LACTOSE(TagType.ALLERGEN, "Laktoza", "Lactose"), - SESAME(TagType.ALLERGEN, "Sezam", "Sesame"), - - // Dietary - VEGAN(TagType.DIETARY, "Wegańskie", "Vegan"), - VEGETARIAN(TagType.DIETARY, "Wegetariańskie", "Vegetarian"); - - private final TagType type; - private final String labelPl; - private final String labelEn; - - TagValue(TagType type, String labelPl, String labelEn) { - this.type = type; - this.labelPl = labelPl; - this.labelEn = labelEn; - } - - public String getLabel(DishTranslation.Language language) { - return switch (language) { - case PL -> labelPl; - case EN -> labelEn; - }; - } - } - - public enum TagType { - CUISINE, - ALLERGEN, - DIETARY - } -} - diff --git a/src/main/java/com/backend/model/entities/User.java b/src/main/java/com/backend/model/entities/User.java index f8e35cc..6e096bb 100644 --- a/src/main/java/com/backend/model/entities/User.java +++ b/src/main/java/com/backend/model/entities/User.java @@ -1,21 +1,17 @@ package com.backend.model.entities; -import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinTable; import jakarta.persistence.ManyToMany; -import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.HashSet; -import java.util.List; import java.util.Set; import java.util.UUID; @@ -39,19 +35,4 @@ public class User { ) private Set favouriteFacilities = new HashSet<>(); - @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) - private List preferences = new ArrayList<>(); - - public void addPreference(UserPreference preference) { - preferences.add(preference); - preference.setUser(this); - } - - public void removePreference(UserPreference preference) { - preferences.remove(preference); - preference.setUser(null); - } - - - } diff --git a/src/main/java/com/backend/model/entities/UserPreference.java b/src/main/java/com/backend/model/entities/UserPreference.java deleted file mode 100644 index f7c2375..0000000 --- a/src/main/java/com/backend/model/entities/UserPreference.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.backend.model.entities; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; -import jakarta.persistence.UniqueConstraint; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.util.UUID; - -@Entity -@Table( - name = "user_preferences", - uniqueConstraints = @UniqueConstraint(columnNames = {"user_id", "tag_id"}) -) -@Getter -@Setter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class UserPreference { - - @Id - @GeneratedValue(strategy = GenerationType.UUID) - private UUID id; - - @ManyToOne - @JoinColumn(name = "user_id") - private User user; - - @ManyToOne - @JoinColumn(name = "tag_id") - private Tag tag; - - @Enumerated(EnumType.STRING) - private PreferenceType preferenceType; - - - public enum PreferenceType { - INCLUDE, - EXCLUDE - } -} diff --git a/src/main/java/com/backend/repositories/DishRepository.java b/src/main/java/com/backend/repositories/DishRepository.java index d5e39ed..ed8c754 100644 --- a/src/main/java/com/backend/repositories/DishRepository.java +++ b/src/main/java/com/backend/repositories/DishRepository.java @@ -11,4 +11,5 @@ @Repository public interface DishRepository extends JpaRepository { + Optional> findByRestaurantId(UUID id); } diff --git a/src/main/java/com/backend/repositories/RestaurantRepository.java b/src/main/java/com/backend/repositories/RestaurantRepository.java index 381a02f..b1d48a0 100644 --- a/src/main/java/com/backend/repositories/RestaurantRepository.java +++ b/src/main/java/com/backend/repositories/RestaurantRepository.java @@ -2,23 +2,12 @@ import com.backend.model.entities.Restaurant; 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.time.LocalDate; import java.util.List; import java.util.UUID; @Repository public interface RestaurantRepository extends JpaRepository { List findAllByOwners_Id(String ownerId); - - @Query(""" - SELECT DISTINCT r FROM Restaurant r - LEFT JOIN FETCH r.dailyMenus dm - LEFT JOIN FETCH dm.dishes d - LEFT JOIN FETCH d.tags - """) - List findAllRestaurantsWithTodayMenu(); } diff --git a/src/main/java/com/backend/repositories/TagRepository.java b/src/main/java/com/backend/repositories/TagRepository.java deleted file mode 100644 index 8f9af46..0000000 --- a/src/main/java/com/backend/repositories/TagRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.backend.repositories; - -import com.backend.model.entities.Tag; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -@Repository -public interface TagRepository extends JpaRepository { - Optional findByValue(Tag.TagValue value); - List findAllByValueIn(Collection values); - -} diff --git a/src/main/java/com/backend/services/MenuService.java b/src/main/java/com/backend/services/MenuService.java index 4cd63e4..04216eb 100644 --- a/src/main/java/com/backend/services/MenuService.java +++ b/src/main/java/com/backend/services/MenuService.java @@ -5,10 +5,8 @@ import com.backend.model.dtos.LocalizedDailyMenuDTO; import com.backend.model.dtos.LocalizedDishDTO; import com.backend.model.dtos.MessageDTO; -import com.backend.model.dtos.TagDTO; import com.backend.model.entities.DailyMenu; import com.backend.model.entities.Dish; -import com.backend.model.entities.DishTranslation; import com.backend.model.entities.Restaurant; import com.backend.model.valueObjects.Price; import com.backend.repositories.DailyMenuRepository; @@ -67,14 +65,7 @@ public LocalizedDailyMenuDTO getLocalizedDailyMenuByRestaurantId(UUID id, String .map(dish -> new LocalizedDishDTO( dish, localizedNames.getOrDefault(dish.getId(), dish.getName()), - dish.getPrice(), - dish.getTags().stream() - .map(tag -> new TagDTO( - tag.getValue(), - tag.getTagType(), - tag.getValue().getLabel(DishTranslation.Language.valueOf(language)) - )) - .collect(Collectors.toSet()) + dish.getPrice() )) .collect(Collectors.toList()); @@ -131,14 +122,7 @@ public List getLocalizedScheduledAndActiveMenusByRestaura .map(dish -> new LocalizedDishDTO( dish, localizedNames.getOrDefault(dish.getId(), dish.getName()), - dish.getPrice(), - dish.getTags().stream() - .map(tag -> new TagDTO( - tag.getValue(), - tag.getTagType(), - tag.getValue().getLabel(DishTranslation.Language.valueOf(language)) - )) - .collect(Collectors.toSet()) + dish.getPrice() )) .collect(Collectors.toList()) )) @@ -263,7 +247,7 @@ public void updateAndApproveMenu(UUID restaurantId, DailyMenuDTO request, String dish.setCategory(Dish.Category.valueOf(dto.getCategory())); dish.setName(dto.getName()); dish.setPrice(new Price(dto.getPrice(), "PLN")); - dish.setTags(dto.getTags()); + dish.setAllergens(dto.getAllergens()); dishRepository.save(dish); dishTranslationService.upsertBothLanguages(dish, dto.getName(), sourceLanguageHeader); //aiservice.index(dish) diff --git a/src/main/java/com/backend/services/ProdAIService.java b/src/main/java/com/backend/services/ProdAIService.java index 354f90b..2f09f73 100644 --- a/src/main/java/com/backend/services/ProdAIService.java +++ b/src/main/java/com/backend/services/ProdAIService.java @@ -2,10 +2,8 @@ import com.backend.model.dtos.AIDishDTO; import com.backend.model.entities.Dish; -import com.backend.model.entities.Tag; import com.backend.model.valueObjects.Price; import com.backend.repositories.DishRepository; -import com.backend.repositories.TagRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -20,12 +18,8 @@ import org.springframework.ai.chat.client.ChatClient; -import java.util.HashSet; import java.util.List; import java.util.ArrayList; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -34,7 +28,6 @@ public class ProdAIService implements MenuAIService { private final ChatClient.Builder chatClientBuilder; private final DishRepository dishRepository; - private final TagRepository tagRepository; public List parseMenuFromImage(byte[] imageBytes) { @@ -49,8 +42,6 @@ public List parseMenuFromImage(byte[] imageBytes) { 2. category: Either "SOUP" or "MAIN_COURSE" (string, required) 3. price: Numeric value with 2 decimal places (number, required) 4. allergens: Array of allergen codes (array, can be empty) - 5. cuisines: Array of cuisine types (array, can be empty) - 6. dietary: Array of dietary types (array, can be empty) CATEGORY RULES (choose one): - "SOUP": zupy, rosół, barszcz, krem, chłodnik, zupa, bulion, consommé @@ -62,52 +53,13 @@ CATEGORY RULES (choose one): - If price is unclear or missing: use 0.00 - Remove any currency symbols (zł, PLN) - ALLOWED TAG VALUES (STRICT - use ONLY these exact strings): - - ALLERGENS: - - "GLUTEN" - - "LACTOSE" - - "NUTS" - - CUISINES: - - "ITALIAN" - - "POLISH" - - "ASIAN" - - "FAST_FOOD" - - DIETARY: - - "VEGAN" - - "VEGETARIAN" - - TAGGING RULES: - - Use ONLY values from the lists above (no variations, no translations) - - If unsure → return empty array [] - - Prefer empty array [] over incorrect tag - - Do NOT invent new tags - - Do NOT mix categories (e.g. GLUTEN must NOT appear in cuisines) - - Try to always pick a cuisine - - ALLERGEN HINTS: + ALLERGEN CODES (use exact strings): + - "MEAT": kurczak, wołowina, wieprzowina, schabowy, kotlet, ryba, łosoś, krewetki, etc. - "GLUTEN": makaron, spaghetti, pierogi, kluski, panierowany, w panierce, pieczywo - "LACTOSE": ser, śmietana, kremowy, mleko, masło, parmezan, mozzarella - "NUTS": orzechy, migdały, orzeszki, pistacje - - CUISINE HINTS: - - "POLISH": schabowy, pierogi, rosół, bigos - - "ITALIAN": pizza, spaghetti, pasta, makaron - - "ASIAN": curry, ramen, sushi, stir-fry, noodles - - "FAST_FOOD": burger, frytki, hot-dog - - DIETARY HINTS: - - "VEGAN": Use ONLY if the dish contains NO animal products. - This means: - - NO meat (kurczak, wołowina, wieprzowina, ryba, etc.) - - NO dairy (ser, mleko, śmietana, masło) - - NO eggs - If there is ANY doubt → do NOT assign. - - "VEGETARIAN": Use if the dish contains NO meat or fish, but MAY contain dairy or eggs. - Examples: dishes with cheese, cream, or eggs are vegetarian but NOT vegan. - If meat or fish is present → DO NOT assign. + + Use empty array [] if no allergens apply. EXAMPLES OF EXPECTED OUTPUT: [ @@ -174,59 +126,9 @@ private Dish convertToEntity(AIDishDTO dto) { dish.setName(dto.getName()); dish.setCategory(Dish.Category.valueOf(dto.getCategory())); dish.setPrice(new Price(dto.getPrice(), "PLN")); - - Set tags = new HashSet<>(); - - // CUISINE - if (dto.getCuisines() != null) { - tags.addAll(mapTags(dto.getCuisines(),Tag.TagType.CUISINE)); - } - - // ALLERGENS - if (dto.getAllergens() != null) { - tags.addAll(mapTags(dto.getAllergens(), Tag.TagType.ALLERGEN)); - } - - // DIETARY - if (dto.getDietary() != null) { - tags.addAll(mapTags(dto.getDietary(), Tag.TagType.DIETARY)); - } - - dish.setTags(tags); - + dish.setAllergens(dto.getAllergens()); return dish; } - - private Set mapTags(Set values, Tag.TagType expectedType) { - if (values == null || values.isEmpty()) { - return Set.of(); - } - - return values.stream() - .map(v -> { - try { - Tag.TagValue enumValue = Tag.TagValue.valueOf(v); - - if (enumValue.getType() != expectedType) { - log.warn("LLM returned wrong tag type: {} (expected: {}, actual: {})", - v, expectedType, enumValue.getType()); - return null; - } - - return tagRepository.findByValue(enumValue) - .orElseGet(() -> { - log.warn("Tag not found in DB (skipping): {}", v); - return null; - }); - - } catch (IllegalArgumentException e) { - log.warn("Invalid tag from LLM (skipping): {}", v); - return null; - } - }) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - } } diff --git a/src/main/java/com/backend/services/RecommendationService.java b/src/main/java/com/backend/services/RecommendationService.java deleted file mode 100644 index 59dbc16..0000000 --- a/src/main/java/com/backend/services/RecommendationService.java +++ /dev/null @@ -1,153 +0,0 @@ -package com.backend.services; - -import com.backend.model.dtos.RankedRestaurantDTO; -import com.backend.model.dtos.RestaurantListDTO; -import com.backend.model.entities.DailyMenu; -import com.backend.model.entities.Dish; -import com.backend.model.entities.Restaurant; -import com.backend.model.entities.Tag; -import com.backend.model.entities.User; -import com.backend.model.entities.UserPreference; -import com.backend.repositories.RestaurantRepository; -import com.backend.repositories.UserRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; -import org.springframework.web.server.ResponseStatusException; - -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -@Service -@RequiredArgsConstructor -public class RecommendationService { - - private final RestaurantRepository restaurantRepository; - private final UserRepository userRepository; - - private User findUserById(String userId) { - return userRepository.findById(userId) - .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found")); - } - - public List getRankedRestaurants(String userId) { - User user = findUserById(userId); - - List restaurants = - restaurantRepository.findAllRestaurantsWithTodayMenu(); - - Set include = new HashSet<>(); - Set exclude = new HashSet<>(); - - for (UserPreference p : user.getPreferences()) { - if (p.getPreferenceType() == UserPreference.PreferenceType.INCLUDE) { - include.add(p.getTag()); - } else { - exclude.add(p.getTag()); - } - } - - return restaurants.stream() - .map(r -> new RankedRestaurantDTO( - new RestaurantListDTO(r), - calculateScore(r, include, exclude) - )) - .sorted(Comparator.comparingDouble(RankedRestaurantDTO::score).reversed()) - .toList(); - } - - private double calculateScore(Restaurant restaurant, - Set include, - Set exclude) { - - DailyMenu activeMenu = restaurant.getDailyMenus().stream() - .filter(dm -> dm.getStatus() == DailyMenu.Status.ACTIVE) - .findFirst() - .orElse(null); - - if (activeMenu == null) { - return -Double.MAX_VALUE; - } - - List dishes = restaurant.getTodayMenu().getDishes(); - - if (dishes == null || dishes.isEmpty()) { - return -10; - } - - double score = 0; - - int totalDishes = dishes.size(); - int allergenHits = 0; - boolean hasDietaryMatch = false; - - for (Dish dish : dishes) { - - Set tags = dish.getTags(); - - // ------------------------- - // ALLERGEN (ratio-based) - // ------------------------- - boolean hasExcluded = false; - - for (Tag t : tags) { - if (exclude.contains(t) && t.getTagType()== Tag.TagType.ALLERGEN) { - hasExcluded = true; - allergenHits++; - break; - } - } - - if (hasExcluded) { - continue; - } - - // ------------------------- - // DIETARY / INCLUDE bonus - // ------------------------- - for (Tag t : tags) { - if (include.contains(t) && t.getTagType() == Tag.TagType.DIETARY) { - score += 3; - hasDietaryMatch = true; - } - } - - // ------------------------- - // CUISINE/ALLERGEN bonus - // ------------------------- - for (Tag t : tags) { - if ((t.getTagType() == Tag.TagType.CUISINE || t.getTagType() == Tag.TagType.ALLERGEN )&& include.contains(t)) { - score += 2; - } - } - } - - // ------------------------- - // ALLERGEN penalty (ratio-based) - // ------------------------- - double allergenRatio = (double) allergenHits / totalDishes; - double allergenPenalty = allergenRatio * 20; - - // ------------------------- - // DIETARY penalty (no match) - // ------------------------- - double dietaryPenalty = 0; - - boolean hasAnyDietaryPreference = include.stream() - .anyMatch(t -> t.getTagType() == Tag.TagType.DIETARY); - - if (hasAnyDietaryPreference && !hasDietaryMatch) { - dietaryPenalty = 20; - } - - // ------------------------- - // FINAL SCORE - // ------------------------- - double finalScore = score - - allergenPenalty - - dietaryPenalty; - - return finalScore / Math.sqrt(totalDishes); - } -} \ No newline at end of file diff --git a/src/main/java/com/backend/services/TagService.java b/src/main/java/com/backend/services/TagService.java deleted file mode 100644 index 83d688f..0000000 --- a/src/main/java/com/backend/services/TagService.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.backend.services; - -import com.backend.model.dtos.TagDTO; -import com.backend.model.entities.DishTranslation; -import com.backend.model.entities.Tag.TagType; -import com.backend.repositories.TagRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class TagService { - - private final TagRepository tagRepository; - - @Transactional(readOnly = true) - public List getAllTags(DishTranslation.Language language) { - return tagRepository.findAll().stream() - .map(tag -> TagDTO.from(tag, language)) - .toList(); - } - - @Transactional(readOnly = true) - public Map> getAllTagsGrouped(DishTranslation.Language language) { - return tagRepository.findAll().stream() - .map(tag -> TagDTO.from(tag, language)) - .collect(Collectors.groupingBy(TagDTO::tagType)); - } -} diff --git a/src/main/java/com/backend/services/UserService.java b/src/main/java/com/backend/services/UserService.java index 69c9c60..06e6bc0 100644 --- a/src/main/java/com/backend/services/UserService.java +++ b/src/main/java/com/backend/services/UserService.java @@ -2,17 +2,11 @@ import com.backend.model.dtos.FacilityDTO; import com.backend.model.dtos.KeycloakUserDTO; -import com.backend.model.dtos.PreferenceRequest; import com.backend.model.dtos.RestaurantListDTO; -import com.backend.model.dtos.UpdatePreferencesRequest; -import com.backend.model.dtos.UserPreferenceDTO; import com.backend.model.dtos.UserProfileDTO; import com.backend.model.entities.Facility; -import com.backend.model.entities.Tag; import com.backend.model.entities.User; -import com.backend.model.entities.UserPreference; import com.backend.repositories.FacilityRepository; -import com.backend.repositories.TagRepository; import com.backend.repositories.UserRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -23,18 +17,15 @@ import org.springframework.web.server.ResponseStatusException; import java.util.List; -import java.util.Map; -import java.util.Set; import java.util.UUID; -import java.util.stream.Collectors; @Service @RequiredArgsConstructor @Slf4j public class UserService { private final UserRepository userRepository; + private final KeycloakService keycloakService; private final FacilityRepository facilityRepository; - private final TagRepository tagRepository; @Transactional public User getOrCreateUserFromJwt(Jwt jwt) { log.info("In filter"); @@ -121,63 +112,4 @@ public void removeFromFavourites(Jwt jwt, UUID facilityId) { user.getFavouriteFacilities().remove(facility); userRepository.save(user); } - - @Transactional - public void updatePreferences(Jwt jwt, UpdatePreferencesRequest request) { - String userId = jwt.getSubject(); - - User user = userRepository.findById(userId) - .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found")); - - - Set requestedValues = request.preferences().stream() - .map(PreferenceRequest::tagValue) - .collect(Collectors.toSet()); - - Map tagsByValue = tagRepository.findAllByValueIn(requestedValues).stream() - .collect(Collectors.toMap(Tag::getValue, t -> t)); - - Map requested = request.preferences().stream() - .collect(Collectors.toMap(PreferenceRequest::tagValue, PreferenceRequest::preferenceType)); - - - Map existing = user.getPreferences().stream() - .collect(Collectors.toMap(p -> p.getTag().getValue(), p -> p)); - - // delete preferences not included in request - existing.entrySet().stream() - .filter(e -> !requested.containsKey(e.getKey())) - .forEach(e -> user.removePreference(e.getValue())); - - // add new or update - requested.forEach((tagValue, preferenceType) -> { - if (existing.containsKey(tagValue)) { - // type changed (INCLUDE -> EXCLUDE) - existing.get(tagValue).setPreferenceType(preferenceType); - } else { - Tag tag = tagsByValue.get(tagValue); - if (tag == null) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Unknown tag: " + tagValue); - } - user.addPreference(UserPreference.builder() - .user(user) - .tag(tag) - .preferenceType(preferenceType) - .build()); - } - }); - } - - - public List getPreferences(Jwt jwt) { - String userId = jwt.getSubject(); - - User user = userRepository.findById(userId) - .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found")); - - return user.getPreferences().stream() - .map(UserPreferenceDTO::from) - .toList(); - } - } \ No newline at end of file diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 121e5f5..bfdaf0d 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -141,60 +141,45 @@ INSERT INTO daily_menu_dishes (daily_menu_id, dish_id) VALUES ('c5555555-aaaa-bbbb-cccc-555555555555', 'd5555555-aaaa-bbbb-cccc-000000000003'); ------------------------------------------------------------ --- DISH TAGS +-- DISH ALLERGENS ------------------------------------------------------------ -INSERT INTO tags (id, tag_value) VALUES - -- Cuisine - ('a0000000-0000-0000-0000-000000000001', 'ITALIAN'), - ('a0000000-0000-0000-0000-000000000002', 'POLISH'), - ('a0000000-0000-0000-0000-000000000003', 'ASIAN'), - ('a0000000-0000-0000-0000-000000000004', 'FAST_FOOD'), - - -- Allergen - ('a0000000-0000-0000-0000-000000000005', 'NUTS'), - ('a0000000-0000-0000-0000-000000000006', 'GLUTEN'), - ('a0000000-0000-0000-0000-000000000007', 'LACTOSE'), - ('a0000000-0000-0000-0000-000000000010', 'SESAME'), - - -- Dietary - ('a0000000-0000-0000-0000-000000000008', 'VEGAN'), - ('a0000000-0000-0000-0000-000000000009', 'VEGETARIAN'); - --- Bistro Świetlica tags -INSERT INTO dish_tags (dish_id, tag_id) VALUES -('d1111111-aaaa-bbbb-cccc-000000000001', 'a0000000-0000-0000-0000-000000000006'), -- Potato Dumplings (contains flour) -('d1111111-aaaa-bbbb-cccc-000000000001', 'a0000000-0000-0000-0000-000000000007'), -- Potato Dumplings (may contain dairy) -('d1111111-aaaa-bbbb-cccc-000000000002', 'a0000000-0000-0000-0000-000000000007'); -- Red Beet Soup (may contain sour cream) +-- Bistro Świetlica allergens +INSERT INTO dish_allergens (dish_id, allergen) VALUES +('d1111111-aaaa-bbbb-cccc-000000000001', 'GLUTEN'), -- Potato Dumplings (contains flour) +('d1111111-aaaa-bbbb-cccc-000000000001', 'LACTOSE'), -- Potato Dumplings (may contain dairy) +('d1111111-aaaa-bbbb-cccc-000000000002', 'LACTOSE'); -- Red Beet Soup (may contain sour cream) -- Pumpkin Cream Soup has no major allergens in this list --- Bistro by Jelonek tags -INSERT INTO dish_tags (dish_id, tag_id) VALUES -('d2222222-aaaa-bbbb-cccc-000000000001', 'a0000000-0000-0000-0000-000000000006'), -- Chicken Teriyaki Bowl (contains soy sauce) -('d2222222-aaaa-bbbb-cccc-000000000001', 'a0000000-0000-0000-0000-000000000003'), -- Chicken Teriyaki Bowl (Asian)) -('d2222222-aaaa-bbbb-cccc-000000000002', 'a0000000-0000-0000-0000-000000000006'), -- Miso Soup (contains miso paste) -('d2222222-aaaa-bbbb-cccc-000000000002', 'a0000000-0000-0000-0000-000000000003'), -- Miso Soup (Asian) -('d2222222-aaaa-bbbb-cccc-000000000003', 'a0000000-0000-0000-0000-000000000003'); -- Salmon Rice Bowl (Asian) - --- Bistro4mat tags -INSERT INTO dish_tags (dish_id, tag_id) VALUES -('d3333333-aaaa-bbbb-cccc-000000000001', 'a0000000-0000-0000-0000-000000000006'), -- Chicken Wrap (contains tortilla) -('d3333333-aaaa-bbbb-cccc-000000000001', 'a0000000-0000-0000-0000-000000000007'), -- Chicken Wrap (may contain cheese/sauce) -('d3333333-aaaa-bbbb-cccc-000000000002', 'a0000000-0000-0000-0000-000000000007'), -- Tomato Cream Soup (contains cream) -('d3333333-aaaa-bbbb-cccc-000000000003', 'a0000000-0000-0000-0000-000000000007'); -- Greek Salad (contains feta cheese) - --- Bistro 11 tags -INSERT INTO dish_tags (dish_id, tag_id) VALUES -('d4444444-aaaa-bbbb-cccc-000000000003', 'a0000000-0000-0000-0000-000000000008'), -- Boiled Potatoes (Vegan) -('d4444444-aaaa-bbbb-cccc-000000000003', 'a0000000-0000-0000-0000-000000000009'); -- Boiled Potatoes (Vegetarian) - --- Neon Bistro tags -INSERT INTO dish_tags (dish_id, tag_id) VALUES -('d5555555-aaaa-bbbb-cccc-000000000001', 'a0000000-0000-0000-0000-000000000006'), -- Caesar Salad (contains croutons) -('d5555555-aaaa-bbbb-cccc-000000000001', 'a0000000-0000-0000-0000-000000000007'), -- Caesar Salad (contains parmesan cheese) -('d5555555-aaaa-bbbb-cccc-000000000002', 'a0000000-0000-0000-0000-000000000007'), -- Broccoli Cream Soup (contains cream) -('d5555555-aaaa-bbbb-cccc-000000000003', 'a0000000-0000-0000-0000-000000000003'), -- Tuna Roll (Asian) -('d5555555-aaaa-bbbb-cccc-000000000003', 'a0000000-0000-0000-0000-000000000006'); -- Tuna Roll (may contain soy sauce or tempura) +-- Bistro by Jelonek allergens +INSERT INTO dish_allergens (dish_id, allergen) VALUES +('d2222222-aaaa-bbbb-cccc-000000000001', 'GLUTEN'), -- Chicken Teriyaki Bowl (contains soy sauce) +('d2222222-aaaa-bbbb-cccc-000000000001', 'MEAT'), -- Chicken Teriyaki Bowl (contains chicken) +('d2222222-aaaa-bbbb-cccc-000000000002', 'GLUTEN'), -- Miso Soup (contains miso paste) +('d2222222-aaaa-bbbb-cccc-000000000003', 'MEAT'); -- Salmon Rice Bowl (contains fish/meat) + +-- Bistro4mat allergens +INSERT INTO dish_allergens (dish_id, allergen) VALUES +('d3333333-aaaa-bbbb-cccc-000000000001', 'GLUTEN'), -- Chicken Wrap (contains tortilla) +('d3333333-aaaa-bbbb-cccc-000000000001', 'MEAT'), -- Chicken Wrap (contains chicken) +('d3333333-aaaa-bbbb-cccc-000000000001', 'LACTOSE'), -- Chicken Wrap (may contain cheese/sauce) +('d3333333-aaaa-bbbb-cccc-000000000002', 'LACTOSE'), -- Tomato Cream Soup (contains cream) +('d3333333-aaaa-bbbb-cccc-000000000003', 'LACTOSE'); -- Greek Salad (contains feta cheese) + +-- Bistro 11 allergens +INSERT INTO dish_allergens (dish_id, allergen) VALUES +('d4444444-aaaa-bbbb-cccc-000000000001', 'MEAT'), -- Pork Chop (contains pork) +('d4444444-aaaa-bbbb-cccc-000000000002', 'MEAT'); -- Chicken Broth Soup (contains chicken) +-- Boiled Potatoes have no major allergens in this list + +-- Neon Bistro allergens +INSERT INTO dish_allergens (dish_id, allergen) VALUES +('d5555555-aaaa-bbbb-cccc-000000000001', 'GLUTEN'), -- Caesar Salad (contains croutons) +('d5555555-aaaa-bbbb-cccc-000000000001', 'LACTOSE'), -- Caesar Salad (contains parmesan cheese) +('d5555555-aaaa-bbbb-cccc-000000000001', 'MEAT'), -- Caesar Salad (usually contains chicken) +('d5555555-aaaa-bbbb-cccc-000000000002', 'LACTOSE'), -- Broccoli Cream Soup (contains cream) +('d5555555-aaaa-bbbb-cccc-000000000003', 'MEAT'), -- Tuna Roll (contains fish/meat) +('d5555555-aaaa-bbbb-cccc-000000000003', 'GLUTEN'); -- Tuna Roll (may contain soy sauce or tempura) ------------------------------------------------------------ -- VENDING MACHINES' LOCATIONS (might require more detailed in person mapping) @@ -289,10 +274,11 @@ VALUES ( 'eeeeeeee-1111-1111-1111-eeeeeeeeeeee' ); -INSERT INTO dish_tags (dish_id, tag_id) +INSERT INTO dish_allergens (dish_id, allergen) VALUES - ('eeeeeeee-1111-1111-1111-eeeeeeeeeeee', 'a0000000-0000-0000-0000-000000000006'), --gluten - ('eeeeeeee-1111-1111-1111-eeeeeeeeeeee', 'a0000000-0000-0000-0000-000000000007'); --lactose + ('eeeeeeee-1111-1111-1111-eeeeeeeeeeee', 'GLUTEN'), + ('eeeeeeee-1111-1111-1111-eeeeeeeeeeee', 'LACTOSE'), + ('eeeeeeee-1111-1111-1111-eeeeeeeeeeee', 'MEAT'); INSERT INTO restaurant_owners (restaurant_id, user_id) VALUES ( diff --git a/src/main/resources/db/migration/V4__tag_chema.sql b/src/main/resources/db/migration/V4__tag_chema.sql deleted file mode 100644 index ee93984..0000000 --- a/src/main/resources/db/migration/V4__tag_chema.sql +++ /dev/null @@ -1,23 +0,0 @@ -CREATE TABLE tags ( - id UUID NOT NULL PRIMARY KEY, - tag_value VARCHAR(50) NOT NULL UNIQUE -); - -CREATE TABLE dish_tags ( - dish_id UUID NOT NULL, - tag_id UUID NOT NULL, - PRIMARY KEY (dish_id, tag_id) -); - -CREATE TABLE user_preferences ( - id UUID NOT NULL PRIMARY KEY, - user_id VARCHAR(255) NOT NULL, - tag_id UUID NOT NULL, - preference_type VARCHAR(20) NOT NULL CHECK (preference_type IN ('INCLUDE', 'EXCLUDE')), - CONSTRAINT uq_user_tag UNIQUE (user_id, tag_id) -); - -alter table if exists dish_tags add constraint fk_dish_tags_dish foreign key (dish_id) references dish; -alter table if exists dish_tags add constraint fk_dish_tags_tag foreign key (tag_id) references tags; -alter table if exists user_preferences add constraint fk_user_preferences_user foreign key (user_id) references keycloak_user; -alter table if exists user_preferences add constraint fk_user_preferences_tag foreign key (tag_id) references tags; \ No newline at end of file diff --git a/src/main/resources/db/migration/V5__seed_tags.sql b/src/main/resources/db/migration/V5__seed_tags.sql deleted file mode 100644 index dcfec9e..0000000 --- a/src/main/resources/db/migration/V5__seed_tags.sql +++ /dev/null @@ -1,16 +0,0 @@ -INSERT INTO tags (id, tag_value) VALUES - -- Cuisine - ('a0000000-0000-0000-0000-000000000001', 'ITALIAN'), - ('a0000000-0000-0000-0000-000000000002', 'POLISH'), - ('a0000000-0000-0000-0000-000000000003', 'ASIAN'), - ('a0000000-0000-0000-0000-000000000004', 'FAST_FOOD'), - - -- Allergen - ('a0000000-0000-0000-0000-000000000005', 'NUTS'), - ('a0000000-0000-0000-0000-000000000006', 'GLUTEN'), - ('a0000000-0000-0000-0000-000000000007', 'LACTOSE'), - - -- Dietary - ('a0000000-0000-0000-0000-000000000008', 'VEGAN'), - ('a0000000-0000-0000-0000-000000000009', 'VEGETARIAN') -ON CONFLICT (id) DO NOTHING; \ No newline at end of file diff --git a/src/main/resources/db/migration/V6__remove_dish_allergens.sql b/src/main/resources/db/migration/V6__remove_dish_allergens.sql deleted file mode 100644 index 3a9d64c..0000000 --- a/src/main/resources/db/migration/V6__remove_dish_allergens.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE dish DROP CONSTRAINT IF EXISTS FKm9q52lhbluv5a316ehhmhb57u; -DROP TABLE dish_allergens; \ No newline at end of file diff --git a/src/main/resources/db/migration/V7__add_sesame_tag.sql b/src/main/resources/db/migration/V7__add_sesame_tag.sql deleted file mode 100644 index a72c54a..0000000 --- a/src/main/resources/db/migration/V7__add_sesame_tag.sql +++ /dev/null @@ -1,3 +0,0 @@ -INSERT INTO tags (id, tag_value) VALUES - ('a0000000-0000-0000-0000-000000000010', 'SESAME') -ON CONFLICT (id) DO NOTHING; \ No newline at end of file diff --git a/src/test/java/com/backend/controllersTests/RestaurantControllerTest.java b/src/test/java/com/backend/controllersTests/RestaurantControllerTest.java index b10bd99..cb939e2 100644 --- a/src/test/java/com/backend/controllersTests/RestaurantControllerTest.java +++ b/src/test/java/com/backend/controllersTests/RestaurantControllerTest.java @@ -4,7 +4,6 @@ import com.backend.filters.SaveUserFilter; import com.backend.model.dtos.RestaurantDetailsDTO; import com.backend.model.entities.Restaurant; -import com.backend.services.RecommendationService; import com.backend.services.RestaurantService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -40,9 +39,6 @@ class RestaurantControllerTest { @MockitoBean private RestaurantService restaurantService; - @MockitoBean - private RecommendationService recommendationService; - @Test void shouldReturnRestaurantById() throws Exception { diff --git a/src/test/java/com/backend/model/MenuProcessingListenerTest.java b/src/test/java/com/backend/model/MenuProcessingListenerTest.java index d6ae1b4..eaea5f2 100644 --- a/src/test/java/com/backend/model/MenuProcessingListenerTest.java +++ b/src/test/java/com/backend/model/MenuProcessingListenerTest.java @@ -58,7 +58,7 @@ void shouldCreateDraftAfterSuccessfulAiProcessing() { Dish parsedDish = new Dish(); parsedDish.setName("Tomato soup"); parsedDish.setCategory(Dish.Category.SOUP); - parsedDish.setTags(Set.of()); + parsedDish.setAllergens(Set.of()); MessageDTO message = new MessageDTO(menuId, restaurantId, LocalDate.now(), new byte[] {1, 2, 3}, "menu.jpg", "owner-1"); diff --git a/src/test/java/com/backend/servicesTests/MenuServiceTest.java b/src/test/java/com/backend/servicesTests/MenuServiceTest.java index a5782e3..18546ba 100644 --- a/src/test/java/com/backend/servicesTests/MenuServiceTest.java +++ b/src/test/java/com/backend/servicesTests/MenuServiceTest.java @@ -6,7 +6,6 @@ import com.backend.model.entities.DailyMenu; import com.backend.model.entities.Dish; import com.backend.model.entities.Restaurant; -import com.backend.model.entities.Tag; import com.backend.model.entities.User; import com.backend.repositories.DailyMenuRepository; import com.backend.repositories.DishRepository; @@ -247,7 +246,7 @@ void shouldUpdateAndApproveMenu() { dishDTO.setName("Pizza"); dishDTO.setCategory("MAIN_COURSE"); dishDTO.setPrice(BigDecimal.valueOf(25.0)); - dishDTO.setTags(Set.of()); + dishDTO.setAllergens(Set.of(Dish.Allergens.GLUTEN)); DailyMenuDTO request = new DailyMenuDTO(); request.setDate(LocalDate.now()); @@ -290,10 +289,7 @@ void shouldCreateMenu() { dishDTO.setName("Pizza"); dishDTO.setCategory("MAIN_COURSE"); dishDTO.setPrice(BigDecimal.valueOf(25.0)); - - Tag gluten = new Tag(); - gluten.setValue(Tag.TagValue.GLUTEN); - dishDTO.setTags(Set.of(gluten)); + dishDTO.setAllergens(Set.of(Dish.Allergens.GLUTEN)); DailyMenuDTO request = new DailyMenuDTO(); request.setDate(LocalDate.now()); @@ -380,7 +376,7 @@ void shouldScheduleFuturePublishedMenu() { dishDTO.setName("Soup"); dishDTO.setCategory("SOUP"); dishDTO.setPrice(BigDecimal.valueOf(19.0)); - dishDTO.setTags(Set.of()); + dishDTO.setAllergens(Set.of()); DailyMenuDTO request = new DailyMenuDTO(); request.setDate(futureDate); @@ -422,11 +418,7 @@ void shouldAllowEditingScheduledMenuById() { dishDTO.setName("Edited Pizza"); dishDTO.setCategory("MAIN_COURSE"); dishDTO.setPrice(BigDecimal.valueOf(31.0)); - - Tag gluten = new Tag(); - gluten.setValue(Tag.TagValue.GLUTEN); - - dishDTO.setTags(Set.of(gluten)); + dishDTO.setAllergens(Set.of(Dish.Allergens.GLUTEN)); DailyMenuDTO request = new DailyMenuDTO(); request.setId(menuId); diff --git a/src/test/java/com/backend/servicesTests/RecommendationServiceTest.java b/src/test/java/com/backend/servicesTests/RecommendationServiceTest.java deleted file mode 100644 index 21f01f1..0000000 --- a/src/test/java/com/backend/servicesTests/RecommendationServiceTest.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.backend.servicesTests; - -import com.backend.model.dtos.RankedRestaurantDTO; -import com.backend.model.entities.*; -import com.backend.repositories.RestaurantRepository; -import com.backend.repositories.UserRepository; -import com.backend.services.RecommendationService; -import org.junit.jupiter.api.BeforeEach; -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.util.List; -import java.util.Set; -import java.util.UUID; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class RecommendationServiceTest { - - @Mock - private RestaurantRepository restaurantRepository; - - @Mock - private UserRepository userRepository; - - @InjectMocks - private RecommendationService recommendationService; - - private User user; - - @BeforeEach - void setup() { - user = new User(); - user.setId(UUID.randomUUID().toString()); - } - - @Test - void shouldReturnVeryLowScoreWhenNoActiveMenu() { - - Restaurant restaurant = new Restaurant(); - restaurant.setName("No active menu"); - - DailyMenu inactive = new DailyMenu(); - inactive.setStatus(DailyMenu.Status.INACTIVE); - - restaurant.setDailyMenus(Set.of(inactive)); - - when(userRepository.findById(user.getId())) - .thenReturn(java.util.Optional.of(user)); - - when(restaurantRepository.findAllRestaurantsWithTodayMenu()) - .thenReturn(List.of(restaurant)); - - List result = - recommendationService.getRankedRestaurants(user.getId()); - - assertEquals(1, result.size()); - - assertEquals(-Double.MAX_VALUE, result.getFirst().score()); - } - - @Test - void shouldGiveHigherScoreForMatchingDietaryTags() { - - Tag vegan = new Tag(); - vegan.setValue(Tag.TagValue.VEGAN); - - UserPreference pref = new UserPreference(); - pref.setPreferenceType(UserPreference.PreferenceType.INCLUDE); - pref.setTag(vegan); - - user.setPreferences(List.of(pref)); - - Dish dish = new Dish(); - dish.setTags(Set.of(vegan)); - - DailyMenu menu = new DailyMenu(); - menu.setStatus(DailyMenu.Status.ACTIVE); - menu.setDishes(List.of(dish)); - - Restaurant restaurant = new Restaurant(); - restaurant.setDailyMenus(Set.of(menu)); - - when(userRepository.findById(user.getId())) - .thenReturn(java.util.Optional.of(user)); - - when(restaurantRepository.findAllRestaurantsWithTodayMenu()) - .thenReturn(List.of(restaurant)); - - List result = - recommendationService.getRankedRestaurants(user.getId()); - - assertTrue(result.getFirst().score() > 0); - } - - @Test - void shouldPenalizeExcludedTags() { - - Tag nuts = new Tag(); - nuts.setValue(Tag.TagValue.NUTS); - - UserPreference pref = new UserPreference(); - pref.setPreferenceType(UserPreference.PreferenceType.EXCLUDE); - pref.setTag(nuts); - - user.setPreferences(List.of(pref)); - - Dish dish = new Dish(); - dish.setTags(Set.of(nuts)); - - DailyMenu menu = new DailyMenu(); - menu.setStatus(DailyMenu.Status.ACTIVE); - menu.setDishes(List.of(dish)); - - Restaurant restaurant = new Restaurant(); - restaurant.setDailyMenus(Set.of(menu)); - - when(userRepository.findById(user.getId())) - .thenReturn(java.util.Optional.of(user)); - - when(restaurantRepository.findAllRestaurantsWithTodayMenu()) - .thenReturn(List.of(restaurant)); - - List result = - recommendationService.getRankedRestaurants(user.getId()); - - assertTrue(result.getFirst().score() < 0); - } - - @Test - void shouldSortRestaurantsByScoreDescending() { - - Tag vegan = new Tag(); - vegan.setValue(Tag.TagValue.VEGAN); - - UserPreference pref = new UserPreference(); - pref.setPreferenceType(UserPreference.PreferenceType.INCLUDE); - pref.setTag(vegan); - - user.setPreferences(List.of(pref)); - - Dish matchingDish = new Dish(); - matchingDish.setTags(Set.of(vegan)); - - Dish nonMatchingDish = new Dish(); - nonMatchingDish.setTags(Set.of()); - - DailyMenu active1 = new DailyMenu(); - active1.setStatus(DailyMenu.Status.ACTIVE); - active1.setDishes(List.of(matchingDish)); - - DailyMenu active2 = new DailyMenu(); - active2.setStatus(DailyMenu.Status.ACTIVE); - active2.setDishes(List.of(nonMatchingDish)); - - Restaurant better = new Restaurant(); - better.setName("Better"); - better.setDailyMenus(Set.of(active1)); - - Restaurant worse = new Restaurant(); - worse.setName("Worse"); - worse.setDailyMenus(Set.of(active2)); - - when(userRepository.findById(user.getId())) - .thenReturn(java.util.Optional.of(user)); - - when(restaurantRepository.findAllRestaurantsWithTodayMenu()) - .thenReturn(List.of(worse, better)); - - List result = - recommendationService.getRankedRestaurants(user.getId()); - - assertEquals("Better", - result.get(0).restaurant().getName()); - } -} \ No newline at end of file diff --git a/src/test/java/com/backend/servicesTests/RestaurantServiceTest.java b/src/test/java/com/backend/servicesTests/RestaurantServiceTest.java index 19ff799..72d3a33 100644 --- a/src/test/java/com/backend/servicesTests/RestaurantServiceTest.java +++ b/src/test/java/com/backend/servicesTests/RestaurantServiceTest.java @@ -84,7 +84,7 @@ void setUp() { dailyMenu.setId(UUID.randomUUID()); dailyMenu.setStatus(DailyMenu.Status.ACTIVE); - Set dailyMenus = new HashSet<>(); + List dailyMenus = new ArrayList<>(); dailyMenus.add(dailyMenu); restaurant.setDailyMenus(dailyMenus);