Add isInvitation to BilletOrder, orga details in PDF footer, rename Sortie libre

- Add isInvitation (nullable bool) to BilletOrder: null=no badge, true=invitation
- PDF footer: add SIRET, email, phone of organizer
- PDF: show invitation badge based on ticket.isInvitation instead of design
- Rename "Sortie libre" to "Sortie - Entree illimitee"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-03-21 16:36:29 +01:00
parent fba654fad7
commit e1e98e752d
4 changed files with 62 additions and 2 deletions

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20260321220000 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add is_invitation to billet_order';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE billet_order ADD COLUMN IF NOT EXISTS is_invitation BOOLEAN DEFAULT NULL');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE billet_order DROP COLUMN IF EXISTS is_invitation');
}
}

View File

@@ -37,6 +37,9 @@ class BilletOrder
#[ORM\Column(length: 20)]
private string $state = self::STATE_VALID;
#[ORM\Column(nullable: true)]
private ?bool $isInvitation = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $firstScannedAt = null;
@@ -129,6 +132,18 @@ class BilletOrder
return self::STATE_VALID === $this->state;
}
public function isInvitation(): ?bool
{
return $this->isInvitation;
}
public function setIsInvitation(?bool $isInvitation): static
{
$this->isInvitation = $isInvitation;
return $this;
}
public function getFirstScannedAt(): ?\DateTimeImmutable
{
return $this->firstScannedAt;

View File

@@ -298,9 +298,9 @@
{% if ticket.billet.definedExit %}
<span class="badge-exit-def">Sortie definitive</span>
{% else %}
<span class="badge-exit-libre">Sortie libre</span>
<span class="badge-exit-libre">Sortie - Entree illimitee</span>
{% endif %}
{% if design %}
{% if ticket.invitation %}
<span class="badge-invitation" style="background: {{ inv_color }};">{{ inv_title }}</span>
{% endif %}
</div>
@@ -341,9 +341,15 @@
{% endif %}
<td>
<div class="footer-org">{{ organizer.companyName ?? (organizer.firstName ~ ' ' ~ organizer.lastName) }}</div>
{% if organizer.siret %}
<div class="footer-details">SIRET: {{ organizer.siret }}</div>
{% endif %}
{% if organizer.address %}
<div class="footer-details">{{ organizer.address }}{% if organizer.postalCode %}, {{ organizer.postalCode }}{% endif %}{% if organizer.city %} {{ organizer.city }}{% endif %}</div>
{% endif %}
{% if organizer.email or organizer.phone %}
<div class="footer-details">{% if organizer.email %}{{ organizer.email }}{% endif %}{% if organizer.email and organizer.phone %}{% endif %}{% if organizer.phone %}{{ organizer.phone }}{% endif %}</div>
{% endif %}
</td>
<td class="footer-powered">E-Ticket<br>by E-Cosplay</td>
</tr>

View File

@@ -21,6 +21,7 @@ class BilletOrderTest extends TestCase
self::assertSame(0.0, $ticket->getUnitPriceHTDecimal());
self::assertSame(BilletOrder::STATE_VALID, $ticket->getState());
self::assertTrue($ticket->isValid());
self::assertNull($ticket->isInvitation());
self::assertNull($ticket->getFirstScannedAt());
self::assertMatchesRegularExpression('/^ETICKET-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/', $ticket->getReference());
self::assertInstanceOf(\DateTimeImmutable::class, $ticket->getCreatedAt());
@@ -82,6 +83,18 @@ class BilletOrderTest extends TestCase
self::assertTrue($ticket->isValid());
}
public function testSetAndGetIsInvitation(): void
{
$ticket = new BilletOrder();
$result = $ticket->setIsInvitation(true);
self::assertTrue($ticket->isInvitation());
self::assertSame($ticket, $result);
$ticket->setIsInvitation(null);
self::assertNull($ticket->isInvitation());
}
public function testSetAndGetFirstScannedAt(): void
{
$ticket = new BilletOrder();