From 16a7ff446831e1cb6f3d0036aec64d42c52a9890 Mon Sep 17 00:00:00 2001 From: Matt Blenkinsop Date: Tue, 21 Oct 2025 10:56:32 +0100 Subject: [PATCH] Bug 40192: Add additional fields to ERM titles --- Koha/AdditionalField.pm | 1 + Koha/ERM/EHoldings/Title.pm | 2 +- Koha/ERM/EHoldings/Titles.pm | 2 +- Koha/REST/V1/ERM/EHoldings/Titles/Local.pm | 9 ++++++ Koha/REST/V1/ExtendedAttributeTypes.pm | 1 + Koha/Schema/Result/ErmEholdingsTitle.pm | 32 +++++++++++++++++++ .../definitions/erm_eholdings_title.yaml | 10 ++++++ .../swagger/paths/erm_eholdings_titles.yaml | 4 +++ .../paths/extended_attribute_types.yaml | 1 + .../en/modules/admin/additional-fields.tt | 3 +- .../prog/js/fetch/erm-api-client.js | 3 +- .../ERM/EHoldingsLocalTitleResource.vue | 8 +++-- 12 files changed, 69 insertions(+), 7 deletions(-) diff --git a/Koha/AdditionalField.pm b/Koha/AdditionalField.pm index ead7d3e4fb5..bf5e5c08146 100644 --- a/Koha/AdditionalField.pm +++ b/Koha/AdditionalField.pm @@ -64,6 +64,7 @@ sub to_api { 'erm_packages' => 'package', 'aqorders' => 'order', 'aqbooksellers:vendor' => 'vendor', + 'erm_titles' => 'title' }; my $json = $self->SUPER::to_api($params); diff --git a/Koha/ERM/EHoldings/Title.pm b/Koha/ERM/EHoldings/Title.pm index 6192b75588f..3a07b41460a 100644 --- a/Koha/ERM/EHoldings/Title.pm +++ b/Koha/ERM/EHoldings/Title.pm @@ -22,7 +22,7 @@ use MIME::Base64 qw( decode_base64 ); use Koha::Database; -use base qw(Koha::Object); +use base qw(Koha::Object::Mixin::AdditionalFields Koha::Object); use C4::Biblio qw( AddBiblio TransformKohaToMarc GetMarcFromKohaField ); diff --git a/Koha/ERM/EHoldings/Titles.pm b/Koha/ERM/EHoldings/Titles.pm index 5b914345bd1..cd3390f9e8a 100644 --- a/Koha/ERM/EHoldings/Titles.pm +++ b/Koha/ERM/EHoldings/Titles.pm @@ -21,7 +21,7 @@ use Koha::Database; use Koha::ERM::EHoldings::Title; -use base qw(Koha::Objects); +use base qw(Koha::Objects::Mixin::AdditionalFields Koha::Objects); =head1 NAME diff --git a/Koha/REST/V1/ERM/EHoldings/Titles/Local.pm b/Koha/REST/V1/ERM/EHoldings/Titles/Local.pm index 10e556980b1..9041cc43a77 100644 --- a/Koha/REST/V1/ERM/EHoldings/Titles/Local.pm +++ b/Koha/REST/V1/ERM/EHoldings/Titles/Local.pm @@ -90,12 +90,17 @@ sub add { my $resources = delete $body->{resources} // []; my $create_linked_biblio = delete $body->{create_linked_biblio} // 0; + my $extended_attributes = delete $body->{extended_attributes} // []; my $title = Koha::ERM::EHoldings::Title->new_from_api($body) ->store( { create_linked_biblio => $create_linked_biblio } ); $title->resources($resources); + my @extended_attributes = + map { { 'id' => $_->{field_id}, 'value' => $_->{value} } } @{$extended_attributes}; + $title->extended_attributes( \@extended_attributes ); + $c->res->headers->location( $c->req->url->to_string . '/' . $title->title_id ); return $c->render( status => 201, @@ -152,10 +157,14 @@ sub update { my $resources = delete $body->{resources} // []; my $create_linked_biblio = delete $body->{create_linked_biblio} // 0; + my $extended_attributes = delete $body->{extended_attributes} // []; $title->set_from_api($body)->store( { create_linked_biblio => $create_linked_biblio } ); $title->resources($resources); + my @extended_attributes = + map { { 'id' => $_->{field_id}, 'value' => $_->{value} } } @{$extended_attributes}; + $title->extended_attributes( \@extended_attributes ); return $c->render( status => 200, diff --git a/Koha/REST/V1/ExtendedAttributeTypes.pm b/Koha/REST/V1/ExtendedAttributeTypes.pm index 5893e51d325..782880210e6 100644 --- a/Koha/REST/V1/ExtendedAttributeTypes.pm +++ b/Koha/REST/V1/ExtendedAttributeTypes.pm @@ -55,6 +55,7 @@ sub list { package => 'erm_packages', order => 'aqorders', vendor => 'aqbooksellers:vendor', + title => 'erm_titles' }; return try { diff --git a/Koha/Schema/Result/ErmEholdingsTitle.pm b/Koha/Schema/Result/ErmEholdingsTitle.pm index d8b2ef732b1..a9049e616a7 100644 --- a/Koha/Schema/Result/ErmEholdingsTitle.pm +++ b/Koha/Schema/Result/ErmEholdingsTitle.pm @@ -297,6 +297,38 @@ __PACKAGE__->has_many( # Created by DBIx::Class::Schema::Loader v0.07049 @ 2023-09-13 11:06:45 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:SOFpN45kBTi/qvW5OBnYDA +__PACKAGE__->has_many( + "additional_field_values", + "Koha::Schema::Result::AdditionalFieldValue", + sub { + my ($args) = @_; + + return { + "$args->{foreign_alias}.record_id" => { -ident => "$args->{self_alias}.title_id" }, + + "$args->{foreign_alias}.field_id" => + { -in => \'(SELECT id FROM additional_fields WHERE tablename="erm_titles")' }, + }; + }, + { 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}.title_id" }, + + "$args->{foreign_alias}.field_id" => + { -in => \'(SELECT id FROM additional_fields WHERE tablename="erm_titles")' }, + }; + }, + { cascade_copy => 0, cascade_delete => 0 }, +); + =head2 koha_objects_class Missing POD for koha_objects_class. diff --git a/api/v1/swagger/definitions/erm_eholdings_title.yaml b/api/v1/swagger/definitions/erm_eholdings_title.yaml index 6bbadd61e4b..c1eae480a32 100644 --- a/api/v1/swagger/definitions/erm_eholdings_title.yaml +++ b/api/v1/swagger/definitions/erm_eholdings_title.yaml @@ -173,6 +173,16 @@ properties: type: - boolean - "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_eholdings_titles.yaml b/api/v1/swagger/paths/erm_eholdings_titles.yaml index 87e037b5b3a..f68eaeb8539 100644 --- a/api/v1/swagger/paths/erm_eholdings_titles.yaml +++ b/api/v1/swagger/paths/erm_eholdings_titles.yaml @@ -153,6 +153,8 @@ type: string enum: - resources.package + - extended_attributes + - +strings collectionFormat: csv - $ref: "../swagger.yaml#/parameters/match" - $ref: "../swagger.yaml#/parameters/order_by" @@ -278,6 +280,8 @@ enum: - resources - resources.package + - 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 4b7b56d71b7..675a80a2506 100644 --- a/api/v1/swagger/paths/extended_attribute_types.yaml +++ b/api/v1/swagger/paths/extended_attribute_types.yaml @@ -24,6 +24,7 @@ - order - subscription - vendor + - title - $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 529221ac3d9..456e8ec6284 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 @@ -30,7 +30,7 @@ [% marcfield_tables = ['subscription', 'aqorders'] %] -[% searchable_tables = ['subscription', 'aqbasket', 'aqinvoices', 'erm_licenses', 'erm_agreements', 'erm_packages', 'aqbooksellers'] %] +[% searchable_tables = ['subscription', 'aqbasket', 'aqinvoices', 'erm_licenses', 'erm_agreements', 'erm_packages', 'aqbooksellers', 'erm_titles'] %] [% show_marcfield = marcfield_tables.grep('^' _ tablename _ '$').size ? 1 : 0 %] [% show_searchable = searchable_tables.grep('^' _ tablename _ '$').size ? 1 : 0 %] @@ -146,6 +146,7 @@ [% WRAPPER table_option value="erm_agreements" %]Agreements[% END %] [% WRAPPER table_option value="erm_licenses" %]Licenses[% END %] [% WRAPPER table_option value="erm_packages" %]Packages[% END %] + [% WRAPPER table_option value="erm_titles" %]Titles[% 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 b618e0d672b..ef1737f4afc 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 @@ -155,7 +155,8 @@ export class ERMAPIClient { this.httpClient.get({ endpoint: "eholdings/local/titles/" + id, headers: { - "x-koha-embed": "resources,resources.package", + "x-koha-embed": + "resources,resources.package,extended_attributes,+strings", }, }), delete: id => diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/EHoldingsLocalTitleResource.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/EHoldingsLocalTitleResource.vue index 828ef67235a..8a1cf7d0557 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/EHoldingsLocalTitleResource.vue +++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/EHoldingsLocalTitleResource.vue @@ -68,6 +68,7 @@ export default { props, additionalToolbarButtons, moduleStore: "ERMStore", + extendedAttributesResourceType: "title", resourceAttrs: [ { name: "publication_title", @@ -440,7 +441,7 @@ export default { const tableOptions = { url: baseResource.getResourceTableUrl(), options: { - embed: "resources.package", + embed: "resources.package,extended_attributes,+strings", searchCols: [ { search: defaults.publication_title }, null, @@ -488,6 +489,7 @@ export default { let title_id = title.title_id; delete title.title_id; delete title.biblio_id; + delete title._strings; // Cannot use the map/keepAttrs because of the reserved keyword 'package' title.resources.forEach(function (e) { @@ -499,7 +501,7 @@ export default { return baseResource.apiClient.update(title, title_id).then( title => { baseResource.setMessage($__("Title updated")); - return title + return title; }, error => {} ); @@ -507,7 +509,7 @@ export default { return baseResource.apiClient.create(title).then( title => { baseResource.setMessage($__("Title created")); - return title + return title; }, error => {} ); -- 2.50.1