diff --git a/config/routes/easyadmin.yaml b/config/routes/easyadmin.yaml
new file mode 100644
index 0000000..a88552e
--- /dev/null
+++ b/config/routes/easyadmin.yaml
@@ -0,0 +1,3 @@
+easyadmin:
+ resource: .
+ type: easyadmin.routes
\ No newline at end of file
diff --git a/migrations/Version20241109231434.php b/migrations/Version20241109231434.php
new file mode 100644
index 0000000..a2dc1c6
--- /dev/null
+++ b/migrations/Version20241109231434.php
@@ -0,0 +1,49 @@
+addSql('ALTER TABLE bank_accounts_audit CHANGE diffs diffs JSON DEFAULT NULL');
+ $this->addSql('ALTER TABLE confirmation_token_audit CHANGE diffs diffs JSON DEFAULT NULL');
+ $this->addSql('ALTER TABLE confirmer_audit CHANGE diffs diffs JSON DEFAULT NULL');
+ $this->addSql('ALTER TABLE departments_audit CHANGE diffs diffs JSON DEFAULT NULL');
+ $this->addSql('ALTER TABLE payment_orders ADD mathematically_correct_checked TINYINT(1) NOT NULL, ADD mathematically_correct_timestamp DATETIME DEFAULT NULL, ADD mathematically_correct_confirmer_name VARCHAR(255) DEFAULT NULL, ADD mathematically_correct_confirmer_id INT DEFAULT NULL, ADD mathematically_correct_remark LONGTEXT DEFAULT NULL, ADD factually_correct_checked TINYINT(1) NOT NULL, ADD factually_correct_timestamp DATETIME DEFAULT NULL, ADD factually_correct_confirmer_name VARCHAR(255) DEFAULT NULL, ADD factually_correct_confirmer_id INT DEFAULT NULL, ADD factually_correct_remark LONGTEXT DEFAULT NULL');
+
+ //Move the old data from mathematically_correct and factually_correct to the new fields
+ $this->addSql('UPDATE payment_orders SET mathematically_correct_checked = mathematically_correct, factually_correct_checked = factually_correct');
+
+ //Drop the old columns
+ $this->addSql('ALTER TABLE payment_orders DROP mathematically_correct, DROP factually_correct');
+ $this->addSql('ALTER TABLE payment_orders_audit CHANGE diffs diffs JSON DEFAULT NULL');
+ $this->addSql('ALTER TABLE user_audit CHANGE diffs diffs JSON DEFAULT NULL');
+ }
+
+ public function down(Schema $schema): void
+ {
+ // this down() migration is auto-generated, please modify it to your needs
+ $this->addSql('ALTER TABLE bank_accounts_audit CHANGE diffs diffs LONGTEXT DEFAULT NULL');
+ $this->addSql('ALTER TABLE confirmation_token_audit CHANGE diffs diffs LONGTEXT DEFAULT NULL');
+ $this->addSql('ALTER TABLE confirmer_audit CHANGE diffs diffs LONGTEXT DEFAULT NULL');
+ $this->addSql('ALTER TABLE departments_audit CHANGE diffs diffs LONGTEXT DEFAULT NULL');
+ $this->addSql('ALTER TABLE payment_orders ADD mathematically_correct TINYINT(1) NOT NULL, ADD factually_correct TINYINT(1) NOT NULL, DROP mathematically_correct_checked, DROP mathematically_correct_timestamp, DROP mathematically_correct_confirmer_name, DROP mathematically_correct_confirmer_id, DROP mathematically_correct_remark, DROP factually_correct_checked, DROP factually_correct_timestamp, DROP factually_correct_confirmer_name, DROP factually_correct_confirmer_id, DROP factually_correct_remark');
+ $this->addSql('ALTER TABLE payment_orders_audit CHANGE diffs diffs LONGTEXT DEFAULT NULL');
+ $this->addSql('ALTER TABLE user_audit CHANGE diffs diffs LONGTEXT DEFAULT NULL');
+ }
+}
diff --git a/src/Admin/Field/CheckField.php b/src/Admin/Field/CheckField.php
new file mode 100644
index 0000000..36bebde
--- /dev/null
+++ b/src/Admin/Field/CheckField.php
@@ -0,0 +1,23 @@
+setProperty($propertyName)
+ ->setLabel($label)
+ ->setTemplatePath('admin/field/check.html.twig')
+ ->setTextAlign('center');
+ }
+}
\ No newline at end of file
diff --git a/src/Admin/Filter/CheckFilter.php b/src/Admin/Filter/CheckFilter.php
new file mode 100644
index 0000000..37d88ff
--- /dev/null
+++ b/src/Admin/Filter/CheckFilter.php
@@ -0,0 +1,38 @@
+setFilterFqcn(__CLASS__)
+ ->setProperty($propertyName)
+ ->setLabel($label)
+ ->setFormType(BooleanFilterType::class)
+ ->setFormTypeOption('translation_domain', 'EasyAdminBundle');
+ }
+
+ public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
+ {
+ $property = $filterDataDto->getProperty() . '.checked';
+
+ $queryBuilder
+ ->andWhere(sprintf('%s.%s %s :%s', $filterDataDto->getEntityAlias(), $property, $filterDataDto->getComparison(), $filterDataDto->getParameterName()))
+ ->setParameter($filterDataDto->getParameterName(), $filterDataDto->getValue());
+ }
+}
\ No newline at end of file
diff --git a/src/Controller/Admin/DashboardController.php b/src/Controller/Admin/DashboardController.php
index 14f1c56..2ff6de9 100644
--- a/src/Controller/Admin/DashboardController.php
+++ b/src/Controller/Admin/DashboardController.php
@@ -53,7 +53,7 @@ public function configureDashboard(): Dashboard
->setTitle('StuRa Finanzen');
}
- #[Route(path: '/admin', name: 'admin_dashboard')]
+ #[Route(path: '/admin', name: 'admin')]
public function index(): Response
{
return $this->render('admin/dashboard.html.twig');
diff --git a/src/Controller/Admin/PaymentOrderCrudController.php b/src/Controller/Admin/PaymentOrderCrudController.php
index a9c51c2..a6f34a8 100644
--- a/src/Controller/Admin/PaymentOrderCrudController.php
+++ b/src/Controller/Admin/PaymentOrderCrudController.php
@@ -18,12 +18,15 @@
namespace App\Controller\Admin;
+use App\Admin\Field\CheckField;
use App\Admin\Field\ConfirmationField;
use App\Admin\Field\FieldChangesField;
use App\Admin\Field\VichyFileField;
+use App\Admin\Filter\CheckFilter;
use App\Admin\Filter\ConfirmedFilter;
use App\Admin\Filter\DepartmentTypeFilter;
use App\Admin\Filter\MoneyAmountFilter;
+use App\Entity\Embeddable\Check;
use App\Entity\FieldChanges;
use App\Entity\PaymentOrder;
use App\Entity\User;
@@ -64,7 +67,13 @@
final class PaymentOrderCrudController extends AbstractCrudController
{
- public function __construct(private readonly PaymentOrderMailLinkGenerator $mailToGenerator, private readonly DashboardControllerRegistry $dashboardControllerRegistry, private EntityManagerInterface $entityManager, private readonly ConfirmationEmailSender $confirmationEmailSender, private readonly AdminUrlGenerator $adminURLGenerator, private readonly MessageBusInterface $messageBus)
+ public function __construct(
+ private readonly PaymentOrderMailLinkGenerator $mailToGenerator,
+ private EntityManagerInterface $entityManager,
+ private readonly ConfirmationEmailSender $confirmationEmailSender,
+ private readonly AdminUrlGenerator $adminURLGenerator,
+ private readonly MessageBusInterface $messageBus
+ )
{
}
@@ -163,9 +172,9 @@ public function configureFilters(Filters $filters): Filters
->add(EntityFilter::new('department', 'payment_order.department.label'))
->add(DepartmentTypeFilter::new('department_type', 'payment_order.department_type.label'))
->add(MoneyAmountFilter::new('amount', 'payment_order.amount.label'))
- ->add(BooleanFilter::new('factually_correct', 'payment_order.factually_correct.label'))
+ ->add(CheckFilter::new('factually_correct', 'payment_order.factually_correct.label'))
+ ->add(CheckFilter::new('mathematically_correct', 'payment_order.mathematically_correct.label'))
->add(BooleanFilter::new('exported', 'payment_order.exported.label'))
- ->add(BooleanFilter::new('mathematically_correct', 'payment_order.mathematically_correct.label'))
->add(ConfirmedFilter::new('confirmed', 'payment_order.confirmed.label'))
->add(TextFilter::new('funding_id', 'payment_order.funding_id.label'))
->add(DateTimeFilter::new('creation_date', 'creation_date'))
@@ -191,40 +200,6 @@ public function resendConfirmationEmail(AdminContext $context): Response
return $this->redirect($context->getReferrer() ?? '/admin');
}
- /**
- * Handler for action if user click "check mathematically" button in admin page.
- */
- public function checkMathematicallyCorrect(AdminContext $context): Response
- {
- $this->denyAccessUnlessGranted('ROLE_PO_MATHEMATICALLY');
-
- /** @var PaymentOrder $payment_order */
- $payment_order = $context->getEntity()
- ->getInstance();
- $payment_order->setMathematicallyCorrect(true);
- $this->entityManager->flush();
- $this->addFlash('success', 'payment_order.action.mathematically_correct.success');
-
- return $this->redirect($context->getReferrer() ?? '/admin');
- }
-
- /**
- * Handler for action if user click "check factually" button in admin page.
- */
- public function checkFactuallyCorrect(AdminContext $context): Response
- {
- $this->denyAccessUnlessGranted('ROLE_PO_FACTUALLY');
-
- /** @var PaymentOrder $payment_order */
- $payment_order = $context->getEntity()
- ->getInstance();
- $payment_order->setFactuallyCorrect(true);
- $this->entityManager->flush();
- $this->addFlash('success', 'payment_order.action.factually_correct.success');
-
- return $this->redirect($context->getReferrer() ?? '/admin');
- }
-
public function configureAssets(Assets $assets): Assets
{
return $assets
@@ -321,28 +296,24 @@ public function configureActions(Actions $actions): Actions
//Hide action if no contact emails are associated with department
$emailAction->displayIf(fn(PaymentOrder $paymentOrder): bool => null !== $this->mailToGenerator->generateContactMailLink($paymentOrder));
- $hhv_action = Action::new('contactHHV', 'payment_order.action.contact_hhv', 'fas fa-comment-dots')
- ->linkToUrl(fn(PaymentOrder $paymentOrder): string => $this->mailToGenerator->getHHVMailLink($paymentOrder))
- ->setCssClass('btn btn-secondary text-dark');
-
$resend_confirmation_action = Action::new('resendConfirmation', 'payment_order.action.resend_confirmation', 'fas fa-redo')
->linkToCrudAction('resendConfirmationEmail')
->displayIf(fn(PaymentOrder $paymentOrder): bool => $this->isGranted('ROLE_EDIT_PAYMENT_ORDERS') && !$paymentOrder->isConfirmed())
->setCssClass('btn btn-secondary text-dark');
$mathematically_correct_action = Action::new('mathematicallyCorrect', 'payment_order.action.mathematically_correct', 'fas fa-check')
- ->linkToCrudAction('checkMathematicallyCorrect')
+ ->linkToRoute('payment_order_check', fn (PaymentOrder $paymentOrder) => ['type' => 'mathematically_correct', 'id' => $paymentOrder->getId()])
->displayIf(fn(PaymentOrder $paymentOrder): bool => $this->isGranted('ROLE_PO_MATHEMATICALLY')
&& $paymentOrder->isConfirmed()
- && !$paymentOrder->isMathematicallyCorrect())
+ && !$paymentOrder->isMathematicallyCorrectChecked())
->setCssClass('btn btn-success');
$factually_correct_action = Action::new('factuallyCorrect', 'payment_order.action.factually_correct', 'fas fa-check')
- ->linkToCrudAction('checkFactuallyCorrect')
+ ->linkToRoute('payment_order_check', fn (PaymentOrder $paymentOrder) => ['type' => 'factually_correct', 'id' => $paymentOrder->getId()])
->displayIf(fn(PaymentOrder $paymentOrder): bool => $this->isGranted('ROLE_PO_FACTUALLY')
&& $paymentOrder->isConfirmed()
- && !$paymentOrder->isFactuallyCorrect()
- && $paymentOrder->isMathematicallyCorrect())
+ && !$paymentOrder->isFactuallyCorrectChecked()
+ && $paymentOrder->isMathematicallyCorrectChecked())
->setCssClass('btn btn-success');
$manual_confirmation = Action::new('manual_confirmation', 'payment_order.action.manual_confirmation', 'fas fa-exclamation-triangle')
@@ -356,8 +327,6 @@ public function configureActions(Actions $actions): Actions
$actions->add(Crud::PAGE_EDIT, $emailAction);
$actions->add(Crud::PAGE_DETAIL, $emailAction);
- $actions->add(Crud::PAGE_EDIT, $hhv_action);
- $actions->add(Crud::PAGE_DETAIL, $hhv_action);
$actions->disable(Crud::PAGE_NEW);
@@ -430,8 +399,8 @@ public function configureFields(string $pageName): iterable
//$creationDate = TextField::new('creation_date', 'creation_date');
//Status informations
- $statusPanel = FormField::addPanel('payment_order.group.status');
- $mathematicallyCorrect = BooleanField::new('mathematically_correct', 'payment_order.mathematically_correct.label')
+ $statusPanel = FormField::addFieldset('payment_order.group.status');
+ $mathematicallyCorrect = BooleanField::new('mathematically_correct.checked', 'payment_order.mathematically_correct.label')
->setHelp('payment_order.mathematically_correct.help')
//Disable fields (and show coloumns as read only tags) if user does not have proper permissions to change
//factually and mathematically correct status
@@ -439,7 +408,7 @@ public function configureFields(string $pageName): iterable
->renderAsSwitch($this->isGranted('ROLE_PO_MATHEMATICALLY'));
$exported = BooleanField::new('exported', 'payment_order.exported.label')
->setHelp('payment_order.exported.help');
- $factuallyCorrect = BooleanField::new('factually_correct', 'payment_order.factually_correct.label')
+ $factuallyCorrect = BooleanField::new('factually_correct.checked', 'payment_order.factually_correct.label')
->setHelp('payment_order.factually_correct.help')
->setFormTypeOption('disabled', !$this->isGranted('ROLE_PO_FACTUALLY'))
->renderAsSwitch($this->isGranted('ROLE_PO_FACTUALLY'));
@@ -452,14 +421,14 @@ public function configureFields(string $pageName): iterable
$references_exported = BooleanField::new('references_exported', 'payment_order.references_exported.label');
//Payee informations
- $payeePanel = FormField::addPanel('payment_order.group.receiver');
+ $payeePanel = FormField::addFieldset('payment_order.group.receiver');
$bankInfoAccountOwner = TextField::new('bank_info.account_owner', 'bank_info.account_owner.label');
$bankInfoStreet = TextField::new('bank_info.street', 'bank_info.street.label');
$bankInfoZipCode = TextField::new('bank_info.zip_code', 'bank_info.zip_code.label');
$bankInfoCity = TextField::new('bank_info.city', 'bank_info.city.label');
//Payee bank account infos
- $bankInfoPanel = FormField::addPanel('payment_order.group.bank_info');
+ $bankInfoPanel = FormField::addFieldset('payment_order.group.bank_info');
$bankInfoIban = TextField::new('bank_info.iban', 'bank_info.iban.label');
$bankInfoBic = TextField::new('bank_info.bic', 'bank_info.bic.label')
->setRequired(false)
@@ -515,21 +484,21 @@ public function configureFields(string $pageName): iterable
FormField::addTab('payment_order.tab.status', 'fas fa-list-check'),
//Status infos
FormField::addColumn(),
- FormField::addPanel('payment_order.section.status.confirmation'),
+ FormField::addFieldset('payment_order.section.status.confirmation'),
BooleanField::new('confirmed', 'payment_order.confirmed.label'),
$requiredConfirmations,
$confirmation1,
$confirmation2,
FormField::addColumn(),
- FormField::addPanel('payment_order.section.status.review'),
- $mathematicallyCorrect,
+ FormField::addFieldset('payment_order.section.status.review'),
+ CheckField::new('mathematically_correct', 'payment_order.mathematically_correct.label'),
+ CheckField::new('factually_correct', 'payment_order.factually_correct.label'),
$exported,
- $factuallyCorrect,
$booking_date,
$references_exported,
- FormField::addPanel('payment_order.section.edited_fields'),
+ FormField::addFieldset('payment_order.section.edited_fields'),
FieldChangesField::new('field_changes', ""),
];
diff --git a/src/Controller/Admin/PaymentOrderManualConfirmController.php b/src/Controller/Admin/PaymentOrderHelperController.php
similarity index 51%
rename from src/Controller/Admin/PaymentOrderManualConfirmController.php
rename to src/Controller/Admin/PaymentOrderHelperController.php
index 28d5537..b23533b 100644
--- a/src/Controller/Admin/PaymentOrderManualConfirmController.php
+++ b/src/Controller/Admin/PaymentOrderHelperController.php
@@ -21,16 +21,26 @@
use App\Entity\PaymentOrder;
use App\Form\PaymentOrderManualConfirmationType;
use App\Services\EmailConfirmation\ManualConfirmationHelper;
+use App\Services\PaymentOrder\CheckHelper;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\Form\Extension\Core\Type\SubmitType;
+use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
+/**
+ * This controller contains various helping methods for the PaymentOrder entity.
+ */
#[Route(path: '/admin/payment_order')]
-final class PaymentOrderManualConfirmController extends AbstractController
+final class PaymentOrderHelperController extends AbstractController
{
+ public function __construct(private readonly EntityManagerInterface $entityManager)
+ {
+ }
+
#[Route(path: '/{id}/confirm', name: 'payment_order_manual_confirm')]
public function manualConfirmation(
PaymentOrder $paymentOrder,
@@ -46,7 +56,7 @@ public function manualConfirmation(
if ($paymentOrder->isConfirmed()) {
$this->addFlash('error', 'payment_order.manual_confirm.already_confirmed');
- return $this->redirectToRoute('admin_dashboard');
+ return $this->redirectToRoute('admin');
}
$form = $this->createForm(PaymentOrderManualConfirmationType::class);
@@ -60,7 +70,7 @@ public function manualConfirmation(
//Show a success flash notification
$this->addFlash('success', 'payment_order.manual_confirm.success');
- return $this->redirectToRoute('admin_dashboard');
+ return $this->redirectToRoute('admin');
}
return $this->render('admin/payment_order/manual_confirm.html.twig', [
@@ -69,4 +79,58 @@ public function manualConfirmation(
'form' => $form->createView(),
]);
}
+
+ /**
+ * This method show a detail form where the user can check the factually_correct or mathematically_correct field
+ * with a optional remark
+ * @param PaymentOrder $paymentOrder
+ * @param string $type
+ * @param Request $request
+ * @return void
+ */
+ #[Route(path: '/{id}/check/{type}', name: 'payment_order_check')]
+ public function doCheck(
+ PaymentOrder $paymentOrder,
+ string $type,
+ Request $request,
+ CheckHelper $checkHelper,
+
+ ): Response {
+ //Ensure that the type is valid
+ if (!in_array($type, CheckHelper::ALLOWED_FIELDS, true)) {
+ throw $this->createNotFoundException();
+ }
+
+ //Check if the current user is allowed to check the field
+ if ($type === CheckHelper::FACTUALLY_CORRECT) {
+ $this->denyAccessUnlessGranted('ROLE_PO_FACTUALLY');
+ }
+ if ($type === CheckHelper::MATHEMATICALLY_CORRECT) {
+ $this->denyAccessUnlessGranted('ROLE_PO_MATHEMATICALLY');
+ }
+
+ //Create the form
+ $form = $this->createFormBuilder()
+ ->add('remark', TextareaType::class, ['required' => false, 'label' => 'Anmerkung'])
+ ->add('submit', SubmitType::class, ['label' => 'Prüfen'])
+ ->getForm();
+
+ $form->handleRequest($request);
+ if ($form->isSubmitted() && $form->isValid()) {
+ $remark = $form->get('remark')->getData();
+ $checkHelper->check($paymentOrder, $type, $remark);
+
+ $this->entityManager->flush();
+
+ $this->addFlash('success', 'payment_order.check.success');
+
+ return $this->redirectToRoute('admin_payment_order_detail', ['entityId' => $paymentOrder->getId()]);
+ }
+
+ return $this->render('admin/payment_order/check.html.twig', [
+ 'entity' => $paymentOrder,
+ 'type' => $type,
+ 'form' => $form->createView(),
+ ]);
+ }
}
diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php
index d3e7b77..fac0963 100644
--- a/src/Controller/SecurityController.php
+++ b/src/Controller/SecurityController.php
@@ -38,7 +38,7 @@ public function login(AuthenticationUtils $authenticationUtils): Response
'last_username' => $lastUsername,
'error' => $error,
'csrf_token_intention' => 'authenticate',
- 'target_path' => $this->generateUrl('admin_dashboard'),
+ 'target_path' => $this->generateUrl('admin'),
'forgot_password_enabled' => true,
'forgot_password_path' => $this->generateUrl('app_forgot_password_request'),
diff --git a/src/Entity/Embeddable/Check.php b/src/Entity/Embeddable/Check.php
new file mode 100644
index 0000000..e240c57
--- /dev/null
+++ b/src/Entity/Embeddable/Check.php
@@ -0,0 +1,99 @@
+checked;
+ }
+
+ public function setChecked(bool $checked): Check
+ {
+ $this->checked = $checked;
+ return $this;
+ }
+
+ public function getTimestamp(): ?\DateTime
+ {
+ return $this->timestamp;
+ }
+
+ public function setTimestamp(?\DateTime $timestamp): Check
+ {
+ $this->timestamp = $timestamp;
+ return $this;
+ }
+
+ public function getConfirmerName(): ?string
+ {
+ return $this->confirmerName;
+ }
+
+ public function setConfirmerName(?string $confirmerName): Check
+ {
+ $this->confirmerName = $confirmerName;
+ return $this;
+ }
+
+ public function getConfirmerID(): ?int
+ {
+ return $this->confirmerID;
+ }
+
+ public function setConfirmerID(?int $confirmerID): Check
+ {
+ $this->confirmerID = $confirmerID;
+ return $this;
+ }
+
+ public function getRemark(): ?string
+ {
+ return $this->remark;
+ }
+
+ public function setRemark(?string $remark): Check
+ {
+ $this->remark = $remark;
+ return $this;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Entity/PaymentOrder.php b/src/Entity/PaymentOrder.php
index 0b380b5..0da14cb 100644
--- a/src/Entity/PaymentOrder.php
+++ b/src/Entity/PaymentOrder.php
@@ -20,6 +20,7 @@
use App\Entity\Contracts\DBElementInterface;
use App\Entity\Contracts\TimestampedElementInterface;
+use App\Entity\Embeddable\Check;
use App\Entity\Embeddable\Confirmation;
use App\Entity\Embeddable\PayeeInfo;
use App\EntityListener\PaymentOrderChangedFieldsListener;
@@ -227,19 +228,21 @@ class PaymentOrder implements DBElementInterface, TimestampedElementInterface, \
*******************************************************************************************************************/
/**
- * @var bool "mathematisch richtig"
+ * @var Check "mathematisch richtig"
*/
- #[ORM\Column(type: Types::BOOLEAN)]
- private bool $mathematically_correct = false;
-
- #[ORM\Column(type: Types::BOOLEAN)]
- private bool $exported = false;
+ #[ORM\Embedded(Check::class)]
+ #[Assert\Valid]
+ private Check $mathematically_correct;
/**
- * @var bool "sachlich richtig"
+ * @var Check "sachlich richtig"
*/
+ #[ORM\Embedded(Check::class)]
+ #[Assert\Valid]
+ private Check $factually_correct;
+
#[ORM\Column(type: Types::BOOLEAN)]
- private bool $factually_correct = false;
+ private bool $exported = false;
/**
* @var Confirmation The first confirmation for this payment order
@@ -297,6 +300,9 @@ public function __construct()
$this->confirmation1 = new Confirmation();
$this->confirmation2 = new Confirmation();
+
+ $this->mathematically_correct = new Check();
+ $this->factually_correct = new Check();
}
public function getId(): ?int
@@ -468,48 +474,41 @@ public function getAmountString(): ?string
}
/**
- * Returns whether this payment order was checked as mathematically correct.
- * This means it was checked that the amount and data in this payment order matches the data on the invoice.
+ * Returns the check object for "mathematically correct".
+ * @return Check
*/
- public function isMathematicallyCorrect(): bool
+ public function getMathematicallyCorrect(): Check
{
return $this->mathematically_correct;
}
/**
- * Sets whether this payment order was checked as mathematically correct.
+ * Returns whether this payment order was checked as mathematically correct.
* This means it was checked that the amount and data in this payment order matches the data on the invoice.
*/
- public function setMathematicallyCorrect(bool $mathematically_correct): PaymentOrder
+ public function isMathematicallyCorrectChecked(): bool
{
- $this->mathematically_correct = $mathematically_correct;
-
- return $this;
+ return $this->mathematically_correct->isChecked();
}
+
/**
- * Returns whether this payment order was checked as factually correct.
- * This means it was checked that this payment is really needed. In our context it also means that an payment order
- * was payed out and is finished.
+ * Returns the check object for "factually correct".
+ * @return Check
*/
- public function isFactuallyCorrect(): bool
+ public function getFactuallyCorrect(): Check
{
return $this->factually_correct;
}
/**
- * Sets whether this payment order was checked as factually correct.
+ * Returns whether this payment order was checked as factually correct.
* This means it was checked that this payment is really needed. In our context it also means that an payment order
* was payed out and is finished.
*/
- public function setFactuallyCorrect(bool $factually_correct): PaymentOrder
+ public function isFactuallyCorrectChecked(): bool
{
- $this->factually_correct = $factually_correct;
-
- //Update the status of booking date
- $this->booking_date = $factually_correct ? new \DateTime() : null;
-
- return $this;
+ return $this->factually_correct->isChecked();
}
/**
@@ -706,7 +705,7 @@ public function setSubmitterEmail(string $submitter_email): PaymentOrder
}
/**
- * Returns whether this is an payment order for an resolution of the FSR-Kom (these are handled differently).
+ * Returns whether this is a payment order for a resolution of the FSR-Kom (these are handled differently).
*/
public function isFsrKomResolution(): bool
{
@@ -714,7 +713,7 @@ public function isFsrKomResolution(): bool
}
/**
- * Sets whether this is an payment order for an resolution of the FSR-Kom (these are handled differently).
+ * Sets whether this is a payment order for a resolution of the FSR-Kom (these are handled differently).
*/
public function setFsrKomResolution(bool $fsr_kom_resolution): PaymentOrder
{
@@ -758,7 +757,6 @@ public function getBookingDate(): ?DateTime
/**
* Manually set the datetime when this payment was booked in banking.
* Set to null if payment_order was not booked yet.
- * The value is set automatically to now when the "factually_checked" field is set.
*/
public function setBookingDate(?DateTime $booking_date): PaymentOrder
{
diff --git a/src/EntityListener/PaymentOrderChangedFieldsListener.php b/src/EntityListener/PaymentOrderChangedFieldsListener.php
index 8097ea3..96e1202 100644
--- a/src/EntityListener/PaymentOrderChangedFieldsListener.php
+++ b/src/EntityListener/PaymentOrderChangedFieldsListener.php
@@ -50,7 +50,7 @@ public function __construct(private readonly Security $security, private readonl
public function preUpdate(PaymentOrder $paymentOrder, PreUpdateEventArgs $eventArgs): void
{
- //Ensure that we have an logged in user. We do not track other changes
+ //Ensure that we have a logged-in user. We do not track other changes
$user = $this->security->getUser();
if (!$user instanceof User) {
return;
diff --git a/src/EventSubscriber/PaymentOrderCheckAddInfoSubscriber.php b/src/EventSubscriber/PaymentOrderCheckAddInfoSubscriber.php
new file mode 100644
index 0000000..f742925
--- /dev/null
+++ b/src/EventSubscriber/PaymentOrderCheckAddInfoSubscriber.php
@@ -0,0 +1,77 @@
+getEntityInstance();
+
+ //Only trigger for PaymentOrder entities
+ if (!($paymentOrder instanceof PaymentOrder)) {
+ return;
+ }
+
+ //Check if the checked state of the "factually_correct" or "mathematically_correct" fields have changed
+ $old_data = $this->entityManager->getUnitOfWork()->getOriginalEntityData($paymentOrder);
+
+ //If the "factually_checked" field has changed
+ if ($old_data['factually_correct.checked'] !== $paymentOrder->getFactuallyCorrect()->isChecked()) {
+ //Perform check if required (was not filled out before
+ if ($paymentOrder->getFactuallyCorrect()->isChecked() && $paymentOrder->getFactuallyCorrect()->getTimestamp() === null) {
+ //Uncheck the field temporarily to avoid the exception thrown by the checkHelper, if already checked
+ $paymentOrder->getFactuallyCorrect()->setChecked(false);
+ $this->checkHelper->check($paymentOrder, 'factually_correct');
+ }
+ //Perform uncheck if required
+ elseif (!$paymentOrder->getFactuallyCorrect()->isChecked() && $paymentOrder->getFactuallyCorrect()->getTimestamp() !== null) {
+ //Check the field temporarily to avoid the exception thrown by the checkHelper, if already unchecked
+ $paymentOrder->getFactuallyCorrect()->setChecked(true);
+ $this->checkHelper->uncheck($paymentOrder, 'factually_correct');
+ }
+ }
+
+ //Do the same for the mathematically_correct field
+ if ($old_data['mathematically_correct.checked'] !== $paymentOrder->getMathematicallyCorrect()->isChecked()) {
+ //Perform check if required (was not filled out before
+ if ($paymentOrder->getMathematicallyCorrect()->isChecked() && $paymentOrder->getMathematicallyCorrect()->getTimestamp() === null) {
+ //Uncheck the field temporarily to avoid the exception thrown by the checkHelper, if already checked
+ $paymentOrder->getMathematicallyCorrect()->setChecked(false);
+ $this->checkHelper->check($paymentOrder, 'mathematically_correct');
+ }
+ //Perform uncheck if required
+ elseif (!$paymentOrder->getMathematicallyCorrect()->isChecked() && $paymentOrder->getMathematicallyCorrect()->getTimestamp() !== null) {
+ //Check the field temporarily to avoid the exception thrown by the checkHelper, if already unchecked
+ $paymentOrder->getMathematicallyCorrect()->setChecked(true);
+ $this->checkHelper->uncheck($paymentOrder, 'mathematically_correct');
+ }
+ }
+ }
+
+ public static function getSubscribedEvents(): array
+ {
+ return [
+ BeforeEntityUpdatedEvent::class => ['addCheckInfoToPaymentOrder']
+ ];
+ }
+}
\ No newline at end of file
diff --git a/src/Services/PaymentOrder/CheckHelper.php b/src/Services/PaymentOrder/CheckHelper.php
new file mode 100644
index 0000000..fbd2714
--- /dev/null
+++ b/src/Services/PaymentOrder/CheckHelper.php
@@ -0,0 +1,118 @@
+security->isGranted('ROLE_PO_FACTUALLY')) {
+ throw new AccessDeniedException('You are not allowed to check this field');
+ }
+ if ($field === self::MATHEMATICALLY_CORRECT && !$this->security->isGranted('ROLE_PO_MATHEMATICALLY')) {
+ throw new AccessDeniedException('You are not allowed to check this field');
+ }
+
+ //Retrieve the check object
+ $check = $field === self::FACTUALLY_CORRECT ? $paymentOrder->getFactuallyCorrect() : $paymentOrder->getMathematicallyCorrect();
+
+ //Ensure that check is not already checked
+ if ($check->isChecked()) {
+ throw new \LogicException('This field is already checked. Use uncheck() to uncheck it');
+ }
+
+ //Retrieve the user object
+ $user = $this->security->getUser();
+ if (!$user instanceof User) {
+ throw new \LogicException('This method only works with logged in users');
+ }
+
+ //Fill in the data from the currently logged in user
+ $check->setChecked(true)
+ ->setConfirmerID($user->getId())
+ ->setConfirmerName($user->getFullName())
+ ->setTimestamp(new \DateTime())
+ ->setRemark($remark);
+
+ //If the field is factually_correct, mark the paymentOrder as booked
+ if ($field === self::FACTUALLY_CORRECT) {
+ if ($paymentOrder->getBookingDate() === null) {
+ $paymentOrder->setBookingDate(new \DateTime());
+ }
+ }
+
+ //TODO: Add an event if both checks are checked
+ }
+
+ /**
+ * Uncheck the given field of the given PaymentOrder (factually_correct or mathematically_correct) and remove the data
+ * from the currently logged in user. If the field is not allowed, an exception is thrown.
+ * @param PaymentOrder $paymentOrder
+ * @param string $field
+ * @return void
+ */
+ public function uncheck(PaymentOrder $paymentOrder, string $field): void
+ {
+ if (!in_array($field, self::ALLOWED_FIELDS, true)) {
+ throw new \InvalidArgumentException('Invalid field');
+ }
+
+ //Check if the current user is allowed to check the field
+ if ($field === self::FACTUALLY_CORRECT && !$this->security->isGranted('ROLE_PO_FACTUALLY')) {
+ throw new AccessDeniedException('You are not allowed to check this field');
+ }
+ if ($field === self::MATHEMATICALLY_CORRECT && !$this->security->isGranted('ROLE_PO_MATHEMATICALLY')) {
+ throw new AccessDeniedException('You are not allowed to check this field');
+ }
+
+ //Retrieve the check object
+ $check = $field === self::FACTUALLY_CORRECT ? $paymentOrder->getFactuallyCorrect() : $paymentOrder->getMathematicallyCorrect();
+
+ //Remove all data from the check object
+ $check->setChecked(false)
+ ->setConfirmerID(null)
+ ->setConfirmerName(null)
+ ->setTimestamp(null)
+ ->setRemark(null);
+ }
+}
\ No newline at end of file
diff --git a/templates/admin/field/check.html.twig b/templates/admin/field/check.html.twig
new file mode 100644
index 0000000..9c4977e
--- /dev/null
+++ b/templates/admin/field/check.html.twig
@@ -0,0 +1,19 @@
+{# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #}
+{# @var field \EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto #}
+{# @var entity \EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto #}
+
+{# @var check \App\Entity\Embeddable\Check #}
+
+{% set check = field.value %}
+{% if not check.checked %}
+ Noch nicht geprüft
+{% else %}
+ Geprüft
+ {{ check.timestamp|format_datetime }}
+ {{ check.confirmerName }}
+ {% if check.remark %}
+
+ {{ check.remark }}
+
+ {% endif %}
+{% endif %}
\ No newline at end of file
diff --git a/templates/admin/payment_order/check.html.twig b/templates/admin/payment_order/check.html.twig
new file mode 100644
index 0000000..6cd7c6c
--- /dev/null
+++ b/templates/admin/payment_order/check.html.twig
@@ -0,0 +1,17 @@
+{% extends "@EasyAdmin/page/content.html.twig" %}
+{% form_theme form "@EasyAdmin/crud/form_theme.html.twig" %}
+{% import "admin/payment_order/tables.macro.twig" as tables %}
+
+{% block page_title %}
+ {% if type == 'factually_correct' %}Sachliche{% else %}Rechnerische{% endif %}
+ Prüfung von {{ entity.iDString }}{% endblock %}
+
+{% block page_content %}
+
+ {{ tables.paymentOrder(entity) }}
+
+
Es kann eine optionale Anmerkung zur Prüfung angegeben werden
+ + {{ form_start(form) }} + {{ form_end(form) }} +{% endblock %} \ No newline at end of file diff --git a/templates/admin/payment_order/manual_confirm.html.twig b/templates/admin/payment_order/manual_confirm.html.twig index aed0a8f..f9a9e8d 100644 --- a/templates/admin/payment_order/manual_confirm.html.twig +++ b/templates/admin/payment_order/manual_confirm.html.twig @@ -1,5 +1,6 @@ {% extends "@EasyAdmin/page/content.html.twig" %} {% form_theme form "@EasyAdmin/crud/form_theme.html.twig" %} +{% import "admin/payment_order/tables.macro.twig" as tables %} {% block page_title %}{% trans %}payment_order.manual_confirmation.title{% endtrans %} {{ entity.iDString }}{% endblock %} @@ -12,30 +13,7 @@{% trans %}payment_order.manual_confirmation.additional_notifications_receiver{% endtrans %} {{ notifications_risky | join(', ') }}
{% trans %}payment_order.notification_user.department{% endtrans %}: | -{{ entity.department.name }} | -
{% trans %}payment_order.notification_user.project_name{% endtrans %}: | -{{ entity.projectName }} | -
{% trans %}payment_order.notification_user.amount{% endtrans %}: | -{{ entity.amountString }} € | -
{% trans %}payment_order.notification_user.datetime{% endtrans %} | -{{ entity.creationDate | format_datetime }} | -
{% trans %}payment_order.notification_user.id{% endtrans %}: | -{{ entity.iDString }} | -
{% trans %}payment_order.manual_confirmation.explanation3{% endtrans %}
diff --git a/templates/admin/payment_order/tables.macro.twig b/templates/admin/payment_order/tables.macro.twig new file mode 100644 index 0000000..fefcdd2 --- /dev/null +++ b/templates/admin/payment_order/tables.macro.twig @@ -0,0 +1,32 @@ +{% macro paymentOrder(entity) %} + {# @var \App\Entity\PaymentOrder entity #} + +{% trans %}payment_order.notification_user.department{% endtrans %}: | +{{ entity.department.name }} | +
{% trans %}payment_order.notification_user.project_name{% endtrans %}: | +{{ entity.projectName }} | +
{% trans %}payment_order.notification_user.amount{% endtrans %}: | +{{ entity.amountString }} € | +
Mittelfreigabe | +{{ entity.fundingId }} {% if entity.resolutionDate %}({{ entity.resolutionDate | format_date }}){% endif %} | +
{% trans %}payment_order.notification_user.datetime{% endtrans %} | +{{ entity.creationDate | format_datetime }} | +
{% trans %}payment_order.notification_user.id{% endtrans %}: | +{{ entity.iDString }} | +