From 19a4eb996b8646b4bbf8a7ed7b53bf9247b289f9 Mon Sep 17 00:00:00 2001
From: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Date: Mon, 24 Apr 2023 15:30:31 +0200
Subject: [PATCH] Bug 30708: Allow attributes to be multivalued

This is not working as it, but we are going to fix the problem when
working on the "Set default values for items added in batch to a train"

Sponsored-by: BULAC - http://www.bulac.fr/

Signed-off-by: BULAC - http://www.bulac.fr/
Signed-off-by: Heather Hernandez <heather_hernandez@nps.gov>
Signed-off-by: Laurence Rault <laurence.rault@biblibre.com>
---
 .../data/mysql/atomicupdate/bug_30708.pl      |  3 +-
 installer/data/mysql/kohastructure.sql        |  3 +-
 .../Preservation/TrainsFormAddItem.vue        | 78 ++++++++++++++-----
 .../components/Preservation/TrainsShow.vue    | 19 ++---
 t/cypress/integration/Preservation/Trains.ts  |  6 ++
 5 files changed, 78 insertions(+), 31 deletions(-)

diff --git a/installer/data/mysql/atomicupdate/bug_30708.pl b/installer/data/mysql/atomicupdate/bug_30708.pl
index 2817d9776e7..2f80c19c7b7 100755
--- a/installer/data/mysql/atomicupdate/bug_30708.pl
+++ b/installer/data/mysql/atomicupdate/bug_30708.pl
@@ -97,10 +97,11 @@ return {
         unless ( TableExists('preservation_processing_attributes_items') ) {
             $dbh->do(q{
                 CREATE TABLE `preservation_processing_attributes_items` (
+                  `processing_attribute_item_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'primary key',
                   `processing_attribute_id` int(11) NOT NULL COMMENT 'link with preservation_processing_attributes',
                   `train_item_id` int(11) NOT NULL COMMENT 'link with preservation_trains_items',
                   `value` varchar(255) NULL COMMENT 'value for this attribute',
-                  PRIMARY KEY (`processing_attribute_id`,`train_item_id`),
+                  PRIMARY KEY (`processing_attribute_item_id`),
                   CONSTRAINT `preservation_processing_attributes_items_ibfk_1` FOREIGN KEY (`processing_attribute_id`) REFERENCES `preservation_processing_attributes` (`processing_attribute_id`) ON DELETE CASCADE ON UPDATE CASCADE,
                   CONSTRAINT `preservation_processing_attributes_items_ibfk_2` FOREIGN KEY (`train_item_id`) REFERENCES `preservation_trains_items` (`train_item_id`) ON DELETE CASCADE ON UPDATE CASCADE
                 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql
index e869ea57b84..cf207448cd8 100644
--- a/installer/data/mysql/kohastructure.sql
+++ b/installer/data/mysql/kohastructure.sql
@@ -4825,10 +4825,11 @@ DROP TABLE IF EXISTS `preservation_processing_attributes_items`;
 /*!40101 SET @saved_cs_client     = @@character_set_client */;
 /*!40101 SET character_set_client = utf8 */;
 CREATE TABLE `preservation_processing_attributes_items` (
+  `processing_attribute_item_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'primary key',
   `processing_attribute_id` int(11) NOT NULL COMMENT 'link with preservation_processing_attributes',
   `train_item_id` int(11) NOT NULL COMMENT 'link with preservation_trains_items',
   `value` varchar(255) NULL COMMENT 'value for this attribute',
-  PRIMARY KEY (`processing_attribute_id`,`train_item_id`),
+  PRIMARY KEY (`processing_attribute_item_id`),
   CONSTRAINT `preservation_processing_attributes_items_ibfk_1` FOREIGN KEY (`processing_attribute_id`) REFERENCES `preservation_processing_attributes` (`processing_attribute_id`) ON DELETE CASCADE ON UPDATE CASCADE,
   CONSTRAINT `preservation_processing_attributes_items_ibfk_2` FOREIGN KEY (`train_item_id`) REFERENCES `preservation_trains_items` (`train_item_id`) ON DELETE CASCADE ON UPDATE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Preservation/TrainsFormAddItem.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Preservation/TrainsFormAddItem.vue
index 7294fee78fc..0b1f010998a 100644
--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Preservation/TrainsFormAddItem.vue
+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Preservation/TrainsFormAddItem.vue
@@ -60,6 +60,29 @@
                                     v-model="attribute.value"
                                 />
                             </span>
+                            <a
+                                v-if="
+                                    attributes.length == counter + 1 ||
+                                    attributes[counter + 1]
+                                        .processing_attribute_id !=
+                                        attribute.processing_attribute_id
+                                "
+                                class="btn btn-link"
+                                @click="
+                                    addAttribute(
+                                        attribute.processing_attribute_id
+                                    )
+                                "
+                                ><font-awesome-icon icon="plus" />
+                                {{ $__("Add") }}</a
+                            >
+                            <a
+                                v-else
+                                class="btn btn-link"
+                                @click="removeAttribute(counter)"
+                                ><font-awesome-icon icon="minus" />
+                                {{ $__("Remove") }}</a
+                            >
                         </li>
                     </ol>
                 </fieldset>
@@ -238,28 +261,34 @@ export default {
                 error => {}
             )
             this.updateDefaultValues()
-            this.attributes = this.processing.attributes.map(attribute => {
-                let value = ""
+            this.attributes = []
+            this.processing.attributes.forEach(attribute => {
+                let values = []
                 if (!apply_default_value) {
-                    let existing_attribute = this.train_item.attributes.find(
-                        a =>
-                            a.processing_attribute_id ==
-                            attribute.processing_attribute_id
-                    )
-                    if (existing_attribute) {
-                        value = existing_attribute.value
-                    }
+                    this.train_item.attributes
+                        .filter(
+                            a =>
+                                a.processing_attribute_id ==
+                                attribute.processing_attribute_id
+                        )
+                        .forEach(a => values.push(a.value))
                 } else if (attribute.type == "db_column") {
-                    value =
+                    values.push(
                         this.default_values[attribute.processing_attribute_id]
+                    )
+                } else {
+                    values.push("")
                 }
-                return {
-                    processing_attribute_id: attribute.processing_attribute_id,
-                    name: attribute.name,
-                    type: attribute.type,
-                    option_source: attribute.option_source,
-                    value,
-                }
+                values.forEach(value =>
+                    this.attributes.push({
+                        processing_attribute_id:
+                            attribute.processing_attribute_id,
+                        name: attribute.name,
+                        type: attribute.type,
+                        option_source: attribute.option_source,
+                        value,
+                    })
+                )
             })
             const client_av = APIClient.authorised_values
             let av_cat_array = this.processing.attributes
@@ -280,6 +309,19 @@ export default {
                 })
                 .then(() => this.loaded())
         },
+        addAttribute(processing_attribute_id) {
+            let last_index = this.attributes.findLastIndex(
+                attribute =>
+                    attribute.processing_attribute_id == processing_attribute_id
+            )
+            let new_attribute = (({ value, ...keepAttrs }) => keepAttrs)(
+                this.attributes[last_index]
+            )
+            this.attributes.splice(last_index + 1, 0, new_attribute)
+        },
+        removeAttribute(counter) {
+            this.attributes.splice(counter, 1)
+        },
         onSubmit(e) {
             e.preventDefault()
 
diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Preservation/TrainsShow.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Preservation/TrainsShow.vue
index daea14636a5..3126273b80f 100644
--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Preservation/TrainsShow.vue
+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Preservation/TrainsShow.vue
@@ -263,21 +263,15 @@ export default {
                             let item_row = {}
                             this.train.default_processing.attributes.forEach(
                                 attribute => {
-                                    let v = ""
-                                    if (item.attributes.length >= 0) {
-                                        let a = item.attributes.find(
+                                    item_row[
+                                        attribute.processing_attribute_id
+                                    ] = item.attributes
+                                        .filter(
                                             a =>
                                                 a.processing_attribute_id ==
                                                 attribute.processing_attribute_id
                                         )
-                                        if (a) {
-                                            v = a.value
-                                        }
-                                    }
-
-                                    item_row[
-                                        attribute.processing_attribute_id
-                                    ] = v
+                                        .map(a => a.value)
                                 }
                             )
                             item_row.item = item
@@ -294,6 +288,9 @@ export default {
                                 name: a.name,
                                 title: a.name,
                                 data: a.processing_attribute_id,
+                                render: (data, type, row) => {
+                                    return data.join("<br/>")
+                                },
                             })
                         )
                         this.item_table.columns.push({
diff --git a/t/cypress/integration/Preservation/Trains.ts b/t/cypress/integration/Preservation/Trains.ts
index 94bd7732966..fb5203e73bc 100644
--- a/t/cypress/integration/Preservation/Trains.ts
+++ b/t/cypress/integration/Preservation/Trains.ts
@@ -99,6 +99,12 @@ function get_train_items() {
                 processing_attributes[0].processing_attribute_id,
             value: "Argentina",
         },
+        {
+            processing_attribute: processing_attributes[0],
+            processing_attribute_id:
+                processing_attributes[0].processing_attribute_id,
+            value: "Paraguay",
+        },
         {
             processing_attribute: processing_attributes[1],
             processing_attribute_id:
-- 
2.25.1