Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ name: main

on:
push:
branches: [ master, beta ]
branches:
- master
- 'beta/**'
pull_request:

jobs:
Expand Down Expand Up @@ -318,7 +320,7 @@ jobs:
- run: true

deploy-beta:
if: github.ref == 'refs/heads/beta'
if: ${{ startsWith(github.ref_name, 'beta') }}
needs: [checks-passed, workdir]
uses: ./.github/workflows/deploy-template.yml
with:
Expand Down
33 changes: 33 additions & 0 deletions app/AccountancyModule/Components/DataGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Ublaboo\DataGrid\Column\Action;
use Ublaboo\DataGrid\Filter\FilterSelect;
use Ublaboo\DataGrid\Localization\SimpleTranslator;

use function array_map;
use function array_reverse;
Expand All @@ -29,6 +30,38 @@ public function __construct()
//disable autocomplete - issue #1443
$this['filter']->getElementPrototype()->setAttribute('autocomplete', 'off');
};

$translator = new SimpleTranslator([
'ublaboo_datagrid.no_item_found_reset' => 'Nenalezeny žádné záznamy. Můžete zrušit filtr',
'ublaboo_datagrid.no_item_found' => 'Nenalezeny žádné záznamy.',
'ublaboo_datagrid.here' => 'zde',
'ublaboo_datagrid.items' => 'Položky',
'ublaboo_datagrid.all' => 'vše',
'ublaboo_datagrid.from' => 'od',
'ublaboo_datagrid.reset_filter' => 'Zrušit filtr',
'ublaboo_datagrid.group_actions' => 'Hromadné akce',
'ublaboo_datagrid.show' => 'Zobrazit',
'ublaboo_datagrid.add' => 'Přidat',
'ublaboo_datagrid.edit' => 'Upravit',
'ublaboo_datagrid.show_all_columns' => 'Zobrazit všechny sloupce',
'ublaboo_datagrid.show_default_columns' => 'Zobrazit výchozí sloupce',
'ublaboo_datagrid.hide_column' => 'Skrýt sloupec',
'ublaboo_datagrid.action' => 'Akce',
'ublaboo_datagrid.previous' => 'Předchozí',
'ublaboo_datagrid.next' => 'Další',
'ublaboo_datagrid.choose' => 'Vybrat',
'ublaboo_datagrid.choose_input_required' => 'Text hromadné akce nesmí být prázdný',
'ublaboo_datagrid.execute' => 'Provést',
'ublaboo_datagrid.save' => 'Uložit',
'ublaboo_datagrid.cancel' => 'Zrušit',
'ublaboo_datagrid.multiselect_choose' => 'Vybrat',
'ublaboo_datagrid.multiselect_selected' => '{0} vybráno',
'ublaboo_datagrid.filter_submit_button' => 'Filtrovat',
'ublaboo_datagrid.show_filter' => 'Zobrazit filtr',
'ublaboo_datagrid.per_page_submit' => 'Změnit',
]);

$this->setTranslator($translator);
}

/**
Expand Down
201 changes: 201 additions & 0 deletions app/AccountancyModule/PaymentModule/components/EmailButton.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
<?php

declare(strict_types=1);

namespace App\AccountancyModule\PaymentModule\Components;

use App\AccountancyModule\Components\BaseControl;
use Model\Common\Services\CommandBus;
use Model\Common\Services\QueryBus;
use Model\DTO\Payment\Group;
use Model\DTO\Payment\Payment;
use Model\Google\Exception\OAuthNotSet;
use Model\Google\InvalidOAuth;
use Model\Payment\Commands\Mailing\SendPaymentInfo;
use Model\Payment\Commands\Mailing\SendPaymentReminder;
use Model\Payment\EmailNotSet;
use Model\Payment\EmailTemplateNotSet;
use Model\Payment\EmailType;
use Model\Payment\InvalidBankAccount;
use Model\Payment\MailingService;
use Model\Payment\ReadModel\Queries\GroupEmailQuery;

use function array_filter;

class EmailButton extends BaseControl
{
public const NO_MAILER_MESSAGE = 'Nemáte nastavený mail pro odesílání u skupiny';
public const NO_BANK_ACCOUNT_MESSAGE = 'Skupina nemá nastavený bankovní účet';

public const NO_TEMPLATE_ASSIGNED = 'Skupina nemá nastavenou šablonu pro upomínku';

/** @param Payment[] $payments */
public function __construct(private QueryBus $queryBus, private CommandBus $commandBus, private MailingService $mailing, private bool $isEditable, private array $payments, private Group|null $group)
{
}

public function render(): void
{
$email = $this->queryBus->handle(new GroupEmailQuery($this->group->id, EmailType::get(EmailType::PAYMENT_REMINDER)));
$paymentsForSendEmail = $this->paymentsAvailableForGroupInfoSending($this->payments);

$this->template->setParameters([
'canSend' => $this->canSend(),
'isReminderSendActive' => $email !== null && $email->isEnabled(),
'isGroupSendActive' => $this->group->getState() === 'open' && ! empty($paymentsForSendEmail),
]);
$this->template->setFile(__DIR__ . '/templates/EmailButton.latte');
$this->template->render();
}

public function canSend(): bool
{
return ! ($this->group->getOauthId() === null) && ! ($this->group->getBankAccountId() === null);
}

public function renderLight(): void
{
$this->template->setParameters(['style' => 'light']);
$this->render();
}

/**
* rozešle všechny neposlané e-maily
*/
public function handleSendGroup(): void
{
$this->sendPaymentInfoEmails($this->paymentsAvailableForGroupInfoSending($this->payments));
}

public function handleSendGroupReminder(): void
{
$this->sendPaymentReminderEmails($this->paymentsAvailableForGroupReminderSending($this->payments));
}

public function handleSendTest(): void
{
if (! $this->isEditable) {
$this->presenter->flashMessage('Neplatný požadavek na odeslání testovacího e-mailu!', 'danger');
$this->presenter->redirect('this');
}

try {
$email = $this->mailing->sendTestMail($this->group->id);
$this->presenter->flashMessage('Testovací e-mail byl odeslán na ' . $email . '.');
} catch (OAuthNotSet) {
$this->presenter->flashMessage(self::NO_MAILER_MESSAGE, 'warning');
} catch (InvalidOAuth $e) {
$this->oauthError($e);
} catch (InvalidBankAccount) {
$this->presenter->flashMessage(self::NO_BANK_ACCOUNT_MESSAGE, 'warning');
} catch (EmailNotSet) {
$this->flashMessage('Nemáte nastavený e-mail ve skautisu, na který by se odeslal testovací e-mail!', 'danger');
}

$this->redirect('this');
}

/** @param Payment[] $payments */
private function sendPaymentInfoEmails(array $payments): void
{
$sentCount = 0;

try {
foreach ($payments as $payment) {
$this->commandBus->handle(new SendPaymentInfo($payment->getId()));
$sentCount++;
}
} catch (OAuthNotSet) {
$this->presenter->flashMessage(self::NO_MAILER_MESSAGE, 'warning');
$this->presenter->redirect('this');
} catch (InvalidBankAccount) {
$this->presenter->flashMessage(self::NO_BANK_ACCOUNT_MESSAGE, 'warning');
$this->presenter->redirect('this');
} catch (InvalidOAuth $e) {
$this->oauthError($e);
$this->presenter->redirect('this');
}

if ($sentCount > 0) {
$this->presenter->flashMessage(
$sentCount === 1
? 'Informační e-mail byl odeslán'
: 'Informační e-maily (' . $sentCount . ') byly odeslány',
'success',
);
}

$this->presenter->redirect('this');
}

/** @param Payment[] $payments */
private function sendPaymentReminderEmails(array $payments): void
{
$sentCount = 0;

try {
foreach ($payments as $payment) {
$this->commandBus->handle(new SendPaymentReminder($payment->getId()));
$sentCount++;
}
} catch (OAuthNotSet) {
$this->presenter->flashMessage(self::NO_MAILER_MESSAGE, 'warning');
$this->presenter->redirect('this');
} catch (InvalidBankAccount) {
$this->presenter->flashMessage(self::NO_BANK_ACCOUNT_MESSAGE, 'warning');
$this->presenter->redirect('this');
} catch (InvalidOAuth $e) {
$this->oauthError($e);
$this->presenter->redirect('this');
} catch (EmailTemplateNotSet) {
$this->presenter->flashMessage(self::NO_TEMPLATE_ASSIGNED, 'warning');
$this->presenter->redirect('this');
}

if ($sentCount > 0) {
$this->presenter->flashMessage(
$sentCount === 1
? 'E-mail s upomínkou byl odeslán'
: 'E-maily s upomínkou byly odeslány (celkem: ' . $sentCount . ')',
'success',
);
}

$this->presenter->redirect('this');
}

/**
* @param Payment[] $payments
*
* @return Payment[]
*/
private function paymentsAvailableForGroupInfoSending(array $payments): array
{
return array_filter(
$payments,
function (Payment $p) {
return ! $p->isClosed() && ! empty($p->getEmailRecipients()) && $p->getSentEmails() === [];
},
);
}

/**
* @param Payment[] $payments
*
* @return Payment[]
*/
private function paymentsAvailableForGroupReminderSending(array $payments): array
{
return array_filter(
$payments,
function (Payment $p) {
return $p->isOverdue();
},
);
}

private function oauthError(InvalidOAuth $e): void
{
$this->presenter->flashMessage($e->getExplainedMessage(), 'danger');
}
}
25 changes: 21 additions & 4 deletions app/AccountancyModule/PaymentModule/components/GroupForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ private function formSucceeded(BaseForm $form): void
$emails = [
EmailType::PAYMENT_INFO => $this->buildEmailTemplate($v, EmailType::PAYMENT_INFO),
EmailType::PAYMENT_COMPLETED => $this->buildEmailTemplate($v, EmailType::PAYMENT_COMPLETED),
EmailType::PAYMENT_REMINDER => $this->buildEmailTemplate($v, EmailType::PAYMENT_REMINDER),
];

$emails = array_filter($emails);
Expand All @@ -178,6 +179,7 @@ private function formSucceeded(BaseForm $form): void
$emails,
$oAuthId,
$v->bankAccount,
$v->emails[EmailType::PAYMENT_REMINDER]?->remindersEnabled ?? false,
);

$this->flashMessage('Skupina byla upravena');
Expand All @@ -190,6 +192,7 @@ private function formSucceeded(BaseForm $form): void
$emails,
$oAuthId,
$v->bankAccount,
$v->emails[EmailType::PAYMENT_REMINDER]?->remindersEnabled ?? false,
);

$this->flashMessage('Skupina byla založena');
Expand Down Expand Up @@ -218,6 +221,11 @@ private function buildDefaultsFromGroup(): array

foreach (EmailType::getAvailableEnums() as $emailType) {
$emails[$emailType->toString()] = $this->getEmailDefaults($this->groupId, $emailType);
if ($emailType->toString() !== EmailType::PAYMENT_REMINDER) {
continue;
}

$emails[$emailType->toString()]['remindersEnabled'] = $group->isRemindersEnabled();
}

return [
Expand All @@ -240,28 +248,37 @@ private function addEmailsToForm(BaseForm $form): void
$emails = [
EmailType::PAYMENT_INFO => 'E-mail s platebními údaji',
EmailType::PAYMENT_COMPLETED => 'E-mail při dokončení platby',
// EmailType::PAYMENT_CANCELED => 'E-mail při zrušení platby',
EmailType::PAYMENT_REMINDER => 'E-mail upomínka platby',
];

foreach ($emails as $type => $caption) {
$group = $form->addGroup($caption, false);
$container = $emailsContainer->addContainer($type);
$container->setCurrentGroup($group);

$subjectId = $type . '_subject';
$bodyId = $type . '_body';
$subjectId = $type . '_subject';
$bodyId = $type . '_body';
$remindersId = $type . '_reminders';

// Only payment info email is always saved
if ($type !== EmailType::PAYMENT_INFO) {
$container->addCheckbox('enabled', 'Aktivní')
->setOption('class', 'form-check')
->addCondition($form::FILLED)
->toggle($subjectId)
->toggle($bodyId);
->toggle($bodyId)
->toggle($remindersId);
}

if ($type === EmailType::PAYMENT_REMINDER) {
$container->addCheckbox('remindersEnabled', 'Automaticky odeslat email po splatnosti')
->setOption('id', $remindersId);
}

$container->addText('subject', 'Předmět e-mailu')
->setOption('id', $subjectId);
$container->addTextArea('body', 'Text mailu')
$container->addTextArea('body', 'Text mailu', 10, 20)
->setOption('id', $bodyId)
->setHtmlAttribute('class', 'form-control')
->setDefaultValue($this->getDefaultEmailBody($type));
Expand Down
Loading