Commit 41976f7f authored by Ghislain Loas's avatar Ghislain Loas
Browse files

dev#74223 : Enables Search on catalogue before creating a new purchase suggestion

parent d3efee72
Pipeline #6572 passed with stage
in 34 minutes and 35 seconds
- ticket #74223 : Suggestions d'achat : activer la variable "SEARCH RECORD BEFORE SUGGEST" permet à l'utilisateur de vérifier si la suggestion existe déjà dans le catalogue.
\ No newline at end of file
......@@ -941,6 +941,7 @@ class AbonneController extends ZendAfi_Controller_Action {
$this->_forward('suggestion-achat-inactive');
return;
}
if (Class_SuggestionAchat::find($this->_getParam('id'))) {
$this->_forward('suggestion-achat-ok');
return;
......@@ -949,31 +950,66 @@ class AbonneController extends ZendAfi_Controller_Action {
$form = ZendAfi_Form_SuggestionAchat::forUser($this->_user);
$form->setAction($this->view->url());
if ($this->_request->isPost()) {
$post = $this->_request->getPost();
unset($post['submit']);
$this->view->form = $form;
$this->view->records = [];
$this->view->preferences = Class_Profil::getCurrentProfil()->getCfgModulesPreferences('abonne', 'suggestion-achat-add');
$suggestion = $form->newBuySuggest($post);
if (!$this->_request->isPost())
return;
if ($form->isValid($suggestion)) {
$post = $this->_request->getPost();
unset($post['submit']);
// $suggestion->save(); always return true without considering webservice answers. UX choice ?
$suggestion->save();
$suggestion = $form->newBuySuggest($post);
try {
$suggestion->sendMail('noreply@'.$this->_request->getHttpHost());
} catch (Zend_Mail_Exception $e) {
$this->_helper->notify($this->_('Aucun courriel envoyé, erreur: %s',
$this->_($e->getMessage())));
}
if (!$form->isValid($suggestion))
return;
$this->_helper->notify($this->_('Suggestion d\'achat enregistrée'));
return $this->_redirect(Class_Url::absolute($this->view->url(['action' => 'suggestion-achat'])));
}
if (!$this->_getConfirmation($suggestion))
return;
// $suggestion->save(); always return true without considering webservice answers. UX choice ?
$suggestion->save();
try {
$suggestion->sendMail('noreply@'.$this->_request->getHttpHost());
} catch (Zend_Mail_Exception $e) {
$this->_helper->notify($this->_('Aucun courriel envoyé, erreur: %s',
$this->_($e->getMessage())));
}
$this->view->form = $form;
$this->view->preferences = Class_Profil::getCurrentProfil()->getCfgModulesPreferences('abonne', 'suggestion-achat-add');
$this->_helper->notify($this->_('Suggestion d\'achat enregistrée'));
return $this->_redirect(Class_Url::absolute($this->view->url(['action' => 'suggestion-achat'])));
}
protected function _getConfirmation($suggestion) {
if (!Class_AdminVar::isSearchRecordBeforeSuggestEnabled())
return true;
if ($this->_getParam('validate_suggestion', null))
return true;
$params = array_filter([$suggestion->getTitre(),
$suggestion->getAuteur()]);
if (!$params = array_filter($params))
return false;
$criteria = (new Class_CriteresRecherche())
->setParams(['page' => 1,
'tri' => Class_CriteresRecherche::SORT_TITLE,
'expressionRecherche' => implode(' ', $params),
'type_doc' => $this->_getPost('DocType')]);
$criteria->setDefaultPageSize(30);
$search_result = Class_MoteurRecherche::getInstance()->lancerRecherche($criteria);
if ($this->view->records = $search_result->fetchRecords())
return false;
return true;
}
......
<?php
$this->openBoite($this->_('Suggérer un achat'));
$send_form_button = '';
if ($this->records) {
echo $this->tag('p', $this->_('Les documents suivants sont dans le catalogue.'));
echo $this->tag('p', $this->_('Votre suggestion en fait-elle partie ?'));
echo $this->button(new Class_Entity(['Text' => $this->_('Oui'),
'Url' => $this->url(['action' => 'suggestion-achat']),
'Attribs' => ['title' => $this->_('Annuler et revenir à la liste des suggestions.')]]));
$send_form_button = new Class_Entity(['Text' => $this->_('Non'),
'Attribs' => ['title' => $this->_('Envoyer la suggestion'),
'onclick' => "var form = $('#suggestion'); form.attr('action', form.attr('action') + '?validate_suggestion=1'); $('#submit').click();"]]);
echo $this->button($send_form_button);
$send_form_button->setText($this->_('Envoyer'));
echo $this->ListeNotices_Mur($this->records);
$submit = $this->form->getElement('submit');
$submit
->setLabel($this->_('Relancer la recherche'))
->setAttribs(['title' => $this->_('Relance la recherche ou envoie la suggestion en cas de recherche infructueuse')]);
}
if (trim($this->preferences['help-text']))
echo $this->tag('div',
$this->preferences['help-text'],
['class' => 'help-text']);
echo $this->renderForm($this->form);
if ($send_form_button)
echo $this->button($send_form_button);
$this->closeBoite();
?>
......@@ -232,6 +232,8 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
'ENABLE_BOOKMARKABLE_SEARCHES_NOTIFY' => Class_AdminVar_Meta::newOnOff($this->_('Les utilisateurs peuvent recevoir les nouveautés de leurs recherches favorites par email'), ['value' => 0]),
Class_AdminVar_UserDoubleDetectOn::KEY => Class_AdminVar_Meta::newMultiInput($this->_('Champs servant à la détection des doublons. Champs possibles : %s', (new Class_AdminVar_UserDoubleDetectOn)->knownAsList()),
['validate' => 'ZendAfi_Validate_UserDoubleDetectOn']),
'SEARCH_RECORD_BEFORE_SUGGEST' => Class_AdminVar_Meta::newOnOff($this->_('Permet à l\'utilisateur de vérifier si la suggestion existe déjà dans le catalogue.'))
];
}
......@@ -1009,6 +1011,11 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
}
public function isSearchRecordBeforeSuggestEnabled() {
return Class_AdminVar::isModuleEnabled('SEARCH_RECORD_BEFORE_SUGGEST');
}
public function shouldKeepLastSigbRecord() {
return Class_AdminVar::isModuleEnabled('KEEP_LAST_SIGB_RECORD');
}
......
......@@ -35,7 +35,7 @@ class Class_MoteurRecherche_Result {
$_facets,
$_criteres_recherche,
$_duration,
$_settings,
$_settings = [],
$_facet_provider,
$_facet_metadata = [],
$_terms;
......
......@@ -31,6 +31,7 @@ class Class_SuggestionAchat extends Storm_Model_Abstract {
protected $_default_attribute_values = ['date_creation' => '',
'titre' => '',
'auteur' => '',
'isbn' => '',
'bib_id' => '',
'commentaire' => '',
'description_url' => ''];
......
......@@ -36,33 +36,45 @@ class Class_WebService_SIGB_Nanook_BuySuggestForm extends ZendAfi_Form_Suggestio
$this
->addElement('text', 'Title', ['label' => $this->_('Titre').' *',
'placeholder' => $this->_('ex: Harry Potter à l\'école des sorciers'),
'size' => 80,
'required' => true,
'allowEmpty' => false])
->addElement('text', 'Author', ['label' => $this->_('Auteur').' *',
'placeholder' => 'ex: Joanne Kathleen Rowling',
'size' => 80,
'required' => true,
'allowEmpty' => false])
->addElement('text', 'Isbn', ['label' => $this->_('Code-barres / ISBN'),
'placeholder' => 'ex: 2-07-054127-4',
'size' => 17])
->addElement('url', 'Url', ['label' => $this->_('URL'),
'placeholder' => 'http://www...',
'size' => 80])
->addElement('textarea', 'Comment', ['label' => '',
'cols' => 70,
'rows' => 10])
->addElement('text', 'Library', ['label' => $this->_('Site'),
'value' => Class_Users::getIdentity()->getLibelleBib(),
'disabled' => true])
->addElement('text',
'Title',
['label' => $this->_('Titre').' *',
'placeholder' => $this->_('ex: Harry Potter à l\'école des sorciers'),
'size' => 80,
'required' => true,
'allowEmpty' => false])
->addElement('text',
'Author',
['label' => $this->_('Auteur').' *',
'placeholder' => 'ex: Joanne Kathleen Rowling',
'size' => 80,
'required' => true,
'allowEmpty' => false])
->addElement('text',
'Isbn',
['label' => $this->_('Code-barres / ISBN'),
'placeholder' => 'ex: 2-07-054127-4',
'size' => 17])
->addElement('url',
'Url',
['label' => $this->_('URL'),
'placeholder' => 'http://www...',
'size' => 80])
->addElement('textarea',
'Comment',
['label' => $this->_('Commentaire'),
'cols' => 70,
'rows' => 10])
->addElement('text',
'Library',
['label' => $this->_('Site'),
'value' => Class_Users::getIdentity()->getLibelleBib(),
'disabled' => true])
->addElement('select', 'DocType', ['label' => $this->_('Type de document').' *',
'multioptions' => $sorted_type_docs,
......
......@@ -74,4 +74,14 @@ class Class_WebService_SIGB_Suggestion extends Class_Entity {
return $this;
}
public function getTitre() {
return $this->getTitle();
}
public function getAuteur() {
return $this->getAuthor();
}
}
\ No newline at end of file
......@@ -22,10 +22,13 @@
class ZendAfi_Form_SuggestionAchat extends ZendAfi_Form_SuggestionAchat_Abstract {
public function init() {
parent::init();
$this
->addElement('text', 'titre', ['label' => $this->_('Titre').' *',
'placeholder' => $this->_('ex: Harry Potter à l\'école des sorciers'),
'size' => 80])
->addElement('text',
'titre',
['label' => $this->_('Titre').' *',
'placeholder' => $this->_('ex: Harry Potter à l\'école des sorciers'),
'size' => 80])
->addElement('text', 'auteur', ['label' => $this->_('Auteur'),
'placeholder' => 'ex: Joanne Kathleen Rowling',
......@@ -35,30 +38,43 @@ class ZendAfi_Form_SuggestionAchat extends ZendAfi_Form_SuggestionAchat_Abstract
'placeholder' => 'ex: 2-07-054127-4',
'size' => 17])
->addElement('select', 'type_doc_id', ['label' => $this->_('Type de document').' *',
'multioptions' => Class_TypeDoc::getUserFriendlyTypeDocs()])
->addElement('url', 'description_url', ['label' => $this->_('Lien internet vers une description'),
'placeholder' => 'ex: http://fr.wikipedia.org/wiki/Harry_Potter_à_l\'école_des_sorciers',
'size' => 80]);
$common_fields = ['titre', 'auteur', 'type_doc_id',
'description_url', 'isbn', 'bib_id'];
->addElement('select',
'type_doc_id',
['label' => $this->_('Type de document').' *',
'multioptions' => Class_TypeDoc::getUserFriendlyTypeDocs()])
->addElement('url',
'description_url',
['label' => $this->_('Lien internet vers une description'),
'placeholder' => 'ex: http://fr.wikipedia.org/wiki/Harry_Potter_à_l\'école_des_sorciers',
'size' => 80]);
$common_fields = ['titre',
'auteur',
'type_doc_id',
'description_url',
'isbn',
'bib_id'];
if ($this->addBibSelector())
$common_fields[] = 'bib_id';
$this->addElement('textarea', 'commentaire', ['label' => '',
'cols' => 70,
'rows' => 10])
$this
->addElement('textarea',
'commentaire',
['label' => $this->_('Commentaire'),
'cols' => 70,
'rows' => 10])
->addDisplayGroup($common_fields,
'suggestion',
['legend' => $this->_('Informations sur le document')])
->addDisplayGroup($common_fields,
'suggestion',
['legend' => $this->_('Informations sur le document')])
->addDisplayGroup(['commentaire'],
'commentaires',
['legend' => $this->_('Pourquoi suggérez-vous ce document ?') . ' *'])
->addDisplayGroup(['commentaire'],
'commentaires',
['legend' => $this->_('Pourquoi suggérez-vous ce document ?') . ' *'])
->addElement('submit', 'submit', ['label' => $this->_('Envoyer')]);
->addElement('submit', 'submit', ['label' => $this->_('Envoyer')]);
}
......@@ -87,5 +103,3 @@ class ZendAfi_Form_SuggestionAchat extends ZendAfi_Form_SuggestionAchat_Abstract
return $this;
}
}
?>
......@@ -18,9 +18,12 @@
* along with BOKEH; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class ZendAfi_Form_SuggestionAchat_Abstract extends ZendAfi_Form {
protected $_user;
public static function forUser($user) {
$sigb_comm = $user->getSIGBComm();
$form = $sigb_comm
......@@ -44,13 +47,10 @@ class ZendAfi_Form_SuggestionAchat_Abstract extends ZendAfi_Form {
}
public function init() {
parent::init();
$this
->setAttrib('id', 'suggestion')
->setAttrib('class', 'zend_form');
}
}
?>
\ No newline at end of file
......@@ -3733,3 +3733,20 @@ a[href*="bookmarked-searches/notify"] img {
opacity: 0.4;
}
.abonne_suggestion-achat-add .colContenu .contenu p {
margin: 0.5em 0;
}
.abonne_suggestion-achat-add .colContenu .contenu button {
margin-right: 1em;
}
.abonne_suggestion-achat-add .colContenu .contenu form + button {
float: left;
margin-left: 15px;
margin-top: -30px;
}
.abonne_suggestion-achat-add .colContenu .contenu .liste_mur + form input[type="submit"] {
margin-left: 105px;
}
\ No newline at end of file
......@@ -227,13 +227,14 @@ class AbonneControllerSuggestionAchatNanookAddPostTest extends AbstractAbonneCon
$mock_transport = new MockMailTransport();
Zend_Mail::setDefaultTransport($mock_transport);
$this->postDispatch('/opac/abonne/suggestion-achat-add', ['DocType' => Class_TypeDoc::LIVRE,
'Site' => '12',
'Title' => 'fu',
'Author' => 'mf',
'Isbn' => '2-07-0541 27_4',
'Url' => '',
'Comment' => 'no']);
$this->postDispatch('/opac/abonne/suggestion-achat-add',
['DocType' => Class_TypeDoc::LIVRE,
'Site' => '12',
'Title' => 'fu',
'Author' => 'mf',
'Isbn' => '2-07-0541 27_4',
'Url' => '',
'Comment' => 'no']);
}
......@@ -281,3 +282,72 @@ class AbonneControllerSuggestionAchatNanookAddPostErrorsTest extends AbstractAbo
$this->assertRedirect();
}
}
class AbonneControllerSuggestionAchatNanookAddPostAndRecordsFoundTest extends AbstractAbonneControllerSuggestionAchatNanookTestCase {
protected $_storm_default_to_volatile = true;
public function setUp() {
parent::setUp();
Class_AdminVar::set('SEARCH_RECORD_BEFORE_SUGGEST', 1);
$mock_transport = new MockMailTransport();
Zend_Mail::setDefaultTransport($mock_transport);
$search_result = $this
->mock()->beStrict()
->whenCalled('fetchRecords')
->answers([$this->fixture('Class_Notice',
['id' => 1,
'titre_principal' => 'Trolls de Troy'])]);
$search_engine = $this
->mock()
->whenCalled('lancerRecherche')
->answers($search_result);
Class_MoteurRecherche::setInstance($search_engine);
$this->postDispatch('/opac/abonne/suggestion-achat-add',
['DocType' => Class_TypeDoc::LIVRE,
'Site' => '12',
'Title' => 'Trolls de Troy',
'Author' => 'connais pas',
'Isbn' => '',
'Url' => '',
'Comment' => '']);
}
/** @test */
public function recordsListShouldContainsTrollsDeTroy() {
$this->assertXPathContentContains('//div', 'Trolls de Troy');
}
/** @test */
public function buttonOuiShouldContainsLinkToSuggestionAchat() {
$this->assertXPathContentContains('//button[contains(@data-url,"suggestion-achat")]', 'Oui');
}
/** @test */
public function buttonNonShouldContainsOnclickSubmitForm() {
$this->assertXPathContentContains('//button[contains(@onclick,"var form = $(\'#suggestion\'); form.attr(\'action\', form.attr(\'action\') + \'?validate_suggestion=1\'); $(\'#submit\').click();")]', 'Non');
}
/** @test */
public function formSuggestionAchatShouldBePresent() {
$this->assertXPath('//form[contains(@action, "/abonne/suggestion-achat-add")]//input[@value="Relancer la recherche"]');
}
/** @test */
public function buttonEnvoyerShouldContainsOnclickSubmitForm() {
$this->assertXPathContentContains('//button[contains(@onclick,"var form = $(\'#suggestion\'); form.attr(\'action\', form.attr(\'action\') + \'?validate_suggestion=1\'); $(\'#submit\').click();")]', 'Envoyer');
}
}
\ No newline at end of file
......@@ -1107,4 +1107,95 @@ class AbonneControllerSuggestionAchatInactiveTest
'les suggestions d\'achats ne sont pas possibles pour le moment.',
$this->_response->getBody());
}
}
class AbonneControllerSuggestionAchatAddPostAndRecordsFoundTest extends AbonneControllerSuggestionAchatAddPostTestCase {
protected $_storm_default_to_volatile = true;
public function setUp() {
parent::setUp();
Class_AdminVar::set('SEARCH_RECORD_BEFORE_SUGGEST', 1);
$mock_transport = new MockMailTransport();
Zend_Mail::setDefaultTransport($mock_transport);
$search_result = $this
->mock()->beStrict()
->whenCalled('fetchRecords')
->answers([$this->fixture('Class_Notice',
['id' => 1,
'titre_principal' => 'Trolls de Troy'])]);
$search_engine = $this
->mock()
->whenCalled('lancerRecherche')
->answers($search_result);
Class_MoteurRecherche::setInstance($search_engine);
$this->postDispatch('/opac/abonne/suggestion-achat-add',
['DocType' => Class_TypeDoc::LIVRE,
'Site' => '12',
'titre' => 'Trolls de Troy']);
}
/** @test */
public function recordsListShouldContainsTrollsDeTroy() {
$this->assertXPathContentContains('//div', 'Trolls de Troy', $this->_response->getBody());
}
}
class AbonneControllerSuggestionAchatAddPostWithValidateSuggestionTest extends AbonneControllerSuggestionAchatAddPostTestCase {
protected $_storm_default_to_volatile = true;
public function setUp() {
parent::setUp();
Class_AdminVar::set('SEARCH_RECORD_BEFORE_SUGGEST', 1);
$mock_transport = new MockMailTransport();
Zend_Mail::setDefaultTransport($mock_transport);
$search_result = $this
->mock()->beStrict()
->whenCalled('fetchRecords')
->answers([$this->fixture('Class_Notice',
['id' => 1,
'titre_principal' => 'Le mystère de la patate. Une enquête de l\'inspecteur Lapou'])]);
$search_engine = $this
->mock()
->whenCalled('lancerRecherche')
->answers($search_result);
Class_MoteurRecherche::setInstance($search_engine);
$this->postDispatch('/opac/abonne/suggestion-achat-add/validate_suggestion/1',
['titre' => 'Le mystère de la patate',
'auteur' => 'Bénédicte Guettier',
'type_doc_id' => Class_TypeDoc::LIVRE,
'commentaire' => 'Une enquête de l\'inspecteur Lapou']);
}
/** @test */
public function responseShouldRedirect() {