Student.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. namespace App\Models;
  3. use App\ValueObjects\Cpf;
  4. use Illuminate\Database\Eloquent\Factories\HasFactory;
  5. use Illuminate\Database\Eloquent\Model;
  6. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  7. use Illuminate\Database\Eloquent\Relations\HasMany;
  8. use Illuminate\Database\Eloquent\SoftDeletes;
  9. use Illuminate\Validation\ValidationException;
  10. /**
  11. * @property int $id
  12. * @property string $name
  13. * @property \Illuminate\Support\Carbon|null $birth_date
  14. * @property \App\ValueObjects\Cpf|null $document_number
  15. * @property string|null $gender
  16. * @property string|null $email
  17. * @property string|null $phone
  18. * @property string|null $postal_code
  19. * @property string|null $street
  20. * @property string|null $address_number
  21. * @property string|null $neighborhood
  22. * @property int|null $state_id
  23. * @property string|null $complement
  24. * @property string|null $payer_name
  25. * @property string|null $how_did_you_know_us
  26. * @property string|null $notes
  27. * @property string $status
  28. * @property \Illuminate\Support\Carbon|null $created_at
  29. * @property \Illuminate\Support\Carbon|null $updated_at
  30. * @property \Illuminate\Support\Carbon|null $deleted_at
  31. * @property int $unit_id
  32. * @property int|null $city_id
  33. * @property string|null $photo_url
  34. * @property-read \App\Models\City|null $city
  35. * @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\StudentContract> $contracts
  36. * @property-read int|null $contracts_count
  37. * @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\StudentResponsible> $responsibles
  38. * @property-read int|null $responsibles_count
  39. * @property-read \App\Models\State|null $state
  40. * @property-read \App\Models\Unit $unit
  41. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student newModelQuery()
  42. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student newQuery()
  43. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student onlyTrashed()
  44. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student query()
  45. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereAddressNumber($value)
  46. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereBirthDate($value)
  47. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereCityId($value)
  48. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereComplement($value)
  49. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereCreatedAt($value)
  50. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereDeletedAt($value)
  51. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereDocumentNumber($value)
  52. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereEmail($value)
  53. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereGender($value)
  54. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereHowDidYouKnowUs($value)
  55. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereId($value)
  56. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereName($value)
  57. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereNeighborhood($value)
  58. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereNotes($value)
  59. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student wherePayerName($value)
  60. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student wherePhone($value)
  61. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student wherePhotoUrl($value)
  62. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student wherePostalCode($value)
  63. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereStateId($value)
  64. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereStatus($value)
  65. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereStreet($value)
  66. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereUnitId($value)
  67. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student whereUpdatedAt($value)
  68. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student withTrashed(bool $withTrashed = true)
  69. * @method static \Illuminate\Database\Eloquent\Builder<static>|Student withoutTrashed()
  70. * @mixin \Eloquent
  71. */
  72. class Student extends Model
  73. {
  74. use HasFactory, SoftDeletes;
  75. public const STATUS_ACTIVE = 'active';
  76. public const STATUS_EX_STUDENT = 'ex_student';
  77. public const STATUS_LOCKED = 'locked';
  78. public const STATUS_LEAD = 'lead';
  79. private ?array $responsibleForCreation = null;
  80. protected $table = 'students';
  81. protected $guarded = ['id'];
  82. protected $casts = [
  83. 'birth_date' => 'date',
  84. 'document_number' => Cpf::class,
  85. 'created_at' => 'datetime',
  86. 'updated_at' => 'datetime',
  87. 'deleted_at' => 'datetime',
  88. ];
  89. protected static function booted(): void
  90. {
  91. static::creating(function (Student $student): void {
  92. if ($student->isMinor() && empty($student->responsibleForCreation)) {
  93. throw ValidationException::withMessages([
  94. 'responsible' => __('validation.minor_requires_responsible'),
  95. ]);
  96. }
  97. if (empty($student->status)) {
  98. $student->status = self::STATUS_LEAD;
  99. }
  100. });
  101. static::deleting(function (Student $student): void {
  102. if ($student->hasActiveContract()) {
  103. throw ValidationException::withMessages([
  104. 'student' => __('validation.student_has_active_contracts'),
  105. ]);
  106. }
  107. });
  108. }
  109. public function withResponsibleForCreation(?array $responsible): self
  110. {
  111. $this->responsibleForCreation = $responsible;
  112. return $this;
  113. }
  114. public function isMinor(): bool
  115. {
  116. return $this->birth_date !== null && $this->birth_date->age < 18;
  117. }
  118. public function hasActiveContract(): bool
  119. {
  120. return $this->contracts()->latestVersion()->where('status', 'active')->exists();
  121. }
  122. public function calculateStatus(): string
  123. {
  124. $contracts = $this->contracts()->latestVersion()->get();
  125. if ($contracts->isEmpty()) {
  126. return self::STATUS_LEAD;
  127. }
  128. $today = now()->startOfDay();
  129. $hasActive = $contracts->contains(function ($contract) use ($today) {
  130. return $contract->status === 'active' &&
  131. $contract->end_date &&
  132. $contract->end_date->startOfDay()->gte($today);
  133. });
  134. if ($hasActive) {
  135. return self::STATUS_ACTIVE;
  136. }
  137. $hasLocked = $contracts->contains(function ($contract) {
  138. return $contract->status === 'frozen';
  139. });
  140. if ($hasLocked) {
  141. return self::STATUS_LOCKED;
  142. }
  143. return self::STATUS_EX_STUDENT;
  144. }
  145. public function updateStatus(): void
  146. {
  147. $newStatus = $this->calculateStatus();
  148. if ($this->status !== $newStatus) {
  149. $this->status = $newStatus;
  150. $this->saveQuietly();
  151. }
  152. }
  153. public function contracts(): HasMany
  154. {
  155. return $this->hasMany(StudentContract::class);
  156. }
  157. public function responsibles(): HasMany
  158. {
  159. return $this->hasMany(StudentResponsible::class);
  160. }
  161. public function unit(): BelongsTo
  162. {
  163. return $this->belongsTo(Unit::class, 'unit_id');
  164. }
  165. public function city(): BelongsTo
  166. {
  167. return $this->belongsTo(City::class, 'city_id');
  168. }
  169. public function state(): BelongsTo
  170. {
  171. return $this->belongsTo(State::class, 'state_id');
  172. }
  173. }