diff --git a/VERSIONS_HOTLINE/123018 b/VERSIONS_HOTLINE/123018 new file mode 100644 index 0000000000000000000000000000000000000000..e7504004c1eea385a326e256338a12ae4e62e959 --- /dev/null +++ b/VERSIONS_HOTLINE/123018 @@ -0,0 +1 @@ + - ticket #123018 : Ajout de la variable 'champ_unique_sigb' dans les profils de données pour permettre de dédoublonner les exemplaires sur un sous-champ. \ No newline at end of file diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php index bcd6a0e21a975efed75035f4a6bf11ffb1802693..6491a66541b5ef2ee6456f513a60e910707878c6 100644 --- a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php +++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php @@ -287,6 +287,12 @@ class Cosmo_DataProfileControllerEditUnimarcKohaTest extends Cosmo_DataProfileCo } + /** @test */ + public function itemUniqSubfieldShouldBePresent() { + $this->assertXPath('//form//select[@id="champ_itemid_sigb"]/option[@value="9"][@selected]'); + } + + /** @test */ public function itemCodebarreIn949Dollar6ShouldBePresent() { $this->assertXPath('//form//select[@id="champ_code_barres"]/option[@value="949"][contains(@label,"949$6")]'); diff --git a/cosmogramme/php/classes/classe_notice_integration.php b/cosmogramme/php/classes/classe_notice_integration.php index e350082240cbf46ae998f4c63b787aeddeda7e30..ced79492d0930a853edde813bb905bdca585e35c 100644 --- a/cosmogramme/php/classes/classe_notice_integration.php +++ b/cosmogramme/php/classes/classe_notice_integration.php @@ -799,16 +799,8 @@ class notice_integration { $exemplaires []= $exemplaire; } - if (!empty($code_barres)) { - $unicite_codes_barres = Class_CosmoVar::get(Class_Notice_DoubleFinder::VAR_BARCODE_UNIQ_MODE); - $delete_duplicates_args = ['id_notice' => $id_notice, - 'code_barres' => $code_barres]; - - if ($unicite_codes_barres == Class_CosmoVar::UNIQ_BARCODE_WITHIN_LIBRARY) - $delete_duplicates_args['id_int_bib'] = $this->id_int_bib; - - Class_Exemplaire::deleteBy($delete_duplicates_args); - } + $this->_deleteAllExemplairesWithCodeBarres($code_barres, $id_notice); + $this->_deleteAllExemplairesWithSubfield($exemplaires, $id_notice); foreach($exemplaires as $exemplaire) $exemplaire->save(); @@ -826,6 +818,48 @@ class notice_integration { } + protected function _deleteAllExemplairesWithCodeBarres($code_barres, $id_notice) { + if (empty($code_barres)) + return $this; + + $unicite_codes_barres = Class_CosmoVar::get(Class_Notice_DoubleFinder::VAR_BARCODE_UNIQ_MODE); + $delete_duplicates_args = ['id_notice' => $id_notice, + 'code_barres' => $code_barres]; + + if ($unicite_codes_barres == Class_CosmoVar::UNIQ_BARCODE_WITHIN_LIBRARY) + $delete_duplicates_args['id_int_bib'] = $this->id_int_bib; + + Class_Exemplaire::deleteBy($delete_duplicates_args); + + return $this; + } + + + protected function _deleteAllExemplairesWithSubfield($exemplaires, $id_notice) { + if (null == ($profil = Class_IntProfilDonnees::find($this->id_profil))) + return $this; + + if ('' == ($sous_champ = $profil->getItemUniqSubfield())) + return $this; + + $item_id_sigbs_to_delete = array_map(function($item) use ($sous_champ) + { return $item->getSubfield($sous_champ); }, + $exemplaires); + + $items_to_delete = array_filter( Class_Exemplaire::findAllBy(['id_notice' => $id_notice]), + function($item) use ($item_id_sigbs_to_delete, $sous_champ) + { + return in_array($item->getSubfield($sous_champ), + $item_id_sigbs_to_delete); + }); + + foreach($items_to_delete as $item) + $item->delete(); + + return $this; + } + + public function supprimerExemplaire($id_notice,$ex) { if((!$id_notice) || !($notice = Class_Notice::find($id_notice))) { diff --git a/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php b/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php index 5944f3bdf3e08de98c1231b24978c2248802a17b..cfbbf45795b4798a8276cc11739bd7f97c620b1b 100644 --- a/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php +++ b/cosmogramme/tests/php/classes/KohaRecordIntegrationTest.php @@ -822,3 +822,83 @@ class KohaRecordIntegrationMultipleSECTIntegrationTest extends KohaRecordIntegra $this->assertContains('HSECT0002 HSECT0001 HSECT0003', Class_Notice::find(1)->getFacettes()); } } + + + + +abstract class NoticeIntegrationWithSubfieldDeduplicationTest extends KohaRecordIntegrationTestCase { + public function setUp() { + parent::setUp(); + $this->_notice_integration = new notice_integration(); + $this->loadNotice('unimarc_oblivion'); + + $zone995 = serialize([['code' => '9', 'valeur' => '1']]); + + (new Class_Exemplaire)->setId(23) + ->setIdProfile(45) + ->setIdNotice(1) + ->setIdIntBib(1) + ->setIdOrigine(14370) + ->setZone995($zone995) + ->assertSave(); + + $zone995 = serialize([['code' => '9', 'valeur' => '12'], + ['code' => 'a', 'valeur' => 'BIB']]); + + (new Class_Exemplaire)->setId(24) + ->setIdProfile(45) + ->setIdNotice(1) + ->setIdIntBib(1) + ->setIdOrigine(14370) + ->setZone995($zone995) + ->assertSave(); + + $this->loadNotice('unimarc_oblivion'); + } +} + + + + +class NoticeIntegrationWithSubfieldDeduplicationDollarNineTest extends NoticeIntegrationWithSubfieldDeduplicationTest { + + /** @test */ + public function withDedupShouldHaveTwoItem() { + $this->assertEquals(2,count(Class_Exemplaire::findAllBy(['id_notice' => 1]))); + } + + + /** @test */ + public function itemWithId23ShouldHaveBeenDeleted() { + $this->assertNull(Class_Exemplaire::find(23)); + } + + + /** @test */ + public function itemWithId24ShouldBeKept() { + $this->assertNotNull(Class_Exemplaire::find(24)); + } + + + /** @test */ + public function itemWithId25ShouldHaveBeenCreated() { + $this->assertNotNull(Class_Exemplaire::find(25)); + } +} + + + +class NoticeIntegrationWithSubfieldDeduplicationNoneTest extends NoticeIntegrationWithSubfieldDeduplicationTest { + public function getProfilDonnees() { + return Class_IntProfilDonnees::forKoha() + ->setIdProfil(45) + ->setItemUniqSubfield('') + ->getRawAttributes(); + } + + + /** @test */ + public function withNoDedupShouldHaveThreeItem() { + $this->assertEquals(3,count(Class_Exemplaire::findAllBy(['id_notice' => 1]))); + } +} \ No newline at end of file diff --git a/library/Class/Exemplaire.php b/library/Class/Exemplaire.php index 12d61c09e6758464af731b53a28458abc8f4b288..29cf027b0039348bc403ef4e3c137de15062ef69 100644 --- a/library/Class/Exemplaire.php +++ b/library/Class/Exemplaire.php @@ -64,6 +64,8 @@ class Class_ExemplaireLoader extends Storm_Model_Loader { class Class_Exemplaire extends Storm_Model_Abstract { use Trait_Translator, Trait_TimeSource; + const VAR_UNIQ_SUBFIELDS = 'unicite_sous_champs'; + protected $_table_name = 'exemplaires', $_table_primary = 'id', diff --git a/library/Class/IntProfilDonnees.php b/library/Class/IntProfilDonnees.php index 078d705e6181e730430e19ef6a9af395ea3e73f0..c4f01ab9ec3747c82c467d7503426c7a31f4e64d 100644 --- a/library/Class/IntProfilDonnees.php +++ b/library/Class/IntProfilDonnees.php @@ -43,7 +43,8 @@ class IntProfilDonneesLoader extends Storm_Model_Loader { Class_IntProfilDonnees::FIELD_ITEM_EMPLACEMENT => '', Class_IntProfilDonnees::FIELD_ITEM_ANNEXE => '', Class_IntProfilDonnees::FIELD_ITEM_BUNDLE_ID => '', - Class_IntProfilDonnees::FIELD_ITEM_AVAILABILITY => '']; + Class_IntProfilDonnees::FIELD_ITEM_AVAILABILITY => '', + Class_IntProfilDonnees::FIELD_ITEM_UNIQ_SUBFIELD => '']; } @@ -348,6 +349,7 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { FIELD_ITEM_AVAILABILITY = 'champ_availability', FIELD_ITEM_URL = 'champ_url', FIELD_ITEM_ID_ORIGINE = 'champ_id_origine', + FIELD_ITEM_UNIQ_SUBFIELD = 'champ_itemid_sigb', PROFILE_FIELDS = 'champs', PROFILE_DOC_TYPES = 'type_doc', @@ -616,7 +618,8 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { self::FIELD_ITEM_GENRE => '', self::FIELD_ITEM_SECTION => 'q', self::FIELD_ITEM_EMPLACEMENT => 'e', - self::FIELD_ITEM_ANNEXE => 'b'], + self::FIELD_ITEM_ANNEXE => 'b', + self::FIELD_ITEM_UNIQ_SUBFIELD => '9'], ['zone' => '801', 'champ' => 'c', 'format' => self::NOVELTY_DATE_FORMAT_AAAA_MM_JJ, @@ -1015,6 +1018,11 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { } + public function setItemUniqSubfield($value) { + return $this->setItemField(self::FIELD_ITEM_UNIQ_SUBFIELD, $value); + } + + public function getBarCodeField() { return unserialize($this->getAttributs())[0][self::FIELD_ITEM_BARCODE]; } @@ -1120,6 +1128,10 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract { } + public function getItemUniqSubfield() { + return $this->getProfilePrefs()->getItemUniqSubfield(); + } + public function getUrlLabel() { return $this->getProfilePrefs()->getItemUrl()['url_zone'][0]; } diff --git a/library/Class/ProfilePrefs.php b/library/Class/ProfilePrefs.php index d331588433817d7ba85786aa6d2491a5885b39f2..c67d139bab3174d59d5dbbe1c8d9275cb6481d01 100644 --- a/library/Class/ProfilePrefs.php +++ b/library/Class/ProfilePrefs.php @@ -207,6 +207,11 @@ class Class_ProfilePrefs extends Class_Entity { } + public function getItemUniqSubfield() { + return $this->getItemPrefs()[Class_IntProfilDonnees::FIELD_ITEM_UNIQ_SUBFIELD]; + } + + public function getItemIdOriginePrefs() { return $this->getItemPrefs()[Class_IntProfilDonnees::FIELD_ITEM_ID_ORIGINE]; } diff --git a/library/Class/ProfileSerializer/DublinCoreRecords.php b/library/Class/ProfileSerializer/DublinCoreRecords.php index 3b58f8ae852bde6876b439b3131a2202d475b681..3bbf7b14d12e73b496a72e3bc1d31ec7cc8c30f7 100644 --- a/library/Class/ProfileSerializer/DublinCoreRecords.php +++ b/library/Class/ProfileSerializer/DublinCoreRecords.php @@ -64,7 +64,8 @@ class Class_ProfileSerializer_DublinCoreRecords extends Class_ProfileSerializer_ Class_IntProfilDonnees::FIELD_ITEM_ANNEXE => '', Class_IntProfilDonnees::FIELD_ITEM_AVAILABILITY => '', Class_IntProfilDonnees::FIELD_ITEM_URL => ['zone' => '995', - 'champ' => 'u']]; + 'champ' => 'u'], + Class_IntProfilDonnees::FIELD_ITEM_UNIQ_SUBFIELD => '']; } diff --git a/library/Class/ProfileSerializer/Numel.php b/library/Class/ProfileSerializer/Numel.php index e2e31f50f85003620c4de5e5ef77631a1dd267f9..11c4a845b34c217b262bb9cd7447477dc1d5924a 100644 --- a/library/Class/ProfileSerializer/Numel.php +++ b/library/Class/ProfileSerializer/Numel.php @@ -51,6 +51,7 @@ class Class_ProfileSerializer_Numel extends Class_ProfileSerializer_DublinCoreRe Class_IntProfilDonnees::FIELD_ITEM_ANNEXE => '8', Class_IntProfilDonnees::FIELD_ITEM_AVAILABILITY => '', Class_IntProfilDonnees::FIELD_ITEM_URL => ['zone' => '995', - 'champ' => 'u']]; + 'champ' => 'u'], + Class_IntProfilDonnees::FIELD_ITEM_UNIQ_SUBFIELD => '']; } } diff --git a/library/Class/ProfileSerializer/UnimarcRecord.php b/library/Class/ProfileSerializer/UnimarcRecord.php index f9baf6a91e38cb5fe137bd5652fcc785a1599b63..fbc5bf60f280e8494ef58059f03a585c4bc9310d 100644 --- a/library/Class/ProfileSerializer/UnimarcRecord.php +++ b/library/Class/ProfileSerializer/UnimarcRecord.php @@ -41,6 +41,7 @@ class Class_ProfileSerializer_UnimarcRecord extends Class_ProfileSerializer_Abst public function populateForm($form) { return $form ->populateItemZone() + ->populateItemUniqId() ->populateItemBarCode() ->populateItemCote() ->populateItemDocType() diff --git a/library/ZendAfi/Form/Cosmo/DataProfile.php b/library/ZendAfi/Form/Cosmo/DataProfile.php index 5ec6bdfcea0c6c4455a1448bdf0d8d82e3e6883f..719021964d79dc9d15c53aa45577467242d4056c 100644 --- a/library/ZendAfi/Form/Cosmo/DataProfile.php +++ b/library/ZendAfi/Form/Cosmo/DataProfile.php @@ -227,7 +227,8 @@ class ZendAfi_Form_Cosmo_DataProfile extends ZendAfi_Form { 'champ_emplacement' => $this->_('emplacement'), 'champ_annexe' => $this->_('annexe'), 'champ_availability' => $this->_('disponibilité'), - 'champ_bundle_id' => $this->_('identifiant de la notice de lot')]; + 'champ_bundle_id' => $this->_('identifiant de la notice de lot'), + Class_IntProfilDonnees::FIELD_ITEM_UNIQ_SUBFIELD => $this->_('identifiant unique dans le SIGB')]; return $this ->addElement('text', @@ -323,6 +324,13 @@ class ZendAfi_Form_Cosmo_DataProfile extends ZendAfi_Form { } + public function populateItemUniqId() { + $this->getElement(Class_IntProfilDonnees::FIELD_ITEM_UNIQ_SUBFIELD) + ->setValue($this->_profile_prefs->getItemUniqSubfield()); + return $this; + } + + public function populateItemBarCode() { $this->champ_code_barres->setValue($this->_profile_prefs->getItemBarCode()); return $this; diff --git a/tests/db/UpgradeDBTest.php b/tests/db/UpgradeDBTest.php index ac83309299a185e9258894ce9400b3274f3ee39d..3b12f3cb61de60c39c9b166823cb2a554cc59198 100644 --- a/tests/db/UpgradeDBTest.php +++ b/tests/db/UpgradeDBTest.php @@ -2335,7 +2335,6 @@ class UpgradeDB_357_Test extends UpgradeDBTestCase { } - /** @test */ public function cosmoVarsShouldContainsOtherIndexFields() { $other_index_fields = $this->query('select * from variables where clef="other_index_fields"')->fetch(); diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTestCase.php b/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTestCase.php index 0da45f295185d80a69fd8bc1baadab5f24b301ad..70c7d4f5c26c0b9e2390c0fd2bd648bf2769beec 100644 --- a/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTestCase.php +++ b/tests/library/Class/Cosmogramme/Integration/PhaseNoticeTestCase.php @@ -66,7 +66,8 @@ abstract class PhaseNoticeTestCase extends Class_Cosmogramme_Integration_PhaseTe 'champ_genre' => '', 'champ_section' => 'q', 'champ_emplacement' => '6', - 'champ_annexe' => '8' + 'champ_annexe' => '8', + 'champ_itemid_sigb' => '', ], 4 => ['zone' => '995', 'champ' => '4',