瀏覽代碼

feat(contracts): add class quantity calculation and corresponding tests

alvesantos 1 周之前
父節點
當前提交
c4562c6578
共有 2 個文件被更改,包括 88 次插入0 次删除
  1. 31 0
      app/Models/StudentContract.php
  2. 57 0
      tests/Unit/StudentContractClassQuantityTest.php

+ 31 - 0
app/Models/StudentContract.php

@@ -138,6 +138,10 @@ public function scopeLatestVersion(Builder $query): Builder
 
     protected static function booted(): void
     {
+        static::saving(function (StudentContract $contract) {
+            $contract->class_quantity = $contract->calculateClassQuantity();
+        });
+
         $updateStudentStatus = function (StudentContract $contract): void {
             if ($contract->student_id) {
                 // Use withoutGlobalScopes or just normal relation if no scopes affect it
@@ -150,6 +154,33 @@ protected static function booted(): void
         static::restored($updateStudentStatus);
     }
 
+    public function calculateClassQuantity(): int
+    {
+        if (!$this->signature_date || !$this->end_date) {
+            return (int) $this->class_quantity; // Fallback to current if missing
+        }
+
+        $start = $this->signature_date->copy()->startOfDay();
+        $end = $this->end_date->copy()->startOfDay();
+
+        if ($start->greaterThan($end)) {
+            return 0;
+        }
+
+        $count = 0;
+        for ($date = $start; $date->lessThanOrEqualTo($end); $date->addDay()) {
+            $dayOfWeek = $date->dayOfWeek; // 0 (Sunday) to 6 (Saturday)
+            if ($this->weekday !== null && $dayOfWeek === (int) $this->weekday) {
+                $count++;
+            }
+            if ($this->second_weekday !== null && $dayOfWeek === (int) $this->second_weekday) {
+                $count++;
+            }
+        }
+
+        return $count;
+    }
+
     public function derivedFrom(): BelongsTo
     {
         return $this->belongsTo(self::class, 'derived_from_contract_id');

+ 57 - 0
tests/Unit/StudentContractClassQuantityTest.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace Tests\Unit;
+
+use App\Models\StudentContract;
+use Carbon\Carbon;
+use Tests\TestCase;
+
+class StudentContractClassQuantityTest extends TestCase
+{
+    public function test_it_calculates_class_quantity_correctly_for_one_weekday(): void
+    {
+        $contract = new StudentContract();
+        $contract->signature_date = Carbon::parse('2023-01-01'); // Sunday
+        $contract->end_date = Carbon::parse('2023-01-31'); // 31 days
+        $contract->weekday = 1; // Monday (2023-01-02, 09, 16, 23, 30) -> 5 occurrences
+
+        $quantity = $contract->calculateClassQuantity();
+
+        $this->assertEquals(5, $quantity);
+    }
+
+    public function test_it_calculates_class_quantity_correctly_for_two_weekdays(): void
+    {
+        $contract = new StudentContract();
+        $contract->signature_date = Carbon::parse('2023-01-01'); // Sunday
+        $contract->end_date = Carbon::parse('2023-01-14'); // 2 weeks
+        $contract->weekday = 1; // Monday (2 occurrences)
+        $contract->second_weekday = 3; // Wednesday (2 occurrences)
+
+        $quantity = $contract->calculateClassQuantity();
+
+        $this->assertEquals(4, $quantity);
+    }
+
+    public function test_it_returns_zero_if_end_date_is_before_signature_date(): void
+    {
+        $contract = new StudentContract();
+        $contract->signature_date = Carbon::parse('2023-01-31');
+        $contract->end_date = Carbon::parse('2023-01-01');
+        $contract->weekday = 1;
+
+        $quantity = $contract->calculateClassQuantity();
+
+        $this->assertEquals(0, $quantity);
+    }
+
+    public function test_it_returns_fallback_if_dates_are_missing(): void
+    {
+        $contract = new StudentContract();
+        $contract->class_quantity = 10;
+        
+        $quantity = $contract->calculateClassQuantity();
+
+        $this->assertEquals(10, $quantity);
+    }
+}