src/Entity/Depense.php line 13

Open in your IDE?
  1. <?php
  2. namespace App\Entity;
  3. use Doctrine\Common\Collections\ArrayCollection;
  4. use Doctrine\Common\Collections\Collection;
  5. use App\Service\ComptaService;
  6. use Doctrine\ORM\Mapping as ORM;
  7. /**
  8.  * @ORM\Entity(repositoryClass="App\Repository\DepenseRepository")
  9.  */
  10. class Depense
  11. {
  12.     /*
  13.      * Par quel moyen la dépense est sortie (11/09/2026).
  14.      *
  15.      * Même convention que les paiements de vente
  16.      * (ComptaService::PAIEMENT_COMPTES) : on ne crée pas un second
  17.      * vocabulaire pour dire la même chose.
  18.      *
  19.      * C'est ce mode qui décide de DEUX choses : le compte de trésorerie
  20.      * qui se vide, et le compte du grand livre qui se crédite. Sans lui,
  21.      * une dépense du bureau payée par virement sortait de la caisse.
  22.      */
  23.     public const MODE_ESPECE       = 1;
  24.     public const MODE_BANQUE       = 2;
  25.     public const MODE_MOBILE_MONEY = 3;
  26.     /** @ORM\Column(type="integer", options={"default":1}, name="modepaiementdepense") */
  27.     private $modepaiementdepense = self::MODE_ESPECE;
  28.     /**
  29.      * @ORM\Id()
  30.      * @ORM\GeneratedValue()
  31.      * @ORM\Column(type="integer")
  32.      */
  33.     private $id;
  34.     /**
  35.      * @ORM\Column(type="string", length=200, nullable=true)
  36.      */
  37.     private $beneficiaire;
  38.     /**
  39.      * @ORM\Column(type="integer")
  40.      */
  41.     private $montantdepense = 0;
  42.     /**
  43.      * @ORM\Column(type="text")
  44.      */
  45.     private $descriptiondepense;
  46.     /**
  47.      * @ORM\Column(type="text")
  48.      */
  49.     private $journaldepense;
  50.     /**
  51.      * @ORM\Column(type="datetime", nullable=true)
  52.      */
  53.     private $datecreationdepense;
  54.     /**
  55.      * @ORM\Column(type="datetime", nullable=true)
  56.      */
  57.     private $datemodificationdepense;
  58.     /**
  59.      * @ORM\Column(type="datetime", nullable=true)
  60.      */
  61.     private $datedepense;
  62.     /**
  63.      * @ORM\Column(type="datetime", nullable=true)
  64.      */
  65.     private $datesuppressiondepense;
  66.     /**
  67.      * @ORM\ManyToOne(targetEntity="Magasin")
  68.      * @ORM\JoinColumn(name="magasinid", referencedColumnName="id", nullable=true)
  69.      */
  70.     private $magasinid;
  71.     /**
  72.      * @ORM\ManyToOne(targetEntity="User")
  73.      * @ORM\JoinColumn(name="ajoutepar", referencedColumnName="id", nullable=true)
  74.      */
  75.     private $ajoutepar;
  76.     /**
  77.      * @ORM\ManyToOne(targetEntity="User")
  78.      * @ORM\JoinColumn(name="supprimepar", referencedColumnName="id", nullable=true)
  79.      */
  80.     private $supprimepar;
  81.     /**
  82.      * @ORM\ManyToOne(targetEntity="User")
  83.      * @ORM\JoinColumn(name="modifiepar", referencedColumnName="id", nullable=true)
  84.      */
  85.     private $modifiepar;
  86.     /**
  87.      * @ORM\ManyToOne(targetEntity="Produit")
  88.      * @ORM\JoinColumn(name="produitid", referencedColumnName="id", nullable=true)
  89.      */
  90.     private $produitid;
  91.     /**
  92.      * @ORM\ManyToOne(targetEntity="DepenseCategorie", inversedBy="depenses")
  93.      * @ORM\JoinColumn(name="categorieid", referencedColumnName="id", nullable=true)
  94.      */
  95.     private $categorieid;
  96.     /**
  97.      * @ORM\ManyToOne(targetEntity="CashSession")
  98.      * @ORM\JoinColumn(name="cash_session_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
  99.      */
  100.     private $cashSession;
  101.     /**
  102.      * Relation vers la table de jointure DepenseVehicule.
  103.      * C'est DepenseVehicule.php qui déclare et possède la table depense_vehicule. 
  104.      *
  105.      * @ORM\OneToMany(
  106.      *     targetEntity="DepenseVehicule",
  107.      *     mappedBy="depense",
  108.      *     cascade={"persist", "remove"},
  109.      *     orphanRemoval=true
  110.      * )
  111.      */
  112.     private $depenseVehicules;
  113.     /**
  114.      * @ORM\OneToMany(targetEntity="DepenseFichier", mappedBy="depenseid", cascade={"persist","remove"})
  115.      */
  116.     private $fichiers;
  117.     /**
  118.      * @ORM\OneToMany(targetEntity="DepenseCommentaire", mappedBy="depenseid", cascade={"persist","remove"})
  119.      */
  120.     private $commentaires;
  121.     public function __construct()
  122.     {
  123.         $this->depenseVehicules = new ArrayCollection();
  124.         $this->fichiers         = new ArrayCollection();
  125.         $this->commentaires     = new ArrayCollection();
  126.     }
  127.     // ── Getters / Setters standards ───────────────────────────────────────────
  128.     public function getId(): ?int
  129.     {
  130.         return $this->id;
  131.     }
  132.     public function getBeneficiaire(): ?string
  133.     {
  134.         return $this->beneficiaire;
  135.     }
  136.     public function setBeneficiaire(?string $v): static
  137.     {
  138.         $this->beneficiaire = $v;
  139.         return $this;
  140.     }
  141.     public function getMontantdepense(): ?int
  142.     {
  143.         return $this->montantdepense;
  144.     }
  145.     public function setMontantdepense(int $v): static
  146.     {
  147.         $this->montantdepense = $v;
  148.         return $this;
  149.     }
  150.     public function getDescriptiondepense(): ?string
  151.     {
  152.         return $this->descriptiondepense;
  153.     }
  154.     public function setDescriptiondepense(string $v): static
  155.     {
  156.         $this->descriptiondepense = $v;
  157.         return $this;
  158.     }
  159.     public function getJournaldepense(): ?string
  160.     {
  161.         return $this->journaldepense;
  162.     }
  163.     public function setJournaldepense(string $v): static
  164.     {
  165.         $this->journaldepense = $v;
  166.         return $this;
  167.     }
  168.     public function getDatecreationdepense(): ?\DateTimeInterface
  169.     {
  170.         return $this->datecreationdepense;
  171.     }
  172.     public function setDatecreationdepense(?\DateTimeInterface $v): static
  173.     {
  174.         $this->datecreationdepense = $v;
  175.         return $this;
  176.     }
  177.     public function getDatedepense(): ?\DateTimeInterface
  178.     {
  179.         return $this->datedepense;
  180.     }
  181.     public function setDatedepense(?\DateTimeInterface $v): static
  182.     {
  183.         $this->datedepense = $v;
  184.         return $this;
  185.     }
  186.     public function getDatesuppressiondepense(): ?\DateTimeInterface
  187.     {
  188.         return $this->datesuppressiondepense;
  189.     }
  190.     public function setDatesuppressiondepense(?\DateTimeInterface $v): static
  191.     {
  192.         $this->datesuppressiondepense = $v;
  193.         return $this;
  194.     }
  195.     public function getDatemodificationdepense(): ?\DateTimeInterface
  196.     {
  197.         return $this->datemodificationdepense;
  198.     }
  199.     public function setDatemodificationdepense(?\DateTimeInterface $v): static
  200.     {
  201.         $this->datemodificationdepense = $v;
  202.         return $this;
  203.     }
  204.     /**
  205.      * Le type de compte de trésorerie que ce mode fait bouger.
  206.      *
  207.      * Vit ici, à côté des constantes, plutôt que dans le résolveur : c'est
  208.      * la dépense qui sait par quel moyen elle est partie, pas la caisse.
  209.      */
  210.     public static function typeCompteDuMode(int $mode): string
  211.     {
  212.         return match ($mode) {
  213.             self::MODE_BANQUE       => TreasuryAccount::TYPE_BANQUE,
  214.             self::MODE_MOBILE_MONEY => TreasuryAccount::TYPE_MOBILE_MONEY,
  215.             default                 => TreasuryAccount::TYPE_CAISSE,
  216.         };
  217.     }
  218.     /** Le compte OHADA de trésorerie correspondant — même table que les ventes. */
  219.     public static function compteTresoDuMode(int $mode): string
  220.     {
  221.         return ComptaService::PAIEMENT_COMPTES[$mode] ?? ComptaService::PAIEMENT_COMPTES[self::MODE_ESPECE];
  222.     }
  223.     public function getModepaiementdepense(): int
  224.     {
  225.         // L'historique n'avait pas de mode : l'espèce est ce que la
  226.         // comptabilité écrivait déjà en dur pour toutes les dépenses.
  227.         return (int) ($this->modepaiementdepense ?: self::MODE_ESPECE);
  228.     }
  229.     public function setModepaiementdepense(?int $v): static
  230.     {
  231.         $this->modepaiementdepense = in_array($v, [self::MODE_ESPECE, self::MODE_BANQUE, self::MODE_MOBILE_MONEY], true)
  232.             ? $v
  233.             : self::MODE_ESPECE;
  234.         return $this;
  235.     }
  236.     public function getMagasinid(): ?Magasin
  237.     {
  238.         return $this->magasinid;
  239.     }
  240.     public function setMagasinid(?Magasin $v): static
  241.     {
  242.         $this->magasinid = $v;
  243.         return $this;
  244.     }
  245.     public function getAjoutepar(): ?User
  246.     {
  247.         return $this->ajoutepar;
  248.     }
  249.     public function setAjoutepar(?User $v): static
  250.     {
  251.         $this->ajoutepar = $v;
  252.         return $this;
  253.     }
  254.     public function getSupprimepar(): ?User
  255.     {
  256.         return $this->supprimepar;
  257.     }
  258.     public function setSupprimepar(?User $v): static
  259.     {
  260.         $this->supprimepar = $v;
  261.         return $this;
  262.     }
  263.     public function getModifiepar(): ?User
  264.     {
  265.         return $this->modifiepar;
  266.     }
  267.     public function setModifiepar(?User $v): static
  268.     {
  269.         $this->modifiepar = $v;
  270.         return $this;
  271.     }
  272.     public function getProduitid(): ?Produit
  273.     {
  274.         return $this->produitid;
  275.     }
  276.     public function setProduitid(?Produit $v): static
  277.     {
  278.         $this->produitid = $v;
  279.         return $this;
  280.     }
  281.     public function getCategorieid(): ?DepenseCategorie
  282.     {
  283.         return $this->categorieid;
  284.     }
  285.     public function setCategorieid(?DepenseCategorie $v): static
  286.     {
  287.         $this->categorieid = $v;
  288.         return $this;
  289.     }
  290.     public function getCashSession(): ?CashSession
  291.     {
  292.         return $this->cashSession;
  293.     }
  294.     public function setCashSession(?CashSession $v): static
  295.     {
  296.         $this->cashSession = $v;
  297.         return $this;
  298.     }
  299.     // ── MULTI-VÉHICULES ───────────────────────────────────────────────────────
  300.     public function getDepenseVehicules(): Collection
  301.     {
  302.         return $this->depenseVehicules;
  303.     }
  304.     public function addDepenseVehicule(DepenseVehicule $dv): static
  305.     {
  306.         if (!$this->depenseVehicules->contains($dv)) {
  307.             $this->depenseVehicules->add($dv);
  308.             $dv->setDepense($this);
  309.         }
  310.         return $this;
  311.     }
  312.     public function removeDepenseVehicule(DepenseVehicule $dv): static
  313.     {
  314.         $this->depenseVehicules->removeElement($dv);
  315.         return $this;
  316.     }
  317.     /**
  318.      * Raccourci pour Twig : retourne les Vehicule directement.
  319.      * Usage : DEPENSE.vehicules
  320.      *
  321.      * @return Vehicule[]
  322.      */
  323.     public function getVehicules(): array
  324.     {
  325.         return array_values(array_filter(
  326.             $this->depenseVehicules
  327.                 ->map(fn(DepenseVehicule $dv) => $dv->getVehicule())
  328.                 ->toArray()
  329.         ));
  330.     }
  331.     /**
  332.      * Synchronise la liste des véhicules depuis le formulaire.
  333.      *
  334.      * @param Vehicule[] $nouveauxVehicules
  335.      * @param User|null  $user
  336.      */
  337.     public function syncVehicules(array $nouveauxVehicules, ?User $user = null): static
  338.     {
  339.         $idsActuels  = $this->depenseVehicules
  340.             ->map(fn(DepenseVehicule $dv) => $dv->getVehicule()?->getId())
  341.             ->toArray();
  342.         $idsNouveaux = array_map(fn(Vehicule $v) => $v->getId(), $nouveauxVehicules);
  343.         // Supprimer les liens absents de la nouvelle liste
  344.         foreach ($this->depenseVehicules->toArray() as $dv) {
  345.             if (!in_array($dv->getVehicule()?->getId(), $idsNouveaux, true)) {
  346.                 $this->depenseVehicules->removeElement($dv);
  347.             }
  348.         }
  349.         // Ajouter les nouveaux liens
  350.         foreach ($nouveauxVehicules as $vehicule) {
  351.             if (!in_array($vehicule->getId(), $idsActuels, true)) {
  352.                 $dv = new DepenseVehicule();
  353.                 $dv->setDepense($this);
  354.                 $dv->setVehicule($vehicule);
  355.                 $dv->setDatecreation(new \DateTime());
  356.                 $dv->setAjoutepar($user);
  357.                 $this->depenseVehicules->add($dv);
  358.             }
  359.         }
  360.         return $this;
  361.     }
  362.     public function hasVehicules(): bool
  363.     {
  364.         return !$this->depenseVehicules->isEmpty();
  365.     }
  366.     /**
  367.      * IDs des véhicules liés — pour pré-cocher les checkboxes.
  368.      *
  369.      * @return int[]
  370.      */
  371.     public function getVehiculesIds(): array
  372.     {
  373.         return array_values(array_filter(
  374.             $this->depenseVehicules
  375.                 ->map(fn(DepenseVehicule $dv) => $dv->getVehicule()?->getId())
  376.                 ->toArray()
  377.         ));
  378.     }
  379.     /**
  380.      * Résumé lisible : "AA-001 · BB-002"
  381.      */
  382.     public function getVehiculesLabel(): string
  383.     {
  384.         $labels = array_filter(
  385.             $this->depenseVehicules
  386.                 ->map(fn(DepenseVehicule $dv) => $dv->getVehicule()?->getImmatriculation())
  387.                 ->toArray()
  388.         );
  389.         return implode(' · ', $labels);
  390.     }
  391.     // ── Fichiers ──────────────────────────────────────────────────────────────
  392.     public function getFichiers(): Collection
  393.     {
  394.         return $this->fichiers;
  395.     }
  396.     public function getFichiersActifs(): Collection
  397.     {
  398.         return $this->fichiers->filter(
  399.             fn(DepenseFichier $f) => $f->getDatesuppression() === null
  400.         );
  401.     }
  402.     public function addFichier(DepenseFichier $f): static
  403.     {
  404.         if (!$this->fichiers->contains($f)) {
  405.             $this->fichiers->add($f);
  406.             $f->setDepenseid($this);
  407.         }
  408.         return $this;
  409.     }
  410.     public function removeFichier(DepenseFichier $f): static
  411.     {
  412.         $this->fichiers->removeElement($f);
  413.         return $this;
  414.     }
  415.     // ── Commentaires ──────────────────────────────────────────────────────────
  416.     public function getCommentaires(): Collection
  417.     {
  418.         return $this->commentaires;
  419.     }
  420.     public function getCommentairesActifs(): Collection
  421.     {
  422.         return $this->commentaires->filter(
  423.             fn(DepenseCommentaire $c) => $c->getDatesuppression() === null
  424.         );
  425.     }
  426.     public function addCommentaire(DepenseCommentaire $c): static
  427.     {
  428.         if (!$this->commentaires->contains($c)) {
  429.             $this->commentaires->add($c);
  430.             $c->setDepenseid($this);
  431.         }
  432.         return $this;
  433.     }
  434.     public function removeCommentaire(DepenseCommentaire $c): static
  435.     {
  436.         $this->commentaires->removeElement($c);
  437.         return $this;
  438.     }
  439.     /**
  440.      * Snapshot scalaire pour le journal d'actions.
  441.      */
  442.     public function toArray(): array
  443.     {
  444.         $fichiers     = [];
  445.         foreach ($this->getFichiersActifs() as $f) { $fichiers[] = $f->getId(); }
  446.         $commentaires = [];
  447.         foreach ($this->getCommentairesActifs() as $c) { $commentaires[] = $c->getId(); }
  448.         return [
  449.             'id'                       => $this->id,
  450.             'beneficiaire'             => $this->beneficiaire,
  451.             'montantdepense'           => $this->montantdepense,
  452.             'descriptiondepense'       => $this->descriptiondepense,
  453.             'magasinid'                => $this->magasinid    ? $this->magasinid->getId()    : null,
  454.             'modepaiementdepense'      => $this->getModepaiementdepense(),
  455.             'categorieid'              => $this->categorieid  ? $this->categorieid->getId()  : null,
  456.             'ajoutepar'                => $this->ajoutepar    ? $this->ajoutepar->getId()    : null,
  457.             'modifiepar'               => $this->modifiepar   ? $this->modifiepar->getId()   : null,
  458.             'supprimepar'              => $this->supprimepar  ? $this->supprimepar->getId()  : null,
  459.             'datedepense'              => $this->datedepense              ? $this->datedepense->format(\DateTimeInterface::ATOM)              : null,
  460.             'datecreationdepense'      => $this->datecreationdepense      ? $this->datecreationdepense->format(\DateTimeInterface::ATOM)      : null,
  461.             'datemodificationdepense'  => $this->datemodificationdepense  ? $this->datemodificationdepense->format(\DateTimeInterface::ATOM)  : null,
  462.             'datesuppressiondepense'   => $this->datesuppressiondepense   ? $this->datesuppressiondepense->format(\DateTimeInterface::ATOM)   : null,
  463.             'fichiers'                 => $fichiers,
  464.             'commentaires'             => $commentaires,
  465.             'vehicules_ids'            => $this->getVehiculesIds(),
  466.             'produitid'                => $this->produitid ? $this->produitid->getId() : null,
  467.             'cash_session_id'          => $this->cashSession ? $this->cashSession->getId() : null,
  468.         ];
  469.     }
  470. }