Skip to content
Snippets Groups Projects
Commit 8cac6efc authored by Anders Austlid's avatar Anders Austlid
Browse files

Merge remote-tracking branch 'origin/main' into bugfix/fix-tests

# Conflicts:
#	src/main/java/ntnu/idatt2016/v233/SmartMat/service/group/FridgeService.java
parents ac71a377 156d79a7
No related branches found
No related tags found
No related merge requests found
Showing
with 182 additions and 62 deletions
......@@ -134,8 +134,10 @@ public class ShoppingListController {
if(product.isEmpty())
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
System.out.println("Removing product from shopping list : " + shoppingListId + " - " + ean);
Optional<ShoppingList> returnVal = shoppingListService
.removeProductFromShoppingList(Long.parseLong(shoppingListId), Long.parseLong(ean));
.removeProductFromShoppingList(Long.parseLong(ean), Long.parseLong(shoppingListId));
return returnVal.map(list -> ResponseEntity.status(HttpStatus.OK).body(list))
.orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND).build());
......
......@@ -114,24 +114,5 @@ public class FridgeController {
return fridgeService.wasteProductFromFridge(fridgeProductId).map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
/**
* Deletes all products in a fridge
* @param fridgeId the id of the fridge
* @return success if the products were deleted, bad request if the fridge doesn't exist
*
@DeleteMapping("/delete/all/{fridgeId}")
public ResponseEntity<String> deleteAllProductsInFridge(@PathVariable("fridgeId") long fridgeId) {
try {
boolean success = fridgeService.deleteAllProductsInFridge(fridgeId);
if (success){
return ResponseEntity.ok("Success");
}
return ResponseEntity.badRequest().body("Fridge not found");
} catch (Exception e) {
return ResponseEntity.status(500).body("Internal server error");
}
}
*/
}
......@@ -19,6 +19,7 @@ import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.stream.Collectors;
/**
* Controller for groups API, providing endpoints for group management
......@@ -324,4 +325,59 @@ public class GroupController {
}
}
/**
* Handles the HTTP DELETE request to remove a user from a group.
* @param auth the authentication object containing the username of the user
* @return a ResponseEntity object containing the list of groups the user is associated with and an HTTP status code of 200,
*/
@GetMapping("/")
public ResponseEntity<List<UserGroupAsso>> getAllGroupsByUser(Authentication auth) {
return ResponseEntity.ok(groupService.getUserGroupAssoByUserName(auth.getName()));
}
/**
* Handles the HTTP DELETE request to remove a user from a group.
* @param groupId the ID of the group to get the members of
* @param username the username of the user to remove from the group
* @param auth the authentication object containing the username of the user
* @return a ResponseEntity object containing the list of groups the
* user is associated with and an HTTP status code of 200,
*/
@DeleteMapping("/removeUser/{groupId}/{username}")
public ResponseEntity<?> removeUserFromGroup(@PathVariable("groupId") long groupId,
@PathVariable("username") String username,
Authentication auth) {
Optional<User> groupAdminOpt = userService.getUserFromUsername(auth.getName());
if (groupAdminOpt.isPresent()) {
User groupAdmin = groupAdminOpt.get();
if (!(groupService.isUserAssociatedWithGroup(groupAdmin.getUsername(), groupId)
&& (groupService.getUserGroupAssoAuthority(groupAdmin.getUsername(), groupId).equals("ADMIN"))
|| groupAdmin.getUsername().equals(username)))
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("You are not authorized to remove this user.");
}
Optional<Group> groupOpt = groupService.getGroupById(groupId);
Optional<User> userOpt = userService.getUserFromUsername(username);
if (groupOpt.isEmpty() || userOpt.isEmpty()) {
return ResponseEntity.notFound().build();
}
User user = userOpt.get();
UserGroupAsso userGroupAsso = user.getGroup().stream()
.filter(asso -> asso.getGroup().getGroupId() == groupId)
.findFirst()
.orElse(null);
if (userGroupAsso != null) {
groupService.removeUserFromGroup(userGroupAsso);
return ResponseEntity.ok("User removed successfully.");
} else {
return ResponseEntity.notFound().build();
}
}
}
......@@ -79,4 +79,40 @@ public class WasteController {
return wasteService.getCakeDiagram(groupId).map(ResponseEntity::ok).orElseGet(()->ResponseEntity.notFound().build());
}
/**
* Get the information of the last months of a specific group.
*
* @param groupId the id of the group to get the information for
* @return a ResponseEntity object containing an array of doubles representing the waste for each category
* in the last four months, or a not found response if the group does not exist or has no waste data
*/
@GetMapping("/statistic/lastMonths/{groupId}")
public ResponseEntity<double[]> getInformationOfLastMoths(@PathVariable("groupId") long groupId){
return wasteService.getLastMonth(groupId).map(ResponseEntity::ok).orElseGet(()->ResponseEntity.notFound().build());
}
/**
* Retrieves the amount of money lost due to expired products in a specific group.
* The amount is calculated based on the total cost of the expired products.
*
* @param groupId the ID of the group to retrieve the lost money from
* @return a ResponseEntity with the lost money as a Double if found, or a ResponseEntity with status 404 if the group is not found
*/
@GetMapping("/statistic/lostMoney/{groupId}")
public ResponseEntity<Double> getLostMoney(@PathVariable("groupId") long groupId){
return wasteService.getLostMoney(groupId).map(ResponseEntity::ok).orElseGet(()->ResponseEntity.notFound().build());
}
/**
* Retrieves the amount of CO2 emitted annually per person in a specific group.
*
* @param groupId the ID of the group to retrieve the statistic for
* @return a ResponseEntity containing the amount of CO2 emitted annually per person in the group,
* or a ResponseEntity with HTTP status 404 (not found) if the group or data is not found
*/
@GetMapping("/statistic/annuallyCO2/{groupId}")
public ResponseEntity<Double> getCO2Annually(@PathVariable("groupId") long groupId){
return wasteService.getCO2PerPerson(groupId).map(ResponseEntity::ok).orElseGet(()->ResponseEntity.notFound().build());
}
}
......@@ -8,6 +8,7 @@ import ntnu.idatt2016.v233.SmartMat.service.AllergyService;
import ntnu.idatt2016.v233.SmartMat.service.product.CategoryService;
import ntnu.idatt2016.v233.SmartMat.service.product.ProductService;
import ntnu.idatt2016.v233.SmartMat.util.CategoryUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
......@@ -110,13 +111,13 @@ public class ProductController {
* @return The product that was deleted.
*/
@DeleteMapping("ean/{ean}")
public ResponseEntity<Product> deleteProduct(@PathVariable long ean) {
public ResponseEntity<String> deleteProduct(@PathVariable long ean) {
Optional<Product> product = productService.getProductById(ean);
if(product.isPresent()) {
productService.deleteProductById(product.get().getEan());
return ResponseEntity.ok(product.get());
return ResponseEntity.ok("Product deleted");
}
return ResponseEntity.notFound().build();
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Product not found");
}
......
......@@ -6,16 +6,19 @@ import ntnu.idatt2016.v233.SmartMat.dto.request.AllergyRequest;
import ntnu.idatt2016.v233.SmartMat.dto.request.RegisterUserRequest;
import ntnu.idatt2016.v233.SmartMat.dto.enums.Authority;
import ntnu.idatt2016.v233.SmartMat.dto.request.UpdateUserRequest;
import ntnu.idatt2016.v233.SmartMat.entity.product.Allergy;
import ntnu.idatt2016.v233.SmartMat.entity.user.User;
import ntnu.idatt2016.v233.SmartMat.service.user.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Optional;
import java.util.stream.Collectors;
/**
......@@ -105,14 +108,13 @@ public class UserController {
* @return a ResponseEntity with a boolean indicating whether the operation was successful
*/
@PostMapping("/addAllergy")
public ResponseEntity<Boolean> addAllergyToUser(@RequestBody AllergyRequest allergyRequest) {
try {
return userService.addAllergyToUser(allergyRequest.getUsername(), allergyRequest.getAllergyName())
.map(user -> ResponseEntity.ok(user.getAllergies().size() > 0))
.orElseGet(() -> ResponseEntity.notFound().build());
}catch (Exception e){
return ResponseEntity.status(409).body(false);
}
public ResponseEntity<String> addAllergyToUser(@RequestBody AllergyRequest allergyRequest,
Authentication authentication) {
if(!allergyRequest.getUsername().equals(authentication.getName()) &&
!authentication.getAuthorities().contains(new SimpleGrantedAuthority(Authority.ADMIN.name())))
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
return userService.addAllergyToUser(allergyRequest.getUsername(), allergyRequest.getAllergyName());
}
/**
......@@ -122,14 +124,14 @@ public class UserController {
* @return a ResponseEntity with a boolean indicating whether the operation was successful
*/
@DeleteMapping("/deleteAllergy")
public ResponseEntity<Boolean> deleteAllergyFromUser(@RequestBody AllergyRequest allergyRequest) {
try {
return userService.deleteAllergy(allergyRequest.getUsername(), allergyRequest.getAllergyName())
.map(user -> ResponseEntity.ok(true))
.orElseGet(() -> ResponseEntity.notFound().build());
}catch (Exception e){
return ResponseEntity.status(409).body(false);
}
public ResponseEntity<String> deleteAllergyFromUser(@RequestBody AllergyRequest allergyRequest,
Authentication authentication) {
if(!allergyRequest.getUsername().equals(authentication.getName()) &&
!authentication.getAuthorities().contains(new SimpleGrantedAuthority(Authority.ADMIN.name())))
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
return userService.removeAllergyFromUser(allergyRequest.getUsername(), allergyRequest.getAllergyName());
}
......
......@@ -3,7 +3,6 @@ package ntnu.idatt2016.v233.SmartMat.dto.request;
/**
* FridgeProductRequest is a record class representing a request to add a product to a fridge.
* @param groupId the id of the group
* @param productId the id of the product
*/
public record FridgeProductRequest(long fridgeProductId, long groupId, long ean, int amount, int days) {
public record FridgeProductRequest(long fridgeProductId, long groupId, long ean, int amount, int days, double price) {
}
......@@ -40,6 +40,12 @@ public class Recipe {
@Column(name = "recipe_description")
String description;
@Column(name = "image_url")
String imageUrl;
@Column(name = "guide")
String guide;
@ManyToMany(fetch = FetchType.LAZY,
cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}
,mappedBy = "recipes"
......
......@@ -53,4 +53,7 @@ public class Waste {
@Column(name = "unit")
String unit;
@Column(name = "buy_price")
double buyPrice;
}
......@@ -2,6 +2,8 @@ package ntnu.idatt2016.v233.SmartMat.entity.fridgeProduct;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonIncludeProperties;
import jakarta.persistence.*;
import lombok.*;
import ntnu.idatt2016.v233.SmartMat.entity.group.Fridge;
......@@ -11,7 +13,7 @@ import java.sql.Date;
@AllArgsConstructor
@NoArgsConstructor
@Getter @Setter
@Data
@Entity(name = "fridge_product")
@Builder
public class FridgeProductAsso {
......@@ -23,12 +25,13 @@ public class FridgeProductAsso {
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinColumn(name = "fridge_id")
@JsonIgnoreProperties({"products"})
@JsonIgnore
private Fridge fridgeId;
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinColumn(name = "ean")
@JsonIgnoreProperties({"fridges"})
@JsonIncludeProperties({"HibernateLazyInitializer", "handler", "ean", "name", "description", "category",
"url", "allergies", "bestBefore", "expirationDate", "unit", "amount"})
private Product ean;
@Column(name = "purchase_date")
......@@ -40,5 +43,8 @@ public class FridgeProductAsso {
@Column(name = "amount")
private double amount;
@Column(name = "buy_price")
private double buyPrice;
}
......@@ -42,7 +42,7 @@ public class Fridge{
@OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH},
fetch = FetchType.LAZY, mappedBy = "fridgeId")
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonIgnoreProperties("fridge")
@JsonIgnoreProperties("fridgeId")
List<FridgeProductAsso> products;
......
......@@ -56,8 +56,10 @@ public class Group {
private ShoppingList shoppingList;
@OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH},
fetch = FetchType.LAZY, mappedBy = "group")
@OneToMany(cascade = {CascadeType.ALL},
fetch = FetchType.LAZY, mappedBy = "group",
orphanRemoval = true
)
@JsonIgnoreProperties("group")
private List<UserGroupAsso> user = new ArrayList<>();
......
package ntnu.idatt2016.v233.SmartMat.entity.group;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
import lombok.*;
......@@ -26,13 +27,13 @@ public class UserGroupAsso {
@ManyToOne
@MapsId("username")
@JoinColumn(name = "username")
@JsonIgnoreProperties("group")
@JsonIgnore
private User user;
@ManyToOne
@MapsId("group_id")
@JoinColumn(name = "group_id")
@JsonIgnoreProperties({"group", "user"})
@JsonIgnoreProperties({"user", "fridge", "shoppingList"})
private Group group;
@Column(name = "primary_group")
......
......@@ -9,6 +9,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import ntnu.idatt2016.v233.SmartMat.entity.user.User;
import java.util.ArrayList;
import java.util.List;
/**
......@@ -49,4 +50,15 @@ public class Allergy{
@JsonIgnore
private List<User> users;
/**
* adds a user to the allergy
* @param tempuser adds a user to the list of users with this allergy
*/
public void addUser(User tempuser) {
if (users == null)
users = new ArrayList<>();
users.add(tempuser);
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package ntnu.idatt2016.v233.SmartMat.entity.product;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonIncludeProperties;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
......@@ -52,7 +53,7 @@ public class Product{
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH},
fetch = FetchType.LAZY)
@JoinColumn(name = "category_name")
@JsonIgnore
@JsonIncludeProperties("categoryName")
Category category;
@Column(name = "image_url")
......@@ -72,13 +73,12 @@ public class Product{
@ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH},
fetch = FetchType.LAZY, mappedBy = "products")
@JsonIgnoreProperties({"products", "users"})
@JsonIncludeProperties("name")
List<Allergy> allergies;
@OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH},
fetch = FetchType.LAZY, mappedBy = "ean")
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonIgnoreProperties({"products"})
@JsonIgnore
List<FridgeProductAsso> fridges;
......
......@@ -55,13 +55,13 @@ public class User implements UserDetails {
private Date dateOfBirth;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "username")
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
@JsonIgnore
private List<UserGroupAsso> group;
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH},
@ManyToMany(fetch = FetchType.LAZY,
cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH},
mappedBy = "users")
@JsonIgnoreProperties({"users", "products"})
private List<Allergy> allergies;
......
......@@ -78,7 +78,7 @@ public interface RecipeRepository extends JpaRepository<Recipe, Long> {
List<Object[]> findTop5RecipesWithProductsRaw(@Param("fridgeId") long fridgeId);
@Query( value = """
SELECT r.recipe_id, r.recipe_name,r.recipe_description, COUNT(fp.ean) as product_count
SELECT r.recipe_id, r.recipe_name,r.recipe_description,r.image_url,r.guide, COUNT(fp.ean) as product_count
FROM recipe r
LEFT JOIN recipe_product rp ON r.recipe_id = rp.recipe_id
LEFT JOIN fridge_product fp ON rp.ean = fp.ean AND fp.fridge_id = :fridgeId
......
......@@ -47,4 +47,7 @@ public interface GroupRepository extends JpaRepository<Group, Long> {
Optional<Group> findByLinkCode(String linkCode);
@Query(value = "SELECT count(*) FROM user_group where group_id = :groupId", nativeQuery = true)
int countAllUserInGroup(@Param("groupId") long groupId);
}
......@@ -73,4 +73,12 @@ public interface UserGroupAssoRepository extends JpaRepository<UserGroupAsso, Us
* @return
*/
String findAuthorityByUser_UsernameAndGroup_GroupId(String username, long groupId);
/**
* Finds all groups a user is a member of
* @param username the username of the user
* @return a list of all groups the user is a member of
*/
List<UserGroupAsso> findAllByUserUsername(String username);
}
......@@ -78,6 +78,7 @@ public class ShoppingListService {
shoppingListRepository.findById(shoppingListId).ifPresent(shoppingList -> {
productRepository.findById(ean).ifPresent(product -> {
shoppingList.addProduct(product);
product.addShoppingList(shoppingList);
shoppingListRepository.save(shoppingList);
});
});
......@@ -92,11 +93,12 @@ public class ShoppingListService {
* @return the shopping list that the product was removed from
*/
public Optional<ShoppingList> removeProductFromShoppingList(long ean, long shoppingListId){
System.out.println("shopping list status : " + shoppingListRepository.findById(shoppingListId).isPresent());
shoppingListRepository.findById(shoppingListId).ifPresent(shoppingList -> {
productRepository.findById(ean).ifPresent(product -> {
shoppingList.getProducts().remove(product);
product.getShoppingLists().remove(shoppingList);
productRepository.save(product);
shoppingListRepository.save(shoppingList);
});
});
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment