From b4b57d7efdd36a5cc484b23182352015acca22ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Tue, 26 Sep 2023 19:04:19 +0200 Subject: [PATCH 01/20] Added querying of education instructors --- .../presenters/ParticipantPresenter.php | 35 +++++ .../templates/Participant/default.latte | 6 + .../Repositories/IInstructorRepository.php | 14 ++ app/model/DTO/Instructor/Instructor.php | 125 ++++++++++++++++++ .../DTO/Instructor/InstructorFactory.php | 32 +++++ .../Instructor/Factory/InstructorFactory.php | 35 +++++ app/model/Instructor/Instructor.php | 91 +++++++++++++ .../Queries/EducationInstructorListQuery.php | 24 ++++ .../EducationInstructorListQueryHandler.php | 22 +++ app/model/Skautis/InstructorRepository.php | 76 +++++++++++ 10 files changed, 460 insertions(+) create mode 100644 app/model/Common/Repositories/IInstructorRepository.php create mode 100644 app/model/DTO/Instructor/Instructor.php create mode 100644 app/model/DTO/Instructor/InstructorFactory.php create mode 100644 app/model/Instructor/Factory/InstructorFactory.php create mode 100644 app/model/Instructor/Instructor.php create mode 100644 app/model/Instructor/ReadModel/Queries/EducationInstructorListQuery.php create mode 100644 app/model/Instructor/ReadModel/QueryHandlers/EducationInstructorListQueryHandler.php create mode 100644 app/model/Skautis/InstructorRepository.php diff --git a/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php b/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php index 5a153806d..fb6aa4523 100644 --- a/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php +++ b/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php @@ -8,7 +8,9 @@ use App\AccountancyModule\ExcelResponse; use App\AccountancyModule\Factories\Participants\IParticipantListFactory; use Model\Auth\Resources\Education; +use Model\Cashbook\ReadModel\Queries\EducationInstructorListQuery; use Model\Cashbook\ReadModel\Queries\EducationParticipantListQuery; +use Model\DTO\Instructor\Instructor; use Model\DTO\Participant\Participant; use Model\DTO\Participant\UpdateParticipant; use Model\ExcelService; @@ -94,6 +96,33 @@ public function actionExportExcel(int $aid): void } } + protected function createComponentInstructorList(): ParticipantList + { + $control = $this->participantListFactory->create( + $this->aid, + $this->eventInstructors(), + true, + true, + true, + false, + false, + ); + + $control->onUpdate[] = function (array $updates): void { + foreach ($updates as $u) { + assert($u instanceof UpdateParticipant); + if (! in_array($u->getField(), UpdateParticipant::getEducationFields())) { + $this->flashMessage(sprintf('Nelze upravit pole: %s', $u->getField()), 'warning'); + $this->redirect('this'); + } + + $this->participants->update(EventType::EDUCATION(), $u); + } + }; + + return $control; + } + protected function createComponentParticipantList(): ParticipantList { $control = $this->participantListFactory->create( @@ -135,6 +164,12 @@ public function actionExport(int $aid): void $this->terminate(); } + /** @return Instructor[] */ + private function eventInstructors(): array + { + return $this->queryBus->handle(new EducationInstructorListQuery($this->event->getId())); + } + /** @return Participant[] */ private function eventParticipants(): array { diff --git a/app/AccountancyModule/EducationModule/templates/Participant/default.latte b/app/AccountancyModule/EducationModule/templates/Participant/default.latte index ef374bf37..fd5a046ca 100644 --- a/app/AccountancyModule/EducationModule/templates/Participant/default.latte +++ b/app/AccountancyModule/EducationModule/templates/Participant/default.latte @@ -3,6 +3,12 @@ {block #content} {include ../header.latte} +
+
+ {control instructorList} +
+
+
{control participantList} diff --git a/app/model/Common/Repositories/IInstructorRepository.php b/app/model/Common/Repositories/IInstructorRepository.php new file mode 100644 index 000000000..24a8016b5 --- /dev/null +++ b/app/model/Common/Repositories/IInstructorRepository.php @@ -0,0 +1,14 @@ +paymentObj = $payment; + } + + public function getId(): int + { + return $this->id; + } + + public function getPersonId(): int + { + return $this->personId; + } + + public function getFirstName(): string + { + return $this->firstName; + } + + public function getLastName(): string + { + return $this->lastName; + } + + public function getNickname(): string|null + { + return $this->nickname; + } + + public function getEducationId(): int + { + return $this->educationId; + } + + public function getEducationName(): string + { + return $this->educationName; + } + + public function getInstructorType(): string + { + return $this->instructorType; + } + + public function getScoutExperience(): string + { + return $this->scoutExperience; + } + + public function getProfessionalExperience(): string + { + return $this->professionalExperience; + } + + public function getEventFocus(): string + { + return $this->eventFocus; + } + + public function getDisplayName(): string + { + return $this->lastName . ' ' . $this->firstName . ($this->nickname !== null ? '(' . $this->nickname . ')' : ''); + } + + public function getPayment(): float + { + return MoneyFactory::toFloat($this->paymentObj->getPayment()); + } + + public function getRepayment(): float + { + return MoneyFactory::toFloat($this->paymentObj->getRepayment()); + } + + public function getOnAccount(): string + { + return $this->paymentObj->getAccount(); + } +} diff --git a/app/model/DTO/Instructor/InstructorFactory.php b/app/model/DTO/Instructor/InstructorFactory.php new file mode 100644 index 000000000..53bd462b4 --- /dev/null +++ b/app/model/DTO/Instructor/InstructorFactory.php @@ -0,0 +1,32 @@ +getId(), + $participant->getPersonId(), + $participant->getFirstName(), + $participant->getLastName(), + $participant->getNickName(), + $participant->getEducationId(), + $participant->getEducationName(), + $participant->getInstructorType(), + $participant->getScoutExperience(), + $participant->getProfessionalExperience(), + $participant->getEventFocus(), + $participant->getPayment(), + ); + } +} diff --git a/app/model/Instructor/Factory/InstructorFactory.php b/app/model/Instructor/Factory/InstructorFactory.php new file mode 100644 index 000000000..a17fa5730 --- /dev/null +++ b/app/model/Instructor/Factory/InstructorFactory.php @@ -0,0 +1,35 @@ +\S+)\s+(?P[^(]+)(\((?P.*)\))?.*/', $skautisInstructor->Person, $matches); + + return new Instructor( + $skautisInstructor->ID, + $skautisInstructor->ID_Person, + $matches['first'], + $matches['last'], + $matches['nick'] ?? null, + $skautisInstructor->ID_EventEducation, + $skautisInstructor->Event, + $skautisInstructor->InstructorType, + $skautisInstructor->ScoutExperience, + $skautisInstructor->ProfessionalExperience, + $skautisInstructor->EventFocus, + $payment, + ); + } +} diff --git a/app/model/Instructor/Instructor.php b/app/model/Instructor/Instructor.php new file mode 100644 index 000000000..3d68e1028 --- /dev/null +++ b/app/model/Instructor/Instructor.php @@ -0,0 +1,91 @@ +id; + } + + public function getPersonId(): int + { + return $this->personId; + } + + public function getfirstName(): string + { + return $this->firstName; + } + + public function getLastName(): string + { + return $this->lastName; + } + + public function getNickname(): string + { + return $this->nickname; + } + + public function getEducationId(): int + { + return $this->educationId; + } + + public function getEducationName(): string + { + return $this->educationName; + } + + public function getInstructorType(): string + { + return $this->instructorType; + } + + public function getScoutExperience(): string + { + return $this->scoutExperience; + } + + public function getProfessionalExperience(): string + { + return $this->professionalExperience; + } + + public function getEventFocus(): string + { + return $this->eventFocus; + } + + public function getPayment(): Payment + { + return $this->payment; + } + + public function getDisplayName(): string + { + return $this->lastName . ' ' . $this->firstName . ($this->nickname !== null ? '(' . $this->nickname . ')' : ''); + } +} diff --git a/app/model/Instructor/ReadModel/Queries/EducationInstructorListQuery.php b/app/model/Instructor/ReadModel/Queries/EducationInstructorListQuery.php new file mode 100644 index 000000000..25505a1c5 --- /dev/null +++ b/app/model/Instructor/ReadModel/Queries/EducationInstructorListQuery.php @@ -0,0 +1,24 @@ +educationId = $id; + } + + public function getEducationId(): SkautisEducationId + { + return $this->educationId; + } +} diff --git a/app/model/Instructor/ReadModel/QueryHandlers/EducationInstructorListQueryHandler.php b/app/model/Instructor/ReadModel/QueryHandlers/EducationInstructorListQueryHandler.php new file mode 100644 index 000000000..552d7bd71 --- /dev/null +++ b/app/model/Instructor/ReadModel/QueryHandlers/EducationInstructorListQueryHandler.php @@ -0,0 +1,22 @@ +instructors->findByEducation($query->getEducationId()); + } +} diff --git a/app/model/Skautis/InstructorRepository.php b/app/model/Skautis/InstructorRepository.php new file mode 100644 index 000000000..6462df0a0 --- /dev/null +++ b/app/model/Skautis/InstructorRepository.php @@ -0,0 +1,76 @@ +skautis->event->InstructorAll(['ID_EventEducation' => $id->toInt()]); + if (! is_array($instructors)) { + return []; // API returns empty object when there are no results + } + + $event = new Event($id->toInt(), EventType::EDUCATION()); + + return $this->processInstructors($instructors, $event); + } + + /** + * @param stdClass[] $instructorsSis + * + * @return InstructorDTO[] + */ + private function processInstructors(array $instructorsSis, Event $event): array + { + $eventPayments = $this->payments->findByEvent($event); + $instructors = []; + foreach ($instructorsSis as $p) { + if (array_key_exists($p->ID, $eventPayments)) { + $payment = $eventPayments[$p->ID]; + } else { + $payment = PaymentFactory::createDefault($p->ID, $event); + } + + $instructors[$p->ID] = InstructorFactory::create($p, $payment); // TODO + } + + foreach (array_diff_key($eventPayments, $instructors) as $paymentToRemove) { + $this->payments->remove($paymentToRemove); //delete zaznam, protoze neexistuje k nemu ucastnik + } + + usort( + $instructors, + fn (Instructor $one, Instructor $two) => strcoll($one->getDisplayName(), $two->getDisplayName()) + ); + + return array_map([InstructorDTOFactory::class, 'create'], $instructors); + } +} From 6829252c9ed479230ff7e33577174a03dbf37e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Tue, 26 Sep 2023 19:37:30 +0200 Subject: [PATCH 02/20] Created a superclass for participants and instructors --- .../Participants/ParticipantList.php | 14 ++--- .../presenters/ParticipantPresenter.php | 2 +- .../Participants/IParticipantListFactory.php | 4 +- app/model/DTO/Instructor/Instructor.php | 45 +++------------ app/model/DTO/Participant/Participant.php | 57 +++++++------------ .../DTO/Participant/ParticipatingPerson.php | 52 +++++++++++++++++ 6 files changed, 90 insertions(+), 84 deletions(-) create mode 100644 app/model/DTO/Participant/ParticipatingPerson.php diff --git a/app/AccountancyModule/Components/Participants/ParticipantList.php b/app/AccountancyModule/Components/Participants/ParticipantList.php index a893fd9e6..d51057e88 100644 --- a/app/AccountancyModule/Components/Participants/ParticipantList.php +++ b/app/AccountancyModule/Components/Participants/ParticipantList.php @@ -6,7 +6,7 @@ use App\AccountancyModule\Components\BaseControl; use App\Forms\BaseForm; -use Model\DTO\Participant\Participant; +use Model\DTO\Participant\ParticipatingPerson; use Model\DTO\Participant\UpdateParticipant; use Model\Participant\ParticipantNotFound; use Nette\Application\BadRequestException; @@ -53,7 +53,7 @@ final class ParticipantList extends BaseControl /** @persistent */ public string|null $sort = 'displayName'; - /** @param Participant[] $currentParticipants */ + /** @param ParticipatingPerson[] $currentParticipants */ public function __construct( public int $aid, private array $currentParticipants, @@ -99,7 +99,7 @@ public function render(): void $this->template->render(); } - /** @param Participant[] $participants */ + /** @param ParticipatingPerson[] $participants */ protected function sortParticipants(array &$participants, string $sort): void { if (! isset(self::SORT_OPTIONS[$sort])) { @@ -107,9 +107,9 @@ protected function sortParticipants(array &$participants, string $sort): void } if ($sort === 'displayName') { - $sortFunction = fn (Participant $a, Participant $b) => strcoll($a->{$sort}, $b->{$sort}); + $sortFunction = fn (ParticipatingPerson $a, ParticipatingPerson $b) => strcoll($a->{$sort}, $b->{$sort}); } else { - $sortFunction = fn (Participant $a, Participant $b) => $a->{$sort} <=> $b->{$sort}; + $sortFunction = fn (ParticipatingPerson $a, ParticipatingPerson $b) => $a->{$sort} <=> $b->{$sort}; } usort($participants, $sortFunction); @@ -144,7 +144,7 @@ public function handleRemove(int $participantId): void $this->onRemove([$participantId]); $this->currentParticipants = array_filter( $this->currentParticipants, - function (Participant $p) use ($participantId) { + function (ParticipatingPerson $p) use ($participantId) { return $p->getId() !== $participantId; }, ); @@ -287,7 +287,7 @@ private function massRemoveSubmitted(SubmitButton $button): void $this->reload('Účastníci byli odebráni'); } - /** @return array Participant's indexed by their ID */ + /** @return array Participant's indexed by their ID */ private function participantsById(): array { $participants = []; diff --git a/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php b/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php index fb6aa4523..d579aac42 100644 --- a/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php +++ b/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php @@ -101,7 +101,7 @@ protected function createComponentInstructorList(): ParticipantList $control = $this->participantListFactory->create( $this->aid, $this->eventInstructors(), - true, + false, true, true, false, diff --git a/app/AccountancyModule/Factories/Participants/IParticipantListFactory.php b/app/AccountancyModule/Factories/Participants/IParticipantListFactory.php index 96ad3665f..637e13533 100644 --- a/app/AccountancyModule/Factories/Participants/IParticipantListFactory.php +++ b/app/AccountancyModule/Factories/Participants/IParticipantListFactory.php @@ -5,11 +5,11 @@ namespace App\AccountancyModule\Factories\Participants; use App\AccountancyModule\Components\Participants\ParticipantList; -use Model\DTO\Participant\Participant; +use Model\DTO\Participant\ParticipatingPerson; interface IParticipantListFactory { - /** @param Participant[] $currentParticipants */ + /** @param ParticipatingPerson[] $currentParticipants */ public function create( int $aid, array $currentParticipants, diff --git a/app/model/DTO/Instructor/Instructor.php b/app/model/DTO/Instructor/Instructor.php index 45cbfbe23..f8c7b5848 100644 --- a/app/model/DTO/Instructor/Instructor.php +++ b/app/model/DTO/Instructor/Instructor.php @@ -4,17 +4,12 @@ namespace Model\DTO\Instructor; +use Model\DTO\Participant\ParticipatingPerson; use Model\Participant\Payment; use Model\Utils\MoneyFactory; -use Nette\SmartObject; /** - * @property-read int $id * @property-read int $personId - * @property-read string $firstName - * @property-read string $lastName - * @property-read string $nickname - * @property-read string $displayName * @property-read int $educationId * @property-read string $educationName * @property-read string $instructorType @@ -25,18 +20,16 @@ * @property-read float $repayment * @property-read string $onAccount */ -class Instructor +class Instructor extends ParticipatingPerson { - use SmartObject; - private Payment $paymentObj; public function __construct( - private int $id, + int $id, private int $personId, - private string $firstName, - private string $lastName, - private string|null $nickname = null, + string $firstName, + string $lastName, + string|null $nickname = null, private int $educationId, private string $educationName, private string $instructorType, @@ -45,34 +38,15 @@ public function __construct( private string $eventFocus, Payment $payment, ) { + parent::__construct($id, $firstName, $lastName, $nickname); $this->paymentObj = $payment; } - public function getId(): int - { - return $this->id; - } - public function getPersonId(): int { return $this->personId; } - public function getFirstName(): string - { - return $this->firstName; - } - - public function getLastName(): string - { - return $this->lastName; - } - - public function getNickname(): string|null - { - return $this->nickname; - } - public function getEducationId(): int { return $this->educationId; @@ -103,11 +77,6 @@ public function getEventFocus(): string return $this->eventFocus; } - public function getDisplayName(): string - { - return $this->lastName . ' ' . $this->firstName . ($this->nickname !== null ? '(' . $this->nickname . ')' : ''); - } - public function getPayment(): float { return MoneyFactory::toFloat($this->paymentObj->getPayment()); diff --git a/app/model/DTO/Participant/Participant.php b/app/model/DTO/Participant/Participant.php index d4193771b..395cac1ab 100644 --- a/app/model/DTO/Participant/Participant.php +++ b/app/model/DTO/Participant/Participant.php @@ -7,16 +7,10 @@ use Cake\Chronos\Date; use Model\Participant\Payment; use Model\Utils\MoneyFactory; -use Nette\SmartObject; /** - * @property-read int $id * @property-read int $personId - * @property-read string $firstName - * @property-read string $lastName - * @property-read string $nickName * @property-read int|null $age - * @property-read string $displayName * @property-read string $street * @property-read string $city * @property-read int $postcode @@ -28,42 +22,38 @@ * @property-read int $days * @property-read bool $isAccepted */ -class Participant +class Participant extends ParticipatingPerson { - use SmartObject; - private Payment $paymentObj; - public function __construct(private int $id, private int $personId, private string $firstName, private string $lastName, private string|null $nickName = null, private int|null $age = null, private Date|null $birthday = null, private string $street, private string $city, private int $postcode, private string $state, private string $unit, private string $unitRegistrationNumber, private int $days, private bool $isAccepted, Payment $payment, private string|null $category = null) - { + public function __construct( + int $id, + private int $personId, + string $firstName, + string $lastName, + string|null $nickName = null, + private int|null $age = null, + private Date|null $birthday = null, + private string $street, + private string $city, + private int $postcode, + private string $state, + private string $unit, + private string $unitRegistrationNumber, + private int $days, + private bool $isAccepted, + Payment $payment, + private string|null $category = null, + ) { + parent::__construct($id, $firstName, $lastName, $nickName); $this->paymentObj = $payment; } - public function getId(): int - { - return $this->id; - } - public function getPersonId(): int { return $this->personId; } - public function getFirstName(): string - { - return $this->firstName; - } - - public function getLastName(): string - { - return $this->lastName; - } - - public function getNickName(): string|null - { - return $this->nickName; - } - public function getAge(): int|null { return $this->age; @@ -104,11 +94,6 @@ public function getUnit(): string return $this->unit; } - public function getDisplayName(): string - { - return $this->lastName . ' ' . $this->firstName . ($this->nickName !== null ? '(' . $this->nickName . ')' : ''); - } - public function getDays(): int { return $this->days; diff --git a/app/model/DTO/Participant/ParticipatingPerson.php b/app/model/DTO/Participant/ParticipatingPerson.php new file mode 100644 index 000000000..89a689a40 --- /dev/null +++ b/app/model/DTO/Participant/ParticipatingPerson.php @@ -0,0 +1,52 @@ +id; + } + + public function getFirstName(): string + { + return $this->firstName; + } + + public function getLastName(): string + { + return $this->lastName; + } + + public function getNickName(): string|null + { + return $this->nickName; + } + + public function getDisplayName(): string + { + return $this->lastName . ' ' . $this->firstName . ($this->nickName !== null ? '(' . $this->nickName . ')' : ''); + } +} From 9452eead6ef751925242d8d129ef17908e02dc87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Tue, 26 Sep 2023 19:39:34 +0200 Subject: [PATCH 03/20] Using ParticipatingPerson in EditParticipantDialog --- .../Components/Participants/EditParticipantDialog.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/AccountancyModule/Components/Participants/EditParticipantDialog.php b/app/AccountancyModule/Components/Participants/EditParticipantDialog.php index 127e62217..8c5ca7d85 100644 --- a/app/AccountancyModule/Components/Participants/EditParticipantDialog.php +++ b/app/AccountancyModule/Components/Participants/EditParticipantDialog.php @@ -8,7 +8,7 @@ use App\Forms\BaseForm; use Assert\Assertion; use Closure; -use Model\DTO\Participant\Participant; +use Model\DTO\Participant\ParticipatingPerson; use Model\DTO\Participant\UpdateParticipant; use function assert; @@ -21,7 +21,7 @@ final class EditParticipantDialog extends Dialog /** @var Closure[] */ public array $onUpdate = []; - /** @param array $participants */ + /** @param array $participants */ public function __construct(private array $participants, private bool $isAllowedDaysUpdate, private bool $isAccountAllowed, private bool $isRepaymentAllowed, private bool $isOnlineLogin) { } @@ -43,7 +43,7 @@ protected function createComponentForm(): BaseForm Assertion::keyExists($this->participants, $this->participantId); $participant = $this->participants[$this->participantId]; - assert($participant instanceof Participant); + assert($participant instanceof ParticipatingPerson); $form = new BaseForm(); From f514a576d93264ce600430ea917818a1e29b91ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Tue, 26 Sep 2023 23:57:06 +0200 Subject: [PATCH 04/20] Editable participant list title --- .../Components/Participants/ParticipantList.php | 2 ++ .../Components/Participants/templates/ParticipantList.latte | 2 +- .../EducationModule/presenters/ParticipantPresenter.php | 1 + .../Factories/Participants/IParticipantListFactory.php | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/AccountancyModule/Components/Participants/ParticipantList.php b/app/AccountancyModule/Components/Participants/ParticipantList.php index d51057e88..82e42f88a 100644 --- a/app/AccountancyModule/Components/Participants/ParticipantList.php +++ b/app/AccountancyModule/Components/Participants/ParticipantList.php @@ -63,6 +63,7 @@ public function __construct( protected bool $isAllowParticipantUpdate, protected bool $isAllowParticipantDelete, protected bool $isOnlineLogin, + protected string $title, ) { } @@ -84,6 +85,7 @@ public function render(): void $this->template->setFile(__DIR__ . '/templates/ParticipantList.latte'); $this->template->setParameters([ 'aid' => $this->aid, + 'title' => $this->title, 'participants' => $this->currentParticipants, 'sort' => $this->sort, 'sortOptions' => $sortOptions, diff --git a/app/AccountancyModule/Components/Participants/templates/ParticipantList.latte b/app/AccountancyModule/Components/Participants/templates/ParticipantList.latte index d70410699..a1e96f296 100644 --- a/app/AccountancyModule/Components/Participants/templates/ParticipantList.latte +++ b/app/AccountancyModule/Components/Participants/templates/ParticipantList.latte @@ -58,7 +58,7 @@ $showUnits bool - zobrazovat číslo jednotky {var $tabIndex = 1}
-

Seznam účastníků

+

{$title}

- + {$showUnits ? 'Skrýt' : 'Zobrazit'} jednotku diff --git a/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php b/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php index aa66835d0..1e1b56fd6 100644 --- a/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php +++ b/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php @@ -106,6 +106,7 @@ protected function createComponentInstructorList(): ParticipantList true, true, false, + false, 'Seznam instruktorů', ); diff --git a/app/AccountancyModule/Factories/Participants/IParticipantListFactory.php b/app/AccountancyModule/Factories/Participants/IParticipantListFactory.php index 2d8b8b0c8..f9fa3ddb4 100644 --- a/app/AccountancyModule/Factories/Participants/IParticipantListFactory.php +++ b/app/AccountancyModule/Factories/Participants/IParticipantListFactory.php @@ -19,6 +19,7 @@ public function create( bool $isAllowParticipantUpdate, bool $isAllowParticipantDelete, bool $isOnlineLogin, + bool $isAllowShowUnits = true, string $title = 'Seznam účastníků', ): ParticipantList; } From a05a9814502273c56f4fe24ac14370a1a3fc39c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Wed, 27 Sep 2023 00:05:08 +0200 Subject: [PATCH 07/20] Education participant tab rename --- app/AccountancyModule/EducationModule/templates/header.latte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/AccountancyModule/EducationModule/templates/header.latte b/app/AccountancyModule/EducationModule/templates/header.latte index 01dae47ed..f9b062305 100644 --- a/app/AccountancyModule/EducationModule/templates/header.latte +++ b/app/AccountancyModule/EducationModule/templates/header.latte @@ -10,7 +10,7 @@
  • - Seznam účastníků + Seznam lidí
  • Date: Thu, 28 Sep 2023 13:00:39 +0200 Subject: [PATCH 08/20] Fixed education payments being deleted --- app/model/Skautis/InstructorRepository.php | 2 ++ app/model/Skautis/ParticipantRepository.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/model/Skautis/InstructorRepository.php b/app/model/Skautis/InstructorRepository.php index 6462df0a0..52f9306c2 100644 --- a/app/model/Skautis/InstructorRepository.php +++ b/app/model/Skautis/InstructorRepository.php @@ -62,9 +62,11 @@ private function processInstructors(array $instructorsSis, Event $event): array $instructors[$p->ID] = InstructorFactory::create($p, $payment); // TODO } + /* foreach (array_diff_key($eventPayments, $instructors) as $paymentToRemove) { $this->payments->remove($paymentToRemove); //delete zaznam, protoze neexistuje k nemu ucastnik } + */ usort( $instructors, diff --git a/app/model/Skautis/ParticipantRepository.php b/app/model/Skautis/ParticipantRepository.php index 209398400..6507e153f 100644 --- a/app/model/Skautis/ParticipantRepository.php +++ b/app/model/Skautis/ParticipantRepository.php @@ -220,9 +220,11 @@ private function processParticipants(array $participantsSis, Event $event): arra $participants[$p->ID] = ParticipantFactory::create($p, $payment); } + /* foreach (array_diff_key($participantPayments, $participants) as $paymentToRemove) { $this->payments->remove($paymentToRemove); //delete zaznam, protoze neexistuje k nemu ucastnik } + */ usort( $participants, From a0c8d92206dec3bb7f4a47b26f1296628ded6145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Thu, 28 Sep 2023 13:56:39 +0200 Subject: [PATCH 09/20] Added the ability to load HPD from instructors --- .../presenters/CashbookPresenter.php | 10 ++++-- .../EducationInstructorIncomeQuery.php | 24 ++++++++++++++ .../EducationInstructorIncomeQueryHandler.php | 32 +++++++++++++++++++ .../EducationParticipantIncomeQuery.php | 1 + 4 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 app/model/Instructor/ReadModel/Queries/EducationInstructorIncomeQuery.php create mode 100644 app/model/Instructor/ReadModel/QueryHandlers/EducationInstructorIncomeQueryHandler.php diff --git a/app/AccountancyModule/EducationModule/presenters/CashbookPresenter.php b/app/AccountancyModule/EducationModule/presenters/CashbookPresenter.php index 3797721c5..f4a64af0c 100644 --- a/app/AccountancyModule/EducationModule/presenters/CashbookPresenter.php +++ b/app/AccountancyModule/EducationModule/presenters/CashbookPresenter.php @@ -17,6 +17,7 @@ use Model\Cashbook\ReadModel\Queries\CategoryListQuery; use Model\Cashbook\ReadModel\Queries\ChitListQuery; use Model\Cashbook\ReadModel\Queries\EducationCashbookIdQuery; +use Model\Cashbook\ReadModel\Queries\EducationInstructorIncomeQuery; use Model\Cashbook\ReadModel\Queries\EducationParticipantCategoryIdQuery; use Model\Cashbook\ReadModel\Queries\EducationParticipantIncomeQuery; use Model\Cashbook\ReadModel\Queries\FinalCashBalanceQuery; @@ -81,6 +82,9 @@ protected function createComponentCashbook(): CashbookControl protected function createComponentFormImportHpd(): BaseForm { $form = new BaseForm(); + $form->addRadioList('from', 'Kategorie:', ['participant' => 'Od účastníků', 'instructor' => 'Od instruktorů']) + ->addRule($form::FILLED, 'Musíte vyplnit kategorii.') + ->setDefaultValue('participant'); $form->addRadioList('isAccount', 'Placeno:', ['N' => 'Hotově', 'Y' => 'Přes účet']) ->addRule($form::FILLED, 'Musíte vyplnit způsob platby.') ->setDefaultValue('N'); @@ -102,14 +106,16 @@ private function formImportHpdSubmitted(BaseForm $form): void $this->editableOnly(); $values = $form->getValues(); - $amount = $this->queryBus->handle(new EducationParticipantIncomeQuery(new SkautisEducationId($this->aid))); + $amount = $values->from === 'instructor' + ? $this->queryBus->handle(new EducationInstructorIncomeQuery(new SkautisEducationId($this->aid))) + : $this->queryBus->handle(new EducationParticipantIncomeQuery(new SkautisEducationId($this->aid))); if ($amount === 0.0) { $this->flashMessage('Nemáte žádné příjmy od účastníků, které by bylo možné importovat.', 'warning'); $this->redirect('default', ['aid' => $this->aid]); } - $purpose = 'úč. příspěvky ' . ($values->isAccount === 'Y' ? '- účet' : '- hotovost'); + $purpose = 'úč. příspěvky - ' . ($values->from === 'instructor' ? 'instruktoři' : 'účastníci') . ' - ' . ($values->isAccount === 'Y' ? 'účet' : 'hotovost'); $body = new ChitBody(null, $this->event->getStartDate(), null); $categoryId = $this->queryBus->handle( diff --git a/app/model/Instructor/ReadModel/Queries/EducationInstructorIncomeQuery.php b/app/model/Instructor/ReadModel/Queries/EducationInstructorIncomeQuery.php new file mode 100644 index 000000000..e70ead0db --- /dev/null +++ b/app/model/Instructor/ReadModel/Queries/EducationInstructorIncomeQuery.php @@ -0,0 +1,24 @@ +educationId = $eventId; + } + + public function getEducationId(): SkautisEducationId + { + return $this->educationId; + } +} diff --git a/app/model/Instructor/ReadModel/QueryHandlers/EducationInstructorIncomeQueryHandler.php b/app/model/Instructor/ReadModel/QueryHandlers/EducationInstructorIncomeQueryHandler.php new file mode 100644 index 000000000..69e1fa4d0 --- /dev/null +++ b/app/model/Instructor/ReadModel/QueryHandlers/EducationInstructorIncomeQueryHandler.php @@ -0,0 +1,32 @@ +queryBus->handle(new EducationInstructorListQuery($query->getEducationId())); + + $totalInstructorIncome = 0.0; + foreach ($instructor as $p) { + assert($p instanceof Instructor); + $totalInstructorIncome += $p->getPayment(); + } + + return $totalInstructorIncome; + } +} diff --git a/app/model/Participant/ReadModel/Queries/EducationParticipantIncomeQuery.php b/app/model/Participant/ReadModel/Queries/EducationParticipantIncomeQuery.php index 6e686b21e..f08cf272a 100644 --- a/app/model/Participant/ReadModel/Queries/EducationParticipantIncomeQuery.php +++ b/app/model/Participant/ReadModel/Queries/EducationParticipantIncomeQuery.php @@ -4,6 +4,7 @@ namespace Model\Cashbook\ReadModel\Queries; +use Model\Cashbook\ReadModel\QueryHandlers\EducationParticipantIncomeQueryHandler; use Model\Event\SkautisEducationId; /** @see EducationParticipantIncomeQueryHandler */ From 9c44da66f80b35a7e2226967c94d0ee1846a24b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Thu, 28 Sep 2023 14:02:26 +0200 Subject: [PATCH 10/20] Renamed buttons for HPD import for education events --- .../EducationModule/presenters/CashbookPresenter.php | 2 +- .../EducationModule/templates/Cashbook/default.latte | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/AccountancyModule/EducationModule/presenters/CashbookPresenter.php b/app/AccountancyModule/EducationModule/presenters/CashbookPresenter.php index f4a64af0c..799b6650f 100644 --- a/app/AccountancyModule/EducationModule/presenters/CashbookPresenter.php +++ b/app/AccountancyModule/EducationModule/presenters/CashbookPresenter.php @@ -82,7 +82,7 @@ protected function createComponentCashbook(): CashbookControl protected function createComponentFormImportHpd(): BaseForm { $form = new BaseForm(); - $form->addRadioList('from', 'Kategorie:', ['participant' => 'Od účastníků', 'instructor' => 'Od instruktorů']) + $form->addRadioList('from', 'Od:', ['participant' => 'Od účastníků', 'instructor' => 'Od instruktorů']) ->addRule($form::FILLED, 'Musíte vyplnit kategorii.') ->setDefaultValue('participant'); $form->addRadioList('isAccount', 'Placeno:', ['N' => 'Hotově', 'Y' => 'Přes účet']) diff --git a/app/AccountancyModule/EducationModule/templates/Cashbook/default.latte b/app/AccountancyModule/EducationModule/templates/Cashbook/default.latte index 534bfc20f..500d41019 100644 --- a/app/AccountancyModule/EducationModule/templates/Cashbook/default.latte +++ b/app/AccountancyModule/EducationModule/templates/Cashbook/default.latte @@ -6,7 +6,7 @@ @@ -27,7 +27,7 @@
  • - Seznam lidí + Seznam osob
  • Date: Sun, 15 Oct 2023 17:15:56 +0200 Subject: [PATCH 19/20] Added missing parameter to ParticipantList factory call --- .../EducationModule/presenters/ParticipantPresenter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php b/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php index c8ef601b0..b3ef41870 100644 --- a/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php +++ b/app/AccountancyModule/EducationModule/presenters/ParticipantPresenter.php @@ -108,6 +108,7 @@ protected function createComponentInstructorList(): ParticipantList true, false, false, + false, 'Seznam instruktorů', ParticipatingPerson::INSTRUCTOR, ); From 5b55574ca5b72fd42b90f88f642738b3d480b31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Sun, 15 Oct 2023 22:47:10 +0200 Subject: [PATCH 20/20] Fixed IsAccepted for instructors --- .../Participants/EditParticipantDialog.php | 2 +- .../Components/Participants/ParticipantList.php | 15 +++++++++------ app/model/DTO/Participant/UpdateParticipant.php | 4 ++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/AccountancyModule/Components/Participants/EditParticipantDialog.php b/app/AccountancyModule/Components/Participants/EditParticipantDialog.php index 1fdfb93c5..be6fc9e98 100644 --- a/app/AccountancyModule/Components/Participants/EditParticipantDialog.php +++ b/app/AccountancyModule/Components/Participants/EditParticipantDialog.php @@ -101,7 +101,7 @@ protected function createComponentForm(): BaseForm $changes[UpdateParticipant::FIELD_IS_ACCOUNT] = $values['isAccount']; } - $this->onUpdate($this->participantId, $changes, $participant->isAccepted()); + $this->onUpdate($this->participantId, $changes, $participant instanceof Participant ? $participant->isAccepted() : null); $this->hide(); }; diff --git a/app/AccountancyModule/Components/Participants/ParticipantList.php b/app/AccountancyModule/Components/Participants/ParticipantList.php index 2b899a0a9..6d3f9499e 100644 --- a/app/AccountancyModule/Components/Participants/ParticipantList.php +++ b/app/AccountancyModule/Components/Participants/ParticipantList.php @@ -6,6 +6,7 @@ use App\AccountancyModule\Components\BaseControl; use App\Forms\BaseForm; +use Model\DTO\Participant\Participant; use Model\DTO\Participant\ParticipatingPerson; use Model\DTO\Participant\UpdateParticipant; use Model\Participant\ParticipantNotFound; @@ -173,7 +174,7 @@ protected function createComponentEditDialog(): EditParticipantDialog { $dialog = new EditParticipantDialog($this->participantsById(), $this->isAllowDaysUpdate, $this->isAllowIsAccount, $this->isAllowRepayment, $this->isOnlineLogin); - $dialog->onUpdate[] = function (int $participantId, array $fields, bool $isAccepted): void { + $dialog->onUpdate[] = function (int $participantId, array $fields, bool|null $isAccepted): void { $changes = []; foreach ($fields as $field => $value) { @@ -243,27 +244,29 @@ private function massEditSubmitted(SubmitButton $button): void foreach ($button->getForm()->getValues()->participantIds as $participantId) { $participant = $currentParticipants[$participantId] ?? throw new ParticipantNotFound('Cannot find participant from the given data'); + $isAccepted = $participant instanceof Participant ? $participant->isAccepted() : null; + if ($values['days'] !== null) { - if ($this->isOnlineLogin && ! $participant->isAccepted()) { + if ($this->isOnlineLogin && ! $isAccepted) { $participantUpdateError[] = $participant->displayName; } else { - $changes[] = new UpdateParticipant($this->aid, $participantId, UpdateParticipant::FIELD_DAYS, $values['days'], $participant->isAccepted()); + $changes[] = new UpdateParticipant($this->aid, $participantId, UpdateParticipant::FIELD_DAYS, $values['days'], $isAccepted); } } if ($values['payment'] !== null) { - $changes[] = new UpdateParticipant($this->aid, $participantId, UpdateParticipant::FIELD_PAYMENT, $values['payment'], $participant->isAccepted()); + $changes[] = new UpdateParticipant($this->aid, $participantId, UpdateParticipant::FIELD_PAYMENT, $values['payment'], $isAccepted); } if ($values['repayment'] !== null) { - $changes[] = new UpdateParticipant($this->aid, $participantId, UpdateParticipant::FIELD_REPAYMENT, $values['repayment'], $participant->isAccepted()); + $changes[] = new UpdateParticipant($this->aid, $participantId, UpdateParticipant::FIELD_REPAYMENT, $values['repayment'], $isAccepted); } if (in_array($values['isAccount'], [self::NO_ACTION, null])) { continue; } - $changes[] = new UpdateParticipant($this->aid, $participantId, UpdateParticipant::FIELD_IS_ACCOUNT, $values['isAccount'], $participant->isAccepted()); + $changes[] = new UpdateParticipant($this->aid, $participantId, UpdateParticipant::FIELD_IS_ACCOUNT, $values['isAccount'], $isAccepted); } if (! empty($participantUpdateError)) { diff --git a/app/model/DTO/Participant/UpdateParticipant.php b/app/model/DTO/Participant/UpdateParticipant.php index 41286b21f..c262287aa 100644 --- a/app/model/DTO/Participant/UpdateParticipant.php +++ b/app/model/DTO/Participant/UpdateParticipant.php @@ -11,7 +11,7 @@ class UpdateParticipant public const FIELD_REPAYMENT = 'repayment'; public const FIELD_IS_ACCOUNT = 'isAccount'; - public function __construct(private int $eventId, private int $participantId, private string $field, private string $value, private bool $isAccepted) + public function __construct(private int $eventId, private int $participantId, private string $field, private string $value, private bool|null $isAccepted) { } @@ -35,7 +35,7 @@ public function getValue(): string return $this->value; } - public function isAccepted(): bool + public function isAccepted(): bool|null { return $this->isAccepted; }