Compare commits

...

4 commits
0.3.4 ... main

Author SHA1 Message Date
96b246462a
add open orders api route 2025-04-23 18:57:55 +02:00
5de80b0da0
update 2025-04-23 17:25:45 +02:00
0e26487156
bump deps 2025-04-04 22:06:46 +02:00
4fbfdcd73d
update foodordertest 2025-04-02 19:35:53 +02:00
8 changed files with 626 additions and 559 deletions

View file

@ -7,8 +7,8 @@
"php": ">=8.4", "php": ">=8.4",
"ext-ctype": "*", "ext-ctype": "*",
"ext-iconv": "*", "ext-iconv": "*",
"api-platform/doctrine-orm": "^4.0", "api-platform/doctrine-orm": "^4.0.0",
"api-platform/symfony": "^4.0", "api-platform/symfony": "4.1.4",
"doctrine/dbal": "^4.1", "doctrine/dbal": "^4.1",
"doctrine/doctrine-bundle": "^2.12", "doctrine/doctrine-bundle": "^2.12",
"doctrine/doctrine-migrations-bundle": "^3.3.1", "doctrine/doctrine-migrations-bundle": "^3.3.1",

1096
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,9 @@
namespace App\Entity; namespace App\Entity;
use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;
use App\Repository\FoodOrderRepository; use App\Repository\FoodOrderRepository;
use App\State\OpenFoodOrderProvider;
use DateInterval; use DateInterval;
use DateTimeImmutable; use DateTimeImmutable;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
@ -15,6 +17,10 @@ use Symfony\Component\Uid\Ulid;
use function iterator_to_array; use function iterator_to_array;
#[ORM\Entity(repositoryClass: FoodOrderRepository::class)] #[ORM\Entity(repositoryClass: FoodOrderRepository::class)]
#[GetCollection(
uriTemplate: '/food_orders/open',
provider: OpenFoodOrderProvider::class,
)]
#[ApiResource] #[ApiResource]
class FoodOrder class FoodOrder
{ {

View file

@ -47,4 +47,19 @@ final class FoodOrderRepository extends ServiceEntityRepository
->filter(static fn(FoodOrder $order): bool => $order->getCreatedAt() >= $date) ->filter(static fn(FoodOrder $order): bool => $order->getCreatedAt() >= $date)
->getValues(); ->getValues();
} }
/**
* @return FoodOrder[]
*/
public function findOpenOrders(): array
{
$now = new DateTimeImmutable;
return $this->createQueryBuilder('o')
->where('o.closedAt IS NULL OR o.closedAt > :now')
->setParameter('now', $now)
->orderBy('o.id', 'DESC')
->getQuery()
->getResult();
}
} }

View file

@ -0,0 +1,21 @@
<?php declare(strict_types=1);
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Repository\FoodOrderRepository;
use Override;
final readonly class OpenFoodOrderProvider implements ProviderInterface
{
public function __construct(
private FoodOrderRepository $repository
) {}
#[Override]
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
return $this->repository->findOpenOrders();
}
}

View file

@ -13,3 +13,36 @@ test('orders', function (): void {
$array = $response->toArray(); $array = $response->toArray();
expect($array['member'][0]['orderItems'])->toHaveCount(10); expect($array['member'][0]['orderItems'])->toHaveCount(10);
}); });
test('open orders', function (): void {
$response = $this->client->request('GET', '/api/food_orders/open');
$this->assertResponseIsSuccessful();
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
$this->assertJsonContains([
'@context' => '/api/contexts/FoodOrder',
'@id' => '/api/food_orders/open',
'@type' => 'Collection',
]);
// Get the response content and verify that all returned orders are open
$array = $response->toArray();
// If we have no items, we should still have a successful response
if ($array['totalItems'] === 0) {
return;
}
// For each order in the response, check that it is not closed
foreach ($array['member'] as $order) {
// An order is considered open if either:
// 1. closedAt is null or
// 2. closedAt is in the future
$closedAt = isset($order['closedAt']) ? new DateTimeImmutable($order['closedAt']) : null;
$now = new DateTimeImmutable;
// Assert that the order is open (not closed)
$isOpen = (! $closedAt instanceof DateTimeImmutable || $closedAt > $now);
expect($isOpen)
->toBeTrue('Order should be open but is closed');
}
});

View file

@ -100,15 +100,15 @@ describe(FoodOrderController::class, function (): void {
$crawler = $this->client->request('GET', "{$this->path}{$order->getId()}"); $crawler = $this->client->request('GET', "{$this->path}{$order->getId()}");
$this->assertResponseIsSuccessful(); $this->assertResponseIsSuccessful();
$tdContent = $crawler->filter( $tdContent = $crawler->filter(
'table.table:nth-child(6) > tbody:nth-child(2) > tr:nth-child(1) > td:nth-child(2)' 'table.table:nth-child(6) > tbody:nth-child(2) > tr:nth-child(1) > td:nth-child(3)'
)->text(); )->text();
$this->assertEquals('A', $tdContent); $this->assertEquals('A', $tdContent);
$tdContent = $crawler->filter( $tdContent = $crawler->filter(
'table.table:nth-child(6) > tbody:nth-child(2) > tr:nth-child(2) > td:nth-child(2)' 'table.table:nth-child(6) > tbody:nth-child(2) > tr:nth-child(2) > td:nth-child(3)'
)->text(); )->text();
$this->assertEquals('B', $tdContent); $this->assertEquals('B', $tdContent);
$tdContent = $crawler->filter( $tdContent = $crawler->filter(
'table.table:nth-child(6) > tbody:nth-child(2) > tr:nth-child(3) > td:nth-child(2)' 'table.table:nth-child(6) > tbody:nth-child(2) > tr:nth-child(3) > td:nth-child(3)'
)->text(); )->text();
$this->assertEquals('C', $tdContent); $this->assertEquals('C', $tdContent);
}); });

View file

@ -1,6 +1,7 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
use Symfony\Component\Dotenv\Dotenv; use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Filesystem\Filesystem;
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';
@ -13,3 +14,6 @@ if (method_exists(Dotenv::class, 'bootEnv')) {
if ($_SERVER['APP_DEBUG']) { if ($_SERVER['APP_DEBUG']) {
umask(0o000); umask(0o000);
} }
$fs = new Filesystem;
$fs->remove(dirname(__DIR__) . '/../var/cache/*');