From f38bf5f9e859d2224ad15275dd2a47be0b02386c Mon Sep 17 00:00:00 2001 From: Matt Blenkinsop Date: Wed, 22 Oct 2025 17:09:30 +0100 Subject: [PATCH] Bug 39438: Add additional fields support to ERM agreement periods This patch enables additional fields functionality for agreement periods in the ERM (Electronic Resource Management) module, allowing libraries to define custom metadata fields for agreement period records. Changes include: - Update Koha::AdditionalField to support erm_agreement_periods table - Modify API definitions to include extended_attributes in responses - Add erm_agreement_periods option to additional fields admin interface - Enhance Vue components to display and manage additional field values - Update ShowElement component to handle period-specific attributes Test plan: 1. Navigate to Administration > Additional fields 2. Create new fields for "Agreement periods" 3. Edit an ERM agreement and add/edit period information 4. Verify additional fields appear and can be populated 5. Confirm values are saved and displayed correctly Signed-off-by: Martin Renvoize --- Koha/AdditionalField.pm | 21 +++++++------- Koha/ERM/Agreement.pm | 9 +++++- Koha/ERM/Agreement/Period.pm | 2 +- Koha/ERM/Agreement/Periods.pm | 2 +- Koha/REST/V1/ExtendedAttributeTypes.pm | 21 +++++++------- .../definitions/erm_agreement_period.yaml | 10 +++++++ api/v1/swagger/paths/erm_agreements.yaml | 2 ++ .../paths/extended_attribute_types.yaml | 1 + .../en/modules/admin/additional-fields.tt | 1 + .../prog/js/fetch/erm-api-client.js | 2 +- .../vue/components/ERM/AgreementResource.vue | 16 ++++++++-- .../prog/js/vue/components/ShowElement.vue | 29 +++++++++++++++++-- 12 files changed, 88 insertions(+), 28 deletions(-) diff --git a/Koha/AdditionalField.pm b/Koha/AdditionalField.pm index bf5e5c08146..82a16a86725 100644 --- a/Koha/AdditionalField.pm +++ b/Koha/AdditionalField.pm @@ -55,16 +55,17 @@ sub to_api { my ( $self, $params ) = @_; my $table_to_resource = { - 'accountlines:credit' => 'credit', - 'accountlines:debit' => 'debit', - 'aqbasket' => 'basket', - 'aqinvoices' => 'invoice', - 'erm_licenses' => 'license', - 'erm_agreements' => 'agreement', - 'erm_packages' => 'package', - 'aqorders' => 'order', - 'aqbooksellers:vendor' => 'vendor', - 'erm_titles' => 'title' + 'accountlines:credit' => 'credit', + 'accountlines:debit' => 'debit', + 'aqbasket' => 'basket', + 'aqinvoices' => 'invoice', + 'erm_licenses' => 'license', + 'erm_agreements' => 'agreement', + 'erm_packages' => 'package', + 'aqorders' => 'order', + 'aqbooksellers:vendor' => 'vendor', + 'erm_titles' => 'title', + 'erm_agreement_periods' => 'agreement_period' }; my $json = $self->SUPER::to_api($params); diff --git a/Koha/ERM/Agreement.pm b/Koha/ERM/Agreement.pm index 6961d074a7b..00167a653ea 100644 --- a/Koha/ERM/Agreement.pm +++ b/Koha/ERM/Agreement.pm @@ -27,6 +27,7 @@ use Koha::Acquisition::Bookseller; use base qw(Koha::Object::Mixin::AdditionalFields Koha::Object); +use Koha::ERM::Agreement::Period; use Koha::ERM::Agreement::Periods; use Koha::ERM::Agreement::Licenses; use Koha::ERM::Agreement::Relationships; @@ -60,7 +61,13 @@ sub periods { $self->periods->delete; for my $period (@$periods) { - $self->_result->add_to_erm_agreement_periods($period); + my $extended_attributes = delete $period->{extended_attributes} // []; + my @extended_attributes = + map { { 'id' => $_->{field_id}, 'value' => $_->{value} } } @{$extended_attributes}; + $period->{agreement_id} = $self->agreement_id; + + my $stored_period = Koha::ERM::Agreement::Period->new($period)->store; + $stored_period->extended_attributes( \@extended_attributes ); } } ); diff --git a/Koha/ERM/Agreement/Period.pm b/Koha/ERM/Agreement/Period.pm index 20e5a6cfb80..5f40a95e429 100644 --- a/Koha/ERM/Agreement/Period.pm +++ b/Koha/ERM/Agreement/Period.pm @@ -19,7 +19,7 @@ use Modern::Perl; use Koha::Database; -use base qw(Koha::Object); +use base qw(Koha::Object::Mixin::AdditionalFields Koha::Object); =head1 NAME diff --git a/Koha/ERM/Agreement/Periods.pm b/Koha/ERM/Agreement/Periods.pm index 07f70bbdc41..d65eeb08544 100644 --- a/Koha/ERM/Agreement/Periods.pm +++ b/Koha/ERM/Agreement/Periods.pm @@ -21,7 +21,7 @@ use Koha::Database; use Koha::ERM::Agreement::Period; -use base qw(Koha::Objects); +use base qw(Koha::Objects::Mixin::AdditionalFields Koha::Objects); =head1 NAME diff --git a/Koha/REST/V1/ExtendedAttributeTypes.pm b/Koha/REST/V1/ExtendedAttributeTypes.pm index 782880210e6..d0892efae3f 100644 --- a/Koha/REST/V1/ExtendedAttributeTypes.pm +++ b/Koha/REST/V1/ExtendedAttributeTypes.pm @@ -46,16 +46,17 @@ 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', - agreement => 'erm_agreements', - package => 'erm_packages', - order => 'aqorders', - vendor => 'aqbooksellers:vendor', - title => 'erm_titles' + basket => 'aqbasket', + credit => 'accountlines:credit', + debit => 'accountlines:debit', + invoice => 'aqinvoices', + license => 'erm_licenses', + agreement => 'erm_agreements', + package => 'erm_packages', + order => 'aqorders', + vendor => 'aqbooksellers:vendor', + title => 'erm_titles', + agreement_period => 'erm_agreement_periods' }; return try { diff --git a/api/v1/swagger/definitions/erm_agreement_period.yaml b/api/v1/swagger/definitions/erm_agreement_period.yaml index e439d4868c7..6e78c1d0a9a 100644 --- a/api/v1/swagger/definitions/erm_agreement_period.yaml +++ b/api/v1/swagger/definitions/erm_agreement_period.yaml @@ -28,6 +28,16 @@ properties: type: - string - "null" + extended_attributes: + description: Related additional field values + type: + - array + items: + $ref: extended_attribute_value.yaml + _strings: + type: + - object + - "null" additionalProperties: false required: - started_on diff --git a/api/v1/swagger/paths/erm_agreements.yaml b/api/v1/swagger/paths/erm_agreements.yaml index 933192191a8..84f26b9142f 100644 --- a/api/v1/swagger/paths/erm_agreements.yaml +++ b/api/v1/swagger/paths/erm_agreements.yaml @@ -189,6 +189,8 @@ type: string enum: - periods + - periods.extended_attributes + - periods+strings - user_roles - user_roles.patron - agreement_licenses diff --git a/api/v1/swagger/paths/extended_attribute_types.yaml b/api/v1/swagger/paths/extended_attribute_types.yaml index 675a80a2506..2324519b6fd 100644 --- a/api/v1/swagger/paths/extended_attribute_types.yaml +++ b/api/v1/swagger/paths/extended_attribute_types.yaml @@ -25,6 +25,7 @@ - subscription - vendor - title + - agreement_period - $ref: "../swagger.yaml#/parameters/match" - $ref: "../swagger.yaml#/parameters/order_by" - $ref: "../swagger.yaml#/parameters/page" 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 3dbb35ca67c..294cc25a0e4 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 @@ -147,6 +147,7 @@ [% WRAPPER table_option value="erm_licenses" %]Licenses[% END %] [% WRAPPER table_option value="erm_packages" %]Packages[% END %] [% WRAPPER table_option value="erm_titles" %]Titles[% END %] + [% WRAPPER table_option value="erm_agreement_periods" %]Agreement periods[% END %] [% END %] [% IF CAN_user_updatecharges_remaining_permissions || CAN_user_parameters_manage_accounts %] diff --git a/koha-tmpl/intranet-tmpl/prog/js/fetch/erm-api-client.js b/koha-tmpl/intranet-tmpl/prog/js/fetch/erm-api-client.js index ef1737f4afc..830b80f7317 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/fetch/erm-api-client.js +++ b/koha-tmpl/intranet-tmpl/prog/js/fetch/erm-api-client.js @@ -21,7 +21,7 @@ export class ERMAPIClient { 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,extended_attributes,+strings", + "periods,periods.extended_attributes,periods+strings,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/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementResource.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementResource.vue index 006004065aa..f5e9d2b2ab4 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementResource.vue +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementResource.vue @@ -169,6 +169,7 @@ export default { type: "table", columnData: "periods", hidden: agreement => !!agreement.periods?.length, + includeAdditionalFields: true, columns: [ { name: $__("Period start"), @@ -208,6 +209,7 @@ export default { ended_on: null, cancellation_deadline: null, notes: null, + extended_attributes: [], }, }, }, @@ -251,6 +253,12 @@ export default { label: $__("Notes"), indexRequired: true, }, + { + name: "additional_fields", + type: "additional_fields", + extended_attributes_resource_type: + "agreement_period", + }, ], hideIn: ["List"], }, @@ -781,8 +789,12 @@ export default { } agreement.periods = agreement.periods.map( - ({ agreement_id, agreement_period_id, ...keepAttrs }) => - keepAttrs + ({ + agreement_id, + agreement_period_id, + _strings, + ...keepAttrs + }) => keepAttrs ); agreement.user_roles = agreement.user_roles.map( diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ShowElement.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ShowElement.vue index 4b28e552307..34e50d36bf9 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ShowElement.vue +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ShowElement.vue @@ -55,7 +55,7 @@
{{ column.name }} @@ -67,7 +67,7 @@ v-bind:key="counter" >