From f6adc294fe9dd8df7cf0a55701f68ad92a821a50 Mon Sep 17 00:00:00 2001 From: Jake Deery Date: Wed, 4 Sep 2024 14:52:58 +0000 Subject: [PATCH] Bug 37576: Add additional fields for ERM agreements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This bug adds support for additional fields in the ERM module's agreements, similar to how Bug 35287 added support for additional fields in the ERM module's licences. To test (k.t.d): a) APPLY PATCH b) Run cypress --spec t/cypress/integration/AdditionalFields_spec.ts 1) Note how the tests pass c) Add new additional fields for 'erm_agreements' 1) Go to /cgi-bin/koha/admin/additional-fields.pl?tablename=erm_agreements 2) Create field one called 'text non-repeatable' 3) Create field two called 'text repeatable', check 'repeatable' 4) Create field three called 'av non-repeatable', pick LANG authorised value 5) Create field four called 'av repeatable', pick LOC authorised value, check repeatable d) Create new agreement 1) Go to /cgi-bin/koha/erm/agreements/add, notice the new additional fields section 2) Complete all mandatory fields for a new licence 3) Experiment with the four different additional field types – it may be useful to watch the Cypress-generated test video for guidance 4) Select some AV options from the AV fields, deselect them, notice the repeatable one allows for multiple selection, the non-repeatable one does not e) Save the agreement, then view it 1) To view the licence, click its name in the table list on /cgi-bin/koha/erm/agreements 2) notice the additional fields on display 3) also notice that the authorised values are in their human-readable form, and not their coded form f) Edit the agreement, then view it again 1) Go to /cgi-bin/koha/erm/agreements/edit/1 2) Play around again with the fields. Save. 3) Repeat step e, have the edits shown up? g) Test searchability 1) Go to /cgi-bin/koha/admin/additional-fields.pl?tablename=erm_agreements 2) Edit one of the fields and make sure searchable is checked (ensure you choose a field that has some data in it) 3) Go to /cgi-bin/koha/erm/agreements 4) Notice that the searchable field(s) are now columns in the table 5) Notice that searchable AV fields contain a drop-down 6) Notice that searchable text fields have an input field 7) Perform a search on the additional field 8) Notice that the searching is working as expected h) SIGN OFF --- Koha/AdditionalField.pm | 1 + Koha/ERM/Agreement.pm | 2 +- Koha/ERM/Agreements.pm | 2 +- Koha/REST/V1/ERM/Agreements.pm | 8 + Koha/REST/V1/ExtendedAttributeTypes.pm | 13 +- Koha/Schema/Result/ErmAgreement.pm | 32 + api/v1/swagger/definitions/erm_agreement.yaml | 10 + api/v1/swagger/paths/erm_agreements.yaml | 6 + .../paths/extended_attribute_types.yaml | 1 + .../en/modules/admin/additional-fields.tt | 3 +- .../vue/components/ERM/AgreementsFormAdd.vue | 12 + .../js/vue/components/ERM/AgreementsList.vue | 51 +- .../js/vue/components/ERM/AgreementsShow.vue | 11 +- .../prog/js/vue/fetch/erm-api-client.js | 2 +- .../integration/AdditionalFields_spec.ts | 568 ++++++++++++++++++ 15 files changed, 709 insertions(+), 13 deletions(-) diff --git a/Koha/AdditionalField.pm b/Koha/AdditionalField.pm index 7e5c16a049..fd9621d681 100644 --- a/Koha/AdditionalField.pm +++ b/Koha/AdditionalField.pm @@ -60,6 +60,7 @@ sub to_api { 'aqbasket' => 'basket', 'aqinvoices' => 'invoice', 'erm_licenses' => 'license', + 'erm_agreements' => 'agreement', 'aqorders' => 'order', }; diff --git a/Koha/ERM/Agreement.pm b/Koha/ERM/Agreement.pm index dac3e56c9e..785c5e30c7 100644 --- a/Koha/ERM/Agreement.pm +++ b/Koha/ERM/Agreement.pm @@ -25,7 +25,7 @@ use Koha::DateUtils qw( dt_from_string ); use Koha::Exceptions; use Koha::Acquisition::Bookseller; -use base qw(Koha::Object); +use base qw(Koha::Object::Mixin::AdditionalFields Koha::Object); use Koha::ERM::Agreement::Periods; use Koha::ERM::Agreement::Licenses; diff --git a/Koha/ERM/Agreements.pm b/Koha/ERM/Agreements.pm index e8b23c82e5..9c786ca107 100644 --- a/Koha/ERM/Agreements.pm +++ b/Koha/ERM/Agreements.pm @@ -24,7 +24,7 @@ use Koha::DateUtils qw( dt_from_string ); use Koha::ERM::Agreement; use Koha::ERM::Agreement::Periods; -use base qw(Koha::Objects); +use base qw(Koha::Objects::Mixin::AdditionalFields Koha::Objects); =head1 NAME diff --git a/Koha/REST/V1/ERM/Agreements.pm b/Koha/REST/V1/ERM/Agreements.pm index dd67576d05..2ba2e0fede 100644 --- a/Koha/REST/V1/ERM/Agreements.pm +++ b/Koha/REST/V1/ERM/Agreements.pm @@ -97,6 +97,7 @@ sub add { my $agreement_licenses = delete $body->{agreement_licenses} // []; my $agreement_relationships = delete $body->{agreement_relationships} // []; my $documents = delete $body->{documents} // []; + my $extended_attributes = delete $body->{extended_attributes} // []; my $agreement = Koha::ERM::Agreement->new_from_api($body)->store; $agreement->periods($periods); @@ -105,6 +106,9 @@ sub add { $agreement->agreement_relationships($agreement_relationships); $agreement->documents($documents); + my @extended_attributes = map { {'id' => $_->{field_id}, 'value' => $_->{value}} } @{$extended_attributes}; + $agreement->extended_attributes( \@extended_attributes ); + $c->res->headers->location($c->req->url->to_string . '/' . $agreement->agreement_id); return $c->render( status => 201, @@ -181,6 +185,7 @@ sub update { my $agreement_licenses = delete $body->{agreement_licenses} // []; my $agreement_relationships = delete $body->{agreement_relationships} // []; my $documents = delete $body->{documents} // []; + my $extended_attributes = delete $body->{extended_attributes} // []; $agreement->set_from_api($body)->store; $agreement->periods($periods); @@ -189,6 +194,9 @@ sub update { $agreement->agreement_relationships($agreement_relationships); $agreement->documents($documents); + my @extended_attributes = map { {'id' => $_->{field_id}, 'value' => $_->{value}} } @{$extended_attributes}; + $agreement->extended_attributes( \@extended_attributes ); + $c->res->headers->location($c->req->url->to_string . '/' . $agreement->agreement_id); return $c->render( status => 200, diff --git a/Koha/REST/V1/ExtendedAttributeTypes.pm b/Koha/REST/V1/ExtendedAttributeTypes.pm index 8dfa4ea6ed..f891c41dd1 100644 --- a/Koha/REST/V1/ExtendedAttributeTypes.pm +++ b/Koha/REST/V1/ExtendedAttributeTypes.pm @@ -46,12 +46,13 @@ sub list { # FIXME: Maybe not the best place for this mapping my $resource_to_table = { - basket => 'aqbasket', - credit => 'accountlines:credit', - debit => 'accountlines:debit', - invoice => 'aqinvoices', - license => 'erm_licenses', - order => 'aqorders', + basket => 'aqbasket', + credit => 'accountlines:credit', + debit => 'accountlines:debit', + invoice => 'aqinvoices', + license => 'erm_licenses', + agreement => 'erm_agreements', + order => 'aqorders', }; return try { diff --git a/Koha/Schema/Result/ErmAgreement.pm b/Koha/Schema/Result/ErmAgreement.pm index b2b97e4f3e..78679d364f 100644 --- a/Koha/Schema/Result/ErmAgreement.pm +++ b/Koha/Schema/Result/ErmAgreement.pm @@ -281,6 +281,38 @@ __PACKAGE__->add_columns( '+is_perpetual' => { is_boolean => 1 } ); +__PACKAGE__->has_many( + "additional_field_values", + "Koha::Schema::Result::AdditionalFieldValue", + sub { + my ($args) = @_; + + return { + "$args->{foreign_alias}.record_id" => { -ident => "$args->{self_alias}.agreement_id" }, + + "$args->{foreign_alias}.field_id" => + { -in => \'(SELECT id FROM additional_fields WHERE tablename="erm_agreements")' }, + }; + }, + { cascade_copy => 0, cascade_delete => 0 }, +); + +__PACKAGE__->has_many( + "extended_attributes", + "Koha::Schema::Result::AdditionalFieldValue", + sub { + my ($args) = @_; + + return { + "$args->{foreign_alias}.record_id" => { -ident => "$args->{self_alias}.agreement_id" }, + + "$args->{foreign_alias}.field_id" => + { -in => \'(SELECT id FROM additional_fields WHERE tablename="erm_agreements")' }, + }; + }, + { cascade_copy => 0, cascade_delete => 0 }, +); + sub koha_object_class { 'Koha::ERM::Agreement'; } diff --git a/api/v1/swagger/definitions/erm_agreement.yaml b/api/v1/swagger/definitions/erm_agreement.yaml index e8fc871d34..d355d69b3c 100644 --- a/api/v1/swagger/definitions/erm_agreement.yaml +++ b/api/v1/swagger/definitions/erm_agreement.yaml @@ -69,6 +69,16 @@ properties: type: - object - "null" + extended_attributes: + description: Related additional field values + type: + - array + items: + $ref: extended_attribute_value.yaml + _strings: + type: + - object + - "null" additionalProperties: false required: diff --git a/api/v1/swagger/paths/erm_agreements.yaml b/api/v1/swagger/paths/erm_agreements.yaml index 43a48e1179..933192191a 100644 --- a/api/v1/swagger/paths/erm_agreements.yaml +++ b/api/v1/swagger/paths/erm_agreements.yaml @@ -69,6 +69,8 @@ enum: - user_roles - vendor + - extended_attributes + - +strings collectionFormat: csv - $ref: "../swagger.yaml#/parameters/match" - $ref: "../swagger.yaml#/parameters/order_by" @@ -198,6 +200,8 @@ - agreement_packages.package - documents - vendor + - extended_attributes + - +strings collectionFormat: csv responses: 200: @@ -265,6 +269,8 @@ - agreement_licenses - agreement_relationships - documents + - extended_attributes + - +strings collectionFormat: csv responses: 200: diff --git a/api/v1/swagger/paths/extended_attribute_types.yaml b/api/v1/swagger/paths/extended_attribute_types.yaml index 7bad73967c..08f8141873 100644 --- a/api/v1/swagger/paths/extended_attribute_types.yaml +++ b/api/v1/swagger/paths/extended_attribute_types.yaml @@ -19,6 +19,7 @@ - debit - invoice - license + - agreement - order - subscription - $ref: "../swagger.yaml#/parameters/match" diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/additional-fields.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/additional-fields.tt index 0c33da6b3b..e26e8690b4 100755 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/additional-fields.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/additional-fields.tt @@ -23,7 +23,7 @@ [% marcfield_tables = ['subscription', 'aqorders'] %] -[% searchable_tables = ['subscription', 'aqbasket', 'aqinvoices', 'erm_licenses'] %] +[% searchable_tables = ['subscription', 'aqbasket', 'aqinvoices', 'erm_licenses', 'erm_agreements'] %] [% show_marcfield = marcfield_tables.grep('^' _ tablename _ '$').size ? 1 : 0 %] [% show_searchable = searchable_tables.grep('^' _ tablename _ '$').size ? 1 : 0 %] @@ -137,6 +137,7 @@ [% END %] [% IF CAN_user_erm %] [% WRAPPER table_option value="erm_licenses" %]ERM Licenses[% END %] + [% WRAPPER table_option value="erm_agreements" %]ERM Agreements[% END %] [% END %] [% ELSE %] diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsFormAdd.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsFormAdd.vue index 645a13b5be..f7e8d26412 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsFormAdd.vue +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsFormAdd.vue @@ -132,6 +132,11 @@ + this.table_url(), table_settings: this.agreement_table_settings, add_filters: true, @@ -161,7 +165,15 @@ export default { }, beforeRouteEnter(to, from, next) { next(vm => { - vm.getAgreementCount().then(() => (vm.initialized = true)) + vm.getAgreementCount().then(() => + vm + .getSearchableAdditionalFields() + .then(() => + vm + .getSearchableAVOptions() + .then(() => (vm.initialized = true)) + ) + ) }) }, methods: { @@ -173,6 +185,41 @@ export default { }, error => {} ) + }, + async getSearchableAdditionalFields() { + const client = APIClient.additional_fields + await client.additional_fields.getAll("agreement").then( + searchable_additional_fields => { + this.searchable_additional_fields = + searchable_additional_fields.filter( + field => field.searchable + ) + }, + error => {} + ) + }, + async getSearchableAVOptions() { + const client_av = APIClient.authorised_values + let av_cat_array = this.searchable_additional_fields + .filter(field => field.authorised_value_category_name) + .map(field => field.authorised_value_category_name) + + await client_av.values + .getCategoriesWithValues([ + ...new Set(av_cat_array.map(av_cat => '"' + av_cat + '"')), + ]) // unique + .then(av_categories => { + av_cat_array.forEach(av_cat => { + let av_match = av_categories.find( + element => element.category_name == av_cat + ) + this.searchable_av_options[av_cat] = + av_match.authorised_values.map(av => ({ + value: av.value, + label: av.description, + })) + }) + }) }, doShow: function ({ agreement_id }, dt, event) { event.preventDefault() diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsShow.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsShow.vue index 27eee68c05..7b49fe88d6 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsShow.vue +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsShow.vue @@ -322,6 +322,12 @@ +
diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/erm-api-client.js b/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/erm-api-client.js index a90ec23797..7bd2318898 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/erm-api-client.js +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/fetch/erm-api-client.js @@ -23,7 +23,7 @@ export class ERMAPIClient extends HttpClient { endpoint: "agreements/" + id, headers: { "x-koha-embed": - "periods,user_roles,user_roles.patron,agreement_licenses,agreement_licenses.license,agreement_relationships,agreement_relationships.related_agreement,documents,agreement_packages,agreement_packages.package,vendor", + "periods,user_roles,user_roles.patron,agreement_licenses,agreement_licenses.license,agreement_relationships,agreement_relationships.related_agreement,documents,agreement_packages,agreement_packages.package,vendor,extended_attributes,+strings", }, }), getAll: (query, params) => diff --git a/t/cypress/integration/AdditionalFields_spec.ts b/t/cypress/integration/AdditionalFields_spec.ts index 9a7885aa5d..3e95e59d9f 100644 --- a/t/cypress/integration/AdditionalFields_spec.ts +++ b/t/cypress/integration/AdditionalFields_spec.ts @@ -168,6 +168,176 @@ function get_licenses_additional_fields() { ]; } +function get_no_additional_fields_agreement() { + return { + agreement_id: 1, + name: "agreement 1", + description: "my first agreement", + agreement_licenses: [], + agreement_packages: [], + agreement_relationships: [], + closure_reason: "", + is_perpetual: false, + license_info: "", + periods: [], + renewal_priority: "", + status: "active", + user_roles: [], + vendor_id: 1, + vendor: [cy.get_vendors_to_relate()[0]], + documents: [ + { + agreement_id: 1, + file_description: "file description", + file_name: "file.json", + notes: "file notes", + physical_location: "file physical location", + uri: "file uri", + uploaded_on: "2022-10-27T11:57:02+00:00", + }, + ], + extended_attributes: [], + _strings: { + "additional_field_values": [] + }, + }; +} +function get_agreement() { + return { + agreement_id: 1, + name: "agreement 1", + description: "my first agreement", + agreement_licenses: [], + agreement_packages: [], + agreement_relationships: [], + closure_reason: "", + is_perpetual: false, + license_info: "", + periods: [], + renewal_priority: "", + status: "active", + user_roles: [], + vendor_id: 1, + vendor: [cy.get_vendors_to_relate()[0]], + documents: [ + { + agreement_id: 1, + file_description: "file description", + file_name: "file.json", + notes: "file notes", + physical_location: "file physical location", + uri: "file uri", + uploaded_on: "2022-10-27T11:57:02+00:00", + }, + ], + extended_attributes: [ + { + field_id: 1, + id: "1", + record_id: "1", + value: "REF", + }, + { + field_id: 1, + id: "2", + record_id: "1", + value: "NFIC", + }, + { + field_id: 2, + id: "3", + record_id: "1", + value: "some text", + }, + { + field_id: 3, + id: "4", + record_id: "1", + value: "some repeatable text", + }, + { + field_id: 4, + id: "5", + record_id: "1", + value: "AF", + }, + ], + _strings: { + additional_field_values: [ + { + field_id: 1, + field_label: "AV Repeatable", + type: "av", + value_str: "Reference, Non-fiction", + }, + { + field_id: 2, + field_label: "Text non-repeatable", + type: "text", + value_str: "some text", + }, + { + field_id: 3, + field_label: "Text repeatable", + type: "text", + value_str: "some repeatable text", + }, + { + field_id: 4, + field_label: "AV Searchable", + type: "av", + value_str: "Afghanistan", + }, + ], + }, + }; +} + +function get_agreements_additional_fields() { + return [ + { + authorised_value_category_name: "CCODE", + extended_attribute_type_id: 1, + marcfield: "", + marcfield_mode: "get", + name: "AV Repeatable", + repeatable: true, + searchable: true, + resource_type: "agreement", + }, + { + authorised_value_category_name: null, + extended_attribute_type_id: 2, + marcfield: "", + marcfield_mode: "get", + name: "Text non-repeatable", + repeatable: false, + searchable: false, + resource_type: "agreement", + }, + { + authorised_value_category_name: null, + extended_attribute_type_id: 3, + marcfield: "", + marcfield_mode: "get", + name: "Text repeatable", + repeatable: true, + searchable: false, + resource_type: "agreement", + }, + { + authorised_value_category_name: "COUNTRY", + extended_attribute_type_id: 4, + marcfield: "", + marcfield_mode: "get", + name: "AV Searchable", + repeatable: false, + searchable: true, + resource_type: "agreement", + }, + ]; +} + function get_av_cats() { return [ { @@ -252,6 +422,10 @@ describe("Additional Fields operations", () => { ); }); + // + // for licenses + // + it("Additional Fields display - Table (licenses)", () => { let license = get_license(); let licenses = [license]; @@ -640,4 +814,398 @@ describe("Additional Fields operations", () => { "#licenses_add form #additional_fields label[for='additional_field_3']" ).should("have.length", 2); }); + + // + // for agreements + // + + it("Additional Fields display - Table (agreements)", () => { + let agreement = get_agreement(); + let agreements = [agreement]; + let agreement_additional_fields = get_agreements_additional_fields(); + let av_cats = get_av_cats(); + + cy.intercept("GET", "/api/v1/extended_attribute_types*", { + body: agreement_additional_fields, + statusCode: 200, + }); + + cy.intercept("GET", "/api/v1/erm/agreements*", { + statusCode: 200, + body: agreements, + headers: { + "X-Base-Total-Count": "1", + "X-Total-Count": "1", + }, + }); + cy.intercept("GET", "/api/v1/erm/agreements/*", agreement); + cy.visit("/cgi-bin/koha/erm/agreements"); + cy.get("#agreements_list").contains("Showing 1 to 1 of 1 entries"); + + cy.get("#agreements_list table tbody tr:first").contains( + get_description_from_av_value( + av_cats, + agreement.extended_attributes[4] + ) + ); + cy.get("#agreements_list table tbody tr:first").contains( + get_description_from_av_value( + av_cats, + agreement.extended_attributes[0] + ) + + ", " + + get_description_from_av_value( + av_cats, + agreement.extended_attributes[1] + ) + ); + }); + + it("Additional Fields display - Show (agreements)", () => { + let empty_agreement = get_no_additional_fields_agreement(); + let agreement = get_agreement(); + let agreements = [agreement]; + let vendors = cy.get_vendors_to_relate(); + let agreement_additional_fields = get_agreements_additional_fields(); + let av_cats = get_av_cats(); + + // Click the 'Edit' button from the list + cy.intercept("GET", "/api/v1/erm/agreements*", { + statusCode: 200, + body: agreements, + headers: { + "X-Base-Total-Count": "1", + "X-Total-Count": "1", + }, + }); + cy.intercept("GET", "/api/v1/erm/agreements/*", empty_agreement).as( + "get-empty-agreement" + ); + + //Intercept vendors request + cy.intercept("GET", "/api/v1/acquisitions/vendors*", { + statusCode: 200, + body: vendors, + }); + cy.intercept("GET", "/api/v1/extended_attribute_types*", { + body: [], + statusCode: 200, + }).as("empty-additional-fields"); + + //Empty additional fields, should not display + cy.visit("/cgi-bin/koha/erm/agreements"); + cy.get("#agreements_list table tbody tr:first td:first a").click(); + cy.wait("@get-empty-agreement"); + cy.get("#agreements_show #additional_fields").should("not.exist"); + + cy.intercept("GET", "/api/v1/extended_attribute_types*", { + body: agreement_additional_fields, + statusCode: 200, + }).as("existing-additional-fields"); + + cy.intercept( + { + pathname: "/api/v1/authorised_value_categories", + query: { + q: '{"me.category_name":["CCODE", "COUNTRY"]}', + }, + }, + { + body: av_cats, + statusCode: 200, + } + ).as("avcategories"); + + cy.intercept("GET", "/api/v1/erm/agreements/*", agreement).as( + "get-agreement" + ); + + // There are additional fields, fieldset should exist + cy.visit("/cgi-bin/koha/erm/agreements"); + cy.get("#agreements_list table tbody tr:first td:first a").click(); + cy.wait("@get-agreement"); + cy.get("#agreements_show #additional_fields").should("exist"); + + // All fields are presented correctly + cy.get( + "#agreements_show #additional_fields label[for='additional_field_1']" + ).contains(agreement_additional_fields[0].name); + cy.get( + "#agreements_show #additional_fields label[for='additional_field_1']" + ) + .parent() + .children("span") + .contains( + get_description_from_av_value( + av_cats, + agreement.extended_attributes[0] + ) + + ", " + + get_description_from_av_value( + av_cats, + agreement.extended_attributes[1] + ) + ); + + cy.get( + "#agreements_show #additional_fields label[for='additional_field_2']" + ).contains(agreement_additional_fields[1].name); + cy.get( + "#agreements_show #additional_fields label[for='additional_field_2']" + ) + .parent() + .children("span") + .contains(agreement.extended_attributes[2].value); + + cy.get( + "#agreements_show #additional_fields label[for='additional_field_3']" + ).contains(agreement_additional_fields[2].name); + cy.get( + "#agreements_show #additional_fields label[for='additional_field_3']" + ) + .parent() + .children("span") + .contains(agreement.extended_attributes[3].value); + + cy.get( + "#agreements_show #additional_fields label[for='additional_field_4']" + ).contains(agreement_additional_fields[3].name); + cy.get( + "#agreements_show #additional_fields label[for='additional_field_4']" + ) + .parent() + .children("span") + .contains( + get_description_from_av_value( + av_cats, + agreement.extended_attributes[4] + ) + ); + }); + + it("Additional Fields entry - Add (agreements)", () => { + let vendors = cy.get_vendors_to_relate(); + let agreement_additional_fields = get_licenses_additional_fields(); + let av_cats = get_av_cats(); + + //Intercept vendors request + cy.intercept("GET", "/api/v1/acquisitions/vendors*", { + statusCode: 200, + body: vendors, + }); + cy.intercept("GET", "/api/v1/extended_attribute_types*", { + body: [], + statusCode: 200, + }).as("empty-additional-fields"); + + // No additional fields, fieldset should not exist + cy.visit("/cgi-bin/koha/erm/agreements/add"); + cy.get("#agreements_add form #additional_fields").should("not.exist"); + + cy.intercept("GET", "/api/v1/extended_attribute_types*", { + body: agreement_additional_fields, + statusCode: 200, + }).as("existing-additional-fields"); + + cy.intercept( + { + pathname: "/api/v1/authorised_value_categories", + query: { + q: '{"me.category_name":["CCODE", "COUNTRY"]}', + }, + }, + { + body: av_cats, + statusCode: 200, + } + ).as("avcategories"); + // There are additional fields, fieldset should exist + cy.visit("/cgi-bin/koha/erm/agreements/add"); + cy.get("#agreements_add form #additional_fields").should("exist"); + + // All additional fields should be listed + cy.get( + "#agreements_add form #additional_fields label[for='additional_field_1']" + ).contains(agreement_additional_fields[0].name); + cy.get( + "#agreements_add form #additional_fields label[for='additional_field_2']" + ).contains(agreement_additional_fields[1].name); + cy.get( + "#agreements_add form #additional_fields label[for='additional_field_3']" + ).contains(agreement_additional_fields[2].name); + cy.get( + "#agreements_add form #additional_fields label[for='additional_field_4']" + ).contains(agreement_additional_fields[3].name); + + cy.get("#additional_fields #additional_field_1 .vs__selected").should( + "not.exist" + ); //new agreement, no pre-selected value + + // Pick one value + cy.get("#additional_fields #additional_field_1 .vs__search").click(); + cy.get( + "#additional_fields #additional_field_1 #vs5__option-0" + ).contains(av_cats[0].authorised_values[0].description); + cy.get("#additional_fields #additional_field_1 #vs5__option-0").click(); + cy.get("#additional_fields #additional_field_1 .vs__selected").contains( + av_cats[0].authorised_values[0].description + ); + cy.get("#additional_fields #additional_field_1 .vs__selected").should( + "have.length", + 1 + ); + + // Pick a second value for the same repeatable AV field + cy.get("#additional_fields #additional_field_1 .vs__search").click(); + cy.get( + "#additional_fields #additional_field_1 #vs5__option-1" + ).contains(av_cats[0].authorised_values[1].description); + cy.get("#additional_fields #additional_field_1 #vs5__option-1").click(); + cy.get("#additional_fields #additional_field_1 .vs__selected").contains( + av_cats[0].authorised_values[1].description + ); + cy.get("#additional_fields #additional_field_1 .vs__selected").should( + "have.length", + 2 + ); + + // Attempt to pick the same value again - should not be possible + cy.get("#additional_fields #additional_field_1 .vs__search").click(); + cy.get( + "#additional_fields #additional_field_1 #vs5__option-1" + ).contains(av_cats[0].authorised_values[1].description); + cy.get("#additional_fields #additional_field_1 #vs5__option-1").click(); + cy.get("#additional_fields #additional_field_1 .vs__selected").should( + "have.length", + 2 + ); + + // Remove the second selected value + cy.get( + "#additional_fields #additional_field_1 .vs__selected button[title='Deselect " + + av_cats[0].authorised_values[1].description + + "'" + ).click(); + cy.get("#additional_fields #additional_field_1 .vs__selected").should( + "have.length", + 1 + ); + cy.get("#additional_fields #additional_field_1 .vs__selected").contains( + av_cats[0].authorised_values[0].description + ); + }); + + it("Additional Fields entry - Edit (agreements)", () => { + let agreement = get_agreement(); + let agreements = [agreement]; + let vendors = cy.get_vendors_to_relate(); + let agreement_additional_fields = get_agreements_additional_fields(); + let av_cats = get_av_cats(); + + // Click the 'Edit' button from the list + cy.intercept("GET", "/api/v1/erm/agreements*", { + statusCode: 200, + body: agreements, + headers: { + "X-Base-Total-Count": "1", + "X-Total-Count": "1", + }, + }); + cy.intercept("GET", "/api/v1/erm/agreements/*", agreement).as( + "get-agreement" + ); + + //Intercept vendors request + cy.intercept("GET", "/api/v1/acquisitions/vendors*", { + statusCode: 200, + body: vendors, + }); + + cy.intercept("GET", "/api/v1/extended_attribute_types*", { + body: agreement_additional_fields, + statusCode: 200, + }).as("existing-additional-fields"); + + cy.intercept( + { + pathname: "/api/v1/authorised_value_categories", + query: { + q: '{"me.category_name":["CCODE", "COUNTRY"]}', + }, + }, + { + body: av_cats, + statusCode: 200, + } + ).as("avcategories"); + + cy.visit("/cgi-bin/koha/erm/agreements"); + cy.get("#agreements_list table tbody tr:first").contains("Edit").click(); + cy.wait("@get-agreement"); + cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! + + // All additional fields should be pre-populated + cy.get("#additional_fields #additional_field_1 .vs__selected").contains( + get_description_from_av_value( + av_cats, + agreement.extended_attributes[0] + ) + ); + cy.get("#additional_fields #additional_field_1 .vs__selected").contains( + get_description_from_av_value( + av_cats, + agreement.extended_attributes[1] + ) + ); + + cy.get( + "#agreements_add form #additional_fields label[for='additional_field_2']" + ) + .parent() + .children("input") + .should("have.value", agreement.extended_attributes[2].value); + + cy.get( + "#agreements_add form #additional_fields label[for='additional_field_3']" + ) + .parent() + .children("input") + .should("have.value", agreement.extended_attributes[3].value); + + cy.get("#additional_fields #additional_field_4 .vs__selected").contains( + get_description_from_av_value( + av_cats, + agreement.extended_attributes[4] + ) + ); + + // Clear text field works + cy.get( + "#agreements_add form #additional_fields label[for='additional_field_2']" + ) + .parent() + .children(".clear_attribute") + .click(); + cy.get( + "#agreements_add form #additional_fields label[for='additional_field_2']" + ) + .parent() + .children("input") + .should("have.value", ""); + + // "+New" text field works + cy.get( + "#agreements_add form #additional_fields label[for='additional_field_3']" + ).should("have.length", 1); + cy.get( + "#agreements_add form #additional_fields label[for='additional_field_3']" + ) + .parent() + .children(".clone_attribute") + .click(); + cy.get( + "#agreements_add form #additional_fields label[for='additional_field_3']" + ).should("have.length", 2); + }); + }); -- 2.43.0