Skip to content

Commit cc2315e

Browse files
authored
Přenos vstupenky (#1386)
* ticket transfer form * ticket transfer form * states * states * fixes * format fix * composer update * composer update * rename * useless condition removed * phpstan fix * phpstan fix * phpstan fix * fixes --------- Co-authored-by: Jan Staněk <[email protected]>
1 parent 4dc2968 commit cc2315e

File tree

17 files changed

+510
-272
lines changed

17 files changed

+510
-272
lines changed

app/AdminModule/Components/UsersGridControl.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ public function createComponentUsersGrid(string $name): DataGrid
176176
->andWhere('uA.validTo IS NULL')
177177
->andWhere('uA.state IN (:states)')
178178
->setParameter('sids', (array) $values)
179-
->setParameter('states', [ApplicationState::PAID, ApplicationState::PAID_FREE, ApplicationState::WAITING_FOR_PAYMENT]);
179+
->setParameter('states', [ApplicationState::PAID, ApplicationState::PAID_FREE, ApplicationState::PAID_TRANSFERED, ApplicationState::WAITING_FOR_PAYMENT]);
180180
});
181181

182182
$columnApproved = $grid->addColumnStatus('approved', 'admin.users.users_approved');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\AdminModule\Forms;
6+
7+
use App\AdminModule\Presenters\AdminBasePresenter;
8+
use App\Model\User\Repositories\UserRepository;
9+
use App\Model\User\User;
10+
use App\Services\ApplicationService;
11+
use Contributte\Translation\Translator;
12+
use Nette;
13+
use Nette\Application\UI\Form;
14+
use Nette\Utils\ImageException;
15+
use stdClass;
16+
17+
use function assert;
18+
19+
/**
20+
* Formulář pro předání registrace jinému uživateli.
21+
*/
22+
class EditUserTransferFormFactory
23+
{
24+
use Nette\SmartObject;
25+
26+
/**
27+
* Upravovaný uživatel.
28+
*/
29+
private User|null $user = null;
30+
31+
public function __construct(
32+
private readonly BaseFormFactory $baseFormFactory,
33+
private readonly UserRepository $userRepository,
34+
private readonly ApplicationService $applicationService,
35+
private readonly Translator $translator,
36+
) {
37+
}
38+
39+
public function create(int $id): Form
40+
{
41+
$this->user = $this->userRepository->findById($id);
42+
43+
$form = $this->baseFormFactory->create();
44+
45+
$form->addSelect('targetUser', 'admin.users.users_target_user', $this->userRepository->getUsersOptions(true))
46+
->addRule(Form::NOT_EQUAL, 'admin.users.users_target_user_empty', 0)
47+
->addRule(Form::NOT_EQUAL, 'admin.users.users_target_user_same', $this->user->getId())
48+
->setHtmlAttribute('data-live-search', 'true');
49+
50+
$form->addSubmit('submit', 'admin.users.users_transfer')
51+
->setDisabled(! $this->user->isRegistered() || ! $this->user->hasPaidAnyApplication())
52+
->setHtmlAttribute('class', 'btn btn-danger')
53+
->setHtmlAttribute('data-toggle', 'confirmation')
54+
->setHtmlAttribute('data-content', $this->translator->translate('admin.users.users_transfer_confirm'));
55+
56+
$form->onSuccess[] = [$this, 'processForm'];
57+
58+
return $form;
59+
}
60+
61+
/**
62+
* Zpracuje formulář.
63+
*
64+
* @throws Nette\Utils\UnknownImageFileException
65+
* @throws ImageException
66+
*/
67+
public function processForm(Form $form, stdClass $values): void
68+
{
69+
$presenter = $form->getPresenter();
70+
assert($presenter instanceof AdminBasePresenter);
71+
72+
$loggedUser = $presenter->getDbUser();
73+
74+
$targetUser = $this->userRepository->findById($values->targetUser);
75+
76+
$this->applicationService->transferRegistration($this->user, $targetUser, $loggedUser);
77+
}
78+
}

app/AdminModule/Presenters/UsersPresenter.php

+17-17
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use App\AdminModule\Forms\AddLectorFormFactory;
1212
use App\AdminModule\Forms\EditUserPersonalDetailsFormFactory;
1313
use App\AdminModule\Forms\EditUserSeminarFormFactory;
14+
use App\AdminModule\Forms\EditUserTransferFormFactory;
1415
use App\Model\Acl\Permission;
1516
use App\Model\Acl\Role;
1617
use App\Model\Acl\SrsResource;
@@ -48,6 +49,9 @@ class UsersPresenter extends AdminBasePresenter
4849
#[Inject]
4950
public EditUserSeminarFormFactory $editUserSeminarFormFactory;
5051

52+
#[Inject]
53+
public EditUserTransferFormFactory $editUserTransferFormFactory;
54+
5155
#[Inject]
5256
public IApplicationsGridControlFactory $applicationsGridControlFactory;
5357

@@ -73,7 +77,6 @@ public function startup(): void
7377
$this->template->results = [];
7478
$this->template->editPersonalDetails = false;
7579
$this->template->editSeminar = false;
76-
$this->template->editPayment = false;
7780
}
7881

7982
public function renderDetail(int $id): void
@@ -137,22 +140,6 @@ public function handleEditSeminar(): void
137140
}
138141
}
139142

140-
/**
141-
* Zobrazí formulář pro editaci údajů o platbě uživatele.
142-
*
143-
* @throws AbortException
144-
*/
145-
public function handleEditPayment(): void
146-
{
147-
$this->template->editPayment = true;
148-
149-
if ($this->isAjax()) {
150-
$this->redrawControl('userDetail');
151-
} else {
152-
$this->redirect('this');
153-
}
154-
}
155-
156143
/** @throws Throwable */
157144
public function handleCancelRegistration(): void
158145
{
@@ -235,6 +222,19 @@ protected function createComponentEditUserSeminarForm(): Form
235222
return $form;
236223
}
237224

225+
/** @throws JsonException */
226+
protected function createComponentEditUserTransferForm(): Form
227+
{
228+
$form = $this->editUserTransferFormFactory->create((int) $this->getParameter('id'));
229+
230+
$form->onSuccess[] = function (Form $form, stdClass $values): void {
231+
$this->flashMessage('admin.users.users_transfered', 'success');
232+
$this->redirect('this');
233+
};
234+
235+
return $form;
236+
}
237+
238238
protected function createComponentApplicationsGrid(): ApplicationsGridControl
239239
{
240240
return $this->applicationsGridControlFactory->create();

app/AdminModule/Presenters/templates/Users/detail.latte

+5
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@
167167
{/if}
168168
</div>
169169

170+
<h3>{_admin.users.users_detail_transfer}</h3>
171+
<div class="card card-body bg-light pb-1 mb-3">
172+
{control editUserTransferForm}
173+
</div>
174+
170175
<h3>{_admin.users.users_detail_schedule}</h3>
171176
<table class="table table-sm table-bordered table-striped">
172177
<thead>

app/ApiModule/Presenters/TicketsPresenter.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public function actionCheckTicket(int $userId, int $subeventId): void
9696
$subevents = [];
9797
$hasSubevent = false;
9898

99-
foreach ($user->getPaidAndFreeApplications() as $application) {
99+
foreach ($user->getPaidAndTransferedAndFreeApplications() as $application) {
100100
if ($application instanceof RolesApplication) {
101101
foreach ($application->getRoles() as $r) {
102102
$roles[] = $r->getName();

app/Model/Application/Application.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -382,12 +382,12 @@ public function isValid(): bool
382382

383383
public function isCanceled(): bool
384384
{
385-
return $this->state === ApplicationState::CANCELED || $this->state === ApplicationState::CANCELED_NOT_PAID;
385+
return $this->state === ApplicationState::CANCELED || $this->state === ApplicationState::CANCELED_NOT_PAID || $this->state === ApplicationState::CANCELED_TRANSFERED;
386386
}
387387

388388
public function isPaid(): bool
389389
{
390-
return $this->state === ApplicationState::PAID || $this->getState() === ApplicationState::PAID_FREE;
390+
return $this->state === ApplicationState::PAID || $this->getState() === ApplicationState::PAID_FREE || $this->getState() === ApplicationState::PAID_TRANSFERED;
391391
}
392392

393393
public function isWaitingForPayment(): bool

app/Model/Enums/ApplicationState.php

+16-6
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,37 @@
77
class ApplicationState
88
{
99
/**
10-
* Čeká na platbu.
10+
* Čeká na platbu
1111
*/
1212
public const WAITING_FOR_PAYMENT = 'waiting_for_payment';
1313

1414
/**
15-
* Automaticky zrušeno kvůli nezaplacení.
15+
* Zrušeno
16+
*/
17+
public const CANCELED = 'canceled';
18+
19+
/**
20+
* Zrušeno (automaticky kvůli nezaplacení)
1621
*/
1722
public const CANCELED_NOT_PAID = 'canceled_not_paid';
1823

1924
/**
20-
* Zrušeno.
25+
* Zrušeno (převod na jiného účastníka)
2126
*/
22-
public const CANCELED = 'canceled';
27+
public const CANCELED_TRANSFERED = 'canceled_transfered';
2328

2429
/**
25-
* Zaplaceno.
30+
* Zaplaceno
2631
*/
2732
public const PAID = 'paid';
2833

2934
/**
30-
* Zaplaceno (zdarma).
35+
* Zaplaceno (zdarma)
3136
*/
3237
public const PAID_FREE = 'paid_free';
38+
39+
/**
40+
* Zaplaceno (převedeno od jiného účastníka)
41+
*/
42+
public const PAID_TRANSFERED = 'paid_transfered';
3343
}

app/Model/Structure/Subevent.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,8 @@ public function countUsers(): int
432432
return $this->applications->filter(static fn (Application $application) => $application->getValidTo() === null && (
433433
$application->getState() === ApplicationState::WAITING_FOR_PAYMENT ||
434434
$application->getState() === ApplicationState::PAID_FREE ||
435-
$application->getState() === ApplicationState::PAID))->count();
435+
$application->getState() === ApplicationState::PAID ||
436+
$application->getState() === ApplicationState::PAID_TRANSFERED))->count();
436437
}
437438

438439
public function countUnoccupied(): int|null

app/Model/User/Repositories/UserRepository.php

+7-2
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public function findAllWithSubevents(array $subeventsIds): Collection
131131
->where('a.validTo IS NULL')
132132
->andWhere('a.state IN (:states)')
133133
->andWhere('s.id IN (:ids)')
134-
->setParameter('states', [ApplicationState::PAID, ApplicationState::PAID_FREE, ApplicationState::WAITING_FOR_PAYMENT])
134+
->setParameter('states', [ApplicationState::PAID, ApplicationState::PAID_FREE, ApplicationState::PAID_TRANSFERED, ApplicationState::WAITING_FOR_PAYMENT])
135135
->setParameter('ids', $subeventsIds)
136136
->getQuery()
137137
->getResult();
@@ -213,7 +213,7 @@ public function findProgramFirstAlternate(Program $program): User|null
213213
*
214214
* @return string[]
215215
*/
216-
public function getUsersOptions(): array
216+
public function getUsersOptions(bool $empty = false): array
217217
{
218218
$users = $this->createQueryBuilder('u')
219219
->select('u.id, u.displayName')
@@ -222,6 +222,11 @@ public function getUsersOptions(): array
222222
->getResult();
223223

224224
$options = [];
225+
226+
if ($empty) {
227+
$options[0] = '';
228+
}
229+
225230
foreach ($users as $user) {
226231
$options[$user['id']] = $user['displayName'];
227232
}

app/Model/User/User.php

+31-4
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,11 @@ public function isInRoleWithSystemName(string $name): bool
677677
return $this->roles->exists(static fn (int $key, Role $role) => $role->getSystemName() === $name);
678678
}
679679

680+
public function isRegistered(): bool
681+
{
682+
return ! $this->isInRoleWithSystemName(Role::NONREGISTERED);
683+
}
684+
680685
/**
681686
* Vrací, zda má uživatel nějakou roli, která nemá cenu podle podakcí.
682687
*/
@@ -784,7 +789,7 @@ public function getNotCanceledSubeventsApplications(): Collection
784789
}
785790

786791
/**
787-
* Vrácí zaplacené přihlášky.
792+
* Vrací zaplacené přihlášky.
788793
*
789794
* @return Collection<int, Application>
790795
*/
@@ -804,11 +809,13 @@ public function getPaidApplications(): Collection
804809
*
805810
* @return Collection<int, Application>
806811
*/
807-
public function getPaidAndFreeApplications(): Collection
812+
public function getPaidAndTransferedAndFreeApplications(): Collection
808813
{
809814
return $this->applications->filter(static fn (Application $application) => $application->getValidTo() === null && (
815+
$application->getState() === ApplicationState::PAID ||
810816
$application->getState() === ApplicationState::PAID_FREE ||
811-
$application->getState() === ApplicationState::PAID));
817+
$application->getState() === ApplicationState::PAID_TRANSFERED
818+
));
812819
}
813820

814821
/**
@@ -1089,12 +1096,32 @@ public function hasSubevent(Subevent $subevent): bool
10891096
return $this->getSubevents()->contains($subevent);
10901097
}
10911098

1099+
/**
1100+
* Vrací zaplacné podakce uživatele.
1101+
*
1102+
* @return Collection<int, Subevent>
1103+
*/
1104+
public function getPaidSubevents(): Collection
1105+
{
1106+
$subevents = new ArrayCollection();
1107+
1108+
foreach ($this->getPaidAndTransferedAndFreeApplications() as $application) {
1109+
if ($application instanceof SubeventsApplication) {
1110+
foreach ($application->getSubevents() as $subevent) {
1111+
$subevents->add($subevent);
1112+
}
1113+
}
1114+
}
1115+
1116+
return $subevents;
1117+
}
1118+
10921119
/**
10931120
* Vrácí, zda má uživatel zaplacenou přihlášku s podakcí.
10941121
*/
10951122
public function hasPaidSubevent(Subevent $subevent): bool
10961123
{
1097-
foreach ($this->getPaidAndFreeApplications() as $application) {
1124+
foreach ($this->getPaidAndTransferedAndFreeApplications() as $application) {
10981125
if ($application instanceof SubeventsApplication && $application->getSubevents()->contains($subevent)) {
10991126
return true;
11001127
}

0 commit comments

Comments
 (0)