<?phpnamespace App\Entity\Cvs;use Doctrine\ORM\Mapping as ORM;/** * Brouillon de CV public — V6 (PDF stocké dans la draft, Candidates uniquement à register) * * Cycle de vie : * 1. CHOICE/THEME/FORM : visiteur remplit le CV * → cv_data + cv_settings écrits dans la draft (autosave debounced) * → AUCUN Candidates créé * * 2. POST /generate (clic "Générer mon CV") : * → Python lit cvs_candidates_drafts via --public-slug * → PDF généré dans uploadPath * → cv_pdf_path stocké dans la draft (pas dans Candidates) * → renvoie pdf_url au front pour preview * * 3. POST /register (clic "Créer mon compte") : * → CRÉATION Users + CRÉATION Candidates * → Transfert cv_data + cv_settings + cv_pdf_path : draft → Candidates * → DELETE draft * * 4. ABANDON (cron purge à 48h) : * → Si draft expirée : DELETE draft + DELETE PDF sur disque * * @ORM\Table( * name="cvs_candidates_drafts", * uniqueConstraints={ * @ORM\UniqueConstraint(name="UNIQ_CVS_CANDIDATES_DRAFTS_PUBLIC_SLUG", columns={"public_slug"}) * }, * indexes={ * @ORM\Index(name="IDX_CVS_CANDIDATES_DRAFTS_EXPIRES_AT", columns={"expires_at"}) * } * ) * @ORM\Entity(repositoryClass="App\Repository\Cvs\PublicCvDraftRepository") */class PublicCvDraft{ /** * @var int|null * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string * * @ORM\Column(name="public_slug", type="string", length=20, unique=true) */ private $publicSlug; /** * @var \DateTimeInterface * * @ORM\Column(name="expires_at", type="datetime") */ private $expiresAt; /** * @var \DateTimeInterface * * @ORM\Column(name="created_at", type="datetime") */ private $createdAt; /** * @var \DateTimeInterface * * @ORM\Column(name="updated_at", type="datetime") */ private $updatedAt; // ------------------------------------------------------------------------- // Colonnes typées (identifiants — pré-remplissage formulaire register) // ------------------------------------------------------------------------- /** * @var string|null * * @ORM\Column(name="first_name", type="string", length=255, nullable=true) */ private $firstName; /** * @var string|null * * @ORM\Column(name="last_name", type="string", length=255, nullable=true) */ private $lastName; /** * @var string|null * * @ORM\Column(name="email", type="string", length=255, nullable=true) */ private $email; /** * @var string|null * * @ORM\Column(name="phone", type="string", length=255, nullable=true) */ private $phone; /** * @var string|null * * @ORM\Column(name="city", type="string", length=255, nullable=true) */ private $city; /** * @var string|null * * @ORM\Column(name="country", type="string", length=255, nullable=true) */ private $country; /** * @var string|null * * @ORM\Column(name="locale", type="string", length=8, nullable=true) */ private $locale; // ------------------------------------------------------------------------- // Colonnes JSON // ------------------------------------------------------------------------- /** * @var string|null * * @ORM\Column(name="cv_data", type="text", nullable=true) */ private $cvData; /** * @var string|null * * @ORM\Column(name="cv_settings", type="text", nullable=true) */ private $cvSettings; /** * @var string|null * * @ORM\Column(name="mode", type="string", length=16, nullable=true) */ private $mode; /** * Chemin absolu du PDF généré (sur disque, dans PYTHON_SCRIPT_CV_UPLOADPATH). * Renseigné après /generate, transféré à Candidates.cv_pdf_path à /register. * * @var string|null * * @ORM\Column(name="cv_pdf_path", type="string", length=500, nullable=true) */ private $cvPdfPath; // ========================================================================= // Getters / Setters // ========================================================================= public function getId(): ?int { return $this->id; } public function getPublicSlug(): ?string { return $this->publicSlug; } public function setPublicSlug(string $publicSlug): self { $this->publicSlug = $publicSlug; return $this; } public function getExpiresAt(): ?\DateTimeInterface { return $this->expiresAt; } public function setExpiresAt(\DateTimeInterface $expiresAt): self { $this->expiresAt = $expiresAt; return $this; } public function getCreatedAt(): ?\DateTimeInterface { return $this->createdAt; } public function setCreatedAt(\DateTimeInterface $createdAt): self { $this->createdAt = $createdAt; return $this; } public function getUpdatedAt(): ?\DateTimeInterface { return $this->updatedAt; } public function setUpdatedAt(\DateTimeInterface $updatedAt): self { $this->updatedAt = $updatedAt; return $this; } public function getFirstName(): ?string { return $this->firstName; } public function setFirstName(?string $firstName): self { $this->firstName = $firstName; return $this; } public function getLastName(): ?string { return $this->lastName; } public function setLastName(?string $lastName): self { $this->lastName = $lastName; return $this; } public function getEmail(): ?string { return $this->email; } public function setEmail(?string $email): self { $this->email = $email; return $this; } public function getPhone(): ?string { return $this->phone; } public function setPhone(?string $phone): self { $this->phone = $phone; return $this; } public function getCity(): ?string { return $this->city; } public function setCity(?string $city): self { $this->city = $city; return $this; } public function getCountry(): ?string { return $this->country; } public function setCountry(?string $country): self { $this->country = $country; return $this; } public function getLocale(): ?string { return $this->locale; } public function setLocale(?string $locale): self { $this->locale = $locale; return $this; } public function getCvData(): ?string { return $this->cvData; } public function setCvData(?string $cvData): self { $this->cvData = $cvData; return $this; } public function getCvSettings(): ?string { return $this->cvSettings; } public function setCvSettings(?string $cvSettings): self { $this->cvSettings = $cvSettings; return $this; } public function getMode(): ?string { return $this->mode; } public function setMode(?string $mode): self { $this->mode = $mode; return $this; } public function getCvPdfPath(): ?string { return $this->cvPdfPath; } public function setCvPdfPath(?string $cvPdfPath): self { $this->cvPdfPath = $cvPdfPath; return $this; } // ========================================================================= // Helpers // ========================================================================= public function isExpired(?\DateTimeInterface $now = null): bool { $now = $now ?? new \DateTime(); return $this->expiresAt < $now; } public function getCvDataArray(): array { if (empty($this->cvData)) { return []; } $decoded = json_decode($this->cvData, true); return is_array($decoded) ? $decoded : []; } public function getCvSettingsArray(): array { if (empty($this->cvSettings)) { return []; } $decoded = json_decode($this->cvSettings, true); return is_array($decoded) ? $decoded : []; }}