From 7b21100bd15f76a954de01cd74f2b6975a1c1ed5 Mon Sep 17 00:00:00 2001
From: gloas <gloas@afi-sa.fr>
Date: Tue, 20 Nov 2018 15:24:51 +0100
Subject: [PATCH] hotline #81316 fix duplication of serialArticles

---
 .../php/classes/classe_notice_integration.php |  64 ++++-------
 .../php/classes/classe_profil_donnees.php     |   2 +-
 cosmogramme/php/classes/classe_unimarc.php    |   6 +-
 .../NoticeIntegrationSerialArticlesTest.php   | 101 +++++++++++++++++-
 .../unimarc_serial_article_l_etudiant.txt     |   1 +
 library/Class/Notice/SerialArticles.php       |  53 ++++++++-
 library/Class/TypeDoc.php                     |   1 +
 7 files changed, 174 insertions(+), 54 deletions(-)
 create mode 100644 cosmogramme/tests/php/classes/unimarc_serial_article_l_etudiant.txt

diff --git a/cosmogramme/php/classes/classe_notice_integration.php b/cosmogramme/php/classes/classe_notice_integration.php
index f3df44dde5e..9ae4bd84284 100644
--- a/cosmogramme/php/classes/classe_notice_integration.php
+++ b/cosmogramme/php/classes/classe_notice_integration.php
@@ -168,7 +168,7 @@ class notice_integration {
 
     $this->notice=$this->analyseur->getNoticeIntegration();
 
-    if($this->notice['type_doc'] == Class_TypeDoc::LIVRE_NUM) {
+    if($this->notice['type_doc'] == Class_TypeDoc::SERIAL_ARTICLE) {
       $this->ecrireArticlePeriodique();
       return;
     }
@@ -220,7 +220,7 @@ class notice_integration {
                   "date_maj"=>date("Y-m-d")];
 
         foreach($this->notice["articles_periodiques"]["articles"] as $id_unimarc) {
-          $clef_unimarc = intval($id_unimarc);
+          $clef_unimarc = (int) $id_unimarc;
 
           if(!$clef_unimarc) {
             $this->notice["warnings"][] = ["Identifiant article de périodique incorrect",
@@ -228,15 +228,12 @@ class notice_integration {
             continue;
           }
 
-          $existe = $sql->fetchOne("select count(*) from notices_articles where clef_unimarc='$clef_unimarc'");
-          if($existe){
-            unset($enreg["clef_unimarc"]);
-            $sql->update("update notices_articles set @SET@ where clef_unimarc='$clef_unimarc'",$enreg);
-          }
-          else {
-            $enreg["clef_unimarc"]=$clef_unimarc;
-            $sql->insert("notices_articles",$enreg);
-          }
+          $instance = new Class_Entity(['UnimarcKey' => $clef_unimarc,
+                                        'NameKey' => $this->notice['articles_periodiques']['clef_chapeau'],
+                                        'NumberKey' => $this->notice['articles_periodiques']['clef_numero'],
+                                        'Updated' => date('Y-m-d'),
+                                        'Quality' => $this->qualite_bib]);
+          Class_Notice_SerialArticles::updateOrInsert($instance);
         }
       }
     }
@@ -929,42 +926,25 @@ class notice_integration {
   }
 
 
-// --------------------------------------------------------------------------------
-// Ecrit une notice : article de périodique
-// --------------------------------------------------------------------------------
-  private function ecrireArticlePeriodique() {
+  protected function ecrireArticlePeriodique() {
     if( 1 == $this->notice["statut"])
       return $this->deleteRecordArticles();
 
-    $title_key = hash('crc32b', $this->notice['titre_princ']);
-
-    $unimarc_key = $this->notice["clef_unimarc"]
-      ? $this->notice["clef_unimarc"]
-      : $title_key;
+    $instance = new Class_Entity(['Title' => $this->notice['titre_princ'],
+                                  'NameKey' => $this->notice['clef_chapeau'],
+                                  'NumberKey' => $this->notice['clef_numero'],
+                                  'ArticleKey' => $this->notice['clef_article'],
+                                  'UnimarcKey' => $this->notice['clef_unimarc'],
+                                  'Unimarc' => $this->notice['unimarc'],
+                                  'Updated' => dateDuJour(0),
+                                  'Quality' => $this->qualite_bib]);
 
-    $article_from_record = Class_Notice_SerialArticles::newInstance(['clef_chapeau' => $this->notice["clef_chapeau"],
-                                                                     'clef_numero' => $this->notice["clef_numero"],
-                                                                     'clef_unimarc' => $unimarc_key,
-                                                                     'unimarc' => $this->notice['unimarc'],
-                                                                     'date_maj' => dateDuJour(0),
-                                                                     'qualite' => $this->qualite_bib,
-                                                                     'clef_article' => $this->notice['clef_article']]);
-
-    if(!$this->notice['clef_unimarc']) {
-      $common_attribs = ['clef_chapeau' => $this->notice['clef_chapeau'],
-                         'clef_numero' => $this->notice['clef_numero']];
-
-      if(!$article = Class_Notice_SerialArticles::findFirstBy(array_merge($common_attribs, ['clef_unimarc' => $title_key])))
-        $article = Class_Notice_SerialArticles::findFirstBy(array_merge($common_attribs, ['clef_article' => $this->notice['clef_article'],
-                                                                                          'clef_unimarc' => '']));
-      return $this->updateOrInsertArticle($article, $article_from_record);
-    }
+    if (!$serial = Class_Notice_SerialArticles::updateOrInsert($instance))
+      return;
 
-    if ($article = Class_Notice_SerialArticles::findFirstBy(['clef_unimarc' => $this->notice['clef_unimarc']])) {
-        $article_from_record->setClefChapeau($article->getClefChapeau());
-        $article_from_record->setClefNumero($article->getClefNumero());
-        return $this->updateOrInsertArticle($article, $article_from_record);
-    }
+    $this->statut = $serial->isNew()
+      ? static::RECORD_INSERT
+      : static::RECORD_RENEW;
   }
 
 
diff --git a/cosmogramme/php/classes/classe_profil_donnees.php b/cosmogramme/php/classes/classe_profil_donnees.php
index 43ff6754cdd..e5beeeb933c 100644
--- a/cosmogramme/php/classes/classe_profil_donnees.php
+++ b/cosmogramme/php/classes/classe_profil_donnees.php
@@ -216,7 +216,7 @@ class profil_donnees {
 			return ['code' => 2, 'libelle' => 'Périodiques'];
 
 		if ($this->isArticlePeriodique($label))
-			return ['code' => 100, 'libelle' => 'Article de périodique'];
+			return ['code' => Class_TypeDoc::SERIAL_ARTICLE, 'libelle' => 'Article de périodique'];
 
 		// First we check 995$r subfield.
 		foreach($this->attributs[0]["type_doc"] as $td)	{
diff --git a/cosmogramme/php/classes/classe_unimarc.php b/cosmogramme/php/classes/classe_unimarc.php
index acc28bbf3b9..4915b3929f5 100644
--- a/cosmogramme/php/classes/classe_unimarc.php
+++ b/cosmogramme/php/classes/classe_unimarc.php
@@ -116,7 +116,7 @@ class notice_unimarc extends iso2709_record {
 
   public function getNoticeIntegration() {
     $type_doc = $this->getTypeDocAsArray();
-    if ($type_doc['code'] == 100)
+    if ($type_doc['code'] == Class_TypeDoc::SERIAL_ARTICLE)
       return $this->getNoticeIntegrationArticlePeriodique();
 
     if ($type_doc['code'] == 2)
@@ -237,8 +237,8 @@ class notice_unimarc extends iso2709_record {
   public function getNoticeIntegrationArticlePeriodique()
   {
     // type de doc
-    $notice["type_doc"] = 100;
-    $notice["infos_type_doc"] = ["code"=>100, 'libelle'=>"article de périodique"];
+    $notice["type_doc"] = Class_TypeDoc::SERIAL_ARTICLE;
+    $notice["infos_type_doc"] = ["code"=> Class_TypeDoc::SERIAL_ARTICLE, 'libelle'=>"article de périodique"];
 
     // statut
     $notice["statut"] = $this->getStatut();
diff --git a/cosmogramme/tests/php/classes/NoticeIntegrationSerialArticlesTest.php b/cosmogramme/tests/php/classes/NoticeIntegrationSerialArticlesTest.php
index b93a536ed30..05afa254ecf 100644
--- a/cosmogramme/tests/php/classes/NoticeIntegrationSerialArticlesTest.php
+++ b/cosmogramme/tests/php/classes/NoticeIntegrationSerialArticlesTest.php
@@ -23,23 +23,116 @@ require_once 'classe_notice_integration.php';
 require_once 'ModelTestCase.php';
 
 
+/** hotline #81316 **/
 class NoticeIntegrationSerialArticlesTraiteNoticeTest extends ModelTestCase {
+
+  protected
+    $_storm_default_to_volatile = true,
+    $_serial;
+
+
   public function setUp() {
     parent::setUp();
 
+    $this->fixture('Class_IntBib',
+                   ['id' => 36,
+                    'libelle' => 'Ma biliothèque',
+                    'qualite' => 4
+                   ]);
+
+    $bib = $this->fixture('Class_Bib',
+                          ['id_site' => 36,
+                           'libelle' => 'Ma biliothèque',
+                           'ville' => 'Annecy',
+                           'visibilite' => Class_Bib::V_DATA]);
+
+    $int_profil =
+      $this->fixture('Class_IntProfilDonnees',
+                     ['id' => 812,
+                      'libelle' => 'notices',
+                      'accents' => Class_IntProfilDonnees::ENCODING_ISO2709,
+                      'rejet_periodiques' => 1,
+                      'id_article_periodique' => 2,
+                      'type_fichier' => Class_IntProfilDonnees::FT_RECORDS,
+                      'format' => Class_IntProfilDonnees::FORMAT_UNIMARC,
+                      'attributs' => [
+                                      [Class_IntProfilDonnees::PROFILE_DOC_TYPES => [['code' => '2',
+                                                                                      'label' => 'as',
+                                                                                      'zone_995' => 'REV;']],
+                                       Class_IntProfilDonnees::FIELD_ITEM_BARCODE => 'f',
+                                       Class_IntProfilDonnees::FIELD_ITEM_COTE => 'k',
+                                       Class_IntProfilDonnees::FIELD_ITEM_TYPE_DOC => 'r',
+                                       Class_IntProfilDonnees::FIELD_ITEM_GENRE => '',
+                                       Class_IntProfilDonnees::FIELD_ITEM_SECTION => 'q',
+                                       Class_IntProfilDonnees::FIELD_ITEM_EMPLACEMENT => 'u',
+                                       Class_IntProfilDonnees::FIELD_ITEM_ANNEXE => 'a'],
+                                      ['zone' => '995',
+                                       'champ' => 'n',
+                                       'format' => Class_IntProfilDonnees::NOVELTY_DATE_FORMAT_VALUES,
+                                       'jours' => '0',
+                                       'valeurs' => 'nouveaute']
+                      ]]);
+
     $integration = new notice_integration;
-    $integration->setParamsIntegration(1, 0, 1);
+    $integration->setParamsIntegration(36,
+                                       Class_Cosmogramme_Integration::TYPE_OPERATION_INCREMENT,
+                                       812);
 
     $runner = $this->mock();
 
     $integration->setServiceRunner($runner);
     $integration->traiteNotice(file_get_contents(__DIR__ . '/unimarc_serial_article.txt'));
-    $integration->traiteNotice(file_get_contents(__DIR__ . '/unimarc_serial_article.txt'));
+    $integration->traiteNotice(file_get_contents(__DIR__ . '/unimarc_serial_article_l_etudiant.txt'));
+    $integration->traiteNotice(file_get_contents(__DIR__ . '/unimarc_serial_article_l_etudiant.txt'));
+
+    $this->_serial = Class_Notice_SerialArticles::findFirstBy(['clef_unimarc' => 3254100]);
+  }
+
+
+  /** @test */
+  public function fifteenSerialArticleShouldExists() {
+    $this->assertEquals(15, count(Class_Notice_SerialArticles::findAllBy([])));
+  }
+
+
+  /** @test */
+  public function clefChapeauShouldBeLEtudiant() {
+    $this->assertEquals('L ETUDIANT', $this->_serial->getClefChapeau());
+  }
+
+
+  /** @test */
+  public function clefNumeroShouldBe425() {
+    $this->assertEquals('425', $this->_serial->getClefNumero());
+  }
+
+
+  /** @test */
+  public function clefUnimarcShouldBe3254100() {
+    $this->assertEquals('3254100', $this->_serial->getClefUnimarc());
+  }
+
+
+  /** @test */
+  public function clefArticleShouldBePublicOuPrive() {
+    $this->assertEquals('PUBLIC OU PRIVE  QUE', $this->_serial->getClefArticle());
+  }
+
+
+  /** @test */
+  public function unimarcShouldBeSet() {
+    $this->assertNotNull($this->_serial->getUnimarc());
+  }
+
+
+  /** @test */
+  public function dataMajShouldBeSet() {
+    $this->assertNotNull($this->_serial->getDateMaj());
   }
 
 
   /** @test */
-  public function afterMultipleTraiteNoticeOnlyOnSerialArticleShouldExists() {
-    $this->assertEquals(1, count(Class_Notice_SerialArticles::count()));
+  public function qualiteShouldBe4() {
+    $this->assertEquals('4', $this->_serial->getQualite());
   }
 }
\ No newline at end of file
diff --git a/cosmogramme/tests/php/classes/unimarc_serial_article_l_etudiant.txt b/cosmogramme/tests/php/classes/unimarc_serial_article_l_etudiant.txt
new file mode 100644
index 00000000000..9fa6fda4f92
--- /dev/null
+++ b/cosmogramme/tests/php/classes/unimarc_serial_article_l_etudiant.txt
@@ -0,0 +1 @@
+01484naa0 2200181   450 0010008000001000041000082000082000492150013001313070006001443300823001506060038009736060060010116060078010716060034011496060055011837000034012388010030012723254100  a20180209d2018    uu|y0frey0103    ba1 aPublic ou privé, quel lycée pour vous ?b[périodique]fCatherine de Coppet  app.12-16  a5  aC'est un débat qui agite souvent les familles à la fin de la classe de troisième : aller dans un lycée public ou dans un lycée privé ? La France compte à peine plus de lycées publics que de lycées privés, tous types d'établissements confondus (généraux, technologiques et professionnels), alors que cet écart est beaucoup plus important, en faveur du public, au niveau élémentaire ou au collège. Même si jusqu'à la troisième, vous avez passé toute votre scolarité dans le public, la question pourra donc se poser pour vous d'intégrer un lycée privé à un moment de votre parcours. Mais comment vous décider ? Au-delà des clichés persistants, qui collent à la peau du public comme du privé, "l'Etudiant" a recueilli les témoignages de lycéens pour vous aider à choisir. Suivez le guide.| 32303668aLycées32557578xTarifs| 32301864aEcoles privées32419532xProgrammes d'études| 33254101aEtablissements publics locaux d'enseignement32518476xAdmission| 31115046aOrientation scolaire| 32511231aElèves du secondaire31057652xEnquêtes |33204968aCoppetbCatherine de 0aFRbIndexpressec20180209
diff --git a/library/Class/Notice/SerialArticles.php b/library/Class/Notice/SerialArticles.php
index 0d6b1686db8..2b6823ab1a5 100644
--- a/library/Class/Notice/SerialArticles.php
+++ b/library/Class/Notice/SerialArticles.php
@@ -19,8 +19,53 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
+class NoticeSerialArticlesLoader extends Storm_Model_Loader {
+  public function updateOrInsert($instance) {
+    $serial = ($serial = Class_Notice_SerialArticles::findWith($instance))
+      ? $serial
+      : Class_Notice_SerialArticles::newInstance(['qualite' => $instance->getQuality()]);
+
+    if ($serial->getQualite() < $instance->getQuality())
+      return;
+
+    $update_columns = array_filter(['clef_chapeau' => $instance->getNameKey(),
+                                    'clef_numero' => $instance->getNumberKey(),
+                                    'clef_article' => $instance->getArticleKey(),
+                                    'clef_unimarc' => $instance->getUnimarcKey(),
+                                    'unimarc' => $instance->getUnimarc(),
+                                    'date_maj' => $instance->getUpdated(),
+                                    'qualite' => $instance->getQuality()]);
+
+    $serial->updateAttributes($update_columns);
+    $serial->save();
+    return $serial;
+  }
+
+
+  public function findWith($instance) {
+    if ($unimarc_key = $instance->getUnimarcKey())
+      return Class_Notice_SerialArticles::findFirstBy(['clef_unimarc' => $unimarc_key]);
+
+    $unimarc_key = hash('crc32b',
+                        $instance->getTitle());
+
+    if($article = Class_Notice_SerialArticles::findFirstBy(['clef_chapeau' => $instance->getNameKey(),
+                                                            'clef_numero' => $instance->getNumberKey(),
+                                                            'clef_unimarc' => $unimarc_key]))
+      return $article;
+
+    return Class_Notice_SerialArticles::findFirstBy(['clef_chapeau' => $instance->getNameKey(),
+                                                     'clef_numero' => $instance->getNumberKey(),
+                                                     'clef_article' => $instance->getArticleKey(),
+                                                     'clef_unimarc' => '']);
+  }
+}
+
+
+
 class Class_Notice_SerialArticles extends Storm_Model_Abstract {
   protected
+    $_loader_class = 'NoticeSerialArticlesLoader',
     $_table_name = 'notices_articles',
     $_table_primary = 'id_article';
 
@@ -29,7 +74,9 @@ class Class_Notice_SerialArticles extends Storm_Model_Abstract {
                                           'clef_numero' => '',
                                           'clef_article' => '',
                                           'clef_unimarc' => '',
-                                          'unimarc' => ''];
+                                          'unimarc' => '',
+                                          'qualite' => '',
+                                          'date_maj' => ''];
 
 
   public function validate() {
@@ -39,6 +86,4 @@ class Class_Notice_SerialArticles extends Storm_Model_Abstract {
     if (!$this->getClefNumero())
       $this->addError('Clé numero requise');
   }
-}
-
-?>
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/library/Class/TypeDoc.php b/library/Class/TypeDoc.php
index c78e159c9b2..243e3bcc36b 100644
--- a/library/Class/TypeDoc.php
+++ b/library/Class/TypeDoc.php
@@ -308,6 +308,7 @@ class Class_TypeDoc extends Storm_Model_Abstract {
   const ARTICLE = 8;
   const RSS = 9;
   const SITE = 10;
+  const SERIAL_ARTICLE = 100;
   const LIVRE_NUM = 100;
   const DIAPORAMA = 101;
   const EPUB = 102;
-- 
GitLab