From a13a0b5d8a44729587b04bb4b43cc77eab678cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Stan=C4=9Bk?= Date: Wed, 27 Dec 2017 16:54:32 +0100 Subject: [PATCH] upravy registrace --- .../presenters/MaturityPresenter.php | 105 +++-- .../MailingModule/forms/SendForm.php | 2 +- .../components/ApplicationsGridControl.php | 397 +++++------------- .../components/UsersGridControl.php | 107 +++-- app/AdminModule/forms/EditUserSeminarForm.php | 14 +- app/AdminModule/presenters/UsersPresenter.php | 3 +- .../components/ApplicationsGridControl.php | 294 ++++--------- app/WebModule/forms/RolesForm.php | 13 +- app/lang/common.cs_CZ.neon | 4 +- app/model/ACL/Role.php | 15 + app/model/ACL/RoleRepository.php | 2 +- app/model/Mailing/Template.php | 19 +- app/model/User/Application/Application.php | 20 + .../Application/ApplicationRepository.php | 15 +- .../User/Application/RolesApplication.php | 7 +- .../RolesApplicationRepository.php | 3 + .../User/Application/SubeventsApplication.php | 7 +- .../SubeventsApplicationRepository.php | 3 + app/model/User/User.php | 26 +- app/model/User/UserRepository.php | 38 +- app/services/ApplicationService.php | 243 ++++++++--- app/services/PdfExportService.php | 66 ++- app/services/SkautIsEventService.php | 3 +- app/utils/Validators.php | 32 +- migrations/Version20171227152222.php | 33 ++ 25 files changed, 711 insertions(+), 760 deletions(-) create mode 100644 migrations/Version20171227152222.php diff --git a/app/ActionModule/presenters/MaturityPresenter.php b/app/ActionModule/presenters/MaturityPresenter.php index 19833ef27..0c4be5a32 100644 --- a/app/ActionModule/presenters/MaturityPresenter.php +++ b/app/ActionModule/presenters/MaturityPresenter.php @@ -10,8 +10,13 @@ use App\Model\Program\ProgramRepository; use App\Model\Settings\Settings; use App\Model\Settings\SettingsRepository; +use App\Model\User\Application; use App\Model\User\ApplicationRepository; +use App\Model\User\RolesApplication; +use App\Model\User\RolesApplicationRepository; +use App\Model\User\SubeventsApplicationRepository; use App\Model\User\UserRepository; +use App\Services\ApplicationService; use App\Services\MailService; use App\Services\ProgramService; use Doctrine\Common\Collections\ArrayCollection; @@ -66,9 +71,31 @@ class MaturityPresenter extends ActionBasePresenter */ public $programService; + /** + * @var ApplicationService + * @inject + */ + public $applicationService; + + /** + * @var RolesApplicationRepository + * @inject + */ + public $rolesApplicationRepository; + + /** + * @var SubeventsApplicationRepository + * @inject + */ + public $subeventsApplicationRepository; + /** * Zkontroluje splatnost přihlášek. + * @throws \App\Model\Settings\SettingsException + * @throws \Throwable + * @throws \Ublaboo\Mailing\Exception\MailingException + * @throws \Ublaboo\Mailing\Exception\MailingMailCreationException */ public function actionCheck() { @@ -80,44 +107,54 @@ public function actionCheck() if ($maturityReminder !== NULL) $maturityReminderDate = (new \DateTime())->setTime(0, 0)->modify('+' . $maturityReminder . ' days'); - foreach ($this->applicationRepository->findWaitingForPaymentApplications() as $application) { - $maturityDate = $application->getMaturityDate(); - if ($maturityDate === NULL) - continue; - - //zrušení registrace - if ($cancelRegistration !== NULL && $cancelRegistrationDate > $maturityDate) { - $this->userRepository->getEntityManager()->transactional(function ($em) use ($application) { - if ($application->isFirst()) { - $user = $application->getUser(); - - $user->setRoles(new ArrayCollection([$this->roleRepository->findBySystemName(Role::NONREGISTERED)])); - $user->setApproved(TRUE); - foreach ($user->getApplications() as $application) { - $this->applicationRepository->remove($application); + foreach ($this->userRepository->findAllWithWaitingForPaymentApplication() as $user) { + $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($user, $cancelRegistration, $cancelRegistrationDate, $maturityReminder, $maturityReminderDate) { + foreach ($user->getWaitingForPaymentRolesApplications() as $application) { + if ($application->getType() == Application::ROLES) { + $maturityDate = $application->getMaturityDate(); + if ($maturityDate === NULL) + continue; + + if ($cancelRegistration !== NULL && $cancelRegistrationDate > $maturityDate) { + $rolesWithoutFee = $user->getRoles()->filter(function (Role $role) { + return $role->getFee() == 0; + }); + + if ($rolesWithoutFee->isEmpty()) { + $this->applicationService->cancelRegistration($user, ApplicationState::CANCELED_NOT_PAID, NULL); + return; + } else { + $this->applicationService->updateRoles($user, $rolesWithoutFee, NULL); + } } - $this->userRepository->save($user); + } + } - $this->mailService->sendMailFromTemplate($user, '', Template::REGISTRATION_CANCELED, [ - TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME) - ]); - } else { - $application->setState(ApplicationState::CANCELED_NOT_PAID); - $this->applicationRepository->save($application); + foreach ($user->getWaitingForPaymentSubeventsApplications() as $application) { + if ($application->getType() == Application::SUBEVENTS) { + $maturityDate = $application->getMaturityDate(); + if ($maturityDate === NULL) + continue; + + if ($cancelRegistration !== NULL && $cancelRegistrationDate > $maturityDate) { + $this->applicationService->cancelSubeventsApplication($application, ApplicationState::CANCELED_NOT_PAID, NULL); + } } + } + + foreach ($user->getWaitingForPaymentApplications() as $application) { + $maturityDate = $application->getMaturityDate(); + if ($maturityDate === NULL) + continue; - $this->programService->updateUserPrograms($application->getUser()); - }); - continue; - } - - //připomenutí splatnosti - if ($maturityReminder !== NULL && $maturityReminderDate == $maturityDate) { - $this->mailService->sendMailFromTemplate($application->getUser(), '', Template::MATURITY_REMINDER, [ - TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), - TemplateVariable::APPLICATION_MATURITY => $maturityDate->format('j. n. Y') - ]); - } + if ($maturityReminder !== NULL && $maturityReminderDate == $maturityDate) { + $this->mailService->sendMailFromTemplate($application->getUser(), '', Template::MATURITY_REMINDER, [ + TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), + TemplateVariable::APPLICATION_MATURITY => $maturityDate->format('j. n. Y') + ]); + } + } + }); } } } diff --git a/app/AdminModule/MailingModule/forms/SendForm.php b/app/AdminModule/MailingModule/forms/SendForm.php index 223b98dc2..ba9448ec3 100644 --- a/app/AdminModule/MailingModule/forms/SendForm.php +++ b/app/AdminModule/MailingModule/forms/SendForm.php @@ -64,7 +64,7 @@ public function create() $form = $this->baseFormFactory->create(); $recipientRolesMultiSelect = $form->addMultiSelect('recipientRoles', 'admin.mailing.send_recipient_roles', - $this->roleRepository->getRolesWithoutRolesOptionsWithUsersCount([Role::GUEST, Role::UNAPPROVED, Role::NONREGISTERED])); + $this->roleRepository->getRolesWithoutRolesOptionsWithApprovedUsersCount([Role::GUEST, Role::UNAPPROVED, Role::NONREGISTERED])); $recipientUsersMultiSelect = $form->addMultiSelect('recipientUsers', 'admin.mailing.send_recipient_users', $this->userRepository->getUsersOptions()) diff --git a/app/AdminModule/components/ApplicationsGridControl.php b/app/AdminModule/components/ApplicationsGridControl.php index 30e33dab2..48841b1d5 100644 --- a/app/AdminModule/components/ApplicationsGridControl.php +++ b/app/AdminModule/components/ApplicationsGridControl.php @@ -2,14 +2,10 @@ namespace App\AdminModule\Components; -use App\Model\ACL\Role; use App\Model\ACL\RoleRepository; use App\Model\Enums\ApplicationState; use App\Model\Enums\PaymentType; -use App\Model\Mailing\Template; -use App\Model\Mailing\TemplateVariable; use App\Model\Program\ProgramRepository; -use App\Model\Settings\Settings; use App\Model\Settings\SettingsRepository; use App\Model\Structure\SubeventRepository; use App\Model\User\Application; @@ -20,7 +16,7 @@ use App\Services\MailService; use App\Services\PdfExportService; use App\Services\ProgramService; -use Doctrine\Common\Collections\ArrayCollection; +use App\Utils\Validators; use Kdyby\Translation\Translator; use Nette\Application\UI\Control; use Nette\Application\UI\Form; @@ -70,6 +66,9 @@ class ApplicationsGridControl extends Control /** @var ProgramService */ private $programService; + /** @var Validators */ + private $validators; + /** * ApplicationsGridControl constructor. @@ -90,7 +89,7 @@ public function __construct(Translator $translator, ApplicationRepository $appli SubeventRepository $subeventRepository, ApplicationService $applicationService, ProgramRepository $programRepository, MailService $mailService, SettingsRepository $settingsRepository, PdfExportService $pdfExportService, - ProgramService $programService) + ProgramService $programService, Validators $validators) { parent::__construct(); @@ -105,6 +104,7 @@ public function __construct(Translator $translator, ApplicationRepository $appli $this->settingsRepository = $settingsRepository; $this->pdfExportService = $pdfExportService; $this->programService = $programService; + $this->validators = $validators; } /** @@ -125,6 +125,8 @@ public function createComponentApplicationsGrid($name) { $this->user = $this->userRepository->findById($this->getPresenter()->getParameter('id')); + $explicitSubeventsExists = $this->subeventRepository->explicitSubeventsExists(); + $grid = new DataGrid($this, $name); $grid->setTranslator($this->translator); $grid->setDataSource($this->applicationRepository->createQueryBuilder('a') @@ -168,54 +170,55 @@ public function createComponentApplicationsGrid($name) }); -// $grid->addInlineAdd()->onControlAdd[] = function ($container) { -// $container->addMultiSelect('roles', '', $this->roleRepository->getRolesWithoutRolesOptionsWithCapacity([Role::GUEST, Role::UNAPPROVED, Role::NONREGISTERED])) -// ->setAttribute('class', 'datagrid-multiselect'); -// -// if ($this->subeventRepository->explicitSubeventsExists()) { -// $container->addMultiSelect('subevents', '', $this->subeventRepository->getNonRegisteredSubeventsOptionsWithCapacity($this->user)) -// ->setAttribute('class', 'datagrid-multiselect'); -// } -// }; -// $grid->getInlineAdd()->onSubmit[] = [$this, 'add']; -// -// $grid->addInlineEdit()->onControlAdd[] = function ($container) { -// $container->addMultiSelect('roles', '', $this->roleRepository->getRolesWithoutRolesOptionsWithCapacity([Role::GUEST, Role::UNAPPROVED, Role::NONREGISTERED])) -// ->setAttribute('class', 'datagrid-multiselect'); -// -// if ($this->subeventRepository->explicitSubeventsExists()) { -// $container->addMultiSelect('subevents', '', $this->subeventRepository->getSubeventsOptionsWithCapacity()) -// ->setAttribute('class', 'datagrid-multiselect'); -// } -// -// $container->addText('variableSymbol', 'admin.users.users_variable_symbol') -// ->addRule(Form::FILLED, 'admin.users.users_applications_variable_symbol_empty') -// ->addRule(Form::PATTERN, 'admin.users.users_edit_variable_symbol_format', '^\d{1,10}$'); -// -// $paymentMethodSelect = $container->addSelect('paymentMethod', 'admin.users.users_payment_method', $this->preparePaymentMethodOptions()); -// -// $container->addDatePicker('paymentDate', 'admin.users.users_payment_date'); -// -// $paymentMethodSelect -// ->addConditionOn($container['paymentDate'], Form::FILLED) -// ->addRule(Form::FILLED, 'admin.users.users_applications_payment_method_empty'); -// -// $container->addDatePicker('incomeProofPrintedDate', 'admin.users.users_income_proof_printed_date'); -// -// $container->addDatePicker('maturityDate', 'admin.users.users_maturity_date'); -// }; -// $grid->getInlineEdit()->onSetDefaults[] = function ($container, $item) { -// $container->setDefaults([ -// 'roles' => $item->isFirst() ? $this->roleRepository->findRolesIds($item->getUser()->getRoles()) : NULL, -// 'subevents' => $this->subeventRepository->findSubeventsIds($item->getSubevents()), -// 'variableSymbol' => $item->getVariableSymbol(), -// 'paymentMethod' => $item->getPaymentMethod(), -// 'paymentDate' => $item->getPaymentDate(), -// 'incomeProofPrintedDate' => $item->getIncomeProofPrintedDate(), -// 'maturityDate' => $item->getMaturityDate() -// ]); -// }; -// $grid->getInlineEdit()->onSubmit[] = [$this, 'edit']; + if ($explicitSubeventsExists) { + $grid->addInlineAdd()->onControlAdd[] = function ($container) { + $container->addMultiSelect('subevents', '', + $this->subeventRepository->getNonRegisteredSubeventsOptionsWithCapacity($this->user) + ) + ->setAttribute('class', 'datagrid-multiselect') + ->addRule(Form::FILLED, 'admin.users.users_applications_subevents_empty'); + }; + $grid->getInlineAdd()->onSubmit[] = [$this, 'add']; + } + + $grid->addInlineEdit()->onControlAdd[] = function ($container) use ($explicitSubeventsExists) { + $container->addMultiSelect('subevents', '', + $this->subeventRepository->getSubeventsOptionsWithCapacity() + ) + ->setAttribute('class', 'datagrid-multiselect') + ->addRule(Form::FILLED, 'admin.users.users_applications_subevents_empty'); + + $container->addText('variableSymbol', 'admin.users.users_variable_symbol') + ->addRule(Form::FILLED, 'admin.users.users_applications_variable_symbol_empty') + ->addRule(Form::PATTERN, 'admin.users.users_edit_variable_symbol_format', '^\d{1,10}$'); + + $paymentMethodSelect = $container->addSelect('paymentMethod', 'admin.users.users_payment_method', + $this->preparePaymentMethodOptions()); + + $paymentDateText = $container->addDatePicker('paymentDate', 'admin.users.users_payment_date'); + + $paymentMethodSelect + ->addConditionOn($paymentDateText, Form::FILLED) + ->addRule(Form::FILLED, 'admin.users.users_applications_payment_method_empty'); + + $container->addDatePicker('incomeProofPrintedDate', 'admin.users.users_income_proof_printed_date'); + + $container->addDatePicker('maturityDate', 'admin.users.users_maturity_date'); + }; + $grid->getInlineEdit()->onSetDefaults[] = function ($container, $item) { + $container->setDefaults([ + 'subevents' => $this->subeventRepository->findSubeventsIds($item->getSubevents()), + 'variableSymbol' => $item->getVariableSymbol(), + 'paymentMethod' => $item->getPaymentMethod(), + 'paymentDate' => $item->getPaymentDate(), + 'incomeProofPrintedDate' => $item->getIncomeProofPrintedDate(), + 'maturityDate' => $item->getMaturityDate() + ]); + }; + $grid->getInlineEdit()->onSubmit[] = [$this, 'edit']; + $grid->allowRowsInlineEdit(function(Application $item) { + return !$item->isCanceled(); + }); $grid->addAction('generatePaymentProofCash', 'admin.users.users_applications_download_payment_proof_cash'); @@ -238,11 +241,11 @@ public function createComponentApplicationsGrid($name) 'data-content' => $this->translator->translate('admin.users.users_applications_cancel_application_confirm') ])->setClass('btn btn-xs btn-danger'); $grid->allowRowsAction('cancelApplication', function (Application $item) { - return $item->getType() == Application::SUBEVENTS - && !($item->getState() == ApplicationState::CANCELED || $item->getState() == ApplicationState::CANCELED_NOT_PAID); + return $item->getType() == Application::SUBEVENTS && !$item->isCanceled(); }); - $grid->setColumnsSummary(['fee'], function(Application $item, $column) { + + $grid->setColumnsSummary(['fee'], function (Application $item, $column) { return $item->isCanceled() ? 0 : $item->getFee(); }); } @@ -256,76 +259,24 @@ public function createComponentApplicationsGrid($name) */ public function add($values) { -// $selectedRoles = $this->roleRepository->findRolesByIds($values['roles']); -// $selectedSubevents = NULL; -// -// //kontrola roli -// if ($this->user->getApplications()->isEmpty()) { -// if (!$this->validateRolesEmpty($selectedRoles)) { -// $this->getPresenter()->flashMessage('admin.users.users_applications_roles_empty', 'danger'); -// $this->redirect('this'); -// } -// -// if (!$this->validateRolesCapacities($selectedRoles)) { -// $this->getPresenter()->flashMessage('admin.users.users_applications_roles_occupied', 'danger'); -// $this->redirect('this'); -// } -// } else { -// if ($this->validateRolesEmpty($selectedRoles)) { -// $this->getPresenter()->flashMessage('admin.users.users_applications_roles_not_empty', 'danger'); -// $this->redirect('this'); -// } -// } -// -// if ($this->subeventRepository->explicitSubeventsExists()) { -// $selectedSubevents = $this->subeventRepository->findSubeventsByIds($values['subevents']); -// -// //kontrola podakci -// if (!$this->validateSubeventsEmpty($selectedSubevents)) { -// $this->getPresenter()->flashMessage('admin.users.users_applications_subevents_empty', 'danger'); -// $this->redirect('this'); -// } -// -// if (!$this->validateSubeventsCapacities($selectedSubevents)) { -// $this->getPresenter()->flashMessage('admin.users.users_applications_subevents_occupied', 'danger'); -// $this->redirect('this'); -// } -// } -// -// -// //zpracovani zmen -// $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($selectedRoles, $selectedSubevents) { -// $application = new Application(); -// -// if ($this->user->getApplications()->isEmpty()) { -// $this->user->setRoles($selectedRoles); -// $this->userRepository->save($this->user); -// $application->setFirst(TRUE); -// $fee = $this->applicationService->countFee($selectedRoles, $selectedSubevents); -// } else { -// $application->setFirst(FALSE); -// $fee = $this->applicationService->countFee($this->user->getRoles(), $selectedSubevents, FALSE); -// } -// -// $application->setUser($this->user); -// if ($this->subeventRepository->explicitSubeventsExists()) -// $application->setSubevents($selectedSubevents); -// else -// $application->setSubevents(new ArrayCollection([$this->subeventRepository->findImplicit()])); -// $application->setApplicationDate(new \DateTime()); -// $application->setMaturityDate($this->applicationService->countMaturityDate()); -// $application->setFee($fee); -// $application->setState($fee == 0 ? ApplicationState::PAID : ApplicationState::WAITING_FOR_PAYMENT); -// $this->applicationRepository->save($application); -// -// $application->setVariableSymbol($this->applicationService->generateVariableSymbol($application)); -// $this->applicationRepository->save($application); -// -// $this->programService->updateUserPrograms($this->user); -// }); -// -// $this->getPresenter()->flashMessage('admin.users.users_applications_saved', 'success'); -// $this->redirect('this'); + $selectedSubevents = $this->subeventRepository->findSubeventsByIds($values['subevents']); + + if (!$this->validators->validateSubeventsCapacities($selectedSubevents, $this->user)) { + $this->getPresenter()->flashMessage('admin.users.users_applications_subevents_occupied', 'danger'); + $this->redirect('this'); + } + + if (!$this->validators->validateSubeventsRegistered($selectedSubevents, $this->user)) { + $this->getPresenter()->flashMessage('admin.users.users_applications_subevents_registered', 'danger'); + $this->redirect('this'); + } + + $loggedUser = $this->userRepository->findById($this->getPresenter()->user->id); + + $this->applicationService->addSubeventsApplication($this->user, $selectedSubevents, $loggedUser); + + $this->getPresenter()->flashMessage('admin.users.users_applications_saved', 'success'); + $this->redirect('this'); } /** @@ -338,120 +289,57 @@ public function add($values) */ public function edit($id, $values) { -// $selectedRoles = $this->roleRepository->findRolesByIds($values['roles']); -// -// $application = $this->applicationRepository->findById($id); -// -// //kontrola roli -// if ($application->isFirst()) { -// if (!$this->validateRolesEmpty($selectedRoles)) { -// $this->getPresenter()->flashMessage('admin.users.users_applications_roles_empty', 'danger'); -// $this->redirect('this'); -// } -// -// if (!$this->validateRolesCapacities($selectedRoles)) { -// $this->getPresenter()->flashMessage('admin.users.users_applications_roles_occupied', 'danger'); -// $this->redirect('this'); -// } -// } else { -// if ($this->validateRolesEmpty($selectedRoles)) { -// $this->getPresenter()->flashMessage('admin.users.users_applications_roles_not_empty', 'danger'); -// $this->redirect('this'); -// } -// } -// -// if ($this->subeventRepository->explicitSubeventsExists()) { -// $selectedSubevents = $this->subeventRepository->findSubeventsByIds($values['subevents']); -// -// //kontrola podakci -// if (!$this->validateSubeventsEmpty($selectedSubevents)) { -// $this->getPresenter()->flashMessage('admin.users.users_applications_subevents_empty', 'danger'); -// $this->redirect('this'); -// } -// -// if (!$this->validateSubeventsCapacities($selectedSubevents)) { -// $this->getPresenter()->flashMessage('admin.users.users_applications_subevents_occupied', 'danger'); -// $this->redirect('this'); -// } -// -// if (!$this->validateSubeventsRegistered($selectedSubevents, $this->user, $application->getId())) { -// $this->getPresenter()->flashMessage('admin.users.users_applications_subevents_registered', 'danger'); -// $this->redirect('this'); -// } -// } -// -// //zpracovani zmen -// $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($selectedRoles, $selectedSubevents, $application, $values) { -// $oldPaymentDate = $application->getPaymentDate(); -// -// if ($application->isFirst()) { -// $this->user->setRoles($selectedRoles); -// $this->userRepository->save($this->user); -// } -// -// if ($this->subeventRepository->explicitSubeventsExists()) -// $application->setSubevents($selectedSubevents); -// $application->setVariableSymbol($values['variableSymbol']); -// $application->setPaymentMethod($values['paymentMethod']); -// $application->setPaymentDate($values['paymentDate']); -// $application->setIncomeProofPrintedDate($values['incomeProofPrintedDate']); -// $application->setMaturityDate($values['maturityDate']); -// -// if ($application->isFirst()) { -// foreach ($this->user->getApplications() as $application) { -// if ($application->isFirst()) -// $fee = $this->applicationService->countFee($selectedRoles, $selectedSubevents); -// else -// $fee = $this->applicationService->countFee($selectedRoles, $application->getSubevents(), FALSE); -// $application->setFee($fee); -// if ($application->getState() == ApplicationState::WAITING_FOR_PAYMENT || $application->getState() == ApplicationState::PAID) -// $application->setState($fee == 0 || $application->getPaymentDate() ? ApplicationState::PAID : ApplicationState::WAITING_FOR_PAYMENT); -// $this->applicationRepository->save($application); -// } -// } else { -// $fee = $this->applicationService->countFee($this->user->getRoles(), $selectedSubevents, FALSE); -// $application->setFee($fee); -// $application->setState($fee == 0 || $application->getPaymentDate() -// ? ApplicationState::PAID -// : ApplicationState::WAITING_FOR_PAYMENT); -// $this->applicationRepository->save($application); -// } -// -// $this->programService->updateUserPrograms($this->user); -// -// if ($values['paymentDate'] !== NULL && $oldPaymentDate === NULL) { -// $this->mailService->sendMailFromTemplate($this->user, '', Template::PAYMENT_CONFIRMED, [ -// TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), -// TemplateVariable::APPLICATION_SUBEVENTS => $application->getSubeventsText() -// ]); -// } -// }); -// -// $this->getPresenter()->flashMessage('admin.users.users_applications_saved', 'success'); -// $this->redirect('this'); + $application = $this->applicationRepository->findById($id); + + $selectedSubevents = $this->subeventRepository->findSubeventsByIds($values['subevents']); + + if (!$this->validators->validateSubeventsCapacities($selectedSubevents, $this->user)) { + $this->getPresenter()->flashMessage('admin.users.users_applications_subevents_occupied', 'danger'); + $this->redirect('this'); + } + + if (!$this->validators->validateSubeventsRegistered($selectedSubevents, $this->user, $application)) { + $this->getPresenter()->flashMessage('admin.users.users_applications_subevents_registered', 'danger'); + $this->redirect('this'); + } + + $loggedUser = $this->userRepository->findById($this->getPresenter()->user->id); + + $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($application, $selectedSubevents, $values, $loggedUser) { + $this->applicationService->updateSubeventsApplication($application, $selectedSubevents, $loggedUser); + $this->applicationService->updatePayment($application, $values['variableSymbol'], $values['paymentMethod'], + $values['paymentDate'], $values['incomeProofPrintedDate'], $values['maturityDate'], $loggedUser); + }); + + $this->getPresenter()->flashMessage('admin.users.users_applications_saved', 'success'); + $this->redirect('this'); } /** * Vygeneruje příjmový pokladní doklad. * @param $id + * @throws \App\Model\Settings\SettingsException + * @throws \Throwable */ public function handleGeneratePaymentProofCash($id) { $this->pdfExportService->generateApplicationsPaymentProof( - $application = $this->applicationRepository->findById($id), - "prijmovy-pokladni-doklad.pdf" + $application = $this->applicationRepository->findById($id), "prijmovy-pokladni-doklad.pdf", + $this->userRepository->findById($this->getPresenter()->getUser()->id) ); } /** * Vygeneruje potvrzení o přijetí platby. * @param $id + * @throws \App\Model\Settings\SettingsException + * @throws \Throwable */ public function handleGeneratePaymentProofBank($id) { $this->pdfExportService->generateApplicationsPaymentProof( - $application = $this->applicationRepository->findById($id), - "potvrzeni-o-prijeti-platby.pdf" + $application = $this->applicationRepository->findById($id), "potvrzeni-o-prijeti-platby.pdf", + $this->userRepository->findById($this->getPresenter()->getUser()->id) ); } @@ -464,69 +352,14 @@ public function handleGeneratePaymentProofBank($id) public function handleCancelApplication($id) { $application = $this->applicationRepository->findById($id); - $user = $application->getUser(); - - $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($application, $user) { - $application->setState(ApplicationState::CANCELED); - $this->applicationRepository->save($application); - - $this->programService->updateUserPrograms($user); - }); - - $this->getPresenter()->flashMessage('admin.users.users_applications_application_canceled', 'success'); - $this->redirect('this'); - } - - /** - * Ověří, že je vybrána alespoň jedna podakce. - * @param $selectedSubevents - * @return bool - */ - private function validateSubeventsEmpty($selectedSubevents) - { - if ($selectedSubevents->isEmpty()) - return FALSE; - return TRUE; - } - /** - * Ověří obsazenost podakcí. - * @param $selectedSubevents - * @return bool - * @throws \Doctrine\ORM\NonUniqueResultException - */ - private function validateSubeventsCapacities($selectedSubevents) - { - if ($this->user->isApproved()) { - foreach ($selectedSubevents as $subevent) { - if ($subevent->hasLimitedCapacity()) { - if ($subevent->countUnoccupied() < 1 && !$this->user->hasSubevent($subevent)) - return FALSE; - } - } + if ($application->getType() == Application::SUBEVENTS && !$application->isCanceled()) { + $loggedUser = $this->userRepository->findById($this->getPresenter()->user->id); + $this->applicationService->cancelSubeventsApplication($application, ApplicationState::CANCELED, $loggedUser); + $this->getPresenter()->flashMessage('admin.users.users_applications_application_canceled', 'success'); } - return TRUE; - } - /** - * Ověří, zda uživatel podakci již nemá. - * @param $selectedSubevents - * @param User $user - * @param $applicationId - * @return bool - */ - private function validateSubeventsRegistered($selectedSubevents, User $user, $applicationId) - { - foreach ($selectedSubevents as $subevent) { - foreach ($user->getApplications() as $application) { - if ($application->getId() != $applicationId - && ($application->getState() == ApplicationState::PAID - || $application->getState() == ApplicationState::WAITING_FOR_PAYMENT) - && $application->getSubevents()->contains($subevent)) - return FALSE; - } - } - return TRUE; + $this->redirect('this'); } /** diff --git a/app/AdminModule/components/UsersGridControl.php b/app/AdminModule/components/UsersGridControl.php index 19411d6a1..9f9a5a3df 100644 --- a/app/AdminModule/components/UsersGridControl.php +++ b/app/AdminModule/components/UsersGridControl.php @@ -434,22 +434,20 @@ public function changeAttended($id, $attended) * Hromadně schválí uživatele. * @param array $ids * @throws \Nette\Application\AbortException + * @throws \Throwable */ public function groupApprove(array $ids) { $users = $this->userRepository->findUsersByIds($ids); - try { - $this->userRepository->getEntityManager()->transactional(function ($em) use ($users) { - foreach ($users as $user) { - $user->setApproved(TRUE); - $this->userRepository->save($user); - } - }); - - $this->getPresenter()->flashMessage('admin.users.users_group_action_approved', 'success'); - } catch (\Throwable $exception) { } + $this->userRepository->getEntityManager()->transactional(function ($em) use ($users) { + foreach ($users as $user) { + $user->setApproved(TRUE); + $this->userRepository->save($user); + } + }); + $this->getPresenter()->flashMessage('admin.users.users_group_action_approved', 'success'); $this->redirect('this'); } @@ -458,6 +456,7 @@ public function groupApprove(array $ids) * @param array $ids * @param $value * @throws \Nette\Application\AbortException + * @throws \Throwable */ public function groupChangeRoles(array $ids, $value) { @@ -498,16 +497,15 @@ public function groupChangeRoles(array $ids, $value) $this->redirect('this'); } - try { - $this->userRepository->getEntityManager()->transactional(function ($em) use ($selectedRoles, $users, $p) { - foreach ($users as $user) { - $this->applicationService->updateRoles($user, $selectedRoles, $this->userRepository->findById($p->getUser()->id), TRUE); - } - }); + $loggedUser = $this->userRepository->findById($p->getUser()->id); - $p->flashMessage('admin.users.users_group_action_changed_roles', 'success'); - } catch (\Throwable $exception) { } + $this->userRepository->getEntityManager()->transactional(function ($em) use ($selectedRoles, $users, $loggedUser) { + foreach ($users as $user) { + $this->applicationService->updateRoles($user, $selectedRoles, $loggedUser, TRUE); + } + }); + $p->flashMessage('admin.users.users_group_action_changed_roles', 'success'); $this->redirect('this'); } @@ -515,22 +513,20 @@ public function groupChangeRoles(array $ids, $value) * Hromadně označí uživatele jako zúčastněné. * @param array $ids * @throws \Nette\Application\AbortException + * @throws \Throwable */ public function groupMarkAttended(array $ids) { $users = $this->userRepository->findUsersByIds($ids); - try { - $this->userRepository->getEntityManager()->transactional(function ($em) use ($users) { - foreach ($users as $user) { - $user->setAttended(TRUE); - $this->userRepository->save($user); - } - }); - - $this->getPresenter()->flashMessage('admin.users.users_group_action_marked_attended', 'success'); - } catch (\Throwable $exception) { } + $this->userRepository->getEntityManager()->transactional(function ($em) use ($users) { + foreach ($users as $user) { + $user->setAttended(TRUE); + $this->userRepository->save($user); + } + }); + $this->getPresenter()->flashMessage('admin.users.users_group_action_marked_attended', 'success'); $this->redirect('this'); } @@ -538,40 +534,29 @@ public function groupMarkAttended(array $ids) * Hromadně označí uživatele jako zaplacené dnes. * @param array $ids * @param $value - * @throws \App\Model\Settings\SettingsException * @throws \Nette\Application\AbortException - * @throws \Ublaboo\Mailing\Exception\MailingException - * @throws \Ublaboo\Mailing\Exception\MailingMailCreationException + * @throws \Throwable */ public function groupMarkPaidToday(array $ids, $value) { - foreach ($ids as $id) { - $user = $this->userRepository->findById($id); - - foreach ($user->getApplications() as $application) { - if ($application->getState() == ApplicationState::WAITING_FOR_PAYMENT) { - $application->setPaymentMethod($value); - $application->setPaymentDate(new \DateTime()); - $application->setState(ApplicationState::PAID); - $this->applicationRepository->save($application); - - $this->mailService->sendMailFromTemplate($user, '', Template::PAYMENT_CONFIRMED, [ - TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), - TemplateVariable::APPLICATION_SUBEVENTS => $application->getSubeventsText() - ]); + $users = $this->userRepository->findUsersByIds($ids); + + $p = $this->getPresenter(); + + $loggedUser = $this->userRepository->findById($p->getUser()->id); + + $this->userRepository->getEntityManager()->transactional(function ($em) use ($users, $value, $loggedUser) { + foreach ($users as $user) { + foreach ($user->getWaitingForPaymentApplications() as $application) { + $this->applicationService->updatePayment($application, $application->getVariableSymbolText(), + $value, new \DateTime(), $application->getIncomeProofPrintedDate(), + $application->getMaturityDate(), $loggedUser); } } - } + }); - $p = $this->getPresenter(); $p->flashMessage('admin.users.users_group_action_marked_paid_today', 'success'); - - if ($p->isAjax()) { - $p->redrawControl('flashes'); - $this['usersGrid']->reload(); - } else { - $this->redirect('this'); - } + $this->redirect('this'); } /** @@ -598,6 +583,8 @@ public function groupExportUsers(array $ids) /** * Zpracuje export seznamu uživatelů. + * @throws \PHPExcel_Exception + * @throws \Nette\Application\AbortException */ public function handleExportUsers() { @@ -623,6 +610,8 @@ public function groupExportRoles(array $ids) /** * Zpracuje export seznamu uživatelů s rolemi. + * @throws \PHPExcel_Exception + * @throws \Nette\Application\AbortException */ public function handleExportRoles() { @@ -649,6 +638,8 @@ public function groupExportSubeventsAndCategories(array $ids) /** * Zpracuje export seznamu uživatelů s podakcemi a programy podle kategorií. + * @throws \PHPExcel_Exception + * @throws \Nette\Application\AbortException */ public function handleExportSubeventsAndCategories() { @@ -674,6 +665,8 @@ public function groupExportSchedules(array $ids) /** * Zpracuje export harmonogramů uživatelů. + * @throws \PHPExcel_Exception + * @throws \Nette\Application\AbortException */ public function handleExportSchedules() { @@ -688,12 +681,16 @@ public function handleExportSchedules() /** * Vygeneruje doklady o zaplacení. + * @throws \App\Model\Settings\SettingsException + * @throws \Throwable */ public function handleGeneratePaymentProofs() { $ids = $this->session->getSection('srs')->userIds; $users = $this->userRepository->findUsersByIds($ids); - $this->pdfExportService->generateUsersPaymentProofs($users, "doklady.pdf"); + $this->pdfExportService->generateUsersPaymentProofs($users, "doklady.pdf", + $this->userRepository->findById($this->getPresenter()->getUser()->id) + ); } /** diff --git a/app/AdminModule/forms/EditUserSeminarForm.php b/app/AdminModule/forms/EditUserSeminarForm.php index a2ea8661b..a383fe0a7 100644 --- a/app/AdminModule/forms/EditUserSeminarForm.php +++ b/app/AdminModule/forms/EditUserSeminarForm.php @@ -173,19 +173,7 @@ public function processForm(Form $form, \stdClass $values) $this->userRepository->getEntityManager()->transactional(function ($em) use ($values, $loggedUser) { $selectedRoles = $this->roleRepository->findRolesByIds($values['roles']); - - $rolesChanged = TRUE; - - if ($selectedRoles->count() == $this->user->getRoles()->count()) { - $selectedRolesArray = $selectedRoles->map(function (Role $role) {return $role->getId();})->toArray(); - $usersRolesArray = $this->user->getRoles()->map(function (Role $role) {return $role->getId();})->toArray(); - - if (array_diff($selectedRolesArray, $usersRolesArray) === array_diff($usersRolesArray, $selectedRolesArray)) - $rolesChanged = FALSE; - } - - if ($rolesChanged) - $this->applicationService->updateRoles($this->user, $selectedRoles, $loggedUser); + $this->applicationService->updateRoles($this->user, $selectedRoles, $loggedUser); $this->user->setApproved($values['approved']); $this->user->setAttended($values['attended']); diff --git a/app/AdminModule/presenters/UsersPresenter.php b/app/AdminModule/presenters/UsersPresenter.php index 87c2054c6..4ea792924 100644 --- a/app/AdminModule/presenters/UsersPresenter.php +++ b/app/AdminModule/presenters/UsersPresenter.php @@ -10,6 +10,7 @@ use App\Model\ACL\Permission; use App\Model\ACL\Resource; use App\Model\ACL\Role; +use App\Model\Enums\ApplicationState; use App\Model\Enums\PaymentType; use App\Model\Settings\CustomInput\CustomInput; use App\Model\Settings\CustomInput\CustomInputRepository; @@ -186,7 +187,7 @@ public function handleCancelRegistration() $user = $this->userRepository->findById($this->getParameter('id')); $loggedUser = $this->userRepository->findById($this->user->id); - $this->applicationService->cancelRegistration($user, $loggedUser); + $this->applicationService->cancelRegistration($user, ApplicationState::CANCELED, $loggedUser); $this->flashMessage('admin.users.users_registration_canceled', 'success'); $this->redirect('this'); diff --git a/app/WebModule/components/ApplicationsGridControl.php b/app/WebModule/components/ApplicationsGridControl.php index 11ccc0677..6fa6cec9f 100644 --- a/app/WebModule/components/ApplicationsGridControl.php +++ b/app/WebModule/components/ApplicationsGridControl.php @@ -196,6 +196,7 @@ public function createComponentApplicationsGrid($name) return $this->applicationService->getStateText($row); }); + if ($explicitSubeventsExists) { if ($this->applicationService->isAllowedAddApplication($this->user)) { $grid->addInlineAdd()->onControlAdd[] = function ($container) { @@ -222,10 +223,11 @@ public function createComponentApplicationsGrid($name) }; $grid->getInlineEdit()->onSubmit[] = [$this, 'edit']; $grid->allowRowsInlineEdit(function(Application $item) { - return $item->getType() == Application::SUBEVENTS; + return $this->applicationService->isAllowedEditApplication($item); }); } + $grid->addAction('generatePaymentProofBank', 'web.profile.applications_download_payment_proof'); $grid->allowRowsAction('generatePaymentProofBank', function (Application $item) { return $item->getState() == ApplicationState::PAID @@ -239,9 +241,10 @@ public function createComponentApplicationsGrid($name) 'data-content' => $this->translator->translate('web.profile.applications_cancel_application_confirm') ])->setClass('btn btn-xs btn-danger'); $grid->allowRowsAction('cancelApplication', function (Application $item) { - return $item->getType() == Application::SUBEVENTS; + return $this->applicationService->isAllowedEditApplication($item); }); + $grid->setColumnsSummary(['fee'], function(Application $item, $column) { return $item->isCanceled() ? 0 : $item->getFee(); }); @@ -256,69 +259,37 @@ public function createComponentApplicationsGrid($name) */ public function add($values) { -// $selectedSubevents = $this->subeventRepository->findSubeventsByIds($values['subevents']); -// $selectedAndUsersSubevents = $this->user->getSubevents(); -// foreach ($selectedSubevents as $subevent) -// $selectedAndUsersSubevents->add($subevent); -// -// //kontrola podakci -// if (!$this->validators->validateSubeventsEmpty($selectedSubevents)) { -// $this->getPresenter()->flashMessage('web.profile.applications_subevents_empty', 'danger'); -// $this->redirect('this'); -// } -// -// if (!$this->validators->validateSubeventsCapacities($selectedSubevents, $this->user)) { -// $this->getPresenter()->flashMessage('web.profile.applications_subevents_capacity_occupied', 'danger'); -// $this->redirect('this'); -// } -// -// foreach ($this->subeventRepository->findAllExplicitOrderedByName() as $subevent) { -// if (!$this->validators->validateSubeventsIncompatible($selectedAndUsersSubevents, $subevent)) { -// $message = $this->translator->translate('web.profile.applications_incompatible_subevents_selected', NULL, -// ['subevent' => $subevent->getName(), 'incompatibleSubevents' => $subevent->getIncompatibleSubeventsText()] -// ); -// $this->getPresenter()->flashMessage($message, 'danger'); -// $this->redirect('this'); -// } -// if (!$this->validators->validateSubeventsRequired($selectedAndUsersSubevents, $subevent)) { -// $message = $this->translator->translate('web.profile.applications_required_subevents_not_selected', NULL, -// ['subevent' => $subevent->getName(), 'requiredSubevents' => $subevent->getRequiredSubeventsTransitiveText()] -// ); -// $this->getPresenter()->flashMessage($message, 'danger'); -// $this->redirect('this'); -// } -// } -// -// //zpracovani zmen -// $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($selectedSubevents) { -// $application = new Application(); -// $fee = $this->applicationService->countFee($this->user->getRoles(), $selectedSubevents, FALSE); -// $application->setUser($this->user); -// $application->setSubevents($selectedSubevents); -// $application->setApplicationDate(new \DateTime()); -// $application->setMaturityDate($this->applicationService->countMaturityDate()); -// $application->setFee($fee); -// $application->setState($fee == 0 ? ApplicationState::PAID : ApplicationState::WAITING_FOR_PAYMENT); -// $application->setFirst(FALSE); -// $this->applicationRepository->save($application); -// -// $application->setVariableSymbol($this->applicationService->generateVariableSymbol($application)); -// $this->applicationRepository->save($application); -// -// $this->user->addApplication($application); -// $this->userRepository->save($this->user); -// -// $this->programService->updateUserPrograms($this->user); -// -// //zaslani potvrzovaciho e-mailu -// $this->mailService->sendMailFromTemplate($this->user, '', Template::SUBEVENT_ADDED, [ -// TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), -// TemplateVariable::USERS_SUBEVENTS => $this->user->getSubeventsText() -// ]); -// }); -// -// $this->getPresenter()->flashMessage('web.profile.applications_add_subevents_successful', 'success'); -// $this->redirect('this'); + $selectedSubevents = $this->subeventRepository->findSubeventsByIds($values['subevents']); + $selectedAndUsersSubevents = clone $this->user->getSubevents(); + foreach ($selectedSubevents as $subevent) + $selectedAndUsersSubevents->add($subevent); + + if (!$this->validators->validateSubeventsCapacities($selectedSubevents, $this->user)) { + $this->getPresenter()->flashMessage('web.profile.applications_subevents_capacity_occupied', 'danger'); + $this->redirect('this'); + } + + foreach ($this->subeventRepository->findAllExplicitOrderedByName() as $subevent) { + if (!$this->validators->validateSubeventsIncompatible($selectedAndUsersSubevents, $subevent)) { + $message = $this->translator->translate('web.profile.applications_incompatible_subevents_selected', NULL, + ['subevent' => $subevent->getName(), 'incompatibleSubevents' => $subevent->getIncompatibleSubeventsText()] + ); + $this->getPresenter()->flashMessage($message, 'danger'); + $this->redirect('this'); + } + if (!$this->validators->validateSubeventsRequired($selectedAndUsersSubevents, $subevent)) { + $message = $this->translator->translate('web.profile.applications_required_subevents_not_selected', NULL, + ['subevent' => $subevent->getName(), 'requiredSubevents' => $subevent->getRequiredSubeventsTransitiveText()] + ); + $this->getPresenter()->flashMessage($message, 'danger'); + $this->redirect('this'); + } + } + + $this->applicationService->addSubeventsApplication($this->user, $selectedSubevents, $this->user); + + $this->getPresenter()->flashMessage('web.profile.applications_add_subevents_successful', 'success'); + $this->redirect('this'); } /** @@ -331,147 +302,52 @@ public function add($values) */ public function edit($id, $values) { -// $selectedRoles = $this->roleRepository->findRolesByIds($values['roles']); -// -// //kontrola roli -// if (!$this->validateRolesCapacities($selectedRoles)) { -// $this->getPresenter()->flashMessage('web.profile.applications_roles_capacity_occupied', 'danger'); -// $this->redirect('this'); -// } -// -// if (!$this->validateRolesRegisterable($selectedRoles)) { -// $this->getPresenter()->flashMessage('web.profile.applications_role_is_not_registerable', 'danger'); -// $this->redirect('this'); -// } -// -// foreach ($this->roleRepository->findAllRegisterableNowOrUsersOrderedByName($this->user) as $role) { -// $incompatibleRoles = $role->getIncompatibleRoles(); -// if (count($incompatibleRoles) > 0 && !$this->validateRolesIncompatible($selectedRoles, $role)) { -// $messageThis = $role->getName(); -// -// $incompatibleRolesNames = []; -// foreach ($incompatibleRoles as $incompatibleRole) { -// $incompatibleRolesNames[] = $incompatibleRole->getName(); -// } -// $messageOthers = implode(', ', $incompatibleRolesNames); -// -// $message = $this->translator->translate('web.profile.applications_incompatible_roles_selected', NULL, -// ['role' => $messageThis, 'incompatibleRoles' => $messageOthers] -// ); -// $this->getPresenter()->flashMessage($message, 'danger'); -// $this->redirect('this'); -// } -// -// $requiredRoles = $role->getRequiredRolesTransitive(); -// if (count($requiredRoles) > 0 && !$this->validateRolesRequired($selectedRoles, $role)) { -// $messageThis = $role->getName(); -// -// $requiredRolesNames = []; -// foreach ($requiredRoles as $requiredRole) { -// $requiredRolesNames[] = $requiredRole->getName(); -// } -// $messageOthers = implode(', ', $requiredRolesNames); -// -// $message = $this->translator->translate('web.profile.applications_required_roles_not_selected', NULL, -// ['role' => $messageThis, 'requiredRoles' => $messageOthers] -// ); -// $this->getPresenter()->flashMessage($message, 'danger'); -// $this->redirect('this'); -// } -// } -// -// -// if ($this->subeventRepository->explicitSubeventsExists()) { -// $selectedSubevents = $this->subeventRepository->findSubeventsByIds($values['subevents']); -// -// //kontrola podakci -// if (!$this->validateSubeventsEmpty($selectedSubevents)) { -// $this->getPresenter()->flashMessage('web.profile.applications_subevents_empty', 'danger'); -// $this->redirect('this'); -// } -// -// if (!$this->validateSubeventsCapacities($selectedSubevents)) { -// $this->getPresenter()->flashMessage('web.profile.applications_subevents_capacity_occupied', 'danger'); -// $this->redirect('this'); -// } -// -// foreach ($this->subeventRepository->findAllExplicitOrderedByName() as $subevent) { -// $incompatibleSubevents = $subevent->getIncompatibleSubevents(); -// if (count($incompatibleSubevents) > 0 && !$this->validateSubeventsIncompatible($selectedSubevents, $subevent)) { -// $messageThis = $subevent->getName(); -// -// $incompatibleSubeventsNames = []; -// foreach ($incompatibleSubevents as $incompatibleSubevent) { -// $incompatibleSubeventsNames[] = $incompatibleSubevent->getName(); -// } -// $messageOthers = implode(', ', $incompatibleSubeventsNames); -// -// $message = $this->translator->translate('web.profile.applications_incompatible_subevents_selected', NULL, -// ['subevent' => $messageThis, 'incompatibleSubevents' => $messageOthers] -// ); -// $this->getPresenter()->flashMessage($message, 'danger'); -// $this->redirect('this'); -// } -// -// $requiredSubevents = $subevent->getRequiredSubeventsTransitive(); -// if (count($requiredSubevents) > 0 && !$this->validateSubeventsRequired($selectedSubevents, $subevent)) { -// $messageThis = $subevent->getName(); -// -// $requiredSubeventsNames = []; -// foreach ($requiredSubevents as $requiredSubevent) { -// $requiredSubeventsNames[] = $requiredSubevent->getName(); -// } -// $messageOthers = implode(', ', $requiredSubeventsNames); -// -// $message = $this->translator->translate('web.profile.applications_required_subevents_not_selected', NULL, -// ['subevent' => $messageThis, 'requiredSubevents' => $messageOthers] -// ); -// $this->getPresenter()->flashMessage($message, 'danger'); -// $this->redirect('this'); -// } -// } -// } -// -// //zpracovani zmen -// $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($id, $selectedRoles, $selectedSubevents, $values) { -// $application = $this->applicationRepository->findById($id); -// -// if ($this->subeventRepository->explicitSubeventsExists() && !empty($values['subevents'])) -// $application->setSubevents($selectedSubevents); -// else -// $application->setSubevents(new ArrayCollection([$this->subeventRepository->findImplicit()])); -// -// $this->userService->changeRoles($this->user, $selectedRoles); -// -// $this->programService->updateUserPrograms($this->user); -// -// //zaslani potvrzovaciho e-mailu -// $subeventsNames = []; -// foreach ($this->user->getSubevents() as $subevent) { -// $subeventsNames[] = $subevent->getName(); -// } -// -// $this->mailService->sendMailFromTemplate($this->user, '', Template::SUBEVENTS_CHANGED, [ -// TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), -// TemplateVariable::USERS_SUBEVENTS => implode(', ', $subeventsNames) -// ]); -// -// $this->authenticator->updateRoles($this->getPresenter()->getUser()); -// }); -// -// $this->getPresenter()->flashMessage('web.profile.applications_edit_successful', 'success'); -// $this->redirect('this'); + $application = $this->applicationRepository->findById($id); + + $selectedSubevents = $this->subeventRepository->findSubeventsByIds($values['subevents']); + $selectedAndUsersSubevents = clone $this->user->getSubevents(); + foreach ($selectedSubevents as $subevent) + $selectedAndUsersSubevents->add($subevent); + + if (!$this->validators->validateSubeventsCapacities($selectedSubevents, $this->user)) { + $this->getPresenter()->flashMessage('web.profile.applications_subevents_capacity_occupied', 'danger'); + $this->redirect('this'); + } + + foreach ($this->subeventRepository->findAllExplicitOrderedByName() as $subevent) { + if (!$this->validators->validateSubeventsIncompatible($selectedAndUsersSubevents, $subevent)) { + $message = $this->translator->translate('web.profile.applications_incompatible_subevents_selected', NULL, + ['subevent' => $subevent->getName(), 'incompatibleSubevents' => $subevent->getIncompatibleSubeventsText()] + ); + $this->getPresenter()->flashMessage($message, 'danger'); + $this->redirect('this'); + } + if (!$this->validators->validateSubeventsRequired($selectedAndUsersSubevents, $subevent)) { + $message = $this->translator->translate('web.profile.applications_required_subevents_not_selected', NULL, + ['subevent' => $subevent->getName(), 'requiredSubevents' => $subevent->getRequiredSubeventsTransitiveText()] + ); + $this->getPresenter()->flashMessage($message, 'danger'); + $this->redirect('this'); + } + } + + $this->applicationService->updateSubeventsApplication($application, $selectedSubevents, $this->user); + + $this->getPresenter()->flashMessage('web.profile.applications_edit_successful', 'success'); + $this->redirect('this'); } /** * Vygeneruje potvrzení o přijetí platby. * @param $id + * @throws \App\Model\Settings\SettingsException + * @throws \Throwable */ public function handleGeneratePaymentProofBank($id) { $this->pdfExportService->generateApplicationsPaymentProof( - $this->applicationRepository->findById($id), - "potvrzeni-o-prijeti-platby.pdf" + $this->applicationRepository->findById($id), "potvrzeni-o-prijeti-platby.pdf", + $this->userRepository->findById($this->getPresenter()->getUser()->id) ); } @@ -484,22 +360,14 @@ public function handleGeneratePaymentProofBank($id) */ public function handleCancelApplication($id) { -// $application = $this->applicationRepository->findById($id); -// -// if ($this->applicationService->isAllowedCancelApplication($application)) { -// $user = $application->getUser(); -// -// $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($application, $user) { -// $application->setState(ApplicationState::CANCELED); -// $this->applicationRepository->save($application); -// -// $this->programService->updateUserPrograms($user); -// }); -// -// $this->getPresenter()->flashMessage('web.profile.applications_application_canceled', 'success'); -// } -// -// $this->redirect('this'); + $application = $this->applicationRepository->findById($id); + + if ($this->applicationService->isAllowedEditApplication($application)) { + $this->applicationService->cancelSubeventsApplication($application, ApplicationState::CANCELED, $application->getUser()); + $this->getPresenter()->flashMessage('web.profile.applications_application_canceled', 'success'); + } + + $this->redirect('this'); } } diff --git a/app/WebModule/forms/RolesForm.php b/app/WebModule/forms/RolesForm.php index 15a6f9d21..733327f74 100644 --- a/app/WebModule/forms/RolesForm.php +++ b/app/WebModule/forms/RolesForm.php @@ -4,6 +4,7 @@ use App\Model\ACL\Role; use App\Model\ACL\RoleRepository; +use App\Model\Enums\ApplicationState; use App\Model\Program\ProgramRepository; use App\Model\User\User; use App\Model\User\UserRepository; @@ -142,19 +143,10 @@ public function processForm(Form $form, \stdClass $values) { if ($form['submit']->isSubmittedBy()) { $selectedRoles = $this->roleRepository->findRolesByIds($values['roles']); - - if ($selectedRoles->count() == $this->user->getRoles()->count()) { - $selectedRolesArray = $selectedRoles->map(function (Role $role) {return $role->getId();})->toArray(); - $usersRolesArray = $this->user->getRoles()->map(function (Role $role) {return $role->getId();})->toArray(); - - if (array_diff($selectedRolesArray, $usersRolesArray) === array_diff($usersRolesArray, $selectedRolesArray)) - return; - } - $this->applicationService->updateRoles($this->user, $selectedRoles, $this->user); } elseif ($form['cancelRegistration']->isSubmittedBy()) { - $this->applicationService->cancelRegistration($this->user, $this->user); + $this->applicationService->cancelRegistration($this->user, ApplicationState::CANCELED, $this->user); } } @@ -163,7 +155,6 @@ public function processForm(Form $form, \stdClass $values) * @param $field * @param $args * @return bool - * @throws \Doctrine\ORM\NonUniqueResultException */ public function validateRolesCapacities($field, $args) { diff --git a/app/lang/common.cs_CZ.neon b/app/lang/common.cs_CZ.neon index 7dd1dff2b..bc72306fe 100644 --- a/app/lang/common.cs_CZ.neon +++ b/app/lang/common.cs_CZ.neon @@ -185,8 +185,8 @@ mailing: sign_in: "Potvrzení přihlášení se přes skautIS" registration: "Potvrzení registrace" registration_canceled: "Potvrzení zrušení registrace" - registration_changed: "Potvrzení změny registrace" - subevent_added: "Potvrzení přidání podakcí" + roles_changed: "Potvrzení změny rolí" + subevents_changed: "Potvrzení změny podakcí" payment_confirmed: "Potvrzení přijetí platby" maturity_reminder: "Připomínka splatnosti" program_registered: "Přihlášení na program" diff --git a/app/model/ACL/Role.php b/app/model/ACL/Role.php index b2538b593..6fe1ff034 100644 --- a/app/model/ACL/Role.php +++ b/app/model/ACL/Role.php @@ -6,6 +6,7 @@ use App\Model\Program\Category; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\Mapping as ORM; use Kdyby\Doctrine\Entities\Attributes\Identifier; @@ -276,6 +277,15 @@ public function getUsers(): Collection return $this->users; } + /** + * @return Collection + */ + public function getApprovedUsers(): Collection + { + $criteria = Criteria::create()->where(Criteria::expr()->eq('approved', TRUE)); + return $this->users->matching($criteria); + } + /** * @return Collection */ @@ -684,6 +694,11 @@ public function countUsers(): int return $this->users->count(); } + public function countApprovedUsers(): int + { + return $this->getApprovedUsers()->count(); + } + /** * @return int|null */ diff --git a/app/model/ACL/RoleRepository.php b/app/model/ACL/RoleRepository.php index 03612be07..b51be592f 100644 --- a/app/model/ACL/RoleRepository.php +++ b/app/model/ACL/RoleRepository.php @@ -376,7 +376,7 @@ public function getRolesWithoutRolesOptionsWithCapacity(array $withoutRoles) : a * @return array * @throws \Doctrine\ORM\NonUniqueResultException */ - public function getRolesWithoutRolesOptionsWithUsersCount(array $withoutRoles) : array + public function getRolesWithoutRolesOptionsWithApprovedUsersCount(array $withoutRoles) : array { if (empty($withoutRoles)) $roles = $this->createQueryBuilder('r') diff --git a/app/model/Mailing/Template.php b/app/model/Mailing/Template.php index ee1e5214b..252a2d7c6 100644 --- a/app/model/Mailing/Template.php +++ b/app/model/Mailing/Template.php @@ -33,9 +33,14 @@ class Template const REGISTRATION_CANCELED = 'registration_canceled'; /** - * Potvrzení přidání podakcí. + * Potvrzení změny rolí. */ - const SUBEVENT_ADDED = 'subevent_added'; + const ROLES_CHANGED = 'roles_changed'; + + /** + * Potvrzení změny podakcí. + */ + const SUBEVENTS_CHANGED = 'subevents_changed'; /** * Potvrzení přijetí platby. @@ -67,16 +72,6 @@ class Template */ const CUSTOM_INPUT_VALUE_CHANGED = 'custom_input_value_changed'; - /** - * Potvrzení změny rolí. - */ - const ROLES_CHANGED = 'roles_changed'; - - /** - * Potvrzení změny podakcí. - */ - const SUBEVENTS_CHANGED = 'subevents_changed'; - use Identifier; diff --git a/app/model/User/Application/Application.php b/app/model/User/Application/Application.php index b823b80b5..a74771add 100644 --- a/app/model/User/Application/Application.php +++ b/app/model/User/Application/Application.php @@ -180,6 +180,26 @@ public function setUser($user) $this->user = $user; } + public function getRoles(): Collection + { + return new ArrayCollection(); + } + + public function getRolesText(): ?string + { + return NULL; + } + + public function getSubevents(): Collection + { + return new ArrayCollection(); + } + + public function getSubeventsText(): ?string + { + return NULL; + } + /** * @return int */ diff --git a/app/model/User/Application/ApplicationRepository.php b/app/model/User/Application/ApplicationRepository.php index 24b30db40..1e9311007 100644 --- a/app/model/User/Application/ApplicationRepository.php +++ b/app/model/User/Application/ApplicationRepository.php @@ -3,6 +3,8 @@ namespace App\Model\User; use App\Model\Enums\ApplicationState; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Kdyby\Doctrine\EntityRepository; @@ -23,19 +25,6 @@ public function findById($id) return $this->findOneBy(['id' => $id]); } - /** - * Vrací přihlášky čekající na platbu. - * @return Application[] - */ - public function findWaitingForPaymentApplications() - { - return $this->createQueryBuilder('a') - ->where('a.state = :state')->setParameter('state', ApplicationState::WAITING_FOR_PAYMENT) - ->andWhere('a.validTo IS NULL') - ->getQuery() - ->getResult(); - } - /** * Uloží přihlášku. * @param Application $application diff --git a/app/model/User/Application/RolesApplication.php b/app/model/User/Application/RolesApplication.php index b91ed6137..a79e9fc73 100644 --- a/app/model/User/Application/RolesApplication.php +++ b/app/model/User/Application/RolesApplication.php @@ -55,13 +55,8 @@ public function setRoles(Collection $roles): void * Vrací názvy rolí oddělené čárkou. * @return string */ - public function getRolesText() : string + public function getRolesText(): ?string { return implode(', ', $this->roles->map(function (Role $role) {return $role->getName();})->toArray()); } - - public function getSubeventsText(): ?string - { - return NULL; - } } diff --git a/app/model/User/Application/RolesApplicationRepository.php b/app/model/User/Application/RolesApplicationRepository.php index 8c92bde35..7365c314f 100644 --- a/app/model/User/Application/RolesApplicationRepository.php +++ b/app/model/User/Application/RolesApplicationRepository.php @@ -2,6 +2,9 @@ namespace App\Model\User; +use App\Model\Enums\ApplicationState; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Kdyby\Doctrine\EntityRepository; diff --git a/app/model/User/Application/SubeventsApplication.php b/app/model/User/Application/SubeventsApplication.php index 6b82937b8..6724bd1cd 100644 --- a/app/model/User/Application/SubeventsApplication.php +++ b/app/model/User/Application/SubeventsApplication.php @@ -55,13 +55,8 @@ public function setSubevents(Collection $subevents): void * Vrací názvy podakcí oddělené čárkou. * @return string */ - public function getSubeventsText() : string + public function getSubeventsText(): ?string { return implode(', ', $this->subevents->map(function (Subevent $subevent) {return $subevent->getName();})->toArray()); } - - public function getRolesText(): ?string - { - return NULL; - } } diff --git a/app/model/User/Application/SubeventsApplicationRepository.php b/app/model/User/Application/SubeventsApplicationRepository.php index 7a98d2f3a..32ea16dce 100644 --- a/app/model/User/Application/SubeventsApplicationRepository.php +++ b/app/model/User/Application/SubeventsApplicationRepository.php @@ -2,6 +2,9 @@ namespace App\Model\User; +use App\Model\Enums\ApplicationState; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Kdyby\Doctrine\EntityRepository; diff --git a/app/model/User/User.php b/app/model/User/User.php index 861ca8c70..ce6956938 100644 --- a/app/model/User/User.php +++ b/app/model/User/User.php @@ -532,9 +532,9 @@ public function getPaidAndFreeApplications(): Collection /** * Vrátí přihlášky čekající na platbu. - * @return Collection + * @return Collection|Application[] */ - public function getWaitingForPaymentApplications() + public function getWaitingForPaymentApplications(): Collection { $criteria = Criteria::create() ->where(Criteria::expr()->andX( @@ -545,6 +545,28 @@ public function getWaitingForPaymentApplications() return $this->applications->matching($criteria); } + /** + * Vrátí přihlášky rolí čekající na platbu. + * @return Collection|RolesApplication[] + */ + public function getWaitingForPaymentRolesApplications(): Collection + { + return $this->getWaitingForPaymentApplications()->filter(function (Application $application) { + return $application->getType() == Application::ROLES; + }); + } + + /** + * Vrátí přihlášky podakcí čekající na platbu. + * @return Collection|SubeventsApplication[] + */ + public function getWaitingForPaymentSubeventsApplications(): Collection + { + return $this->getWaitingForPaymentApplications()->filter(function (Application $application) { + return $application->getType() == Application::SUBEVENTS; + }); + } + /** * @param Collection $applications */ diff --git a/app/model/User/UserRepository.php b/app/model/User/UserRepository.php index 69109835a..cecb5d5b7 100644 --- a/app/model/User/UserRepository.php +++ b/app/model/User/UserRepository.php @@ -44,9 +44,9 @@ public function findBySkautISUserId($skautISUserId) /** * Vrací uživatele podle id. * @param $ids - * @return \Doctrine\Common\Collections\Collection + * @return Collection|User[] */ - public function findUsersByIds($ids) + public function findUsersByIds($ids): Collection { $criteria = Criteria::create() ->where(Criteria::expr()->in('id', $ids)); @@ -77,6 +77,7 @@ public function findAllSyncedWithSkautIS() return $this->createQueryBuilder('u') ->join('u.roles', 'r') ->where('r.syncedWithSkautIS = true') + ->andWhere('u.external = false') ->getQuery() ->getResult(); } @@ -106,41 +107,41 @@ public function findAllInRoles($rolesIds) ->join('u.roles', 'r') ->where('r.id IN (:ids)')->setParameter('ids', $rolesIds) ->orderBy('u.displayName') - ->distinct() ->getQuery() ->getResult(); } /** - * Vrací schválené uživatele v roli. - * @param $systemName + * Vrací schválené uživatele v rolích. + * @param $rolesIds * @return mixed */ - public function findAllApprovedInRole($systemName) + public function findAllApprovedInRoles($rolesIds) { return $this->createQueryBuilder('u') ->join('u.roles', 'r') - ->where('r.systemName = :name')->setParameter('name', $systemName) + ->where('r.id IN (:ids)')->setParameter('ids', $rolesIds) ->andWhere('u.approved = true') ->orderBy('u.displayName') - ->getQuery()->execute(); + ->getQuery() + ->getResult(); } /** - * Vrací schválené uživatele v rolích. - * @param $rolesIds - * @return mixed + * Vrací uživatele s přihláškou čekající na zaplacení. + * @return Collection|User[] */ - public function findAllApprovedInRoles($rolesIds) + public function findAllWithWaitingForPaymentApplication(): Collection { - return $this->createQueryBuilder('u') - ->join('u.roles', 'r') - ->where('r.id IN (:ids)')->setParameter('ids', $rolesIds) - ->andWhere('u.approved = true') - ->orderBy('u.displayName') - ->distinct() + $result = $this->createQueryBuilder('u') + ->join('u.applications', 'a') + ->where('a.validTo IS NULL') + ->andWhere('a.state = :state') + ->setParameter('state', ApplicationState::WAITING_FOR_PAYMENT) ->getQuery() ->getResult(); + + return new ArrayCollection($result); } /** @@ -158,6 +159,7 @@ public function findProgramAllowed(Program $program) ->innerJoin('a.subevents', 's') ->where('per.name = :permission') ->andWhere('s.id = :sid') + ->andWhere('a.validTo IS NULL') ->andWhere('(a.state = \'' . ApplicationState::PAID . '\' OR a.state = \'' . ApplicationState::PAID_FREE . '\' OR a.state = \'' . ApplicationState::WAITING_FOR_PAYMENT . '\')') ->setParameter('pid', $program->getId()) diff --git a/app/services/ApplicationService.php b/app/services/ApplicationService.php index 04f06d407..dc88edf9b 100644 --- a/app/services/ApplicationService.php +++ b/app/services/ApplicationService.php @@ -9,6 +9,7 @@ use App\Model\Mailing\Template; use App\Model\Mailing\TemplateVariable; use App\Model\Settings\Settings; +use App\Model\Settings\SettingsException; use App\Model\Settings\SettingsRepository; use App\Model\Structure\DiscountRepository; use App\Model\Structure\Subevent; @@ -25,6 +26,8 @@ use Doctrine\Common\Collections\Collection; use Kdyby\Translation\Translator; use Nette; +use Ublaboo\Mailing\Exception\MailingException; +use Ublaboo\Mailing\Exception\MailingMailCreationException; /** @@ -110,57 +113,71 @@ public function __construct(SettingsRepository $settingsRepository, ApplicationR public function register(User $user, Collection $roles, Collection $subevents, User $createdBy, bool $approve = FALSE): void { - $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($user, $roles, $subevents, $createdBy, $approve) { + $rolesApplication = new RolesApplication(); + $subeventsApplication = new SubeventsApplication(); + + $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($user, $roles, $subevents, $createdBy, $approve, &$rolesApplication, &$subeventsApplication) { $rolesApplication = $this->createRolesApplication($user, $roles, $createdBy, $approve); $subeventsApplication = $this->createSubeventsApplication($user, $subevents, $createdBy); $this->programService->updateUserPrograms($user); + }); - $applicatonMaturity = "-"; - $applicationFee = "0"; - $applicationVariableSymbol = "-"; - - if ($rolesApplication->getFee() > 0 && $subeventsApplication->getFee() > 0) { - if ($rolesApplication->getMaturityDate()) - $applicatonMaturity = $rolesApplication->getMaturityDateText(); - $applicationFee = $rolesApplication->getFee() . ", " . $subeventsApplication->getFee(); - $applicationVariableSymbol = $rolesApplication->getVariableSymbolText() . ", " . $subeventsApplication->getVariableSymbolText(); - } elseif ($rolesApplication->getFee() > 0) { - if ($rolesApplication->getMaturityDate()) - $applicatonMaturity = $rolesApplication->getMaturityDateText(); - $applicationFee = $rolesApplication->getFee(); - $applicationVariableSymbol = $rolesApplication->getVariableSymbolText(); - } elseif ($subeventsApplication->getFee() > 0) { - if ($subeventsApplication->getMaturityDate()) - $applicatonMaturity = $subeventsApplication->getMaturityDateText(); - $applicationFee = $subeventsApplication->getFee(); - $applicationVariableSymbol = $subeventsApplication->getVariableSymbolText(); - } + $applicatonMaturity = "-"; + $applicationFee = "0"; + $applicationVariableSymbol = "-"; + + if ($rolesApplication->getFee() > 0 && $subeventsApplication->getFee() > 0) { + if ($rolesApplication->getMaturityDate()) + $applicatonMaturity = $rolesApplication->getMaturityDateText(); + $applicationFee = $rolesApplication->getFee() . ", " . $subeventsApplication->getFee(); + $applicationVariableSymbol = $rolesApplication->getVariableSymbolText() . ", " + . $subeventsApplication->getVariableSymbolText(); + } elseif ($rolesApplication->getFee() > 0) { + if ($rolesApplication->getMaturityDate()) + $applicatonMaturity = $rolesApplication->getMaturityDateText(); + $applicationFee = $rolesApplication->getFee(); + $applicationVariableSymbol = $rolesApplication->getVariableSymbolText(); + } elseif ($subeventsApplication->getFee() > 0) { + if ($subeventsApplication->getMaturityDate()) + $applicatonMaturity = $subeventsApplication->getMaturityDateText(); + $applicationFee = $subeventsApplication->getFee(); + $applicationVariableSymbol = $subeventsApplication->getVariableSymbolText(); + } - $editRegistrationToText = $this->settingsRepository->getDateValueText(Settings::EDIT_REGISTRATION_TO); + $editRegistrationToText = $this->settingsRepository->getDateValueText(Settings::EDIT_REGISTRATION_TO); - $this->mailService->sendMailFromTemplate($user, '', Template::REGISTRATION, [ - TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), - TemplateVariable::EDIT_REGISTRATION_TO => $editRegistrationToText !== NULL ? $editRegistrationToText : '-', - TemplateVariable::APPLICATION_MATURITY => $applicatonMaturity, - TemplateVariable::APPLICATION_FEE => $applicationFee, - TemplateVariable::APPLICATION_VARIABLE_SYMBOL => $applicationVariableSymbol, - TemplateVariable::BANK_ACCOUNT => $this->settingsRepository->getValue(Settings::ACCOUNT_NUMBER) - ]); - }); + $this->mailService->sendMailFromTemplate($user, '', Template::REGISTRATION, [ + TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), + TemplateVariable::EDIT_REGISTRATION_TO => $editRegistrationToText !== NULL ? $editRegistrationToText : '-', + TemplateVariable::APPLICATION_MATURITY => $applicatonMaturity, + TemplateVariable::APPLICATION_FEE => $applicationFee, + TemplateVariable::APPLICATION_VARIABLE_SYMBOL => $applicationVariableSymbol, + TemplateVariable::BANK_ACCOUNT => $this->settingsRepository->getValue(Settings::ACCOUNT_NUMBER) + ]); } /** * @param User $user * @param Collection $roles * @param User $createdBy + * @return bool * @throws \Throwable */ public function updateRoles(User $user, Collection $roles, User $createdBy, bool $approve = FALSE): void { - $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($user, $roles, $createdBy, $approve) { - $oldRoles = clone $user->getRoles(); + $oldRoles = clone $user->getRoles(); + + //pokud se role nezmenily, nic se neprovede + if ($roles->count() == $oldRoles->count()) { + $rolesArray = $roles->map(function (Role $role) {return $role->getId();})->toArray(); + $oldRolesArray = $oldRoles->map(function (Role $role) {return $role->getId();})->toArray(); + + if (array_diff($rolesArray, $oldRolesArray) === array_diff($oldRolesArray, $rolesArray)) + return; + } + $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($user, $roles, $createdBy, $approve, $oldRoles) { $user->setRoles($roles); $this->userRepository->save($user); @@ -215,13 +232,12 @@ public function updateRoles(User $user, Collection $roles, User $createdBy, bool } $this->programService->updateUserPrograms($user); - - //TODO mail -// $this->mailService->sendMailFromTemplate($user, '', Template::ROLES_CHANGED, [ -// TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), -// TemplateVariable::USERS_ROLES => implode(', ', $roles->map(function (Role $role) {return $role->getName();})->toArray()) -// ]); }); + + $this->mailService->sendMailFromTemplate($user, '', Template::ROLES_CHANGED, [ + TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), + TemplateVariable::USERS_ROLES => implode(', ', $roles->map(function (Role $role) {return $role->getName();})->toArray()) + ]); } /** @@ -229,9 +245,9 @@ public function updateRoles(User $user, Collection $roles, User $createdBy, bool * @param User $createdBy * @throws \Throwable */ - public function cancelRegistration(User $user, User $createdBy): void + public function cancelRegistration(User $user, string $state, User $createdBy): void { - $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($user, $createdBy) { + $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($user, $state, $createdBy) { $user->setApproved(TRUE); $user->getRoles()->clear(); $user->addRole($this->roleRepository->findBySystemName(Role::NONREGISTERED)); @@ -239,7 +255,7 @@ public function cancelRegistration(User $user, User $createdBy): void foreach ($user->getNotCanceledApplications() as $application) { $newApplication = clone $application; - $newApplication->setState(ApplicationState::CANCELED); + $newApplication->setState($state); $newApplication->setCreatedBy($createdBy); $newApplication->setValidFrom(new \DateTime()); $this->applicationRepository->save($newApplication); @@ -251,13 +267,11 @@ public function cancelRegistration(User $user, User $createdBy): void $this->userRepository->save($user); $this->programService->updateUserPrograms($user); - - //TODO mail -// $this->mailService->sendMailFromTemplate($user, '', Template::REGISTRATION_CANCELED, [ -// TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), -// TemplateVariable::USERS_ROLES => implode(', ', $roles->map(function (Role $role) {return $role->getName();})->toArray()) -// ]); }); + + $this->mailService->sendMailFromTemplate($user, '', Template::REGISTRATION_CANCELED, [ + TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME) + ]); } /** @@ -269,8 +283,15 @@ public function cancelRegistration(User $user, User $createdBy): void public function addSubeventsApplication(User $user, Collection $subevents, User $createdBy): void { $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($user, $subevents, $createdBy) { - //TODO + $this->createSubeventsApplication($user, $subevents, $createdBy); + + $this->programService->updateUserPrograms($user); }); + + $this->mailService->sendMailFromTemplate($user, '', Template::SUBEVENTS_CHANGED, [ + TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), + TemplateVariable::USERS_SUBEVENTS => $user->getSubeventsText() + ]); } /** @@ -279,11 +300,43 @@ public function addSubeventsApplication(User $user, Collection $subevents, User * @param User $createdBy * @throws \Throwable */ - public function updateSubeventsApplication(Application $application, Collection $subevents, User $createdBy): void + public function updateSubeventsApplication(SubeventsApplication $application, Collection $subevents, User $createdBy): void { + $oldSubevents = clone $application->getSubevents(); + + //pokud se podakce nezmenily, nic se neprovede + if ($subevents->count() == $oldSubevents->count()) { + $subeventsArray = $subevents->map(function (Role $role) {return $role->getId();})->toArray(); + $oldSubeventsArray = $oldSubevents->map(function (Role $role) {return $role->getId();})->toArray(); + + if (array_diff($subeventsArray, $oldSubeventsArray) === array_diff($oldSubeventsArray, $subeventsArray)) + return; + } + $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($application, $subevents, $createdBy) { - //TODO + $user = $application->getUser(); + + $newApplication = clone $application; + $newApplication->setSubevents($subevents); + $newApplication->setFee($this->countSubeventsFee($user->getRoles(), $subevents)); + $newApplication->setState($this->getApplicationState($newApplication)); + $newApplication->setCreatedBy($createdBy); + $newApplication->setValidFrom(new \DateTime()); + $this->applicationRepository->save($newApplication); + + $application->setValidTo(new \DateTime()); + $this->applicationRepository->save($application); + + $user->addApplication($newApplication); + $this->userRepository->save($user); + + $this->programService->updateUserPrograms($user); }); + + $this->mailService->sendMailFromTemplate($application->getUser(), '', Template::SUBEVENTS_CHANGED, [ + TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), + TemplateVariable::USERS_SUBEVENTS => $application->getUser()->getSubeventsText() + ]); } /** @@ -291,26 +344,97 @@ public function updateSubeventsApplication(Application $application, Collection * @param User $createdBy * @throws \Throwable */ - public function cancelSubeventsApplication(Application $application, User $createdBy): void + public function cancelSubeventsApplication(SubeventsApplication $application, string $state, User $createdBy): void { - $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($application, $createdBy) { - //TODO + $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($application, $state, $createdBy) { + $user = $application->getUser(); + + $newApplication = clone $application; + $newApplication->setState($state); + $newApplication->setCreatedBy($createdBy); + $newApplication->setValidFrom(new \DateTime()); + $this->applicationRepository->save($newApplication); + + $application->setValidTo(new \DateTime()); + $this->applicationRepository->save($application); + + $user->addApplication($newApplication); + $this->userRepository->save($user); + + $this->programService->updateUserPrograms($user); }); + + $this->mailService->sendMailFromTemplate($application->getUser(), '', Template::SUBEVENTS_CHANGED, [ + TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), + TemplateVariable::USERS_SUBEVENTS => $application->getUser()->getSubeventsText() + ]); } /** * @param Application $application - * @param \DateTime $paymentDate + * @param string $variableSymbol * @param string $paymentMethod + * @param \DateTime $paymentDate + * @param \DateTime $incomeProofPrintedDate + * @param \DateTime $maturityDate * @param User $createdBy * @throws \Throwable */ - public function updatePayment(Application $application, \DateTime $paymentDate, string $paymentMethod, + public function updatePayment(Application $application, string $variableSymbol, string $paymentMethod, + \DateTime $paymentDate, \DateTime $incomeProofPrintedDate, \DateTime $maturityDate, User $createdBy): void { - $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($application, $paymentDate, $paymentMethod, $createdBy) { - //TODO + $oldVariableSymbol = $application->getVariableSymbolText(); + $oldPaymentMethod = $application->getPaymentMethod(); + $oldPaymentDate = $application->getPaymentDate(); + $oldIncomeProofPrintedDate = $application->getIncomeProofPrintedDate(); + $oldMaturityDate = $application->getMaturityDate(); + + //pokud neni zmena, nic se neprovede + if ($variableSymbol == $oldVariableSymbol && $paymentMethod == $oldPaymentMethod + && $paymentDate == $oldPaymentDate && $incomeProofPrintedDate == $oldIncomeProofPrintedDate + && $maturityDate == $oldMaturityDate) + return; + + $this->applicationRepository->getEntityManager()->transactional(function ($em) use ($application, + $variableSymbol, $paymentMethod, $paymentDate, $incomeProofPrintedDate, $maturityDate, $createdBy) { + $user = $application->getUser(); + + $newApplication = clone $application; + + if ($application->getVariableSymbolText() != $variableSymbol) { + $newVariableSymbol = new VariableSymbol(); + $newVariableSymbol->setVariableSymbol($variableSymbol); + $this->variableSymbolRepository->save($newVariableSymbol); + + $newApplication->setVariableSymbol($newVariableSymbol); + } + + $newApplication->setPaymentMethod($paymentMethod); + $newApplication->setPaymentDate($paymentDate); + $newApplication->setIncomeProofPrintedDate($incomeProofPrintedDate); + $newApplication->setMaturityDate($maturityDate); + + $newApplication->setState($this->getApplicationState($newApplication)); + $newApplication->setCreatedBy($createdBy); + $newApplication->setValidFrom(new \DateTime()); + $this->applicationRepository->save($newApplication); + + $application->setValidTo(new \DateTime()); + $this->applicationRepository->save($application); + + $user->addApplication($newApplication); + $this->userRepository->save($user); + + $this->programService->updateUserPrograms($user); }); + + if ($paymentDate !== NULL && $oldPaymentDate === NULL) { + $this->mailService->sendMailFromTemplate($this->user, '', Template::PAYMENT_CONFIRMED, [ + TemplateVariable::SEMINAR_NAME => $this->settingsRepository->getValue(Settings::SEMINAR_NAME), + TemplateVariable::APPLICATION_SUBEVENTS => $application->getSubeventsText() + ]); + } } /** @@ -526,7 +650,8 @@ public function isAllowedEditRegistration(User $user) */ public function isAllowedEditApplication(Application $application) { - return $application->getState() == ApplicationState::WAITING_FOR_PAYMENT + return $application->getType() == Application::SUBEVENTS && !$application->isCanceled() + && $application->getState() != ApplicationState::PAID && $this->settingsRepository->getDateValue(Settings::EDIT_REGISTRATION_TO) >= (new \DateTime())->setTime(0, 0); } diff --git a/app/services/PdfExportService.php b/app/services/PdfExportService.php index 675b2706d..de1a47711 100644 --- a/app/services/PdfExportService.php +++ b/app/services/PdfExportService.php @@ -35,6 +35,9 @@ class PdfExportService extends Nette\Object /** @var ApplicationRepository */ private $applicationRepository; + /** @var ApplicationService */ + private $applicationService; + /** * PdfExportService constructor. @@ -42,12 +45,14 @@ class PdfExportService extends Nette\Object * @param SettingsRepository $settingsRepository * @param ApplicationRepository $applicationRepository */ - public function __construct($dir, SettingsRepository $settingsRepository, ApplicationRepository $applicationRepository) + public function __construct($dir, SettingsRepository $settingsRepository, + ApplicationRepository $applicationRepository, ApplicationService $applicationService) { $this->dir = $dir; $this->settingsRepository = $settingsRepository; $this->applicationRepository = $applicationRepository; + $this->applicationService = $applicationService; $this->fpdi = new FPDI(); $this->fpdi->fontpath = $dir . '/fonts/'; @@ -59,15 +64,24 @@ public function __construct($dir, SettingsRepository $settingsRepository, Applic * Vygeneruje doklad o zaplacení pro přihlášku. * @param Application $application * @param $filename + * @param User $createdBy + * @throws \App\Model\Settings\SettingsException + * @throws \Throwable */ - public function generateApplicationsPaymentProof(Application $application, $filename) + public function generateApplicationsPaymentProof(Application $application, $filename, User $createdBy) { - $this->prepareApplicationsPaymentProof($application); + $this->prepareApplicationsPaymentProof($application, $createdBy); $this->fpdi->Output($filename, 'D'); exit; } - private function prepareApplicationsPaymentProof(Application $application) + /** + * @param Application $application + * @param User $createdBy + * @throws \App\Model\Settings\SettingsException + * @throws \Throwable + */ + private function prepareApplicationsPaymentProof(Application $application, User $createdBy) { if ($application->getState() == ApplicationState::PAID) { if ($application->getPaymentMethod() == PaymentType::BANK) @@ -75,9 +89,10 @@ private function prepareApplicationsPaymentProof(Application $application) else if ($application->getPaymentMethod() == PaymentType::CASH) $this->addIncomeProofPage($application); - if (!$application->getIncomeProofPrintedDate() && $application->getPaymentDate()) { - $application->setIncomeProofPrintedDate(new \DateTime()); - $this->applicationRepository->save($application); + if (!$application->getIncomeProofPrintedDate()) { + $this->applicationService->updatePayment($application, $application->getVariableSymbolText(), + $application->getPaymentMethod(), $application->getPaymentDate(), new \DateTime(), + $application->getMaturityDate(), $createdBy); } } } @@ -86,37 +101,54 @@ private function prepareApplicationsPaymentProof(Application $application) * Vygeneruje doklady o zaplacení pro uživatele. * @param User $user * @param $filename + * @throws \App\Model\Settings\SettingsException + * @throws \Throwable */ - public function generateUsersPaymentProof(User $user, $filename) + public function generateUsersPaymentProof(User $user, $filename, User $createdBy) { - $this->prepareUsersPaymentProof($user); + $this->prepareUsersPaymentProof($user, $createdBy); $this->fpdi->Output($filename, 'D'); exit; } - - private function prepareUsersPaymentProof(User $user) + + /** + * @param User $user + * @param User $createdBy + * @throws \App\Model\Settings\SettingsException + * @throws \Throwable + */ + private function prepareUsersPaymentProof(User $user, User $createdBy) { foreach ($user->getApplications() as $application) { - $this->prepareApplicationsPaymentProof($application); + $this->prepareApplicationsPaymentProof($application, $createdBy); } } - + /** * Vygeneruje doklady o zaplacení pro více uživatelů. * @param $users * @param $filename + * @param User $createdBy + * @throws \App\Model\Settings\SettingsException + * @throws \Throwable */ - public function generateUsersPaymentProofs($users, $filename) + public function generateUsersPaymentProofs($users, $filename, User $createdBy) { - $this->prepareUsersPaymentProofs($users); + $this->prepareUsersPaymentProofs($users, $createdBy); $this->fpdi->Output($filename, 'D'); exit; } - private function prepareUsersPaymentProofs($users) + /** + * @param $users + * @param User $createdBy + * @throws \App\Model\Settings\SettingsException + * @throws \Throwable + */ + private function prepareUsersPaymentProofs($users, User $createdBy) { foreach ($users as $user) { - $this->prepareUsersPaymentProof($user); + $this->prepareUsersPaymentProof($user, $createdBy); } } diff --git a/app/services/SkautIsEventService.php b/app/services/SkautIsEventService.php index 0bc82182d..a955e6910 100644 --- a/app/services/SkautIsEventService.php +++ b/app/services/SkautIsEventService.php @@ -41,8 +41,7 @@ public function syncEventParticipants($eventId, array $participants) } foreach ($participants as $p) { - if (!$p->isExternal()) - $this->insertParticipant($p->getSkautISPersonId(), $eventId); + $this->insertParticipant($p->getSkautISPersonId(), $eventId); } } diff --git a/app/utils/Validators.php b/app/utils/Validators.php index c32b55b76..467ae0cb0 100644 --- a/app/utils/Validators.php +++ b/app/utils/Validators.php @@ -6,6 +6,7 @@ use App\Model\ACL\RoleRepository; use App\Model\Structure\Subevent; use App\Model\Structure\SubeventRepository; +use App\Model\User\Application; use App\Model\User\User; use Doctrine\Common\Collections\Collection; @@ -124,18 +125,6 @@ public function validateRolesRegisterable(Collection $selectedRoles, User $user) return TRUE; } - /** - * Ověří, že je vybrána alespoň jedna podakce. - * @param $selectedSubevents - * @return bool - */ - public function validateSubeventsEmpty(Collection $selectedSubevents): bool - { - if ($selectedSubevents->isEmpty()) - return FALSE; - return TRUE; - } - /** * Ověří kapacitu podakcí. * @param Collection|Subevent[] $selectedSubevents @@ -191,4 +180,23 @@ public function validateSubeventsRequired(Collection $selectedSubevents, Subeven return TRUE; } + + /** + * Ověří, zda uživatel podakci již nemá. + * @param Collection $selectedSubevents + * @param User $user + * @param Application|null $editedApplication + * @return bool + */ + public function validateSubeventsRegistered(Collection $selectedSubevents, User $user, + Application $editedApplication = NULL): bool + { + foreach ($selectedSubevents as $subevent) { + foreach ($user->getNotCanceledSubeventsApplications() as $application) { + if ($application !== $editedApplication && $application->getSubevents()->contains($subevent)) + return FALSE; + } + } + return TRUE; + } } \ No newline at end of file diff --git a/migrations/Version20171227152222.php b/migrations/Version20171227152222.php new file mode 100644 index 000000000..15bb13fb9 --- /dev/null +++ b/migrations/Version20171227152222.php @@ -0,0 +1,33 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('UPDATE `mail_template` SET `text` = \'Byl/a jsi přihlášen/a na web akce: %nazev-seminare%. Toto přihlášení není registrací k účasti na akci. Pokud se chceš akce zúčastnit, tak se nezapomeň na webu zaregistrovat.\' WHERE `mail_template`.`id` = 1'); + $this->addSql('UPDATE `mail_template` SET `text` = \'Byl/a jsi zaregistrován/a na akci: %nazev-seminare%. Nezapomeň zaplatit registrační poplatek. Více informací o platbě najdeš na webu ve svém profilu. Zrušit svou registraci můžeš přes web do: %zmena-registrace-do%.\' WHERE `mail_template`.`id` = 2'); + $this->addSql('UPDATE `mail_template` SET `text` = \'Tvoje účast na akci: %nazev-seminare% byla zrušena. Pokud jde o omyl, tak se znovu zaregistruj na webu.\' WHERE `mail_template`.`id` = 3'); + $this->addSql('UPDATE `mail_template` SET `type` = \'roles_changed\', `subject` = \'%nazev-seminare%: změna rolí\', `text` = \'Na akci: %nazev-seminare%, na kterou jsi se již dříve registroval/a, Ti byly změněny role. Tvoje stávájící role jsou: %role%.\' WHERE `mail_template`.`id` = 4'); + $this->addSql('UPDATE `mail_template` SET `type` = \'subevents_changed\', `subject` = \'%nazev-seminare%: změna podakcí\', `text` = \'Na akci: %nazev-seminare%, na kterou jsi se již dříve registroval/a, Ti byly změněny podakce. Tvoje stávájící podakce jsou: %podakce%.\' WHERE `mail_template`.`id` = 5'); + $this->addSql('UPDATE `mail_template` SET `text` = \'Tvůj poplatek za účast na akci: %nazev-seminare% byl přijat organizátorem. Po spuštění přihlašování na programy si budeš moci na webu vybírat jednotlivé programy.\' WHERE `mail_template`.`id` = 6'); + $this->addSql('UPDATE `mail_template` SET `text` = \'Blíží se splatnost poplatku za Tvou účast na akci: %nazev-seminare%. Pokud neobdržíme Tvou platbu do: %splatnost%, tak bude Tvé místo uvolněno dalšímu zájemci.\' WHERE `mail_template`.`id` = 7'); + $this->addSql('UPDATE `mail_template` SET `text` = \'Byl jsi přhlášen na program: \"%nazev-programu%\", zkontroluj si svůj rozvrh.\' WHERE `mail_template`.`id` = 8'); + $this->addSql('UPDATE `mail_template` SET `text` = \'Byl jsi odhlášen z programu: \"%nazev-programu%\", zkontroluj si svůj rozvrh.\' WHERE `mail_template`.`id` = 9'); + $this->addSql('UPDATE `mail_template` SET `text` = \'Uživateli: %uzivatel% byly aktualizovány údaje ve vlastních polích přihlášky.\' WHERE `mail_template`.`id` = 11'); + $this->addSql('DELETE FROM `template_template_variable` WHERE `template_template_variable`.`template_id` = 4 AND `template_template_variable`.`template_variable_id` = 4'); + } + + public function down(Schema $schema) + { + } +}