180 lines
7.0 KiB
PHP
180 lines
7.0 KiB
PHP
<?php
|
|
|
|
namespace App\Actions\Entries;
|
|
|
|
use App\Exceptions\AuditionAdminException;
|
|
use App\Exceptions\ManageEntryException;
|
|
use App\Models\Audition;
|
|
use App\Models\AuditLogEntry;
|
|
use App\Models\Entry;
|
|
|
|
use function array_key_exists;
|
|
use function auditionSetting;
|
|
use function auth;
|
|
use function request;
|
|
|
|
class UpdateEntry
|
|
{
|
|
protected Entry $entry;
|
|
|
|
protected string $log_message = '';
|
|
|
|
protected array $log_affected = [];
|
|
|
|
public function __construct()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @throws ManageEntryException
|
|
*/
|
|
public function __invoke(Entry|int $entry, array $updateData): void
|
|
{
|
|
$this->updateEntry($entry, $updateData);
|
|
}
|
|
|
|
/**
|
|
* @throws ManageEntryException
|
|
*/
|
|
public function updateEntry(Entry|int $entry, array $updateData): void
|
|
{
|
|
if (is_int($entry)) {
|
|
$entry = Entry::find($entry);
|
|
}
|
|
if (! $entry || ! $entry->exists) {
|
|
throw new AuditionAdminException('Invalid entry provided');
|
|
}
|
|
$this->entry = $entry;
|
|
if (array_key_exists('for_seating', $updateData)) {
|
|
$this->updateForSeating($updateData['for_seating']);
|
|
}
|
|
if (array_key_exists('for_advancement', $updateData)) {
|
|
$this->updateForAdvancement($updateData['for_advancement']);
|
|
}
|
|
if (array_key_exists('audition_id', $updateData)) {
|
|
$this->updateAudition($updateData['audition_id']);
|
|
}
|
|
if (array_key_exists('audition', $updateData)) {
|
|
$this->updateAudition($updateData['audition']);
|
|
}
|
|
$this->entry->save();
|
|
if (auth()->user()) {
|
|
$this->log_affected['auditions'][] = $this->entry->audition_id;
|
|
$this->log_affected['entries'][] = $this->entry->id;
|
|
$this->log_affected['students'][] = $this->entry->student_id;
|
|
$this->log_affected['schools'][] = $this->entry->student->school_id;
|
|
AuditLogEntry::create([
|
|
'user' => auth()->user()->email,
|
|
'ip_address' => request()->ip(),
|
|
'message' => $this->log_message,
|
|
'affected' => $this->log_affected,
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @throws ManageEntryException
|
|
*/
|
|
private function updateAudition(Audition|int $audition): void
|
|
{
|
|
|
|
if (is_int($audition)) {
|
|
$audition = Audition::find($audition);
|
|
}
|
|
if (! $audition || ! $audition->exists) {
|
|
throw new AuditionAdminException('Invalid audition provided');
|
|
}
|
|
|
|
if ($this->entry->audition->hasFlag('seats_published')) {
|
|
throw new AuditionAdminException('Cannot change the audition for an entry where seating for that entry\'s current audition is published');
|
|
}
|
|
if ($this->entry->audition->hasFlag('advancement_published')) {
|
|
throw new AuditionAdminException('Cannot change the audition for an entry where advancement for that entry\'s current audition is published');
|
|
}
|
|
if ($audition->hasFlag('seats_published')) {
|
|
throw new AuditionAdminException('Cannot change the entry to an audition with published seating');
|
|
}
|
|
if ($audition->hasFlag('advancement_published')) {
|
|
throw new AuditionAdminException('Cannot change the entry to an audition with published advancement');
|
|
}
|
|
if ($this->entry->student->grade > $audition->maximum_grade) {
|
|
throw new AuditionAdminException('The student is too old to enter that audition');
|
|
}
|
|
if ($this->entry->student->grade < $audition->minimum_grade) {
|
|
throw new AuditionAdminException('The student is too young to enter that audition');
|
|
}
|
|
if ($this->entry->scoreSheets()->count() > 0) {
|
|
throw new AuditionAdminException('Cannot change the audition for an entry with scores');
|
|
}
|
|
if ($audition->id !== $this->entry->audition_id &&
|
|
Entry::where('student_id', $this->entry->student_id)
|
|
->where('audition_id', $audition->id)->exists()) {
|
|
throw new AuditionAdminException('That student is already entered in that audition');
|
|
}
|
|
// Escape if we're not actually making a change
|
|
if ($this->entry->audition_id == $audition->id) {
|
|
return;
|
|
}
|
|
// OK we're allowed to change the audition
|
|
$oldAudition = $this->entry->audition;
|
|
$this->entry->audition_id = $audition->id;
|
|
$this->log_message .= 'Changed entry '.$this->entry->id.' from '.$oldAudition->name.' to '.$audition->name.'<br>';
|
|
$this->log_affected['auditions'][] = $oldAudition->id;
|
|
// Deal with our draw number
|
|
if ($audition->hasFlag('drawn')) {
|
|
$draw_number = $audition->entries()->max('draw_number');
|
|
$this->entry->draw_number = $draw_number + 1;
|
|
$this->log_message .= 'Entry '.$this->entry->id.' draw number set to '.$this->entry->draw_number.'<br>';
|
|
} else {
|
|
$this->entry->draw_number = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @throws ManageEntryException
|
|
*/
|
|
private function updateForSeating($forSeating): void
|
|
{
|
|
if ($this->entry->for_seating == $forSeating) {
|
|
return;
|
|
}
|
|
if ($forSeating) {
|
|
if ($this->entry->audition->hasFlag('seats_published')) {
|
|
throw new AuditionAdminException('Cannot add seating to an entry in an audition where seats are published');
|
|
}
|
|
$this->entry->for_seating = 1;
|
|
$this->log_message .= 'Entry '.$this->entry->id.' is entered for seating '.'<br>';
|
|
} else {
|
|
if ($this->entry->audition->hasFlag('seats_published')) {
|
|
throw new AuditionAdminException('Cannot remove seating from an entry in an audition where seats are published');
|
|
}
|
|
$this->entry->for_seating = 0;
|
|
$this->log_message .= 'Entry '.$this->entry->id.' is NOT entered for seating '.'<br>';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @throws ManageEntryException
|
|
*/
|
|
private function updateForAdvancement($forAdvancement): void
|
|
{
|
|
if ($this->entry->for_advancement == $forAdvancement) {
|
|
return;
|
|
}
|
|
if ($forAdvancement) {
|
|
if ($this->entry->audition->hasFlag('advancement_published')) {
|
|
throw new AuditionAdminException('Cannot add advancement to an entry in an audition where advancement is published');
|
|
}
|
|
$this->entry->for_advancement = 1;
|
|
$this->log_message .= 'Entry '.$this->entry->id.' is entered for '.auditionSetting('advanceTo').'<br>';
|
|
} else {
|
|
if ($this->entry->audition->hasFlag('advancement_published')) {
|
|
throw new AuditionAdminException('Cannot remove advancement from an entry in an audition where advancement is published');
|
|
}
|
|
$this->entry->for_advancement = 0;
|
|
$this->log_message .= 'Entry '.$this->entry->id.' is NOT entered for '.auditionSetting('advanceTo').'<br>';
|
|
}
|
|
|
|
}
|
|
}
|