From 900c9ff397762ec569f1700d8da1aacfae67bbb2 Mon Sep 17 00:00:00 2001 From: Julian Maurice Date: Wed, 5 Feb 2014 11:12:21 +0100 Subject: [PATCH] Bug 11844: Use additional fields for order lines This patch allows to create additional fields for order lines. Once created, these fields can be filled during order line creation or modification. If additional field is linked to a MARC field, there are two possible scenario: - MARC field mode = get: The field cannot be modified and its value is retrieved from the bibliographic record (current behaviour) - MARC field mode = set: The field can be modified and its value is saved to the bibliographic record (new behaviour) If additional field is linked to an authorised value category, then authorised values are used. If not directly linked to an authorised value category, but linked to a MARC field, a search for an AV category is made on MARC default framework. This patch doesn't display additional fields value anywhere (except in order line creation/modification). Future patches will do that. Test plan: 1/ Go to Acquisitions home 2/ In the left menu, click on "Add order line fields" 3/ Click on "New field" button 4/ Give the field a name (unique), no AV category and no MARC field. 5/ Save. 6/ Create 5 other fields: a/ no AV category, a MARC field not linked to AV category, MARC field mode = get b/ no AV category, a MARC field not linked to AV category, MARC field mode = set c/ no AV category, a MARC field linked to AV category, MARC field mode = get d/ no AV category, a MARC field linked to AV category, MARC field mode = set e/ an AV category, no MARC field 7/ Create everything you need to be able to create order lines (supplier, basket, ...) 8/ Create an order line. At bottom of the page, you should see your additional fields, with authorised values dropdrown list for fields (c), (d) and (e). Fields (a) and (c) should be disabled. 9/ Fill these fields with some data and save order line 10/ check that data was correctly saved into biblio for fields (b) and (d), but not for (a) and (c) 11/ modify the same order line, check that values you've filled are correctly retrieved and that values for (a) and (c) were correctly retrieved from the bibliographic record 12/ modify all values, save, and check biblio once again Signed-off-by: Harold Dramer Signed-off-by: Katrin Fischer --- C4/Acquisition.pm | 21 +++++++++--- Koha/Acquisition/Order.pm | 2 +- Koha/AdditionalField.pm | 19 +++++++++++ Koha/Object/Mixin/AdditionalFields.pm | 32 +++++++++++++++++++ Koha/Schema/Result/Aqorder.pm | 17 ++++++++++ acqui/addorder.pl | 15 +++++++++ acqui/neworderempty.pl | 24 ++++++++++++++ admin/additional-fields.pl | 3 ++ .../data/mysql/atomicupdate/bug-11844.pl | 17 ++++++++++ installer/data/mysql/kohastructure.sql | 1 + .../en/includes/additional-fields-entry.inc | 28 ++++++++++------ .../prog/en/modules/acqui/neworderempty.tt | 4 +++ .../en/modules/admin/additional-fields.tt | 26 ++++++++++++++- serials/subscription-add.pl | 14 -------- 14 files changed, 192 insertions(+), 31 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug-11844.pl diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm index 12178420bf..f037bc2f99 100644 --- a/C4/Acquisition.pm +++ b/C4/Acquisition.pm @@ -32,6 +32,7 @@ use Koha::Acquisition::Baskets; use Koha::Acquisition::Booksellers; use Koha::Acquisition::Invoices; use Koha::Acquisition::Orders; +use Koha::AdditionalFieldValue; use Koha::Biblios; use Koha::Exceptions; use Koha::Items; @@ -1865,7 +1866,7 @@ sub TransferOrder { my $order = Koha::Acquisition::Orders->find( $ordernumber ) or return; return if $order->datereceived; - $order = $order->unblessed; + my $orderhash = $order->unblessed; my $basket = GetBasket($basketno); return unless $basket; @@ -1881,11 +1882,12 @@ sub TransferOrder { $sth = $dbh->prepare($query); $rv = $sth->execute('cancelled', $ordernumber); - delete $order->{'ordernumber'}; - delete $order->{parent_ordernumber}; - $order->{'basketno'} = $basketno; + delete $orderhash->{ordernumber}; + delete $orderhash->{parent_ordernumber}; + $orderhash->{basketno} = $basketno; - my $newordernumber = Koha::Acquisition::Order->new($order)->store->ordernumber; + my $neworder = Koha::Acquisition::Order->new($orderhash); + my $newordernumber = $neworder->store->ordernumber; $query = q{ UPDATE aqorders_items @@ -1902,6 +1904,15 @@ sub TransferOrder { $sth = $dbh->prepare($query); $sth->execute($ordernumber, $newordernumber); + # Copy additional fields values + foreach my $afv ($order->additional_field_values->as_list) { + Koha::AdditionalFieldValue->new({ + field_id => $afv->field_id, + record_id => $newordernumber, + value => $afv->value, + })->store; + } + return $newordernumber; } diff --git a/Koha/Acquisition/Order.pm b/Koha/Acquisition/Order.pm index b9059b0132..ea2d16a6b2 100644 --- a/Koha/Acquisition/Order.pm +++ b/Koha/Acquisition/Order.pm @@ -35,7 +35,7 @@ use Koha::Items; use Koha::Number::Price; use Koha::Subscriptions; -use base qw(Koha::Object); +use base qw(Koha::Object Koha::Object::Mixin::AdditionalFields); =head1 NAME diff --git a/Koha/AdditionalField.pm b/Koha/AdditionalField.pm index 721c01fffc..12b0934f78 100644 --- a/Koha/AdditionalField.pm +++ b/Koha/AdditionalField.pm @@ -11,6 +11,25 @@ use Modern::Perl; use base qw(Koha::Object); use C4::Context; +use Koha::MarcSubfieldStructures; + +sub effective_authorised_value_category { + my ($self) = @_; + + my $category = $self->authorised_value_category; + unless ($category) { + if ($self->marcfield) { + my ($tag, $subfield) = split /\$/, $self->marcfield; + + my $mss = Koha::MarcSubfieldStructures->find('', $tag, $subfield); + if ($mss) { + $category = $mss->authorised_value; + } + } + } + + return $category; +} sub _type { 'AdditionalField' } diff --git a/Koha/Object/Mixin/AdditionalFields.pm b/Koha/Object/Mixin/AdditionalFields.pm index 0ee9bd9143..7990eba37c 100644 --- a/Koha/Object/Mixin/AdditionalFields.pm +++ b/Koha/Object/Mixin/AdditionalFields.pm @@ -46,8 +46,36 @@ sub set_additional_fields { $self->additional_field_values->delete; + my $biblionumber; + my $record; + my $record_updated; + if ($self->_result->has_column('biblionumber')) { + $biblionumber = $self->biblionumber; + } + foreach my $additional_field (@$additional_fields) { + my $field = Koha::AdditionalFields->find($additional_field->{id}); my $value = $additional_field->{value}; + + if ($biblionumber and $field->marcfield) { + require Koha::Biblios; + $record //= Koha::Biblios->find($biblionumber)->metadata->record; + + my ($tag, $subfield) = split /\$/, $field->marcfield; + my $marc_field = $record->field($tag); + if ($field->marcfield_mode eq 'get') { + $value = $marc_field ? $marc_field->subfield($subfield) : ''; + } elsif ($field->marcfield_mode eq 'set') { + if ($marc_field) { + $marc_field->update($subfield => $value); + } else { + $marc_field = MARC::Field->new($tag, '', '', $subfield => $value); + $record->append_fields($marc_field); + } + $record_updated = 1; + } + } + if (defined $value) { my $field_value = Koha::AdditionalFieldValue->new({ field_id => $additional_field->{id}, @@ -56,6 +84,10 @@ sub set_additional_fields { })->store; } } + + if ($record_updated) { + C4::Biblio::ModBiblio($record, $biblionumber); + } } =head3 additional_field_values diff --git a/Koha/Schema/Result/Aqorder.pm b/Koha/Schema/Result/Aqorder.pm index 71c8753817..632e427511 100644 --- a/Koha/Schema/Result/Aqorder.pm +++ b/Koha/Schema/Result/Aqorder.pm @@ -822,6 +822,23 @@ __PACKAGE__->belongs_to( }, ); +__PACKAGE__->has_many( + "additional_field_values", + "Koha::Schema::Result::AdditionalFieldValue", + sub { + my ($args) = @_; + + return { + "$args->{foreign_alias}.record_id" => { -ident => "$args->{self_alias}.ordernumber" }, + + # TODO Add column additional_field_values.tablename to avoid subquery ? + "$args->{foreign_alias}.field_id" => + { -in => \'(SELECT id FROM additional_fields WHERE tablename = "aqorders")' }, + }; + }, + { cascade_copy => 0, cascade_delete => 0 }, +); + sub koha_objects_class { 'Koha::Acquisition::Orders'; } diff --git a/acqui/addorder.pl b/acqui/addorder.pl index 25fd4b3109..7297cbb4a0 100755 --- a/acqui/addorder.pl +++ b/acqui/addorder.pl @@ -139,6 +139,8 @@ use Koha::Acquisition::Baskets; use C4::Barcodes; use Koha::DateUtils qw( dt_from_string ); +use Koha::AdditionalFields; + ### "-------------------- addorder.pl ----------" # FIXME: This needs to do actual error checking and possibly return user to the same form, @@ -368,6 +370,19 @@ if ( $basket->{is_standing} || $orderinfo->{quantity} ne '0' ) { my @order_users = split( /:/, $order_users_ids ); ModOrderUsers( $order->ordernumber, @order_users ); + # Retrieve and save additional fields values + my @additional_fields = Koha::AdditionalFields->search({ tablename => 'aqorders' })->as_list; + my @additional_field_values; + foreach my $af (@additional_fields) { + my $id = $af->id; + my $value = $input->param("additional_field_$id"); + push @additional_field_values, { + id => $id, + value => $value, + }; + } + $order->set_additional_fields(\@additional_field_values); + # now, add items if applicable if ($basket->effective_create_items eq 'ordering') { diff --git a/acqui/neworderempty.pl b/acqui/neworderempty.pl index a584ea1d11..4864e5d4c9 100755 --- a/acqui/neworderempty.pl +++ b/acqui/neworderempty.pl @@ -99,6 +99,7 @@ use Koha::ItemTypes; use Koha::Patrons; use Koha::RecordProcessor; use Koha::Subscriptions; +use Koha::AdditionalFields; our $input = CGI->new; my $booksellerid = $input->param('booksellerid'); # FIXME: else ERROR! @@ -419,6 +420,29 @@ my $quantity = $input->param('rr_quantity_to_order') ? $data->{'quantity'}; $quantity //= 0; +# Get additional fields +my $record; +my @additional_fields = Koha::AdditionalFields->search({ tablename => 'aqorders' })->as_list; +my %additional_field_values; +if ($ordernumber) { + my $order = Koha::Acquisition::Orders->find($ordernumber); + foreach my $value ($order->additional_field_values->as_list) { + $additional_field_values{$value->field_id} = $value->value; + } +} elsif ( $biblionumber ) { + foreach my $af (@additional_fields) { + if ($af->marcfield) { + $record //= Koha::Biblios->find($biblionumber)->metadata->record; + my ($field, $subfield) = split /\$/, $af->marcfield; + $additional_field_values{$af->id} = $record->subfield($field, $subfield); + } + } +} +$template->param( + additional_fields => \@additional_fields, + additional_field_values => \%additional_field_values, +); + # fill template $template->param( existing => $biblionumber, diff --git a/admin/additional-fields.pl b/admin/additional-fields.pl index 78dd1a8fc4..5e6b1e32d7 100755 --- a/admin/additional-fields.pl +++ b/admin/additional-fields.pl @@ -51,6 +51,7 @@ if ( $op eq 'add' ) { my $name = $input->param('name') // q{}; my $authorised_value_category = $input->param('authorised_value_category') // q{}; my $marcfield = $input->param('marcfield') // q{}; + my $marcfield_mode = $input->param('marcfield_mode') // 'get'; my $searchable = $input->param('searchable') ? 1 : 0; if ( $field_id and $name ) { my $updated = 0; @@ -60,6 +61,7 @@ if ( $op eq 'add' ) { name => $name, authorised_value_category => $authorised_value_category, marcfield => $marcfield, + marcfield_mode => $marcfield_mode, searchable => $searchable, }); $updated = $af->store ? 1 : 0; @@ -76,6 +78,7 @@ if ( $op eq 'add' ) { name => $name, authorised_value_category => $authorised_value_category, marcfield => $marcfield, + marcfield_mode => $marcfield_mode, searchable => $searchable, }); $inserted = $af->store ? 1 : 0; diff --git a/installer/data/mysql/atomicupdate/bug-11844.pl b/installer/data/mysql/atomicupdate/bug-11844.pl new file mode 100644 index 0000000000..92eb0b60c1 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug-11844.pl @@ -0,0 +1,17 @@ +use Modern::Perl; + +return { + bug_number => '11844', + description => 'Add column additional_fields.marcfield_mode', + up => sub { + my ($args) = @_; + my ($dbh, $out) = @$args{qw(dbh out)}; + + unless ( column_exists( 'additional_fields', 'marcfield_mode' ) ) { + $dbh->do(q{ + ALTER TABLE additional_fields + ADD COLUMN marcfield_mode ENUM('get', 'set') NOT NULL DEFAULT 'get' COMMENT 'mode of operation (get or set) for marcfield' AFTER marcfield + }); + } + }, +}; diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 03d6cbebc9..0937260c76 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -243,6 +243,7 @@ CREATE TABLE `additional_fields` ( `name` varchar(255) NOT NULL DEFAULT '' COMMENT 'name of the field', `authorised_value_category` varchar(32) NOT NULL DEFAULT '' COMMENT 'is an authorised value category', `marcfield` varchar(16) NOT NULL DEFAULT '' COMMENT 'contains the marc field to copied into the record', + `marcfield_mode` ENUM('get', 'set') NOT NULL DEFAULT 'get' COMMENT 'mode of operation (get or set) for marcfield', `searchable` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'is the field searchable?', PRIMARY KEY (`id`), UNIQUE KEY `fields_uniq` (`tablename`(191),`name`(191)) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/additional-fields-entry.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/additional-fields-entry.inc index 24d30b560d..17c7a6f9a2 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/additional-fields-entry.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/additional-fields-entry.inc @@ -5,26 +5,34 @@
    [% END %] [% FOR field IN available %] + [% authorised_value_category = field.effective_authorised_value_category %]
  1. - [% IF field.authorised_value_category %] - + [% ELSE %] + (Authorised values for [% field.authorised_value_category | html %]) + (Authorised values for [% authorised_value_category | html %]) + [% ELSIF field.marcfield && field.marcfield_mode == 'get' %] + [% ELSE %] - [% IF field.marcfield %] - - This value will be filled with the [% field.marcfield | html %] subfield of the selected biblio. - [% ELSE %] - - [% END %] + + [% END %] + + [% IF field.marcfield && field.marcfield_mode == 'get' %] + This value will be filled with the [% field.marcfield | html %] subfield of the selected biblio. + [% ELSIF field.marcfield && field.marcfield_mode == 'set' %] + This value will be saved to the [% field.marcfield %] subfield of the selected biblio. [% END %]
  2. [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt index 451d55f1f3..b3cfee5e77 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt @@ -4,6 +4,7 @@ [% USE KohaDates %] [% USE Price %] [% USE ItemTypes %] +[% USE AuthorisedValues %] [% SET footerjs = 1 %] [% INCLUDE 'doc-head-open.inc' %] [% IF ( ordernumber ) %]Modify order details (line #[% ordernumber | html %])[% ELSE %]New order[% END %] › Basket [% basketno | html %] › Acquisitions › Koha @@ -529,6 +530,9 @@
+ + [% INCLUDE 'additional-fields-entry.inc' available = additional_fields values = additional_field_values %] +
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 b856827209..c41ee06af7 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 @@ -11,7 +11,7 @@ [% INCLUDE 'doc-head-close.inc' %] -[% marcfield_tables = ['subscription'] %] +[% marcfield_tables = ['subscription', 'aqorders'] %] [% searchable_tables = ['subscription', 'aqbasket', 'aqinvoices'] %] [% show_marcfield = marcfield_tables.grep('^' _ tablename _ '$').size ? 1 : 0 %] [% show_searchable = searchable_tables.grep('^' _ tablename _ '$').size ? 1 : 0 %] @@ -118,6 +118,7 @@
    [% IF CAN_user_acquisition_order_manage %] [% WRAPPER table_option value="aqbasket" %]Order baskets[% END %] + [% WRAPPER table_option value="aqorders" %]Order lines[% END %] [% END %] [% IF CAN_user_acquisition_edit_invoices %] [% WRAPPER table_option value="aqinvoices" %]Invoices[% END %] @@ -145,6 +146,7 @@ Authorized value category [% IF show_marcfield %] MARC field + MARC field mode [% END %] [% IF show_searchable %] Searchable @@ -159,6 +161,12 @@ [% field.authorised_value_category | html %] [% IF show_marcfield %] [% field.marcfield | html %] + + [% SWITCH field.marcfield_mode %] + [% CASE 'get' %]Get value from MARC record + [% CASE 'set' %]Save value to MARC record + [% END %] + [% END %] [% IF show_searchable %] @@ -203,6 +211,22 @@ +
  • + + +
  • [% END %] [% IF show_searchable %]
  • diff --git a/serials/subscription-add.pl b/serials/subscription-add.pl index c08142b897..93c619fccd 100755 --- a/serials/subscription-add.pl +++ b/serials/subscription-add.pl @@ -365,16 +365,9 @@ sub redirect_add_subscription { my @additional_fields; my $biblio = Koha::Biblios->find($biblionumber); - my $record = $biblio->metadata->record({ embed_items => 1 }); my $subscription_fields = Koha::AdditionalFields->search({ tablename => 'subscription' }); while ( my $field = $subscription_fields->next ) { my $value = $query->param('additional_field_' . $field->id); - if ($field->marcfield) { - my ($field, $subfield) = split /\$/, $field->marcfield; - if ( $record and $field and $subfield ) { - $value = $record->subfield( $field, $subfield ); - } - } push @additional_fields, { id => $field->id, value => $value, @@ -485,16 +478,9 @@ sub redirect_mod_subscription { my @additional_fields; my $biblio = Koha::Biblios->find($biblionumber); - my $record = $biblio->metadata->record({ embed_items => 1 }); my $subscription_fields = Koha::AdditionalFields->search({ tablename => 'subscription' }); while ( my $field = $subscription_fields->next ) { my $value = $query->param('additional_field_' . $field->id); - if ($field->marcfield) { - my ($field, $subfield) = split /\$/, $field->marcfield; - if ( $record and $field and $subfield ) { - $value = $record->subfield( $field, $subfield ); - } - } push @additional_fields, { id => $field->id, value => $value, -- 2.30.2