src/Finance/Domain/Entity/StudentFee.php line 21

Open in your IDE?
  1. <?php
  2. namespace App\Finance\Domain\Entity;
  3. use App\Entity\SchoolYear;
  4. use App\Entity\Student;
  5. use App\Finance\Domain\Enum\FeeType;
  6. use App\Finance\Domain\Enum\StudentFeeStatus;
  7. use App\Finance\Domain\Repository\StudentFeeRepository;
  8. use Doctrine\DBAL\Types\Types;
  9. use Doctrine\ORM\Mapping as ORM;
  10. use Symfony\Component\Validator\Constraints as Assert;
  11. #[ORM\Entity(repositoryClass: StudentFeeRepository::class)]
  12. #[ORM\Table(name: 'student_fees')]
  13. #[ORM\Index(columns: ['student_id'], name: 'idx_student_id')]
  14. #[ORM\Index(columns: ['school_year_id'], name: 'idx_school_year_id')]
  15. #[ORM\Index(columns: ['fee_type'], name: 'idx_fee_type')]
  16. #[ORM\Index(columns: ['status'], name: 'idx_status')]
  17. #[ORM\Index(columns: ['due_date'], name: 'idx_due_date')]
  18. class StudentFee
  19. {
  20. #[ORM\Id]
  21. #[ORM\GeneratedValue]
  22. #[ORM\Column(type: Types::INTEGER)]
  23. private ?int $id = null;
  24. #[ORM\ManyToOne(targetEntity: Student::class)]
  25. #[ORM\JoinColumn(nullable: false, name: 'student_id')]
  26. #[Assert\NotNull]
  27. private ?Student $student = null;
  28. #[ORM\ManyToOne(targetEntity: SchoolYear::class)]
  29. #[ORM\JoinColumn(nullable: false, name: 'school_year_id')]
  30. #[Assert\NotNull]
  31. private ?SchoolYear $schoolYear = null;
  32. #[ORM\ManyToOne(targetEntity: FeeDefinition::class)]
  33. #[ORM\JoinColumn(nullable: false, name: 'fee_definition_id')]
  34. #[Assert\NotNull]
  35. private ?FeeDefinition $feeDefinition = null;
  36. #[ORM\Column(type: Types::STRING, length: 20, enumType: FeeType::class)]
  37. #[Assert\NotNull]
  38. private FeeType $feeType;
  39. #[ORM\Column(type: Types::STRING, length: 255)]
  40. #[Assert\NotBlank]
  41. private string $name;
  42. #[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 2)]
  43. #[Assert\NotNull]
  44. #[Assert\PositiveOrZero]
  45. private string $amountDue;
  46. #[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 2, options: ['default' => '0.00'])]
  47. private string $amountPaid = '0.00';
  48. #[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 2, options: ['default' => '0.00'])]
  49. private string $balance = '0.00';
  50. #[ORM\Column(type: Types::STRING, length: 20, enumType: StudentFeeStatus::class)]
  51. private StudentFeeStatus $status = StudentFeeStatus::PENDING;
  52. #[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
  53. private ?\DateTimeImmutable $dueDate = null;
  54. #[ORM\Column(type: Types::INTEGER, nullable: true)]
  55. private ?int $installmentNumber = null;
  56. #[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
  57. private \DateTimeImmutable $createdAt;
  58. #[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
  59. private \DateTimeImmutable $updatedAt;
  60. public function __construct()
  61. {
  62. $this->createdAt = new \DateTimeImmutable();
  63. $this->updatedAt = new \DateTimeImmutable();
  64. }
  65. public function getId(): ?int { return $this->id; }
  66. public function getStudent(): ?Student { return $this->student; }
  67. public function setStudent(?Student $student): self
  68. {
  69. $this->student = $student;
  70. $this->updatedAt = new \DateTimeImmutable();
  71. return $this;
  72. }
  73. // Raccourci pour compatibilitĂ© avec les requĂȘtes DQL/Repository
  74. public function getStudentId(): ?int
  75. {
  76. return $this->student?->getId();
  77. }
  78. public function getSchoolYear(): ?SchoolYear { return $this->schoolYear; }
  79. public function setSchoolYear(?SchoolYear $schoolYear): self
  80. {
  81. $this->schoolYear = $schoolYear;
  82. $this->updatedAt = new \DateTimeImmutable();
  83. return $this;
  84. }
  85. public function getSchoolYearId(): ?int
  86. {
  87. return $this->schoolYear?->getId();
  88. }
  89. public function getFeeDefinition(): ?FeeDefinition { return $this->feeDefinition; }
  90. public function setFeeDefinition(?FeeDefinition $feeDefinition): self
  91. {
  92. $this->feeDefinition = $feeDefinition;
  93. $this->updatedAt = new \DateTimeImmutable();
  94. return $this;
  95. }
  96. public function getFeeDefinitionId(): ?int
  97. {
  98. return $this->feeDefinition?->getId();
  99. }
  100. public function getFeeType(): FeeType { return $this->feeType; }
  101. public function setFeeType(FeeType $feeType): self
  102. {
  103. $this->feeType = $feeType;
  104. $this->updatedAt = new \DateTimeImmutable();
  105. return $this;
  106. }
  107. public function getName(): string { return $this->name; }
  108. public function setName(string $name): self
  109. {
  110. $this->name = $name;
  111. $this->updatedAt = new \DateTimeImmutable();
  112. return $this;
  113. }
  114. public function getAmountDue(): string { return $this->amountDue; }
  115. public function setAmountDue(string $amountDue): self
  116. {
  117. $this->amountDue = $amountDue;
  118. $this->recalculateBalance();
  119. return $this;
  120. }
  121. public function getAmountPaid(): string { return $this->amountPaid; }
  122. public function setAmountPaid(string $amountPaid): self
  123. {
  124. $this->amountPaid = $amountPaid;
  125. $this->recalculateBalance();
  126. return $this;
  127. }
  128. public function getBalance(): string { return $this->balance; }
  129. public function getStatus(): StudentFeeStatus { return $this->status; }
  130. public function setStatus(StudentFeeStatus $status): self
  131. {
  132. $this->status = $status;
  133. $this->updatedAt = new \DateTimeImmutable();
  134. return $this;
  135. }
  136. public function getDueDate(): ?\DateTimeImmutable { return $this->dueDate; }
  137. public function setDueDate(?\DateTimeImmutable $dueDate): self
  138. {
  139. $this->dueDate = $dueDate;
  140. $this->updatedAt = new \DateTimeImmutable();
  141. return $this;
  142. }
  143. public function getInstallmentNumber(): ?int { return $this->installmentNumber; }
  144. public function setInstallmentNumber(?int $installmentNumber): self
  145. {
  146. $this->installmentNumber = $installmentNumber;
  147. $this->updatedAt = new \DateTimeImmutable();
  148. return $this;
  149. }
  150. public function getCreatedAt(): \DateTimeImmutable { return $this->createdAt; }
  151. public function getUpdatedAt(): \DateTimeImmutable { return $this->updatedAt; }
  152. public function recalculateBalance(): void
  153. {
  154. $this->balance = bcsub($this->amountDue, $this->amountPaid, 2);
  155. $this->updateStatus();
  156. $this->updatedAt = new \DateTimeImmutable();
  157. }
  158. private function updateStatus(): void
  159. {
  160. if (bccomp($this->balance, '0.00', 2) <= 0) {
  161. $this->status = StudentFeeStatus::PAID;
  162. } elseif (bccomp($this->amountPaid, '0.00', 2) > 0) {
  163. $this->status = StudentFeeStatus::PARTIAL;
  164. } else {
  165. $this->status = StudentFeeStatus::PENDING;
  166. }
  167. }
  168. public function isLate(): bool
  169. {
  170. if (!$this->dueDate) return false;
  171. return new \DateTimeImmutable() > $this->dueDate
  172. && bccomp($this->balance, '0.00', 2) > 0;
  173. }
  174. }