add price feature
All checks were successful
/ ls (pull_request) Successful in 1m37s
/ ls (push) Successful in 1m37s

This commit is contained in:
lubiana 2025-06-29 23:18:23 +02:00
parent 15f8db46a0
commit 64f5341371
Signed by: lubiana
SSH key fingerprint: SHA256:vW1EA0fRR3Fw+dD/sM0K+x3Il2gSry6YRYHqOeQwrfk
18 changed files with 484 additions and 157 deletions

View file

@ -4,6 +4,7 @@ namespace App\Controller;
use App\Entity\FoodOrder;
use App\Form\FoodOrderType;
use App\Form\OrderFinalize;
use App\Repository\FoodOrderRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@ -104,11 +105,21 @@ final class FoodOrderController extends AbstractController
], Response::HTTP_SEE_OTHER);
}
#[Route('/{id}', name: 'app_food_order_show', methods: ['GET'])]
public function show(FoodOrder $foodOrder): Response
#[Route('/{id}', name: 'app_food_order_show', methods: ['GET', 'POST'])]
public function show(Request $request, FoodOrder $foodOrder, EntityManagerInterface $entityManager): Response
{
$form = null;
if ($foodOrder->isClosed()) {
$form = $this->createForm(OrderFinalize::class, $foodOrder);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($foodOrder);
$entityManager->flush();
}
}
return $this->render('food_order/show.html.twig', [
'food_order' => $foodOrder,
'form' => $form,
]);
}
}

View file

@ -3,7 +3,6 @@
namespace App\Controller;
use App\Entity\FoodOrder;
use App\Entity\MenuItem;
use App\Entity\OrderItem;
use App\Form\OrderItemType;
use App\Repository\MenuItemRepository;
@ -108,24 +107,6 @@ final class OrderItemController extends AbstractController
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$menuItem = $menuItemRepository->findOneBy([
'name' => $orderItem->getName(),
'foodVendor' => $foodOrder->getFoodVendor(),
]);
if ($menuItem === null) {
$menuItem = new MenuItem;
$menuItem->setName($orderItem->getName());
$menuItem->setFoodVendor($foodOrder->getFoodVendor());
$entityManager->persist($menuItem);
}
if ($menuItem->getAliasOf() !== null) {
$menuItem = $menuItem->getAliasOf();
$orderItem->setName($menuItem->getName());
}
$orderItem->setMenuItem($menuItem);
$orderItem->setFoodOrder($foodOrder);
$entityManager->persist($orderItem);
$entityManager->flush();

View file

@ -11,6 +11,7 @@ use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid;
use Symfony\Component\Validator\Constraints\Positive;
#[ApiResource]
#[ORM\Entity(repositoryClass: MenuItemRepository::class)]
@ -38,6 +39,7 @@ class MenuItem
#[ORM\Column(type: 'integer', options: [
'default' => 0,
])]
#[Positive]
private int $priceCents = 0;
public function __construct(

View file

@ -47,6 +47,7 @@ class OrderItem
#[ORM\Column(type: 'integer', options: [
'default' => 0,
])]
#[Positive]
private int $priceCents = 0;
public function __construct(

View file

@ -0,0 +1,52 @@
<?php declare(strict_types=1);
namespace App\EventListener;
use App\Entity\MenuItem;
use App\Entity\OrderItem;
use App\Repository\MenuItemRepository;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\PreFlushEventArgs;
use Doctrine\ORM\Events;
use Doctrine\Persistence\ObjectManager;
#[AsDoctrineListener(event: Events::preFlush)]
final readonly class OrderItemPreFlush
{
public function __construct(
private MenuItemRepository $menuItemRepository,
) {}
public function preFlush(PreFlushEventArgs $eventArgs): void
{
foreach (($eventArgs->getObjectManager()->getUnitOfWork()->getIdentityMap()[OrderItem::class] ?? []) as $orderItem) {
$this->checkOrderItem($orderItem, $eventArgs->getObjectManager());
}
}
private function checkOrderItem(OrderItem $orderItem, ObjectManager $objectManager): void
{
$menuItem = $this->menuItemRepository->findOneBy([
'name' => $orderItem->getName(),
'foodVendor' => $orderItem->getFoodOrder()
->getFoodVendor(),
]);
if ($menuItem === null) {
$menuItem = new MenuItem;
$menuItem->setName($orderItem->getName());
$menuItem->setFoodVendor($orderItem->getFoodOrder()->getFoodVendor());
$objectManager->persist($menuItem);
}
if ($menuItem->getAliasOf() !== null) {
$menuItem = $menuItem->getAliasOf();
$orderItem->setName($menuItem->getName());
}
$orderItem->setMenuItem($menuItem);
if ($orderItem->getPriceCents() === 0) {
$orderItem->setPriceCents($menuItem->getPriceCents());
} elseif ($orderItem->getPriceCents() !== $menuItem->getPriceCents()) {
$menuItem->setPriceCents($orderItem->getPriceCents());
$objectManager->persist($menuItem);
}
}
}

View file

@ -1,35 +0,0 @@
<?php declare(strict_types=1);
namespace App\EventListener;
use App\Entity\MenuItem;
use App\Entity\OrderItem;
use App\Repository\MenuItemRepository;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Events;
#[AsEntityListener(event: Events::prePersist, method: 'prePersist', entity: OrderItem::class)]
final readonly class OrderItemPrePersist
{
public function __construct(
private MenuItemRepository $menuItemRepository,
) {}
public function prePersist(OrderItem $orderItem, PrePersistEventArgs $eventArgs): void
{
$menuItem = $this->menuItemRepository->findOneBy([
'name' => $orderItem->getName(),
'foodVendor' => $orderItem->getFoodOrder()
->getFoodVendor(),
]);
if ($menuItem === null) {
$menuItem = new MenuItem;
$menuItem->setName($orderItem->getName());
$menuItem->setFoodVendor($orderItem->getFoodOrder()->getFoodVendor());
$eventArgs->getObjectManager()
->persist($menuItem);
}
$orderItem->setMenuItem($menuItem);
}
}

View file

@ -8,6 +8,7 @@ use Doctrine\ORM\QueryBuilder;
use Override;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
@ -29,6 +30,10 @@ final class MenuItemType extends AbstractType
]),
],
]);
$builder->add('priceCents', MoneyType::class, [
'label' => 'Price',
'divisor' => 100,
]);
$builder->add('aliases', EntityType::class, [
'class' => MenuItem::class,
'choice_label' => 'name',

View file

@ -0,0 +1,32 @@
<?php declare(strict_types=1);
namespace App\Form;
use App\Entity\FoodOrder;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
final class OrderFinalize extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('orderItems', CollectionType::class, [
'entry_type' => OrderItemFinalize::class,
'entry_options' => [
'label' => false,
],
])
->add('save', SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => FoodOrder::class,
]);
}
}

View file

@ -0,0 +1,44 @@
<?php declare(strict_types=1);
namespace App\Form;
use App\Entity\OrderItem;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
final class OrderItemFinalize extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add(child: 'name', options: [
'label' => 'order item',
'disabled' => true,
])
->add(child: 'extras', options: [
'disabled' => true,
])
->add(child: 'createdBy', options: [
'disabled' => true,
])
->add(child: 'priceCents', type: MoneyType::class, options: [
'label' => 'price',
'divisor' => 100,
])
->add(child: 'isPaid', type: CheckboxType::class, options: [
'required' => false,
'label' => 'paid?',
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => OrderItem::class,
]);
}
}