diff --git a/module/Database/migrations/Version20250126144021.php b/module/Database/migrations/Version20250126144021.php new file mode 100644 index 000000000..705e7faf2 --- /dev/null +++ b/module/Database/migrations/Version20250126144021.php @@ -0,0 +1,36 @@ +addSql('ALTER TABLE savedquery ADD category VARCHAR(255)'); + $this->addSql('UPDATE savedquery SET category = trim(split_part(name, \':\', 1)), name = trim(split_part(name, \':\', -1))'); + $this->addSql('ALTER TABLE savedquery ALTER COLUMN category SET NOT NULL'); + // phpcs:enable SlevomatCodingStandard.Functions.RequireMultiLineCall.RequiredMultiLineCall + } + + public function down(Schema $schema): void + { + // phpcs:disable SlevomatCodingStandard.Functions.RequireMultiLineCall.RequiredMultiLineCall + $this->addSql('UPDATE savedquery SET name = concat(category, \': \', name)'); + $this->addSql('ALTER TABLE SavedQuery DROP category'); + // phpcs:enable SlevomatCodingStandard.Functions.RequireMultiLineCall.RequiredMultiLineCall + } +} diff --git a/module/Database/src/Form/Fieldset/MemberFunction.php b/module/Database/src/Form/Fieldset/MemberFunction.php index 395ffa34c..d0f55f573 100644 --- a/module/Database/src/Form/Fieldset/MemberFunction.php +++ b/module/Database/src/Form/Fieldset/MemberFunction.php @@ -28,6 +28,9 @@ public function __construct( 'label' => 'Functie', 'value_options' => InstallationFunctions::getFunctionsArray($translator, $withmember, $withLegacy), ], + 'attributes' => [ + 'value' => InstallationFunctions::Member->value, + ], ]); } diff --git a/module/Database/src/Form/QueryExport.php b/module/Database/src/Form/QueryExport.php index bc5ffc2e0..2bae2483f 100644 --- a/module/Database/src/Form/QueryExport.php +++ b/module/Database/src/Form/QueryExport.php @@ -4,6 +4,7 @@ namespace Database\Form; +use Laminas\Form\Element\Hidden; use Laminas\Form\Element\Select; use Laminas\InputFilter\InputFilterProviderInterface; use Laminas\Mvc\I18n\Translator; @@ -14,6 +15,11 @@ public function __construct(private readonly Translator $translator) { parent::__construct($this->translator); + $this->add([ + 'name' => 'name', + 'type' => Hidden::class, + ]); + $this->add([ 'name' => 'type', 'type' => Select::class, diff --git a/module/Database/src/Form/QuerySave.php b/module/Database/src/Form/QuerySave.php index 6625dde2c..042109469 100644 --- a/module/Database/src/Form/QuerySave.php +++ b/module/Database/src/Form/QuerySave.php @@ -16,6 +16,14 @@ public function __construct(private readonly Translator $translator) { parent::__construct($this->translator); + $this->add([ + 'name' => 'category', + 'type' => Text::class, + 'options' => [ + 'label' => $this->translator->translate('Category'), + ], + ]); + $this->add([ 'name' => 'name', 'type' => Text::class, @@ -29,7 +37,7 @@ public function __construct(private readonly Translator $translator) 'type' => Submit::class, 'attributes' => [ 'label' => $this->translator->translate('Save'), - 'value' => $this->translator->translate('Save'), + 'value' => 'save', ], ]); } diff --git a/module/Database/src/Mapper/SavedQuery.php b/module/Database/src/Mapper/SavedQuery.php index e71e797bb..b0ca471b1 100644 --- a/module/Database/src/Mapper/SavedQuery.php +++ b/module/Database/src/Mapper/SavedQuery.php @@ -55,7 +55,7 @@ public function findByName(string $name): ?SavedQueryModel public function findAll(): array { $qb = $this->getRepository()->createQueryBuilder('q'); - $qb->add('orderBy', 'lower(q.name) ASC'); + $qb->add('orderBy', 'lower(q.category), lower(q.name) ASC'); return $qb->getQuery()->getResult(); } diff --git a/module/Database/src/Model/SavedQuery.php b/module/Database/src/Model/SavedQuery.php index 71fe46ba0..c763de79e 100644 --- a/module/Database/src/Model/SavedQuery.php +++ b/module/Database/src/Model/SavedQuery.php @@ -23,6 +23,12 @@ class SavedQuery #[GeneratedValue(strategy: 'AUTO')] protected ?int $id = null; + /** + * Category. + */ + #[Column(type: 'string')] + protected string $category; + /** * Name. */ @@ -69,6 +75,22 @@ public function setName(string $name): void $this->name = $name; } + /** + * Get the category. + */ + public function getCategory(): string + { + return $this->category; + } + + /** + * Set the category. + */ + public function setCategory(string $category): void + { + $this->category = $category; + } + /** * Set the query. */ diff --git a/module/Database/src/Service/FrontPage.php b/module/Database/src/Service/FrontPage.php index 6fa702664..12b9db39e 100644 --- a/module/Database/src/Service/FrontPage.php +++ b/module/Database/src/Service/FrontPage.php @@ -45,6 +45,8 @@ public function getFrontpageData(): array public function getNotificationCount(): int { - return $this->memberService->getPendingUpdateCount() + (int) $this->apiService->isSyncPaused(); + return $this->memberService->getPendingUpdateCount() + + (int) $this->apiService->isSyncPaused() + + $this->memberService->getPaidProspectivesCount(); } } diff --git a/module/Database/src/Service/Member.php b/module/Database/src/Service/Member.php index ddf4e201b..f6062336f 100644 --- a/module/Database/src/Service/Member.php +++ b/module/Database/src/Service/Member.php @@ -997,6 +997,15 @@ public function getPendingUpdateCount(): int return $this->getMemberUpdateMapper()->getRepository()->count([]); } + /** + * Paid prospective members (separately from frontpage data to reduce number + * of database queries) + */ + public function getPaidProspectivesCount(): int + { + return count($this->getProspectiveMemberMapper()->search('', 'paid')); + } + /** * Get a list of all pending member updates. * diff --git a/module/Database/src/Service/Query.php b/module/Database/src/Service/Query.php index 7143f88a9..2bf8fa8dd 100644 --- a/module/Database/src/Service/Query.php +++ b/module/Database/src/Service/Query.php @@ -47,6 +47,8 @@ public function save(array $data): ?SavedQueryModel { $form = $this->getQuerySaveForm(); + // This is an intentional choice to find the query by name + // (we require unique names even across categories) $query = $this->getSavedQueryMapper()->findByName($data['name']); if (null !== $query) { $form->bind($query); diff --git a/module/Database/view/database/index/index.phtml b/module/Database/view/database/index/index.phtml index 6976117c6..320092e25 100644 --- a/module/Database/view/database/index/index.phtml +++ b/module/Database/view/database/index/index.phtml @@ -16,7 +16,6 @@ use Laminas\View\Renderer\PhpRenderer; * @var int $totalCount */ -$twoColumnMode = $totalCount > 0; ?>
= sprintf( $this->translate('GEWIS currently has %d members (+%d expired) and %d prospective members (%d paid, %d unpaid). Click here to create a meeting or perform a query.'), @@ -47,55 +46,70 @@ $twoColumnMode = $totalCount > 0; ) ?>
- = sprintf( - $this->translatePlural( - 'There is currently %d update pending approval.', - 'There are currently %d updates pending approval.', - $updates, - ), - $this->url('member/updates'), +
+ = sprintf( + $this->translatePlural( + 'There is currently %d update pending approval.', + 'There are currently %d updates pending approval.', $updates, - ) ?> -
-- getTimestamp() - (new DateTime())->getTimestamp(); - if ($syncPausedDifference > 3600) { - echo sprintf( - $this->translate( - 'Synchronisation with other systems is paused until %s.', - ), - $syncPausedUntil->format(DateTimeInterface::ATOM), - ); - } else { - echo sprintf( - $this->translate( - 'Synchronisation with other systems is paused and will resume in %d minutes.', - ), - (int) $syncPausedDifference/60, - ); - } - ?> -
-+ getTimestamp() - (new DateTime())->getTimestamp(); + if ($syncPausedDifference > 3600) { + echo sprintf( + $this->translate( + 'Synchronisation with other systems is paused until %s.', + ), + $syncPausedUntil->format(DateTimeInterface::ATOM), + ); + } else { + echo sprintf( + $this->translate( + 'Synchronisation with other systems is paused and will resume in %d minutes.', + ), + (int) $syncPausedDifference/60, + ); + } + ?> +
+ translate( + '%s prospective member(s) have paid and are pending approval.', + ), + $prospectives['paid'], + ); + ?> +
+