From d522148cb9933e38a5bdef653f4cfea6cdedd6b5 Mon Sep 17 00:00:00 2001
From: Matt Young
Date: Wed, 17 Jul 2024 19:31:02 -0500
Subject: [PATCH] Invoices honor late_fee_waived flag #38 Add ability for admin
to forgive late fee on an entry
---
app/Actions/Entries/UpdateEntry.php | 4 +++-
.../Controllers/Admin/EntryController.php | 12 ++++++------
.../Invoice/InvoiceOneFeePerEntry.php | 3 ++-
.../Invoice/InvoiceOneFeePerStudent.php | 3 ++-
resources/views/admin/entries/edit.blade.php | 15 ++++++++++++---
tests/Feature/Pages/Admin/EntriesEditTest.php | 19 ++++++++++++++++++-
6 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/app/Actions/Entries/UpdateEntry.php b/app/Actions/Entries/UpdateEntry.php
index eeb8d90..9fe0bba 100644
--- a/app/Actions/Entries/UpdateEntry.php
+++ b/app/Actions/Entries/UpdateEntry.php
@@ -86,7 +86,9 @@ class UpdateEntry
if ($this->entry->scoreSheets()->count() > 0) {
throw new ManageEntryException('Cannot change the audition for an entry with scores');
}
- if (Entry::where('student_id', $this->entry->student_id)->where('audition_id', $audition->id)->exists()) {
+ if ($audition->id !== $this->entry->audition_id &&
+ Entry::where('student_id', $this->entry->student_id)
+ ->where('audition_id', $audition->id)->exists()) {
throw new ManageEntryException('That student is already entered in that audition');
}
// OK we're allowed to change the audition
diff --git a/app/Http/Controllers/Admin/EntryController.php b/app/Http/Controllers/Admin/EntryController.php
index d6025a9..78c7d6d 100644
--- a/app/Http/Controllers/Admin/EntryController.php
+++ b/app/Http/Controllers/Admin/EntryController.php
@@ -161,6 +161,7 @@ class EntryController extends Controller
$validData['for_seating'] = $request->get('for_seating') ? 1 : 0;
$validData['for_advancement'] = $request->get('for_advancement') ? 1 : 0;
+ $validData['late_fee_waived'] = $request->get('late_fee_waived') ? 1 : 0;
// If the audition is not set to advance to the next round, then the entry must be for seating
if (! auditionSetting('advanceTo')) {
@@ -171,12 +172,11 @@ class EntryController extends Controller
} catch (ManageEntryException $e) {
return redirect()->route('admin.entries.index')->with('error', $e->getMessage());
}
-
- // $entry->update([
- // 'audition_id' => $validData['audition_id'],
- // 'for_seating' => $validData['for_seating'],
- // 'for_advancement' => $validData['for_advancement'],
- // ]);
+ if ($validData['late_fee_waived']) {
+ $entry->addFlag('late_fee_waived');
+ } else {
+ $entry->removeFlag('late_fee_waived');
+ }
return to_route('admin.entries.index')->with('success', 'Entry updated successfully');
}
diff --git a/app/Services/Invoice/InvoiceOneFeePerEntry.php b/app/Services/Invoice/InvoiceOneFeePerEntry.php
index 1ca5b34..6577546 100644
--- a/app/Services/Invoice/InvoiceOneFeePerEntry.php
+++ b/app/Services/Invoice/InvoiceOneFeePerEntry.php
@@ -39,7 +39,8 @@ class InvoiceOneFeePerEntry implements InvoiceDataService
foreach ($school->students as $student) {
foreach ($entries[$student->id] ?? [] as $entry) {
$entryFee = $entry->audition->entry_fee / 100;
- $lateFee = $this->entryService->isEntryLate($entry) ? auditionSetting('late_fee') / 100 : 0;
+ $lateFee = ($this->entryService->isEntryLate($entry) && ! $entry->hasFlag('late_fee_waived'))
+ ? auditionSetting('late_fee') / 100 : 0;
$invoiceData['lines'][] = [
'student_name' => $student->full_name(true),
diff --git a/app/Services/Invoice/InvoiceOneFeePerStudent.php b/app/Services/Invoice/InvoiceOneFeePerStudent.php
index c5090ac..69b5fe5 100644
--- a/app/Services/Invoice/InvoiceOneFeePerStudent.php
+++ b/app/Services/Invoice/InvoiceOneFeePerStudent.php
@@ -41,7 +41,8 @@ class InvoiceOneFeePerStudent implements InvoiceDataService
foreach ($entries[$student->id] ?? [] as $entry) {
if ($firstEntryForStudent) {
$entryFee = $entry->audition->entry_fee / 100;
- $lateFee = $this->entryService->entryIsLate($entry) ? auditionSetting('late_fee') / 100 : 0;
+ $lateFee = ($this->entryService->isEntryLate($entry) && ! $entry->hasFlag('late_fee_waived'))
+ ? auditionSetting('late_fee') / 100 : 0;
} else {
$entryFee = 0;
$lateFee = 0;
diff --git a/resources/views/admin/entries/edit.blade.php b/resources/views/admin/entries/edit.blade.php
index f34193a..8c96f7e 100644
--- a/resources/views/admin/entries/edit.blade.php
+++ b/resources/views/admin/entries/edit.blade.php
@@ -35,7 +35,8 @@
Audition
@foreach ($auditions as $audition)
@continue($entry->student->grade < $audition->minimum_grade || $entry->student->grade > $audition->maximum_grade)
-
@endforeach
@@ -58,6 +59,12 @@
@else
@endif
+
+
+
+
+
Edit Entry
@@ -70,7 +77,8 @@
Scores
- Edit Scores
+ Edit Scores
+
@@ -96,7 +104,8 @@
@endforeach
- {{ auditionSetting('auditionAbbreviation') }} Total
+ {{ auditionSetting('auditionAbbreviation') }} Total
{{ $score->totalScore('seating')[0] }}
diff --git a/tests/Feature/Pages/Admin/EntriesEditTest.php b/tests/Feature/Pages/Admin/EntriesEditTest.php
index 121d0c2..63ebfe2 100644
--- a/tests/Feature/Pages/Admin/EntriesEditTest.php
+++ b/tests/Feature/Pages/Admin/EntriesEditTest.php
@@ -236,7 +236,7 @@ it('has a link to delete scores', function () {
// Act & Assert
$scoreSheet = ScoreSheet::where('entry_id', $entry->id)->first();
actAsAdmin();
- $response = get(route('admin.entries.edit', $entry))
+ get(route('admin.entries.edit', $entry))
->assertSee(route('scores.destroy', ['score' => $scoreSheet]));
});
@@ -286,3 +286,20 @@ it('does not allow an admin to delete an entry if that entries advancement is pu
->assertRedirect(route('admin.entries.index'));
expect(Entry::find($this->entry->id))->not->toBeNull();
});
+it('allows an admin to waive a late fee on an entry', function () {
+ // Arrange
+ $newAudition = Audition::factory()->create(['minimum_grade' => 1, 'maximum_grade' => 20]);
+ actAsAdmin();
+ // Act & Assert
+ /** @noinspection PhpUnhandledExceptionInspection */
+ patch(route('admin.entries.update', $this->entry), ['audition_id' => $newAudition->id, 'late_fee_waived' => 1])
+ ->assertSessionHasNoErrors()
+ ->assertSessionMissing('error')
+ ->assertSessionHas('success', 'Entry updated successfully')
+ ->assertRedirect(route('admin.entries.index'));
+ $this->entry->refresh();
+ expect($this->entry->audition_id)->toBe($newAudition->id)
+ ->and($this->entry->for_seating)->toBe(0)
+ ->and($this->entry->for_advancement)->toBe(0);
+ $this->assertDatabaseHas('entry_flags', ['entry_id' => $this->entry->id, 'flag_name' => 'late_fee_waived']);
+});