vcard4reseller/backend/src/Entity/CardTemplate.php
Thomas Peterson 408b37a5ea Druckdaten: druckfertige Visitenkarten-PDF (CMYK, Beschnitt, V/R)
- CardTemplate-Entität (Layout pro Firma; company=null = globale Vorlage)
- CardTemplateFactory: Standardlayout, greift Firmen-Branding + QR ab
- CardPdfRenderer (TCPDF): 85x55mm + 2mm Beschnitt, Schnittmarken, CMYK,
  Vorder-/Rückseite, mm-genaue Element-Platzierung, eingebetteter QR
- GET /api/employees/{id}/card.pdf (Auth + Mandantenprüfung)
- Konzept §13 (Druckdaten) ergänzt

Verifiziert: 2 Seiten, CMYK-Farbraum, Schnittmarken, Branding durchgängig.
Offen: PDF/X-1a-Finishing (Ghostscript), Font-Embedding, visueller Editor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:54:02 +02:00

190 lines
3.9 KiB
PHP

<?php
namespace App\Entity;
use App\Repository\CardTemplateRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid;
/**
* Layout-Vorlage für druckbare Ausgaben (Visitenkarte; später Briefpapier).
* company = null ⇒ globale Standardvorlage. Front/Back sind Listen von
* Element-Definitionen (siehe KONZEPT §13), die der CardPdfRenderer interpretiert.
*/
#[ORM\Entity(repositoryClass: CardTemplateRepository::class)]
class CardTemplate implements ResellerOwnedInterface
{
public const TYPE_CARD = 'card';
public const TYPE_LETTERHEAD = 'letterhead';
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME, unique: true)]
private Uuid $id;
#[ORM\Column(length: 120)]
private string $name = 'Standard';
#[ORM\Column(length: 20)]
private string $type = self::TYPE_CARD;
#[ORM\Column(type: 'float')]
private float $widthMm = 85.0;
#[ORM\Column(type: 'float')]
private float $heightMm = 55.0;
#[ORM\Column(type: 'float')]
private float $bleedMm = 2.0;
#[ORM\Column(type: 'float')]
private float $safeMm = 4.0;
/** @var array<int, array<string, mixed>> */
#[ORM\Column(type: 'json')]
private array $front = [];
/** @var array<int, array<string, mixed>> */
#[ORM\Column(type: 'json')]
private array $back = [];
#[ORM\ManyToOne(targetEntity: Company::class)]
private ?Company $company = null;
#[ORM\Column(type: 'datetime_immutable')]
private \DateTimeImmutable $createdAt;
public function __construct()
{
$this->id = Uuid::v7();
$this->createdAt = new \DateTimeImmutable();
}
public function getId(): Uuid
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getType(): string
{
return $this->type;
}
public function setType(string $type): self
{
$this->type = $type;
return $this;
}
public function getWidthMm(): float
{
return $this->widthMm;
}
public function setWidthMm(float $widthMm): self
{
$this->widthMm = $widthMm;
return $this;
}
public function getHeightMm(): float
{
return $this->heightMm;
}
public function setHeightMm(float $heightMm): self
{
$this->heightMm = $heightMm;
return $this;
}
public function getBleedMm(): float
{
return $this->bleedMm;
}
public function setBleedMm(float $bleedMm): self
{
$this->bleedMm = $bleedMm;
return $this;
}
public function getSafeMm(): float
{
return $this->safeMm;
}
public function setSafeMm(float $safeMm): self
{
$this->safeMm = $safeMm;
return $this;
}
/** @return array<int, array<string, mixed>> */
public function getFront(): array
{
return $this->front;
}
/** @param array<int, array<string, mixed>> $front */
public function setFront(array $front): self
{
$this->front = $front;
return $this;
}
/** @return array<int, array<string, mixed>> */
public function getBack(): array
{
return $this->back;
}
/** @param array<int, array<string, mixed>> $back */
public function setBack(array $back): self
{
$this->back = $back;
return $this;
}
public function getCompany(): ?Company
{
return $this->company;
}
public function setCompany(?Company $company): self
{
$this->company = $company;
return $this;
}
public function getReseller(): ?Reseller
{
return $this->company?->getReseller();
}
public function getCreatedAt(): \DateTimeImmutable
{
return $this->createdAt;
}
}