From 51436bda404551b49e27c1785cd515efb63e5023 Mon Sep 17 00:00:00 2001
From: Matt Young
Date: Wed, 17 Jul 2024 18:38:03 -0500
Subject: [PATCH 1/2] Admin can forgive late fee on entry creation #38 Add
ability for admin to forgive late fee on an entry
---
app/Actions/Entries/CreateEntry.php | 4 +--
app/Enums/EntryFlags.php | 2 +-
.../Controllers/Admin/EntryController.php | 6 +++-
app/Models/Entry.php | 1 +
.../views/admin/entries/create.blade.php | 12 ++++++--
.../Feature/Pages/Admin/EntiesCreateTest.php | 29 +++++++++++++++++++
6 files changed, 47 insertions(+), 7 deletions(-)
diff --git a/app/Actions/Entries/CreateEntry.php b/app/Actions/Entries/CreateEntry.php
index daa6825..abc95c0 100644
--- a/app/Actions/Entries/CreateEntry.php
+++ b/app/Actions/Entries/CreateEntry.php
@@ -16,9 +16,9 @@ class CreateEntry
/**
* @throws ManageEntryException
*/
- public function __invoke(Student|int $student, Audition|int $audition, string|array|null $entry_for = null): void
+ public function __invoke(Student|int $student, Audition|int $audition, string|array|null $entry_for = null)
{
- $this->createEntry($student, $audition, $entry_for);
+ return $this->createEntry($student, $audition, $entry_for);
}
/**
diff --git a/app/Enums/EntryFlags.php b/app/Enums/EntryFlags.php
index 7cb14d4..bb87b0d 100644
--- a/app/Enums/EntryFlags.php
+++ b/app/Enums/EntryFlags.php
@@ -8,5 +8,5 @@ enum EntryFlags: string
case DECLINED = 'declined';
case NO_SHOW = 'no_show';
case FAILED_PRELIM = 'failed_prelim';
+ case LATE_FEE_WAIVED = 'late_fee_waived';
}
-
diff --git a/app/Http/Controllers/Admin/EntryController.php b/app/Http/Controllers/Admin/EntryController.php
index 4132e73..d6025a9 100644
--- a/app/Http/Controllers/Admin/EntryController.php
+++ b/app/Http/Controllers/Admin/EntryController.php
@@ -102,6 +102,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;
$enter_for = [];
if ($validData['for_seating']) {
$enter_for[] = 'seating';
@@ -111,10 +112,13 @@ class EntryController extends Controller
}
try {
- $creator($validData['student_id'], $validData['audition_id'], $enter_for);
+ $entry = $creator($validData['student_id'], $validData['audition_id'], $enter_for);
} catch (ManageEntryException $ex) {
return redirect()->route('admin.entries.index')->with('error', $ex->getMessage());
}
+ if ($validData['late_fee_waived']) {
+ $entry->addFlag('late_fee_waived');
+ }
return redirect(route('admin.entries.index'))->with('success', 'The entry has been added.');
}
diff --git a/app/Models/Entry.php b/app/Models/Entry.php
index 1b6eaee..1670c02 100644
--- a/app/Models/Entry.php
+++ b/app/Models/Entry.php
@@ -91,6 +91,7 @@ class Entry extends Model
'declined' => EntryFlags::DECLINED,
'no_show' => EntryFlags::NO_SHOW,
'failed_prelim' => EntryFlags::FAILED_PRELIM,
+ 'late_fee_waived' => EntryFlags::LATE_FEE_WAIVED,
};
$this->flags()->create(['flag_name' => $enum]);
$this->load('flags');
diff --git a/resources/views/admin/entries/create.blade.php b/resources/views/admin/entries/create.blade.php
index d1c4376..1614157 100644
--- a/resources/views/admin/entries/create.blade.php
+++ b/resources/views/admin/entries/create.blade.php
@@ -1,3 +1,4 @@
+
Create Entry
@@ -8,7 +9,8 @@
Student
-
+
@@ -24,16 +26,20 @@
+ checked/>
+ checked/>
@else
@endif
+
+
+
Create Entry
diff --git a/tests/Feature/Pages/Admin/EntiesCreateTest.php b/tests/Feature/Pages/Admin/EntiesCreateTest.php
index 3142c0f..5e038d8 100644
--- a/tests/Feature/Pages/Admin/EntiesCreateTest.php
+++ b/tests/Feature/Pages/Admin/EntiesCreateTest.php
@@ -1,6 +1,7 @@
0,
]);
});
+it('can mark a late fee waived for an entry', function () {
+ $audition = Audition::factory()->closed()->create(['maximum_grade' => 12, 'minimum_grade' => 7]);
+ $student = Student::factory()->create(['grade' => 9]);
+ actAsAdmin();
+ $response = $this->post(route('admin.entries.store'), [
+ 'student_id' => $student->id,
+ 'audition_id' => $audition->id,
+ 'for_seating' => 'on',
+ 'late_fee_waived' => 'on',
+ ]);
+ $response->assertRedirect(route('admin.entries.index'))
+ ->assertSessionDoesntHaveErrors()
+ ->assertSessionMissing('error')
+ ->assertSessionHas('success', 'The entry has been added.');
+ assertDatabaseHas('entries', [
+ 'student_id' => $student->id,
+ 'audition_id' => $audition->id,
+ 'for_seating' => 1,
+ 'for_advancement' => 0,
+ ]);
+ $entry = Entry::where('student_id', $student->id)->where('audition_id', $audition->id)->first();
+
+ assertDatabaseHas('entry_flags', [
+ 'entry_id' => 1,
+ 'flag_name' => 'late_fee_waived',
+ ]);
+
+});
--
2.39.5
From d522148cb9933e38a5bdef653f4cfea6cdedd6b5 Mon Sep 17 00:00:00 2001
From: Matt Young
Date: Wed, 17 Jul 2024 19:31:02 -0500
Subject: [PATCH 2/2] 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']);
+});
--
2.39.5