From ed6250b7b9e31bf71e8fe6c73eff025d5e648f4f Mon Sep 17 00:00:00 2001 From: gloas <gloas@afi-sa.fr> Date: Wed, 15 Feb 2023 15:59:33 +0100 Subject: [PATCH] hotline #171562 fix session activity queue when quota is not activated --- VERSIONS_HOTLINE/171562 | 1 + .../controllers/SessionActivityController.php | 2 +- library/Class/SessionActivity.php | 9 +- library/Class/SessionActivityAttendees.php | 72 ++++++--- library/Class/SessionActivityInscription.php | 5 +- library/Class/User/SessionActivity.php | 4 +- .../Plugin/Manager/AbonneSessionActivity.php | 9 +- .../Manager/SessionActivityInscription.php | 2 +- .../SessionActivityInscriptionBasic.php | 20 ++- .../Form/SessionActivityInscription.php | 4 +- .../snippets/text-mode/php-mode/depends | 10 ++ .../controllers/MultimediaControllerTest.php | 8 + .../AbonneControllerWithQuotasTest.php | 15 +- .../ActivitiesWithQueueAbonneTest.php | 151 ++++++++++++++++++ 14 files changed, 252 insertions(+), 60 deletions(-) create mode 100644 VERSIONS_HOTLINE/171562 create mode 100644 scripts/emacs/yasnippet/snippets/text-mode/php-mode/depends diff --git a/VERSIONS_HOTLINE/171562 b/VERSIONS_HOTLINE/171562 new file mode 100644 index 00000000000..49b178a0e04 --- /dev/null +++ b/VERSIONS_HOTLINE/171562 @@ -0,0 +1 @@ + - correctif #169349 : Activités : Correction de la prise en charge de la file d'attente des inscriptions lorsque celle-ci est activée sans l'option des quotas. \ No newline at end of file diff --git a/application/modules/admin/controllers/SessionActivityController.php b/application/modules/admin/controllers/SessionActivityController.php index 0d9da1d3a05..e8d7a351d85 100644 --- a/application/modules/admin/controllers/SessionActivityController.php +++ b/application/modules/admin/controllers/SessionActivityController.php @@ -66,7 +66,7 @@ class Admin_SessionActivityController extends ZendAfi_Controller_Action { $description = (new Class_TableDescription_SessionActivityInscriptionsExport('')) ->setAgeChildMax($session->getAgeChildMax()) ->setAgeChildMin($session->getAgeChildMin()) - ->setWithQueue($session->isQueueAttendees()); + ->setWithQueue($session->hasQueueAttendees()); $content .= "\n" . $this->view->renderCsv($description, diff --git a/library/Class/SessionActivity.php b/library/Class/SessionActivity.php index 05d47075f9b..804a89092c0 100644 --- a/library/Class/SessionActivity.php +++ b/library/Class/SessionActivity.php @@ -118,7 +118,7 @@ class Class_SessionActivity extends Storm_Model_Abstract { protected $_belongs_to = ['activity' => ['model' => 'Class_Activity'], 'lieu' => ['model' => 'Class_Lieu']]; - protected $_has_many = ['session_activity_inscriptions' => ['model' => 'Class_SessionActivityInscription', + protected $_has_many = ['session_activity_inscriptions' => ['model' => Class_SessionActivityInscription::class, 'role' => 'session_activity', 'dependents' => 'delete'], @@ -277,11 +277,6 @@ class Class_SessionActivity extends Storm_Model_Abstract { } - public function isQueueAttendees() { - return 0 != (int)$this->getQueueAttendees(); - } - - /** * @return Class_SessionActivity */ @@ -365,7 +360,7 @@ class Class_SessionActivity extends Storm_Model_Abstract { $this->getAttendeesMin() . '-' . $this->getAttendeesMax())]; - if ($this->isQueueAttendees()) + if ($this->hasQueueAttendees()) $meta_datas [] = new SessionActivity_MetaData($this->_('Effectif en liste d\'attente'), $this->numberOfAttendeesInQueue()); diff --git a/library/Class/SessionActivityAttendees.php b/library/Class/SessionActivityAttendees.php index 3e9e496cf7a..f867649811f 100644 --- a/library/Class/SessionActivityAttendees.php +++ b/library/Class/SessionActivityAttendees.php @@ -22,13 +22,19 @@ class Class_SessionActivityAttendees { - protected - $_session_activity, - $_session_with_quotas, - $_is_max_registration_limited = true; + protected bool $_session_with_quotas = false; + protected bool $_is_max_registration_limited = true; + + protected Class_SessionActivity $_session_activity; + public static function newFor(Class_SessionActivity $session) { - return $session->isQueueAttendees() + if ( Class_AdminVar::isActivitySessionQuotasEnabled()) + return $session->hasQueueAttendees() + ? new Class_SessionActivityAttendeesWithQueueAndQuotas($session) + : new Class_SessionActivityAttendeesWithQuotas($session); + + return $session->hasQueueAttendees() ? new Class_SessionActivityAttendeesWithQueue($session) : new Class_SessionActivityAttendees($session); } @@ -36,7 +42,6 @@ class Class_SessionActivityAttendees { public function __construct(Class_SessionActivity $session) { $this->_session_activity = $session; - $this->_session_with_quotas = Class_AdminVar::isActivitySessionQuotasEnabled(); } @@ -198,7 +203,7 @@ class Class_SessionActivityAttendees { public function getNextTotalFor($registration = null) : int { - if ($this->_session_activity->isQueueAttendees() + if ($this->_session_activity->hasQueueAttendees() || $this->getEffectifTotalMax() <= 0 || !$registration) return -1; @@ -250,6 +255,13 @@ class Class_SessionActivityAttendees { public function withQueuedInscriptionDo($callback) : self { + $collection = $this + ->_registrations() + ->select('hasQueue'); + + $collection->uasort(fn($inscription_1, $inscription_2) => strcmp($inscription_1->getCreatedAt(), + $inscription_2->getCreatedAt())); + $collection->eachDo($callback); return $this; } @@ -321,7 +333,10 @@ class Class_SessionActivityAttendees { -class Class_SessionActivityAttendeesWithQueue extends Class_SessionActivityAttendees { +class Class_SessionActivityAttendeesWithQueueAndQuotas extends Class_SessionActivityAttendees { + + protected bool $_session_with_quotas = true; + public function isFull() : bool { return $this->isFullAdults() && $this->isFullChildren(); @@ -415,23 +430,6 @@ class Class_SessionActivityAttendeesWithQueue extends Class_SessionActivityAtten } - public function withQueuedInscriptionDo($callback) : self { - $collection = new Storm_Model_Collection($this->_session_activity - ->getSessionActivityInscriptions()); - - $collection = $collection - ->select(fn($inscription) => $inscription->isQueue()); - - $collection - ->uasort(fn($inscription_1, $inscription_2) => strcmp($inscription_1->getCreatedAt(), - $inscription_2->getCreatedAt())); - - $collection->eachDo($callback); - - return $this; - } - - public function acceptVisitor($view) { parent::acceptVisitor($view); @@ -462,3 +460,27 @@ class Class_SessionActivityAttendeesWithQueue extends Class_SessionActivityAtten return $this->getEffectifChildMaxOrTotal() - $this->numberOfChildren(); } } + + + + +class Class_SessionActivityAttendeesWithQueue extends Class_SessionActivityAttendees { + + public function isFull() : bool { + return false; + } + + + public function isFullForQueue(Class_SessionActivityInscription $inscription) : bool { + return $this->_session_activity->getEffectifMax() <= + ($this->_registrations() + ->select(fn($inscription) => ! $inscription->isQueue())->count()); + } +} + + + + +class Class_SessionActivityAttendeesWithQuotas extends Class_SessionActivityAttendees { + protected bool $_session_with_quotas = true; +} diff --git a/library/Class/SessionActivityInscription.php b/library/Class/SessionActivityInscription.php index 0cd2dadbb96..39cb62f3383 100644 --- a/library/Class/SessionActivityInscription.php +++ b/library/Class/SessionActivityInscription.php @@ -120,6 +120,7 @@ class Class_SessionActivityInscription extends Storm_Model_Abstract { $remaining); $error_message = $this->_('Le nombre de participants au total est supérieur au nombre de places total disponibles (%s)', $plural); + $this->checkAttribute('adults', false, $error_message); $this->checkAttribute('children', false, $error_message); @@ -213,8 +214,8 @@ class Class_SessionActivityInscription extends Storm_Model_Abstract { } - public function isQueue() { - return $this->getQueue(); + public function isQueue() : bool { + return (bool) $this->getQueue(); } diff --git a/library/Class/User/SessionActivity.php b/library/Class/User/SessionActivity.php index 81e8039c6f3..635c8628c40 100644 --- a/library/Class/User/SessionActivity.php +++ b/library/Class/User/SessionActivity.php @@ -103,8 +103,8 @@ class Class_User_SessionActivity { } - public function isQueueAttendees() : bool { - return $this->_session_activity->isQueueAttendees(); + public function hasQueueAttendees() : bool { + return $this->_session_activity->hasQueueAttendees(); } } diff --git a/library/ZendAfi/Controller/Plugin/Manager/AbonneSessionActivity.php b/library/ZendAfi/Controller/Plugin/Manager/AbonneSessionActivity.php index 4510ab3eb28..8349451f35a 100644 --- a/library/ZendAfi/Controller/Plugin/Manager/AbonneSessionActivity.php +++ b/library/ZendAfi/Controller/Plugin/Manager/AbonneSessionActivity.php @@ -40,9 +40,8 @@ class ZendAfi_Controller_Plugin_Manager_AbonneSessionActivity if (Class_AdminVar::isActivitySessionQuotasEnabled()) return parent::addAction(); - $this->_redirectToUrlOrReferer($this->_redirect_default_url); - $this->_addWithoutQuotas(); + $this->_redirectToUrlOrReferer($this->_redirect_default_url); } @@ -87,7 +86,7 @@ class ZendAfi_Controller_Plugin_Manager_AbonneSessionActivity public function inscriptionSessionAction() { - if (!$this->_session_activity->isQueueAttendees() + if (!$this->_session_activity->hasQueueAttendees() || !$this->_view->inscription = Class_SessionActivityInscription::findForUserAndSession($this->_user, $this->_session_activity)) return $this->_redirectToReferer(); } @@ -112,7 +111,7 @@ class ZendAfi_Controller_Plugin_Manager_AbonneSessionActivity protected function _redirectInscrireSession() { - if ($this->_session_activity && $this->_session_activity->isQueueAttendees()) + if ($this->_session_activity && $this->_session_activity->hasQueueAttendees()) return $this->_redirect_default_url = Class_Url::absolute(['controller' => 'abonne', 'action' => 'inscription-session', 'id' => $this->_session_activity->getId()]); @@ -172,7 +171,7 @@ class ZendAfi_Controller_Plugin_Manager_AbonneSessionActivity protected function _getSuccessfulAddMessage($model) { - if ($model->getSessionActivity()->isQueueAttendees()) + if ($model->getSessionActivity()->hasQueueAttendees()) return ''; return $this->_('Vous êtes inscrit à la session du %s de l\'activité %s', diff --git a/library/ZendAfi/Controller/Plugin/Manager/SessionActivityInscription.php b/library/ZendAfi/Controller/Plugin/Manager/SessionActivityInscription.php index f10cedb3937..e8e0f71d25f 100644 --- a/library/ZendAfi/Controller/Plugin/Manager/SessionActivityInscription.php +++ b/library/ZendAfi/Controller/Plugin/Manager/SessionActivityInscription.php @@ -53,8 +53,8 @@ class ZendAfi_Controller_Plugin_Manager_SessionActivityInscription if (Class_AdminVar::isActivitySessionQuotasEnabled()) return parent::addAction(); - $this->_redirectToReferer(); $this->_addWithoutQuotas(); + $this->_redirectToReferer(); } diff --git a/library/ZendAfi/Controller/Plugin/Manager/SessionActivityInscriptionBasic.php b/library/ZendAfi/Controller/Plugin/Manager/SessionActivityInscriptionBasic.php index 656ccd28b68..f4693ec3d10 100644 --- a/library/ZendAfi/Controller/Plugin/Manager/SessionActivityInscriptionBasic.php +++ b/library/ZendAfi/Controller/Plugin/Manager/SessionActivityInscriptionBasic.php @@ -31,6 +31,7 @@ class ZendAfi_Controller_Plugin_Manager_SessionActivityInscriptionBasic $_validators = [], $_redirect_default_url; + public function init() { parent::init(); $this->_messages = new Class_SessionActivityInscription_Messages; @@ -45,15 +46,20 @@ class ZendAfi_Controller_Plugin_Manager_SessionActivityInscriptionBasic if (!$this->_canAdd()) return $this->_doOnCannotAdd(); - $attribs = ['stagiaire' => $this->_user, - 'session_activity' => $this->_session_activity]; + $attribs = + ['stagiaire' => $this->_user, + 'session_activity' => $this->_session_activity]; + $inscription = Class_SessionActivityInscription::newInstance($attribs); + $this->_doBeforeSave($inscription); + if (!$inscription->save()) return $this->_helper->notify(implode('<br/>', $inscription->getErrors())); - if (!$inscription->isQueue()) - $this->_notifyRegistration($this->_user); + return $inscription->isQueue() + ? $this->_helper->notify(Class_AdminVar::getValueOrDefault('ACTIVITY_NOTIFICATION_IN_QUEUE')) + : $this->_notifyRegistration($this->_user); } @@ -80,8 +86,9 @@ class ZendAfi_Controller_Plugin_Manager_SessionActivityInscriptionBasic protected function _doAfterDelete($inscription) { - $inscription->getSessionActivity() - ->removeSessionActivityInscription($inscription); + $inscription + ->getSessionActivity() + ->removeSessionActivityInscription($inscription); return $this->_reloadQueue($inscription); } @@ -219,6 +226,7 @@ class ZendAfi_Controller_Plugin_Manager_SessionActivityInscriptionBasic protected function _notifyRegistration($user) { if ($mail_message = $this->_sendMail($user)) $this->_helper->notify($mail_message); + if (!$mail_message) $this->_helper->notify($this->_("Vous êtes bien inscrit à la session %s qui aura lieu à %s", $this->_session_activity->getActivity()->getLabel(), diff --git a/library/ZendAfi/Form/SessionActivityInscription.php b/library/ZendAfi/Form/SessionActivityInscription.php index b5fe6b2f739..086cc5811c3 100644 --- a/library/ZendAfi/Form/SessionActivityInscription.php +++ b/library/ZendAfi/Form/SessionActivityInscription.php @@ -67,7 +67,7 @@ class ZendAfi_Form_SessionActivityInscription extends ZendAfi_Form { return $this; } - if ($session->isQueueAttendees()) { + if ($session->hasQueueAttendees()) { $element_adult->setLabel($this->_getMessages()->adultsWithQueue($session)); return $this; } @@ -89,7 +89,7 @@ class ZendAfi_Form_SessionActivityInscription extends ZendAfi_Form { return $this; } - $label = $session->isQueueAttendees() + $label = $session->hasQueueAttendees() ? $this->_getMessages()->childrenWithQueue($session) : $this->_('Nombre d\'enfants'); diff --git a/scripts/emacs/yasnippet/snippets/text-mode/php-mode/depends b/scripts/emacs/yasnippet/snippets/text-mode/php-mode/depends new file mode 100644 index 00000000000..3e31ad53a02 --- /dev/null +++ b/scripts/emacs/yasnippet/snippets/text-mode/php-mode/depends @@ -0,0 +1,10 @@ +#contributor : Ghislain Loas <ghislain.loas@afi-sa.net> +#name : depends ...(...) +# -- +/** +* @test +* @depends ${function} +*/ +public function ${context}Should${Expectation}() { + $0 +} \ No newline at end of file diff --git a/tests/application/modules/opac/controllers/MultimediaControllerTest.php b/tests/application/modules/opac/controllers/MultimediaControllerTest.php index fe495bc13f8..d94f08e6e14 100644 --- a/tests/application/modules/opac/controllers/MultimediaControllerTest.php +++ b/tests/application/modules/opac/controllers/MultimediaControllerTest.php @@ -562,6 +562,8 @@ class MultimediaControllerAuthenticateNanookBorrowerFromAfiMultimediaTest $axel->setUserGroups([$group])->save(); Class_WebService_SIGB_AbstractRESTService::shouldThrowError(true); + + Class_User_ILSSubscription::setTimeSource(new TimeSourceForTest('2023-02-01')); $this->dispatch('/multimedia/authenticate/login/Axel/password/2022'); } @@ -573,6 +575,12 @@ class MultimediaControllerAuthenticateNanookBorrowerFromAfiMultimediaTest } + public function tearDown() { + Class_User_ILSSubscription::setTimeSource(null); + parent::tearDown(); + } + + /** @test */ public function axelParentalAuthorizationShouldBeUpdatedToOne() { $this->assertEquals(1, Class_Users::find(890)->getParentalAuthorization()); diff --git a/tests/scenarios/Activities/AbonneControllerWithQuotasTest.php b/tests/scenarios/Activities/AbonneControllerWithQuotasTest.php index 2d194763510..5b8bc989544 100644 --- a/tests/scenarios/Activities/AbonneControllerWithQuotasTest.php +++ b/tests/scenarios/Activities/AbonneControllerWithQuotasTest.php @@ -23,7 +23,6 @@ abstract class AbonneControllerWithQuotasTestCase extends AbstractControllerTestCase { protected - $_storm_default_to_volatile = true, $_amadou, $_learn_java, $_learn_python, @@ -660,15 +659,12 @@ class Activities_AbonneControllerWithQuotasWithTotalEffectifTest abstract class AbonneControllerWithQuotasRegisterSessionPostTestCase extends AbonneControllerWithQuotasTestCase { - public function setUp() { - parent::setUp(); - Class_SessionActivity::find(31)->resetAttendees(); - } - protected function _postAdultsAndChildren($adults, $children) { + Class_SessionActivity::find(31)->resetAttendees(); $this->postDispatch('/opac/abonne/inscrire-session/id/31', - ['adults' => $adults, 'children' => $children]); + ['adults' => $adults, + 'children' => $children]); } @@ -677,7 +673,6 @@ abstract class AbonneControllerWithQuotasRegisterSessionPostTestCase 'adults' => $adults, 'children' => $children]); $inscription->assertSave(); - $this->_session_java_fevrier->addSessionActivityInscription($inscription); return $this; } @@ -1002,6 +997,7 @@ class Activities_AbonneControllerWithQuotasRegisterSessionWithNoMoreAdultsPostTe public function setUp() { parent::setUp(); + $this->_session_java_fevrier ->setEffectifMin(1) ->setEffectifInscriptionMax(1) @@ -1017,7 +1013,8 @@ class Activities_AbonneControllerWithQuotasRegisterSessionWithNoMoreAdultsPostTe /** @test */ public function inputAdultLabelShouldContainsNoMoreAdultsRoom() { - $this->assertXPathContentContains('//label[@for="adults"]', 'Aucune place adulte disponible'); + $this->assertXPathContentContains('//label[@for="adults"]', + 'Aucune place adulte disponible'); } diff --git a/tests/scenarios/Activities/ActivitiesWithQueueAbonneTest.php b/tests/scenarios/Activities/ActivitiesWithQueueAbonneTest.php index a48196a6d52..0645b799d98 100644 --- a/tests/scenarios/Activities/ActivitiesWithQueueAbonneTest.php +++ b/tests/scenarios/Activities/ActivitiesWithQueueAbonneTest.php @@ -753,3 +753,154 @@ class ActivitiesWithQueueAbonneWithQuotasFullWithQueueSubscribeInIntonationTest $this->assertXPath('//input[@name="children"][@max="5"]'); } } + + + + +class ActivitiesWithQueueAbonneAndNoQuotaTest extends AbstractControllerTestCase { + public function setUp() { + parent::setUp(); + + Class_AdminVar::set('ACTIVITY', '1'); + + $test_time = new TimeSourceForTest('2023-04-01 14:00:00'); + + Class_Activity::setTimeSource($test_time); + Class_SessionActivity::setTimeSource($test_time); + Class_SessionActivityInscription::setTimeSource($test_time); + + + $students = + $this->fixture(Class_UserGroup::class, + ['id' => 12, + 'libelle' => 'Écoliers', + 'rights' => [Class_UserGroup::RIGHT_SUIVRE_ACTIVITY]]); + + $pierre = + $this->fixture(Class_Users::class, + ['id' => 123, + 'login' => 'Pierre', + 'password' => '123', + 'user_groups' => [$students]]); + + ZendAfi_Auth::getInstance()->logUser($pierre); + + $this->fixture(Class_Activity::class, + ['id' => 1, + 'libelle' => 'Atelier de chansons potaches', + 'description' => 'Devenez auteur et interprète de chanson potaches !']); + + $this->fixture(Class_SessionActivity::class, + ['id' => 1, + 'activity_id' => 1, + 'date_debut' => '2023-05-27', + 'date_fin' => '2023-05-29', + 'effectif_min' => 1, + 'effectif_max' => 1, + 'horaires' => '9h', + 'date_limite_inscription'=>'2023-05-20', + 'queue_attendees' => true + ]) + ->setSessionActivityInscriptions([$this->fixture(Class_SessionActivityInscription::class, + ['id' => 1, + 'stagiaire_id' => 5, + 'session_activity_id' => 1])]); + + $this->dispatch('/abonne/inscrire-session/id/1'); + } + + + /** @test */ + public function responseShouldRedirectToReferer() { + $this->assertRedirectTo('/'); + } + + + /** + * @test + * @depends responseShouldRedirectToReferer + */ + public function flashMessengerShouldContainsYouAreInQueue() { + $this->assertFlashMessengerContentContains('Attention: vous avez été placé en liste d\'attente, si des places se libèrent, vous serez averti par Email'); + } +} + + + + +class ActivitiesWithQueueAbonneAndNoQuotaReleadQueueTest extends AbstractControllerTestCase { + public function setUp() { + parent::setUp(); + + Class_AdminVar::set('ACTIVITY', '1'); + + $test_time = new TimeSourceForTest('2023-04-01 14:00:00'); + + Class_Activity::setTimeSource($test_time); + Class_SessionActivity::setTimeSource($test_time); + Class_SessionActivityInscription::setTimeSource($test_time); + + $students = + $this->fixture(Class_UserGroup::class, + ['id' => 12, + 'libelle' => 'Écoliers', + 'rights' => [Class_UserGroup::RIGHT_SUIVRE_ACTIVITY]]); + + $this->fixture(Class_Users::class, + ['id' => 123, + 'login' => 'Pierre', + 'password' => '123', + 'user_groups' => [$students]]); + + $this->fixture(Class_Users::class, + ['id' => 124, + 'login' => 'Thomas', + 'password' => '124', + 'user_groups' => [$students]]); + + + $this->fixture(Class_Activity::class, + ['id' => 1, + 'libelle' => 'Atelier de chansons potaches', + 'description' => 'Devenez auteur et interprète de chanson potaches !']); + + $this->fixture(Class_SessionActivity::class, + ['id' => 1, + 'activity_id' => 1, + 'date_debut' => '2023-05-27', + 'date_fin' => '2023-05-29', + 'effectif_min' => 1, + 'effectif_max' => 1, + 'horaires' => '9h', + 'date_limite_inscription'=>'2023-05-20', + 'queue_attendees' => true + ]) + ->setSessionActivityInscriptions([$this->fixture(Class_SessionActivityInscription::class, + ['id' => 1, + 'stagiaire_id' => 123, + 'session_activity_id' => 1]), + + $this->fixture(Class_SessionActivityInscription::class, + ['id' => 2, + 'stagiaire_id' => 124, + 'queue' => 1, + 'session_activity_id' => 1])]); + + $this->dispatch('/admin/session-activity-inscription/unsubscribe/id/1/stagiaire_id/123'); + } + + + /** @test */ + public function responseShouldRedirectToReferer() { + $this->assertRedirectTo('/'); + } + + + /** + * @test + * @depends responseShouldRedirectToReferer + */ + public function thomasShouldNoLongerBeInQueue() { + $this->assertFalse(Class_SessionActivityInscription::find(2)->isQueue()); + } +} \ No newline at end of file -- GitLab