Create InvoiceOneFeePerStudentPerEvent implementation of InvoiceDataService and set up ability to select and use it.

This commit is contained in:
Matt Young 2025-09-10 21:20:22 -05:00
parent aa92d66ff4
commit 340fae6747
3 changed files with 106 additions and 0 deletions

View File

@ -6,6 +6,7 @@ use App\Services\EntryService;
use App\Services\Invoice\InvoiceDataService; use App\Services\Invoice\InvoiceDataService;
use App\Services\Invoice\InvoiceOneFeePerEntry; use App\Services\Invoice\InvoiceOneFeePerEntry;
use App\Services\Invoice\InvoiceOneFeePerStudent; use App\Services\Invoice\InvoiceOneFeePerStudent;
use App\Services\Invoice\InvoiceOneFeePerStudentPerEvent;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
@ -42,6 +43,7 @@ class InvoiceDataServiceProvider extends ServiceProvider
return match (auditionSetting('fee_structure')) { return match (auditionSetting('fee_structure')) {
'oneFeePerEntry' => new InvoiceOneFeePerEntry($app->make(EntryService::class)), 'oneFeePerEntry' => new InvoiceOneFeePerEntry($app->make(EntryService::class)),
'oneFeePerStudent' => new InvoiceOneFeePerStudent($app->make(EntryService::class)), 'oneFeePerStudent' => new InvoiceOneFeePerStudent($app->make(EntryService::class)),
'oneFeePerStudentPerEvent' => new InvoiceOneFeePerStudentPerEvent($app->make(EntryService::class)),
default => throw new \Exception('Unknown Invoice Method'), default => throw new \Exception('Unknown Invoice Method'),
}; };
}); });

View File

@ -0,0 +1,101 @@
<?php
namespace App\Services\Invoice;
use App\Models\School;
use App\Services\EntryService;
use Illuminate\Support\Arr;
use function auditionSetting;
class InvoiceOneFeePerStudentPerEvent implements InvoiceDataService
{
/**
* Create a new class instance.
*/
protected $entryService;
public function __construct(EntryService $entryService)
{
$this->entryService = $entryService;
}
public function allData($schoolId)
{
static $schoolInvoiceData = [];
if (Arr::has($schoolInvoiceData, $schoolId)) {
return $schoolInvoiceData[$schoolId];
}
$school = School::findOrFail($schoolId);
$invoiceData['lines'] = [];
$invoiceData['linesTotal'] = 0;
$invoiceData['lateFeesTotal'] = 0;
/** @noinspection PhpArrayIndexImmediatelyRewrittenInspection */
$invoiceData['grandTotal'] = 0;
$entries = $school->entries()->with('audition')->orderBy('created_at', 'desc')->get()->groupBy('student_id');
foreach ($school->students as $student) {
$firstEntryForStudent = true;
foreach ($entries[$student->id] ?? [] as $entry) {
if ($firstEntryForStudent) {
$entryFee = $entry->audition->entry_fee / 100;
$lateFee = ($this->entryService->isEntryLate($entry) && ! $entry->hasFlag('late_fee_waived'))
? auditionSetting('late_fee') / 100 : 0;
} else {
$entryFee = 0;
$lateFee = 0;
}
$invoiceData['lines'][] = [
'student_name' => $student->full_name(true),
'audition' => $entry->audition->name,
'entry_timestamp' => $entry->created_at,
'entry_fee' => $entryFee,
'late_fee' => $lateFee,
];
$invoiceData['linesTotal'] += $entryFee;
$invoiceData['lateFeesTotal'] += $lateFee;
$firstEntryForStudent = false;
}
}
// School Fee Total
if (! auditionSetting('school_fee')) {
$invoiceData['schoolFeeTotal'] = 0;
} else {
$invoiceData['schoolFeeTotal'] = auditionSetting('school_fee') / 100;
}
$invoiceData['grandTotal'] = $invoiceData['linesTotal'] + $invoiceData['lateFeesTotal'] + $invoiceData['schoolFeeTotal'];
$schoolInvoiceData[$school->id] = $invoiceData;
return $invoiceData;
}
public function getLines($schoolId)
{
return $this->allData($schoolId)['lines'];
}
public function getLinesTotal($schoolId)
{
return $this->allData($schoolId)['linesTotal'];
}
public function getLateFeesTotal($schoolId)
{
return $this->allData($schoolId)['lateFeesTotal'];
}
public function getSchoolFeeTotal($schoolId)
{
return $this->allData($schoolId)['schoolFeeTotal'];
}
public function getGrandTotal($schoolId)
{
return $this->allData($schoolId)['grandTotal'];
}
}

View File

@ -85,6 +85,9 @@
<option value="oneFeePerStudent" {{ auditionSetting('fee_structure') === 'oneFeePerStudent' ? 'selected':'' }}> <option value="oneFeePerStudent" {{ auditionSetting('fee_structure') === 'oneFeePerStudent' ? 'selected':'' }}>
One fee per student - one late fee per student if any of their entries are late One fee per student - one late fee per student if any of their entries are late
</option> </option>
<option value="oneFeePerStudentPerEvent" {{ auditionSetting('fee_structure') === 'oneFeePerStudentPerEvent' ? 'selected':'' }}>
One fee per student per event - one late fee per student if any of their entries are late
</option>
</x-form.select> </x-form.select>
<x-form.field label_text="Late Fee" <x-form.field label_text="Late Fee"