diff --git a/README.md b/README.md index 743073eef..4169bad1b 100755 --- a/README.md +++ b/README.md @@ -252,6 +252,7 @@ In the Vite Dev mode browsers will typically send out a Warning("Source-Map-Fehl * 201: There are parameters missing to create a dish * 202: One or more titles haven't been sent * 203: There was an error while counting the number of times dishes were taken + * 204: The servingSize cannot be adjusted, because there are booked combi-meals *CategoryController 3xx* * 301: The choosen titles for the category either are missing or do already exist *ParticipantController 4xx* diff --git a/src/Mealz/MealBundle/Controller/MealAdminController.php b/src/Mealz/MealBundle/Controller/MealAdminController.php index a3cae6020..9fe6f859e 100644 --- a/src/Mealz/MealBundle/Controller/MealAdminController.php +++ b/src/Mealz/MealBundle/Controller/MealAdminController.php @@ -213,6 +213,10 @@ private function handleDay(array $day): void throw new Exception('106: too many meals requested'); } + if (false === $this->dayService->checkMealsUpdatable($dayEntity, $mealCollection)) { + throw new Exception('108: Meals must not have participations when being updated'); + } + $this->dayService->removeUnusedMeals($dayEntity, $mealCollection); // parentMeal is an array of either one meal without variations or 1-2 variations diff --git a/src/Mealz/MealBundle/Repository/DishRepository.php b/src/Mealz/MealBundle/Repository/DishRepository.php index b4166c39f..eeffa7dbc 100644 --- a/src/Mealz/MealBundle/Repository/DishRepository.php +++ b/src/Mealz/MealBundle/Repository/DishRepository.php @@ -6,6 +6,7 @@ use App\Mealz\MealBundle\Entity\Dish; use App\Mealz\MealBundle\Entity\Meal; +use App\Mealz\MealBundle\Entity\Participant; use App\Mealz\MealBundle\EventListener\LocalisationListener; use DateTime; use Doctrine\DBAL\Types\Types; @@ -80,6 +81,43 @@ public function hasDishAssociatedMeals(Dish $dish): bool return 0 < $query->getQuery()->getSingleScalarResult(); } + /** + * @throws NoResultException + * @throws NonUniqueResultException + */ + public function hasDishAssociatedCombiMealsInFuture(Dish $dish): bool + { + $today = new DateTime('today'); + $formattedDate = $today->format('Y-m-d') . ' 12:00:00.000000'; + + $mealRepo = $this->getEntityManager()->getRepository(Meal::class); + $participantRepo = $this->getEntityManager()->getRepository(Participant::class); + $dayQuery = $mealRepo->createQueryBuilder('m') + ->select('DISTINCT d.id') + ->join('m.day', 'd') + ->join('m.dish', 'g') + ->where('g.slug = :slug') + ->setParameter('slug', 'combined-dish'); + + $mealQuery = $mealRepo->createQueryBuilder('m2') + ->select('m2.id') + ->where('m2.day IN (' . $dayQuery->getDQL() . ')') + ->andWhere('m2.dish = :dishId') + ->andWhere('m2.dateTime >= :now') + ->setParameter('dishId', $dish->getId()) + ->setParameter('now', $formattedDate); + + $query = $participantRepo->createQueryBuilder('p') + ->select('COUNT(p.id)') + ->join('p.meal', 'm3') + ->where('m3.id IN (' . $mealQuery->getDQL() . ')') + ->setParameter('slug', 'combined-dish') + ->setParameter('dishId', $dish->getId()) + ->setParameter('now', $formattedDate); + + return 0 < $query->getQuery()->getSingleScalarResult(); + } + /** * Counts the number of Dish was taken in the last X Weeks. * diff --git a/src/Mealz/MealBundle/Repository/DishRepositoryInterface.php b/src/Mealz/MealBundle/Repository/DishRepositoryInterface.php index 1647ac4dc..fe040949f 100644 --- a/src/Mealz/MealBundle/Repository/DishRepositoryInterface.php +++ b/src/Mealz/MealBundle/Repository/DishRepositoryInterface.php @@ -17,6 +17,8 @@ public function getSortedDishesQueryBuilder(array $options = []): QueryBuilder; public function hasDishAssociatedMeals(Dish $dish): bool; + public function hasDishAssociatedCombiMealsInFuture(Dish $dish): bool; + /** * Counts the number of Dish was taken in the last X Weeks. */ diff --git a/src/Mealz/MealBundle/Service/DayService.php b/src/Mealz/MealBundle/Service/DayService.php index 1af3b355a..9d9be4fbf 100644 --- a/src/Mealz/MealBundle/Service/DayService.php +++ b/src/Mealz/MealBundle/Service/DayService.php @@ -7,18 +7,22 @@ use App\Mealz\MealBundle\Entity\Day; use App\Mealz\MealBundle\Entity\Meal; use App\Mealz\MealBundle\Repository\MealRepositoryInterface; +use App\Mealz\MealBundle\Repository\ParticipantRepositoryInterface; use Doctrine\ORM\EntityManagerInterface; class DayService { private MealRepositoryInterface $mealRepository; + private ParticipantRepositoryInterface $participantRepo; private EntityManagerInterface $em; public function __construct( MealRepositoryInterface $mealRepository, + ParticipantRepositoryInterface $participantRepo, EntityManagerInterface $entityManager ) { $this->mealRepository = $mealRepository; + $this->participantRepo = $participantRepo; $this->em = $entityManager; } @@ -60,6 +64,25 @@ public function removeUnusedMeals(Day $day, array $mealCollection): void } } + public function checkMealsUpdatable(Day $day, array $mealCollection): bool + { + $flattenedMeals = array_merge(...array_values($mealCollection)); + $mealIdsOfCol = array_map( + fn ($meal) => $meal['mealId'], + $flattenedMeals + ); + $mealsToUpdate = $day->getMeals()->filter(fn ($meal) => false === in_array($meal->getId(), $mealIdsOfCol)); + + /** @var Meal $meal */ + foreach ($mealsToUpdate as $meal) { + if (true === $meal->hasParticipations()) { + return false; + } + } + + return true; + } + private function removeUnusedMealHelper(Meal $mealEntity, array $mealCollection, Day $day): void { $canRemove = true; diff --git a/src/Mealz/MealBundle/Service/DishService.php b/src/Mealz/MealBundle/Service/DishService.php index dbf28edf2..a6599fb0f 100644 --- a/src/Mealz/MealBundle/Service/DishService.php +++ b/src/Mealz/MealBundle/Service/DishService.php @@ -58,8 +58,8 @@ public function isNew(Dish $dish): bool */ public function updateHelper(Dish $dish, array $parameters): void { - $this->setTitleIfValid($dish, $parameters); $this->setServingSizeIfValid($dish, $parameters); + $this->setTitleIfValid($dish, $parameters); $this->setDescriptionIfValid($dish, $parameters); $this->setCategoryIfValid($dish, $parameters); $this->setDietIfValid($dish, $parameters); @@ -119,6 +119,10 @@ private function setDescriptionIfValid(Dish $dish, array $parameters): void private function setServingSizeIfValid(Dish $dish, array $parameters): void { if (true === $this->apiService->isParamValid($parameters, 'oneServingSize', 'boolean')) { + if (true === $this->hasCombiMealsInFuture($dish)) { + throw new Exception('204: The servingSize cannot be adjusted, because there are booked combi-meals'); + } + $dish->setOneServingSize($parameters['oneServingSize']); if (true === $dish->hasVariations()) { /** @var Dish $variation */ @@ -138,4 +142,9 @@ private function setTitleIfValid(Dish $dish, array $parameters): void $dish->setTitleEn($parameters['titleEn']); } } + + private function hasCombiMealsInFuture(Dish $dish): bool + { + return $this->dishRepository->hasDishAssociatedCombiMealsInFuture($dish); + } } diff --git a/src/Resources/src/locales/de.json b/src/Resources/src/locales/de.json index e583998e2..f83a399e2 100644 --- a/src/Resources/src/locales/de.json +++ b/src/Resources/src/locales/de.json @@ -159,6 +159,7 @@ "201": "Es fehlen noch Informationen um das Gericht estellen zu können.", "202": "Ein oder mehrere Titel für das zu erstellende Gericht scheinen zu fehlen.", "203": "Es gab einen fehler beim zählen, wie häufig einzelne Gerichte bestellt wurden.", + "204": "Das Gericht kann nicht aktualisiert werden, da es in gebuchten Kombi-Meals enthalten ist.", "301": "Die gewählten Titel für die Kategorie fehlen oder existieren schon.", "401": "Um einen Benutzer zu einem Kombi-Gericht hinzuzufügen, müssen zwei Gerichte ausgewählt werden.", "402": "Etwas ist beim Buchen der Mahlzeit schiefgegangen.", diff --git a/src/Resources/src/locales/en.json b/src/Resources/src/locales/en.json index 6002272d9..08afc4dbf 100644 --- a/src/Resources/src/locales/en.json +++ b/src/Resources/src/locales/en.json @@ -159,6 +159,7 @@ "201": "Information is still missing to be able to create the dish.", "202": "One or more titles for the dish being created appear to be missing.", "203": "There was an error when counting how often individual dishes were ordered.", + "204": "The dish can't be updated, because there are booked combi-meals containing it.", "301": "The selected titles for the category are missing or already exist.", "401": "To add a user to a combined meal, two dishes must be selected.", "402": "Something went wrong while booking the meal",