src/Entity/Core/Users.php line 44

Open in your IDE?
  1. <?php
  2. namespace App\Entity\Core;
  3. use App\Entity\Cvs\Candidates;
  4. use App\Repository\Core\UsersRepository;
  5. use Doctrine\DBAL\Types\Types;
  6. use Doctrine\ORM\Mapping as ORM;
  7. use Symfony\Component\Security\Core\User\UserInterface;
  8. use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  9. use Symfony\Component\Validator\Constraints as Assert;
  10. use Vich\UploaderBundle\Mapping\Annotation as Vich;
  11. use Symfony\Component\HttpFoundation\File\File;
  12. use Symfony\Component\HttpFoundation\File\UploadedFile;
  13. use Vich\UploaderBundle\Entity\File as EmbeddedFile;
  14. use ApiPlatform\Core\Annotation\ApiResource;
  15. use Symfony\Component\Serializer\Annotation\Groups;
  16. use Symfony\Component\Serializer\Annotation\SerializedName;
  17. use Serializable;
  18. use DateTimeImmutable;
  19. use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  20. use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
  21. /**
  22. * @ORM\Entity(repositoryClass=UsersRepository::class)
  23. * @ORM\Table(name="users")
  24. * @ORM\HasLifecycleCallbacks()
  25. * @Vich\Uploadable
  26. *
  27. * ⚠️ RÉSERVÉ AUX ADMINISTRATEURS.
  28. *
  29. * Sans `security`, la seule barrière était le mur `^/api` du pare-feu :
  30. * n'importe quel porteur de JWT (un candidat inscrit gratuitement)
  31. * listait tous les comptes via GET /api/users et pouvait en supprimer
  32. * via DELETE /api/users/{id}. Aucun client (mobile, vitrine) ne s'en
  33. * sert ; on garde la ressource pour un éventuel outil d'admin.
  34. *
  35. * @ApiResource(
  36. * attributes={"security"="is_granted('ROLE_ADMIN')"},
  37. * normalizationContext={"groups"={"user:read"}},
  38. * denormalizationContext={"groups"={"user:write"}}
  39. * )
  40. */
  41. class Users implements UserInterface, PasswordAuthenticatedUserInterface, \Serializable
  42. {
  43. /**
  44. * @ORM\Id
  45. * @ORM\GeneratedValue
  46. * @ORM\Column(type="integer")
  47. *
  48. * @Groups("user:read")
  49. */
  50. private $id;
  51. /**
  52. * @var datetime
  53. *
  54. * @ORM\Column(name="createdAt", type="datetime", nullable=true)
  55. *
  56. * @Groups("user:read")
  57. */
  58. private $createdAt;
  59. /**
  60. * @var datetime
  61. *
  62. * @ORM\Column(name="updatedAt", type="datetime", nullable=true)
  63. */
  64. private $updatedAt;
  65. /**
  66. * @var datetime
  67. *
  68. * @ORM\Column(name="last_login", type="datetime", nullable=true)
  69. */
  70. private $lastLogin;
  71. /**
  72. * @ORM\Column(type="string", length=180, unique=true)
  73. * @Groups("user:read")
  74. */
  75. private $email;
  76. /**
  77. * @ORM\Column(type="string", length=180, nullable=true)
  78. * @Groups("user:read")
  79. */
  80. private $name;
  81. /**
  82. * @ORM\Column(type="string", length=180, nullable=true)
  83. * @Groups("user:read")
  84. */
  85. private $lastname;
  86. /**
  87. * @ORM\Column(type="json")
  88. */
  89. private $roles = [];
  90. /**
  91. * @var string The hashed password
  92. * @ORM\Column(type="string")
  93. */
  94. private $password;
  95. /**
  96. * @ORM\Column(type="string", length=180, nullable=true)
  97. */
  98. private $username;
  99. /**
  100. * @ORM\Column(type="boolean", length=180, nullable=true)
  101. */
  102. private $first;
  103. /**
  104. * @ORM\Column(type="boolean", length=180, nullable=true)
  105. */
  106. private $enabled;
  107. /**
  108. * @ORM\Column(type="boolean", length=11, nullable=true)
  109. */
  110. private $verification;
  111. /**
  112. * @var string
  113. *
  114. * @ORM\Column(name="premium", type="boolean", nullable=false)
  115. */
  116. private $premium;
  117. /* ══════════════════════════════════════════════════════════════════════
  118. LE QUOTA DE RÉDACTION PAR IA
  119. ⚠️ DEUX COLONNES, PAS UNE TABLE À PART.
  120. Le compteur vivait dans une table du site vitrine
  121. (`wr_ia_offre_usage`). Deux défauts :
  122. · le quota d'un COMPTE était stocké là où le compte n'existe
  123. pas — l'utilisateur vit ici, dans l'API ;
  124. · l'application mobile et tout autre client passant par l'API
  125. n'auraient pas été décomptés du tout.
  126. Deux colonnes sur l'utilisateur suffisent : un compteur et le jour
  127. auquel il se rapporte.
  128. ⚠️ LE JOUR EST STOCKÉ, PAS DÉDUIT.
  129. Sans lui, il faudrait une purge nocturne pour remettre les
  130. compteurs à zéro — un travail planifié de plus, qui tombe en
  131. panne sans que personne ne le voie, et le quota ne se réinitialise
  132. plus. En comparant la date stockée à celle du jour, la remise à
  133. zéro est implicite : elle a lieu au premier usage suivant.
  134. ══════════════════════════════════════════════════════════════════════ */
  135. /**
  136. * @var int
  137. *
  138. * @ORM\Column(name="ia_offre_count", type="smallint", nullable=false, options={"default": 0, "unsigned": true})
  139. */
  140. private $iaOffreCount = 0;
  141. /**
  142. * @var \DateTimeInterface|null
  143. *
  144. * @ORM\Column(name="ia_offre_day", type="date", nullable=true)
  145. */
  146. private $iaOffreDay;
  147. /**
  148. * ⚠️ UN PLAFOND PROPRE À CE COMPTE, OU RIEN.
  149. *
  150. * `NULL` veut dire « suit le défaut » — 2 sans abonnement, 100 avec.
  151. * C'est la même convention que `share_quota_per_day`, et elle mérite
  152. * d'être la même partout : deux quotas voisins qui traitent
  153. * différemment une valeur vide seraient un piège.
  154. *
  155. * Une valeur ici l'emporte, abonnement ou pas. Elle sert au geste
  156. * commercial — un client qui lance une campagne et a besoin de plus
  157. * que son forfait pour deux semaines.
  158. *
  159. * `0` est une valeur valide et signifie « aucune rédaction ». Ce
  160. * n'est PAS la même chose que vide.
  161. *
  162. * @var int|null
  163. *
  164. * @ORM\Column(name="ia_offre_quota", type="integer", nullable=true, options={"comment":"Plafond de rédactions IA par jour (NULL = selon premium)"})
  165. */
  166. private $iaOffreQuota;
  167. /**
  168. * Le moteur de recherche de candidats est-il ouvert à ce compte ?
  169. *
  170. * ⚠️ DEUX VERROUS, ET IL FAUT LES DEUX (option A).
  171. *
  172. * Accès = `premium` ET `searchEnabled`.
  173. *
  174. * `premium` est le droit COMMERCIAL : il s'achète et il expire.
  175. * `searchEnabled` est l'octroi EFFECTIF, posé compte par compte
  176. * depuis le back-office.
  177. *
  178. * Les deux parce qu'ils ne disent pas la même chose : un abonnement
  179. * qui s'arrête doit couper l'accès automatiquement (d'où `premium`),
  180. * et un abonnement qui démarre ne doit pas ouvrir la recherche sans
  181. * qu'on l'ait décidé (d'où le drapeau).
  182. *
  183. * ⚠️ Conséquence à assumer : un client premium sans le drapeau
  184. * n'aura PAS la recherche et écrira au support. C'est le prix de ce
  185. * modèle — le back-office doit donc afficher les deux états côte à
  186. * côte pour que le diagnostic prenne trois secondes.
  187. *
  188. * Faux à l'inscription. Personne ne l'obtient par défaut.
  189. *
  190. * @var bool|null
  191. *
  192. * @ORM\Column(name="search_enabled", type="boolean", nullable=true, options={"default":0,"comment":"Moteur de recherche candidats ouvert à ce compte"})
  193. */
  194. private $searchEnabled;
  195. /**
  196. * QUAND le recruteur a demandé l'accès au moteur de recherche.
  197. *
  198. * ⚠️ LA DEMANDE VIT ICI, PAS DANS LA BASE DU SITE VITRINE.
  199. *
  200. * Elle y était (liste d'attente locale) : le backoffice de l'API,
  201. * qui seul peut ouvrir l'accès (`searchEnabled`), ne la voyait pas.
  202. * Une demande et la décision qui y répond doivent être au même
  203. * endroit. Null = jamais demandé, ou demande refusée.
  204. *
  205. * @ORM\Column(name="search_requested_at", type="datetime", nullable=true, options={"comment":"Demande d'accès au moteur de recherche"})
  206. */
  207. private $searchRequestedAt;
  208. /**
  209. * Le quota d'envois de CV anonyme, par 24 h glissantes.
  210. *
  211. * ⚠️ NULL N'EST PAS ZÉRO. NULL = « le réglage par défaut ».
  212. *
  213. * Un `0` interdirait tout envoi — ce qui est un réglage LÉGITIME et
  214. * qu'on doit pouvoir poser volontairement (compte signalé, abus).
  215. * Si NULL valait zéro, tous les comptes existants seraient muets du
  216. * jour où la colonne apparaît.
  217. *
  218. * La distinction se paie d'une colonne nullable et se gagne en
  219. * lisibilité : le back-office affiche « par défaut (5) » ou une
  220. * valeur explicite, jamais un zéro ambigu.
  221. *
  222. * @var int|null
  223. *
  224. * @ORM\Column(name="share_quota_per_day", type="integer", nullable=true, options={"comment":"Envois de CV anonyme par 24h (NULL = défaut)"})
  225. */
  226. private $shareQuotaPerDay;
  227. public function getShareQuotaPerDay(): ?int
  228. {
  229. return $this->shareQuotaPerDay;
  230. }
  231. public function setShareQuotaPerDay(?int $shareQuotaPerDay): self
  232. {
  233. $this->shareQuotaPerDay = $shareQuotaPerDay === null
  234. ? null
  235. : max(0, min(500, $shareQuotaPerDay));
  236. return $this;
  237. }
  238. /**
  239. * Le quota EFFECTIF : la valeur du compte, ou le défaut.
  240. *
  241. * ⚠️ UN SEUL ENDROIT RÉPOND À CETTE QUESTION.
  242. *
  243. * Écrire `$user->getShareQuotaPerDay() ?? 5` dans le contrôleur
  244. * marcherait — jusqu'au deuxième endroit qui le fait, avec un autre
  245. * défaut. Et le jour où le défaut change, on en corrige un sur deux.
  246. */
  247. public function quotaPartageParJour(int $defaut = 5): int
  248. {
  249. return $this->shareQuotaPerDay ?? $defaut;
  250. }
  251. public function isSearchEnabled(): bool
  252. {
  253. return (bool) $this->searchEnabled;
  254. }
  255. public function getSearchRequestedAt(): ?\DateTimeInterface
  256. {
  257. return $this->searchRequestedAt;
  258. }
  259. public function setSearchRequestedAt(?\DateTimeInterface $v): self
  260. {
  261. $this->searchRequestedAt = $v;
  262. return $this;
  263. }
  264. public function setSearchEnabled(?bool $searchEnabled): self
  265. {
  266. $this->searchEnabled = (bool) $searchEnabled;
  267. return $this;
  268. }
  269. /**
  270. * Le compte peut-il utiliser le moteur de recherche ? (option A)
  271. *
  272. * Un seul endroit répond à cette question. La dupliquer dans chaque
  273. * endpoint, c'est garantir qu'un jour l'un des deux verrous sera oublié
  274. * quelque part — et ce jour-là, la recherche sera ouverte à tous.
  275. */
  276. public function peutChercher(): bool
  277. {
  278. return $this->isPremium() && $this->isSearchEnabled();
  279. }
  280. /**
  281. * NOTE: This is not a mapped field of entity metadata, just a simple property.
  282. *
  283. * @Vich\UploadableField(mapping="avatars_files", fileNameProperty="image.name", size="image.size", mimeType="image.mimeType", originalName="image.originalName", dimensions="image.dimensions")
  284. *
  285. * @var File|null
  286. */
  287. private $imageFile;
  288. /**
  289. * @ORM\Embedded(class="Vich\UploaderBundle\Entity\File")
  290. *
  291. * @var EmbeddedFile
  292. */
  293. private $image;
  294. /**
  295. * @var \Agencies
  296. *
  297. * @ORM\ManyToOne(targetEntity="App\Entity\Core\Agencies")
  298. * @ORM\JoinColumns({
  299. * @ORM\JoinColumn(name="current_agency_id", referencedColumnName="id", nullable=true)
  300. * })
  301. */
  302. protected $currentAgency;
  303. /**
  304. * @ORM\Column(name="password_forgotten", type="string", length=180, nullable=true)
  305. */
  306. private $passwordForgotten;
  307. /**
  308. * @var datetime
  309. *
  310. * @ORM\Column(name="password_forgotten_last_date", type="datetime", nullable=true)
  311. */
  312. private $passwordForgottenLastDate;
  313. /**
  314. * @var string
  315. *
  316. * @ORM\Column(name="partenariat", type="boolean", nullable=true)
  317. */
  318. private $partenariat;
  319. /**
  320. * @ORM\Column(name="description", type="text", nullable=true)
  321. */
  322. private $description;
  323. /**
  324. * @var string
  325. *
  326. * @ORM\Column(name="notifications_messages", type="boolean", nullable=true)
  327. */
  328. private $notificationsMessages;
  329. /**
  330. * @var string
  331. *
  332. * @ORM\Column(name="notifications_suivis", type="boolean", nullable=true)
  333. */
  334. private $notificationsSuivis;
  335. /**
  336. * @var string
  337. *
  338. * @ORM\Column(name="user_commission_unit", type="float", length=11, nullable=true)
  339. */
  340. private $userCommissionUnit;
  341. /**
  342. * @var string
  343. *
  344. * @ORM\Column(name="user_commission_pourcent", type="float", length=11, nullable=true)
  345. */
  346. private $userCommissionPourcent;
  347. /**
  348. * @var string
  349. *
  350. * @ORM\Column(name="type_account", type="string", length=255, nullable=true)
  351. */
  352. private $typeAccount;
  353. /**
  354. * @var \Candidates
  355. *
  356. * @ORM\ManyToOne(targetEntity="App\Entity\Cvs\Candidates")
  357. * @ORM\JoinColumns({
  358. * @ORM\JoinColumn(name="candidate_id", referencedColumnName="id", nullable=true)
  359. * })
  360. */
  361. protected $candidate;
  362. /**
  363. * @var string
  364. *
  365. * @ORM\Column(name="subscription_customer_stripe", type="string", length=255, nullable=true)
  366. */
  367. private $subscriptionCustomerStripe;
  368. /**
  369. * @ORM\Column(type="string", length=255, nullable=true)
  370. */
  371. private $verificationToken;
  372. /**
  373. * @ORM\Column(type="datetime", nullable=true)
  374. */
  375. private $tokenExpiration;
  376. /**
  377. * @ORM\Column(name="language", type="text", nullable=true)
  378. */
  379. private $language;
  380. /**
  381. * @ORM\Column(name="motif_verification", type="text", nullable=true)
  382. */
  383. private $motif;
  384. public function __construct()
  385. {
  386. $this->image = new \Vich\UploaderBundle\Entity\File();
  387. }
  388. /**
  389. * @ORM\PrePersist
  390. */
  391. public function setCreatedAtValue(): void
  392. {
  393. $this->setCreatedAt( new \DateTime("now"));
  394. $this->setUpdatedAt( new \DateTime("now"));
  395. $this->setPremium(false);
  396. }
  397. /**
  398. * @ORM\PreUpdate
  399. */
  400. public function setUpdatedAtValue(): void
  401. {
  402. $this->setUpdatedAt( new \DateTime("now"));
  403. }
  404. public function __toString()
  405. {
  406. return "#".$this->id." ".$this->getName()." ".$this->getLastname().' ('.$this->getEmail().')';
  407. }
  408. public function getTitlePartner(): ?string
  409. {
  410. return "#".$this->id." ".$this->getName()." ".$this->getLastname();
  411. }
  412. public function serialize(): string
  413. {
  414. return serialize([
  415. $this->id,
  416. $this->email,
  417. $this->password,
  418. // autres propriétés que vous souhaitez sérialiser, sauf $imageFile
  419. ]);
  420. }
  421. public function unserialize($serialized): void
  422. {
  423. list(
  424. $this->id,
  425. $this->email,
  426. $this->password,
  427. // autres propriétés que vous souhaitez désérialiser, sauf $imageFile
  428. ) = unserialize($serialized);
  429. }
  430. public function getId(): ?int
  431. {
  432. return $this->id;
  433. }
  434. /**
  435. * Retourne l'identifiant unique de l'utilisateur pour Symfony 5.3+
  436. * On utilise l'email comme identifiant
  437. */
  438. public function getUserIdentifier(): string
  439. {
  440. return (string) $this->email;
  441. }
  442. public function getEmail(): ?string
  443. {
  444. return $this->email;
  445. }
  446. public function setEmail(string $email): self
  447. {
  448. $this->email = $email;
  449. return $this;
  450. }
  451. /**
  452. * @see UserInterface
  453. */
  454. public function getRoles(): array
  455. {
  456. $roles = $this->roles;
  457. // guarantee every user at least has ROLE_USER
  458. $roles[] = 'ROLE_USER';
  459. return array_unique($roles);
  460. }
  461. public function setRoles(array $roles): self
  462. {
  463. $this->roles = $roles;
  464. return $this;
  465. }
  466. /**
  467. * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
  468. * of 'UploadedFile' is injected into this setter to trigger the update. If this
  469. * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
  470. * must be able to accept an instance of 'File' as the bundle will inject one here
  471. * during Doctrine hydration.
  472. *
  473. * @param File|UploadedFile|null $imageFile
  474. */
  475. public function setImageFile(?File $imageFile = null)
  476. {
  477. $this->imageFile = $imageFile;
  478. if (null !== $imageFile) {
  479. // It is required that at least one field changes if you are using doctrine
  480. // otherwise the event listeners won't be called and the file is lost
  481. $this->setUpdatedAt(new \DateTime("now"));
  482. }
  483. }
  484. public function getImageFile(): ?File
  485. {
  486. return $this->imageFile;
  487. }
  488. public function getImageBase64(): ?string
  489. {
  490. if (!$this->image || !$this->image->getName()) {
  491. return null;
  492. }
  493. // Utiliser $_SERVER['DOCUMENT_ROOT'] qui pointe vers /public
  494. $filePath = $_SERVER['DOCUMENT_ROOT'] . '/uploads/avatars/' . $this->image->getName();
  495. if (!file_exists($filePath)) {
  496. // Debug : retourner le chemin pour voir ce qui cloche
  497. return null; // ou "Path: " . $filePath pour debugger
  498. }
  499. $imageData = file_get_contents($filePath);
  500. $mimeType = $this->image->getMimeType() ?? mime_content_type($filePath);
  501. return 'data:' . $mimeType . ';base64,' . base64_encode($imageData);
  502. }
  503. public function setImage(EmbeddedFile $image): void
  504. {
  505. $this->image = $image;
  506. }
  507. public function getImage(): ?EmbeddedFile
  508. {
  509. return $this->image;
  510. }
  511. /**
  512. * @see UserInterface
  513. */
  514. public function getPassword(): string
  515. {
  516. return (string) $this->password;
  517. }
  518. /**
  519. * @see UserInterface
  520. */
  521. public function getUsername(): string
  522. {
  523. return (string) $this->username;
  524. }
  525. public function setPassword(string $password): self
  526. {
  527. $this->password = $password;
  528. return $this;
  529. }
  530. /**
  531. * @see UserInterface
  532. */
  533. public function getSalt()
  534. {
  535. // not needed when using the "bcrypt" algorithm in security.yaml
  536. }
  537. /**
  538. * @see UserInterface
  539. */
  540. public function eraseCredentials()
  541. {
  542. // If you store any temporary, sensitive data on the user, clear it here
  543. // $this->plainPassword = null;
  544. }
  545. public function getCreatedAt(): ?\DateTimeInterface
  546. {
  547. return $this->createdAt;
  548. }
  549. public function setCreatedAt(?\DateTimeInterface $createdAt): self
  550. {
  551. $this->createdAt = $createdAt;
  552. return $this;
  553. }
  554. public function getUpdatedAt(): ?\DateTimeInterface
  555. {
  556. return $this->updatedAt;
  557. }
  558. public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
  559. {
  560. $this->updatedAt = $updatedAt;
  561. return $this;
  562. }
  563. public function getLastLogin(): ?\DateTimeInterface
  564. {
  565. return $this->lastLogin;
  566. }
  567. public function setLastLogin(?\DateTimeInterface $lastLogin): self
  568. {
  569. $this->lastLogin = $lastLogin;
  570. return $this;
  571. }
  572. public function getName(): ?string
  573. {
  574. return $this->name;
  575. }
  576. public function setName(?string $name): self
  577. {
  578. $this->name = $name;
  579. return $this;
  580. }
  581. public function getLastname(): ?string
  582. {
  583. return $this->lastname;
  584. }
  585. public function setLastname(?string $lastname): self
  586. {
  587. $this->lastname = $lastname;
  588. return $this;
  589. }
  590. public function setUsername(?string $username): self
  591. {
  592. $this->username = $username;
  593. return $this;
  594. }
  595. public function getFirst(): ?bool
  596. {
  597. return $this->first;
  598. }
  599. public function setFirst(?bool $first): self
  600. {
  601. $this->first = $first;
  602. return $this;
  603. }
  604. public function getEnabled(): ?bool
  605. {
  606. return $this->enabled;
  607. }
  608. public function setEnabled(?bool $enabled): self
  609. {
  610. $this->enabled = $enabled;
  611. return $this;
  612. }
  613. public function getPremium(): ?bool
  614. {
  615. return $this->premium;
  616. }
  617. public function setPremium(bool $premium): self
  618. {
  619. $this->premium = $premium;
  620. return $this;
  621. }
  622. public function getPasswordForgotten(): ?string
  623. {
  624. return $this->passwordForgotten;
  625. }
  626. public function setPasswordForgotten(?string $passwordForgotten): self
  627. {
  628. $this->passwordForgotten = $passwordForgotten;
  629. return $this;
  630. }
  631. public function getPasswordForgottenLastDate(): ?\DateTimeInterface
  632. {
  633. return $this->passwordForgottenLastDate;
  634. }
  635. public function setPasswordForgottenLastDate(?\DateTimeInterface $passwordForgottenLastDate): self
  636. {
  637. $this->passwordForgottenLastDate = $passwordForgottenLastDate;
  638. return $this;
  639. }
  640. public function getPartenariat(): ?bool
  641. {
  642. return $this->partenariat;
  643. }
  644. public function setPartenariat(?bool $partenariat): self
  645. {
  646. $this->partenariat = $partenariat;
  647. return $this;
  648. }
  649. public function getDescription(): ?string
  650. {
  651. return $this->description;
  652. }
  653. public function setDescription(?string $description): self
  654. {
  655. $this->description = $description;
  656. return $this;
  657. }
  658. public function getNotificationsMessages(): ?bool
  659. {
  660. return $this->notificationsMessages;
  661. }
  662. public function setNotificationsMessages(?bool $notificationsMessages): self
  663. {
  664. $this->notificationsMessages = $notificationsMessages;
  665. return $this;
  666. }
  667. public function getNotificationsSuivis(): ?bool
  668. {
  669. return $this->notificationsSuivis;
  670. }
  671. public function setNotificationsSuivis(?bool $notificationsSuivis): self
  672. {
  673. $this->notificationsSuivis = $notificationsSuivis;
  674. return $this;
  675. }
  676. public function getUserCommissionUnit(): ?float
  677. {
  678. return $this->userCommissionUnit;
  679. }
  680. public function setUserCommissionUnit(?float $userCommissionUnit): self
  681. {
  682. $this->userCommissionUnit = $userCommissionUnit;
  683. return $this;
  684. }
  685. public function getUserCommissionPourcent(): ?float
  686. {
  687. return $this->userCommissionPourcent;
  688. }
  689. public function setUserCommissionPourcent(?float $userCommissionPourcent): self
  690. {
  691. $this->userCommissionPourcent = $userCommissionPourcent;
  692. return $this;
  693. }
  694. public function getCurrentAgency(): ?Agencies
  695. {
  696. return $this->currentAgency;
  697. }
  698. public function setCurrentAgency(?Agencies $currentAgency): self
  699. {
  700. $this->currentAgency = $currentAgency;
  701. return $this;
  702. }
  703. public function isFirst(): ?bool
  704. {
  705. return $this->first;
  706. }
  707. public function isEnabled(): ?bool
  708. {
  709. return $this->enabled;
  710. }
  711. public function isPremium(): ?bool
  712. {
  713. return $this->premium;
  714. }
  715. public function isPartenariat(): ?bool
  716. {
  717. return $this->partenariat;
  718. }
  719. public function isNotificationsMessages(): ?bool
  720. {
  721. return $this->notificationsMessages;
  722. }
  723. public function isNotificationsSuivis(): ?bool
  724. {
  725. return $this->notificationsSuivis;
  726. }
  727. public function getTypeAccount(): ?string
  728. {
  729. return $this->typeAccount;
  730. }
  731. public function setTypeAccount(?string $description): self
  732. {
  733. $this->typeAccount = $description;
  734. return $this;
  735. }
  736. public function getCandidate(): ?Candidates
  737. {
  738. return $this->candidate;
  739. }
  740. public function setCandidate(?Candidates $candidate): static
  741. {
  742. $this->candidate = $candidate;
  743. return $this;
  744. }
  745. public function getSubscriptionCustomerStripe(): ?string
  746. {
  747. return $this->subscriptionCustomerStripe;
  748. }
  749. public function setSubscriptionCustomerStripe(?string $subscriptionCustomerStripe): static
  750. {
  751. $this->subscriptionCustomerStripe = $subscriptionCustomerStripe;
  752. return $this;
  753. }
  754. public function getVerificationToken(): ?string
  755. {
  756. return $this->verificationToken;
  757. }
  758. public function setVerificationToken(?string $verificationToken): self
  759. {
  760. $this->verificationToken = $verificationToken;
  761. return $this;
  762. }
  763. public function getTokenExpiration(): ?\DateTimeInterface
  764. {
  765. return $this->tokenExpiration;
  766. }
  767. public function setTokenExpiration(?\DateTimeInterface $tokenExpiration): self
  768. {
  769. $this->tokenExpiration = $tokenExpiration;
  770. return $this;
  771. }
  772. public function getLanguage(): ?string
  773. {
  774. return $this->language;
  775. }
  776. public function setLanguage(?string $description): self
  777. {
  778. $this->language = $description;
  779. return $this;
  780. }
  781. public function isVerification(): ?bool
  782. {
  783. return $this->verification;
  784. }
  785. public function setVerification(?bool $verification): self
  786. {
  787. $this->verification = $verification;
  788. return $this;
  789. }
  790. public function getMotif(): ?string
  791. {
  792. return $this->motif;
  793. }
  794. public function setMotif(?string $motif): self
  795. {
  796. $this->motif = $motif;
  797. return $this;
  798. }
  799. public function getIaOffreCount(): int
  800. {
  801. return (int) $this->iaOffreCount;
  802. }
  803. public function setIaOffreCount(int $n): self
  804. {
  805. $this->iaOffreCount = $n;
  806. return $this;
  807. }
  808. public function getIaOffreDay(): ?\DateTimeInterface
  809. {
  810. return $this->iaOffreDay;
  811. }
  812. public function setIaOffreDay(?\DateTimeInterface $jour): self
  813. {
  814. $this->iaOffreDay = $jour;
  815. return $this;
  816. }
  817. /**
  818. * Combien de rédactions ce compte a consommées AUJOURD'HUI.
  819. *
  820. * ⚠️ UN COMPTEUR D'HIER VAUT ZÉRO, IL NE SE PURGE PAS.
  821. *
  822. * La remise à zéro est implicite : si la date stockée n'est pas
  823. * celle du jour, le compteur ne concerne pas aujourd'hui. Pas de
  824. * travail planifié, donc pas de travail planifié en panne.
  825. */
  826. public function iaOffreUtiliseAujourdhui(): int
  827. {
  828. if (!$this->iaOffreDay) {
  829. return 0;
  830. }
  831. return $this->iaOffreDay->format('Y-m-d') === (new \DateTime())->format('Y-m-d')
  832. ? (int) $this->iaOffreCount
  833. : 0;
  834. }
  835. public function getIaOffreQuota(): ?int
  836. {
  837. return $this->iaOffreQuota;
  838. }
  839. public function setIaOffreQuota(?int $n): self
  840. {
  841. $this->iaOffreQuota = $n;
  842. return $this;
  843. }
  844. /**
  845. * Le plafond applicable à ce compte.
  846. *
  847. * ⚠️ LE RÉGLAGE INDIVIDUEL L'EMPORTE, Y COMPRIS À LA BAISSE.
  848. *
  849. * Un abonné à qui l'on a fixé 5 aura 5, pas 100. C'est voulu : le
  850. * champ sert autant à ouvrir qu'à restreindre — un compte qui abuse
  851. * se borne sans qu'on ait à lui retirer son abonnement.
  852. *
  853. * @param int $defaut le plafond selon l'abonnement, décidé par l'appelant
  854. */
  855. public function iaOffrePlafond(int $defaut): int
  856. {
  857. return $this->iaOffreQuota === null ? $defaut : max(0, (int) $this->iaOffreQuota);
  858. }
  859. /** Enregistre une rédaction de plus pour aujourd'hui. */
  860. public function iaOffreIncremente(): self
  861. {
  862. $this->iaOffreCount = $this->iaOffreUtiliseAujourdhui() + 1;
  863. $this->iaOffreDay = new \DateTime();
  864. return $this;
  865. }
  866. }