Bug 15774: Add additional fields to order baskets
authorJesse Weaver <jweaver@bywatersolutions.com>
Wed, 10 Feb 2016 19:29:06 +0000 (12:29 -0700)
committerNick Clemens <nick@bywatersolutions.com>
Thu, 7 Mar 2019 20:37:05 +0000 (20:37 +0000)
This also moves the admin page for additional fields for all tables to a
single common screen, and factors out display/input parsing logic.

Test plan:
  1. Create an additional field for a subscription (under Serials -> Add
     subscription fields).
  2. Apply patch.
  3. Visit Additional fields under administration, and verify that
     the field created above still shows under the list for the
     subscription table.
  4. Create at least four fields for aqbasket for each combination of
     searchable/not-searchable and with/without an authorized value.
  5. Create an order basket, and verify that all fields are visible and
     correctly save.
  6. Edit the basket, verifying that changes to these additional fields
     are saved.
  7. Add an order to the basket (contents are irrelevant).
  8. Go to advanced search within acquisitions.
  9. Verify that only the searchable fields show in the form, and that
     their contents may be searched.

Signed-off-by: Séverine QUEUNE <severine.queune@bulac.fr>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Josef Moravec <josef.moravec@gmail.com>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>

20 files changed:
C4/Acquisition.pm
Koha/AdditionalField.pm
acqui/basket.pl
acqui/basketheader.pl
acqui/histsearch.pl
admin/additional-fields.pl [moved from serials/add_fields.pl with 88% similarity]
koha-tmpl/intranet-tmpl/prog/en/includes/additional-fields-display.inc [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/includes/additional-fields-entry.inc [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc
koha-tmpl/intranet-tmpl/prog/en/includes/filter-orders.inc
koha-tmpl/intranet-tmpl/prog/en/includes/serials-menu.inc
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basketheader.tt
koha-tmpl/intranet-tmpl/prog/en/modules/admin/additional-fields.tt [new file with mode: 0755]
koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt
koha-tmpl/intranet-tmpl/prog/en/modules/serials/add_fields.tt [deleted file]
koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-search.tt
koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt
serials/serials-search.pl
serials/subscription-add.pl

index b1f7588..8ed768b 100644 (file)
@@ -2280,6 +2280,7 @@ sub GetHistory {
     my $search_children_too = $params{search_children_too} || 0;
     my $created_by = $params{created_by} || [];
     my $ordernumbers = $params{ordernumbers} || [];
+    my $additional_fields = $params{additional_fields} // [];
 
     my @order_loop;
     my $total_qty         = 0;
@@ -2443,6 +2444,16 @@ sub GetHistory {
     if ( @$ordernumbers ) {
         $query .= ' AND (aqorders.ordernumber IN ( ' . join (',', ('?') x @$ordernumbers ) . '))';
         push @query_params, @$ordernumbers;
+    if ( @$additional_fields ) {
+        my $matching_record_ids_for_additional_fields = Koha::AdditionalField->get_matching_record_ids( {
+            fields => $additional_fields,
+            tablename => 'aqbasket',
+            exact_match => 0,
+        } );
+        return [] unless @$matching_record_ids_for_additional_fields;
+
+        # No parameterization because record IDs come directly from DB
+        $query .= ' AND aqbasket.basketno IN ( ' . join( ',', @$matching_record_ids_for_additional_fields ) . ' )';
     }
 
     if ( C4::Context->preference("IndependentBranches") ) {
index 563a7f3..7c4903a 100644 (file)
@@ -265,6 +265,63 @@ sub get_matching_record_ids {
     ]
 }
 
+sub update_fields_from_query {
+    my ( $class, $args ) = @_;
+    die "BAD CALL: Don't use update_fields_from_query as an instance method"
+        if ref $class and UNIVERSAL::can($class,'can');
+
+    my $query = $args->{query};
+    my $additional_fields = Koha::AdditionalField->all( { tablename => $args->{tablename} } );
+    for my $field ( @$additional_fields ) {
+        my $af = Koha::AdditionalField->new({ id => $field->{id} })->fetch;
+        if ( $af->{marcfield} ) {
+            my ( $field, $subfield ) = split /\$/, $af->{marcfield};
+            $af->{values} = undef;
+            if ( $args->{marc_record} and $field and $subfield ) {
+                my $value = $args->{marc_record}->subfield( $field, $subfield );
+                $af->{values} = {
+                    $args->{record_id} => $value
+                };
+            }
+        } else {
+            $af->{values} = {
+                $args->{record_id} => $query->param( 'additional_field_' . $field->{id} )
+            } if defined $query->param( 'additional_field_' . $field->{id} );
+        }
+        $af->insert_values;
+    }
+}
+
+sub get_filters_from_query {
+    my ( $class, $args ) = @_;
+    die "BAD CALL: Don't use get_filters_from_query as an instance method"
+        if ref $class and UNIVERSAL::can($class,'can');
+
+    my $query = $args->{query};
+    my $additional_fields = Koha::AdditionalField->all( { tablename => $args->{tablename}, searchable => 1 } );
+    my @additional_field_filters;
+    for my $field ( @$additional_fields ) {
+        my $filter_value = $query->param( 'additional_field_' . $field->{id} );
+        if ( defined $filter_value and $filter_value ne q|| ) {
+            push @additional_field_filters, {
+                name => $field->{name},
+                value => $filter_value,
+                authorised_value_category => $field->{authorised_value_category},
+            };
+        }
+    }
+
+    return \@additional_field_filters;
+}
+
+sub get_filters_as_values {
+    my ( $class, $filters ) = @_;
+    die "BAD CALL: Don't use get_filters_as_values as an instance method"
+        if ref $class and UNIVERSAL::can($class,'can');
+
+    return { map { $_->{name} => $_->{value} } @$filters };
+}
+
 1;
 
 __END__
@@ -414,6 +471,47 @@ This is a static method.
         }
     );
 
+=head2 update_fields_from_query
+
+Updates fields based on user input (best paired with additional-fields-entry.pl) and optionally a MARC record.
+
+This is a static method.
+
+    Koha::AdditionalField->update_fields_from_query( {
+        tablename => 'aqbasket',
+        input => $input,
+        record_id => $basketno,
+        marc_record => GetBiblio( $biblionumber ),
+    } );
+
+=head2 get_filters_from_query
+
+Extracts a list of search filters from user input, to be used with C<get_matching_record_ids> and
+C<get_filters_as_values>.
+
+This is a static method.
+
+    my $filters = Koha::AdditionalField->get_filters_from_query( {
+        tablename => 'aqbasket',
+        input => $input,
+    } );
+
+=head2 get_filters_as_values
+
+Transforms the result of C<get_filters_from_query> into a hashref of C<name> => C<value>, so
+user-entered filters can be redisplayed.
+
+    $template->param(
+        additional_field_values => Koha::AdditionalField->get_filters_as_values(
+            $filters
+        ),
+    );
+
+    [% INCLUDE 'additional-field-entry.inc'
+        values=additional_field_values
+        available=available_additional_fields
+    %]
+
 =head1 AUTHOR
 
 Jonathan Druart <jonathan.druart at biblibre.com>
index 1b55e74..8a09419 100755 (executable)
@@ -43,6 +43,8 @@ use Koha::EDI qw( create_edi_order get_edifact_ean );
 use Koha::CsvProfiles;
 use Koha::Patrons;
 
+use Koha::AdditionalField;
+
 =head1 NAME
 
 basket.pl
@@ -430,6 +432,11 @@ if ( $op eq 'list' ) {
         has_budgets          => $has_budgets,
         duplinbatch          => $duplinbatch,
         csv_profiles         => [ Koha::CsvProfiles->search({ type => 'sql', used_for => 'export_basket' }) ],
+        available_additional_fields => Koha::AdditionalField->all( { tablename => 'aqbasket' } ),
+        additional_field_values => Koha::AdditionalField->fetch_all_values( {
+            tablename => 'aqbasket',
+            record_id => $basketno,
+        } )->{$basketno},
     );
 }
 
index f4650e8..acd3d67 100755 (executable)
@@ -54,6 +54,7 @@ use C4::Acquisition qw/GetBasket NewBasket ModBasketHeader/;
 use C4::Contract qw/GetContracts/;
 
 use Koha::Acquisition::Booksellers;
+use Koha::AdditionalField;
 
 my $input = new CGI;
 my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
@@ -74,6 +75,8 @@ my $basket;
 my $op = $input->param('op');
 my $is_an_edit = $input->param('is_an_edit');
 
+$template->param( available_additional_fields => scalar Koha::AdditionalField->all( { tablename => 'aqbasket' } ) );
+
 if ( $op eq 'add_form' ) {
     my @contractloop;
     if ( $basketno ) {
@@ -94,6 +97,12 @@ if ( $op eq 'add_form' ) {
             }
         }
         $template->param( is_an_edit => 1);
+        $template->param(
+            additional_field_values => Koha::AdditionalField->fetch_all_values( {
+                tablename => 'aqbasket',
+                record_id => $basketno,
+            } )->{$basketno},
+        );
     } else {
     #new basket
         my $basket;
@@ -160,6 +169,13 @@ if ( $op eq 'add_form' ) {
             scalar $input->param('create_items')
         );
     }
+
+    Koha::AdditionalField->update_fields_from_query( {
+        tablename => 'aqbasket',
+        record_id => $basketno,
+        query => $input,
+    } );
+
     print $input->redirect('basket.pl?basketno='.$basketno);
     exit 0;
 }
index 248ff76..a1c7fe6 100755 (executable)
@@ -56,6 +56,7 @@ use C4::Output;
 use C4::Acquisition;
 use C4::Debug;
 use C4::Koha;
+use Koha::AdditionalField;
 use Koha::DateUtils;
 
 my $input = new CGI;
@@ -97,6 +98,12 @@ unless ( $input->param('from') ) {
 }
 $filters->{from_placed_on} = output_pref( { dt => $from_placed_on, dateformat => 'iso', dateonly => 1 } ),
 $filters->{to_placed_on} = output_pref( { dt => $to_placed_on, dateformat => 'iso', dateonly => 1 } ),
+$filters->{additional_fields} = Koha::AdditionalField->get_filters_from_query({
+    tablename => 'aqbasket',
+    query => $input,
+} );
+
+$template->param( available_additional_fields => scalar Koha::AdditionalField->all( { tablename => 'aqbasket', searchable => 1 } ) );
 
 my $order_loop;
 # If we're supplied any value then we do a search. Otherwise we don't.
similarity index 88%
rename from serials/add_fields.pl
rename to admin/additional-fields.pl
index 317f299..be85381 100755 (executable)
@@ -27,16 +27,17 @@ my $input = new CGI;
 
 my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
     {
-        template_name   => "serials/add_fields.tt",
+        template_name   => "admin/additional-fields.tt",
         query           => $input,
         type            => "intranet",
         authnotrequired => 0,
-        flagsrequired   => { serials => '*' },
+        flagsrequired   => { parameters => 1 },
         debug           => 1,
     }
 );
 
-my $op = $input->param('op') // 'list';
+my $tablename = $input->param('tablename');
+my $op = $input->param('op') // ( $tablename ? 'list' : 'list_tables' );
 my $field_id = $input->param('field_id');
 my @messages;
 
@@ -65,7 +66,7 @@ if ( $op eq 'add' ) {
         my $inserted = 0;
         eval {
             my $af = Koha::AdditionalField->new({
-                tablename => 'subscription',
+                tablename => $tablename,
                 name => $name,
                 authorised_value_category => $authorised_value_category,
                 marcfield => $marcfield,
@@ -106,18 +107,21 @@ if ( $op eq 'add_form' ) {
         $field = Koha::AdditionalField->new( { id => $field_id } )->fetch;
     }
 
+    $tablename = $field->{tablename};
+
     $template->param(
         field => $field,
     );
 }
 
 if ( $op eq 'list' ) {
-    my $fields = Koha::AdditionalField->all( { tablename => 'subscription' } );
+    my $fields = Koha::AdditionalField->all( { tablename => $tablename } );
     $template->param( fields => $fields );
 }
 
 $template->param(
     op => $op,
+    tablename => $tablename,
     messages => \@messages,
 );
 
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/additional-fields-display.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/additional-fields-display.inc
new file mode 100644 (file)
index 0000000..41771a8
--- /dev/null
@@ -0,0 +1,11 @@
+[% USE AuthorisedValues %]
+[% FOR field IN available %]
+    <li>
+        <span class="label"> [% field.name %]: </span>
+        [% IF field.authorised_value_category %]
+            [% AuthorisedValues.GetByCode( field.authorised_value_category, values.${field.name} ) %]
+        [% ELSE %]
+            [% values.${field.name} %]
+        [% END %]
+    </li>
+[% END %]
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
new file mode 100644 (file)
index 0000000..a961e55
--- /dev/null
@@ -0,0 +1,33 @@
+[% USE AuthorisedValues %]
+[% IF wrap_fieldset != 0 %]
+<fieldset class="rows">
+    <legend>Additional fields</legend>
+    <ol>
+[% END %]
+        [% FOR field IN available %]
+            <li>
+                <label for="additional_field_[% field.id %]"> [% field.name %]: </label>
+                [% IF field.authorised_value_category %]
+                    <select name="additional_field_[% field.id %]" id="additional_field_[% field.id %]">
+                        [% FOREACH av IN AuthorisedValues.Get( field.authorised_value_category, values.${field.name} ) %]
+                            [% IF av.selected %]
+                                <option value="[% av.authorised_value %]" selected="selected">[% av.lib %]</option>
+                            [% ELSE %]
+                                <option value="[% av.authorised_value %]">[% av.lib %]</option>
+                            [% END %]
+                        [% END %]
+                    </select> (Authorised values for [% field.authorised_value_category %])
+                [% ELSE %]
+                    [% IF field.marcfield %]
+                        <input type="text" value="[% values.${field.name} %]" id="additional_field_[% field.id %]" name="additional_field_[% field.id %]" readonly="readonly" />
+                        This value will be filled with the [% field.marcfield %] subfield of the selected biblio.
+                    [% ELSE %]
+                        <input type="text" value="[% values.${field.name} %]" id="additional_field_[% field.id %]" name="additional_field_[% field.id %]" />
+                    [% END %]
+                [% END %]
+            </li>
+        [% END %]
+[% IF wrap_fieldset != 0 %]
+    </ol>
+</fieldset>
+[% END %]
index 817b5a6..b2f3242 100644 (file)
         </ul>
     [% END %]
 
-    [% IF ( CAN_user_parameters_manage_search_targets || CAN_user_parameters_manage_didyoumean || CAN_user_parameters_manage_column_config || CAN_user_parameters_manage_audio_alerts || ( CAN_user_parameters_manage_sms_providers && Koha.Preference('SMSSendDriver') == 'Email' ) || CAN_user_parameters_manage_usage_stats ) %]
+    [% IF ( CAN_user_parameters_manage_search_targets || CAN_user_parameters_manage_didyoumean || CAN_user_parameters_manage_column_config || CAN_user_parameters_manage_audio_alerts || ( CAN_user_parameters_manage_sms_providers && Koha.Preference('SMSSendDriver') == 'Email' ) || CAN_user_parameters_manage_usage_stats || CAN_user_parameters_manage_additional_fields_baskets || CAN_user_parameters_manage_additional_fields_subscriptions ) %]
         <h5>Additional parameters</h5>
         <ul>
             <!-- <li><a href="/cgi-bin/koha/admin/printers.pl">Network Printers</a></li> -->
             [% IF ( CAN_user_parameters_manage_mana ) %]
                 <li><a href="/cgi-bin/koha/admin/share_content.pl">Share content with Mana KB</a></li>
             [% END %]
+            [% IF ( CAN_user_parameters_manage_additional_fields_baskets || CAN_user_parameters_manage_additional_fields_subscriptions ) %]
+                <li><a href="/cgi-bin/koha/admin/additional-fields.pl">Additional fields</a></li>
+            [% END %]
         </ul>
     [% END %]
 </div>
index 208b2dc..42a3060 100644 (file)
@@ -20,6 +20,7 @@
         <label for="basketgroupname">Basket group:</label>
         <input type="text" name="basketgroupname" id="basketgroupname" value="[% filters.basketgroupname | html %]" />
     </li>
+        [% INCLUDE 'additional-fields-entry.inc' available=available_additional_fields values=additional_field_filters wrap_fieldset=0 %]
     <li>
       <label for="ordernumber">Order line:</label>
       <input type="text" name="ordernumber" id="ordernumber" value="[% filters.ordernumber | html %]" />
index af85c11..e99b614 100644 (file)
@@ -30,7 +30,6 @@
             Manage numbering patterns
         </a>
     </li>
-    <li><a href="/cgi-bin/koha/serials/add_fields.pl">Add subscription fields</a></li>
     [% IF Koha.Preference('Mana') == 1 %]
         <li><a href="/cgi-bin/koha/serials/serials-search.pl?mana=1">Search on Mana</a></li>
     [% END %]
index 43517f8..d07f43c 100644 (file)
                     </li>
                 [% END %]
 
+                [% INCLUDE 'additional-fields-display.inc' available=available_additional_fields values=additional_field_values %]
+
                 </ol>
                 </div> <!-- /.col-sm-6 -->
 
index 26ff7cd..f6a89c7 100644 (file)
                 [% END %]
             </ol>
         </fieldset>
+
+        [% IF available_additional_fields %]
+            [% INCLUDE 'additional-fields-entry.inc' available=available_additional_fields values=additional_field_values %]
+        [% END %]
+
         <fieldset class="action">
             <input type="hidden" name="op" value="add_validate" />
             <input type="submit" value="Save" />
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
new file mode 100755 (executable)
index 0000000..a37401a
--- /dev/null
@@ -0,0 +1,198 @@
+[% USE Asset %]
+[% USE AuthorisedValues %]
+[% SET footerjs = 1 %]
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha &rsaquo; Administration &rsaquo;
+    [% SWITCH op %]
+        [% CASE 'add_form' %][% IF field %]Modify additional field '[% field.name %]'[% ELSE %]Add additional field[% END %]
+        [% CASE %]Manage additional fields
+    [% END %]
+</title>
+[% INCLUDE 'doc-head-close.inc' %]
+[% Asset.css('css/datatables.css') %]
+</head>
+
+<body id="ser_add_fields" class="ser">
+    [% INCLUDE 'header.inc' %]
+    [% INCLUDE 'cat-search.inc' %]
+
+    <div id="breadcrumbs">
+        <a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> &rsaquo;
+        [% SWITCH op %]
+            [% CASE 'add_form' %]<a href="/cgi-bin/koha/admin/additional-fields.pl">Manage additional fields</a> &rsaquo; [% IF field %]Modify field '[% field.name %]'[% ELSE %]Add field[% END %]
+            [% CASE 'list' %]<a href="/cgi-bin/koha/admin/additional-fields.pl">Manage additional fields</a> &rsaquo; Modify fields for '[% tablename %]'
+            [% CASE %]Manage additional fields
+        [% END %]
+    </div>
+
+    <div id="doc3" class="yui-t2">
+    <div id="bd">
+    <div id="yui-main">
+    <div class="yui-b">
+    [% IF op == 'list' %]
+        <div id="toolbar" class="btn-toolbar">
+            <a class="btn btn-default btn-sm" id="newfields" href="?op=add_form&amp;tablename=[% tablename %]"><i class="fa fa-plus"></i> Create field</a>
+        </div>
+    [% END %]
+
+    [% IF messages %]
+        [% FOR message IN messages %]
+            [% IF message.code == 'insert' %]
+                [% IF message.number > 0 %]
+                    <div class="dialog message">The field has been inserted</div>
+                [% ELSE %]
+                    <div class="dialog alert">The field could not be inserted. Perhaps the name already exists?</div>
+                [% END %]
+            [% ELSIF message.code == 'update' %]
+                [% IF message.number > 0 %]
+                    <div class="dialog message">The field has been updated</div>
+                [% ELSE %]
+                    <div class="dialog alert">The field could not be updated. Perhaps the name already exists?</div>
+                [% END %]
+            [% ELSIF message.code == 'delete' %]
+                [% IF message.number > 0 %]
+                    <div class="dialog message">The field has been deleted</div>
+                [% ELSE %]
+                    <div class="dialog alert">The field could not be deleted. Check the log for errors.</div>
+                [% END %]
+            [% END %]
+        [% END %]
+    [% END %]
+
+    [% IF op == 'list_tables' %]
+        <h3>Additional fields</h3>
+        <p>Select a table:</p>
+        [% BLOCK table_option %]
+            <li><a href="?tablename=[% value %]">[% content %] (<tt>[% value %]</tt>)</a></li>
+        [% END %]
+        <ul>
+            [% WRAPPER table_option value="aqbasket" %]Order baskets[% END %]
+            [% WRAPPER table_option value="subscription" %]Subscriptions[% END %]
+        </ul>
+    [% ELSIF op == 'list' %]
+        <h3>Additional fields for '[% tablename %]'</h3>
+        [% IF fields %]
+            <table id="fieldst">
+                <thead>
+                    <tr>
+                        <th>Name</th>
+                        <th>Authorised value category</th>
+                        <th>MARC field</th>
+                        <th>Searchable</th>
+                        <th>Actions</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    [% FOR field IN fields %]
+                        <tr>
+                            <td>[% field.name %]</td>
+                            <td>[% field.authorised_value_category %]</td>
+                            <td>[% field.marcfield %]</td>
+                            <td>
+                                [% IF field.searchable %]Yes[% ELSE %]No[% END %]
+                            </td>
+                            <td class="actions">
+                                <a class="btn btn-default btn-xs" href="?op=add_form&amp;field_id=[% field.id %]"><i class="fa fa-pencil"></i> Edit</a>
+                                <a class="confirmdelete btn btn-default btn-xs" href="?op=delete&amp;field_id=[% field.id %]"><i class="fa fa-trash"></i> Delete</a>
+                            </td>
+                        </tr>
+                    [% END %]
+                </tbody>
+            </table>
+        [% ELSE %]
+            [% IF tablename %]There are no additional fields defined for this table.[% END %]
+        [% END %]
+    [% ELSIF op == 'add_form' %]
+        [% IF field %]
+            <h3>Modify field</h3>
+        [% ELSE %]
+            <h3>Add field</h3>
+        [% END %]
+        <form action="" name="add_form" id="add_field" method="post">
+            <fieldset class="rows">
+                <ol>
+                    <li>
+                        <label for="name" class="required">Name: </label>
+                        <input type="text" name="name" id="name" value="[% field.name | html %]" class="required" required="required" />
+                        <span class="required">Required</span>
+                    </li>
+                    <li>
+                        <label for="av">Authorised value category: </label>
+                        <select name="authorised_value_category">
+                            <option value="">None</option>
+                            [% PROCESS options_for_authorised_value_categories
+                                authorised_value_categories = AuthorisedValues.GetCategories({
+                                    selected => field.authorised_value_category
+                                })
+                            %]
+                        </select>
+                    </li>
+                    <li>
+                        <label for="marcfield">MARC field: </label>
+                        <input type="text" name="marcfield" id="marcfield" value="[% field.marcfield %]" />
+                    </li>
+                    <li>
+                        <label for="searchable">Searchable: </label>
+                        [% IF field.searchable %]
+                            <input type="checkbox" name="searchable" id="searchable" checked="checked" />
+                        [% ELSE %]
+                            <input type="checkbox" name="searchable" id="searchable" />
+                        [% END %]
+                    </li>
+                </ol>
+            </fieldset>
+            <fieldset class="action">
+                [% IF field %]
+                    <input type="hidden" name="field_id" value="[% field.id %]" />
+                [% END %]
+                <input type="hidden" name="tablename" value="[% tablename %]" />
+                <input type="hidden" name="op" value="add" />
+                <input type="submit" value="Save" />
+                <a href="?tablename=[% tablename %]" class="cancel">Cancel</a>
+            </fieldset>
+        </form>
+    [% END %]
+
+    </div>
+    </div>
+
+<div class="yui-b">
+[% INCLUDE 'admin-menu.inc' %]
+</div>
+</div>
+
+[% MACRO jsinclude BLOCK %]
+    [% INCLUDE "datatables.inc" %]
+    <script type="text/javascript">
+        $(document).ready(function(){
+            $('#selecttable').find(":submit").hide();
+            $('#selecttable select').change(function() {
+                $('#selecttable').submit();
+            });
+
+            $("#fieldst").dataTable($.extend(true, {}, dataTablesDefaults, {
+                'bAutoWidth': false,
+                'sDom': 't<"bottom pager"ilpf>',
+                'sPaginationType': 'four_button',
+                'aLengthMenu': [[10, 20, 50, 100, -1], [10, 20, 50, 100, "All"]],
+                'iDisplayLength': 20,
+                'aaSorting': [[ 0, "asc" ]],
+            }));
+
+            $(".confirmdelete").click(function(){
+                return confirm(_("Are you sure you want to delete this field?"));
+            });
+
+            $("#add_field").on('submit', function(){
+                if ( $("#marcfield").val().length > 0
+                    && $("select[name='authorised_value_category']" ).val().length > 0 ) {
+                    alert("You cannot select an authorised value category and a marcfield");
+                    return false;
+                }
+                return true;
+            });
+        });
+    </script>
+[% END %]
+
+[% INCLUDE 'intranet-bottom.inc' %]
index 33312ed..ee1abfc 100644 (file)
                 </dl>
             [% END %]
 
-            [% IF ( ( CAN_user_parameters_manage_search_targets || CAN_user_parameters_manage_didyoumean || CAN_user_parameters_manage_column_config || CAN_user_parameters_manage_audio_alerts || CAN_user_parameters_manage_sms_providers && Koha.Preference('SMSSendDriver') == 'Email' ) || CAN_user_parameters_manage_usage_stats || CAN_user_parameters_manage_mana ) %]
+            [% IF ( ( CAN_user_parameters_manage_search_targets || CAN_user_parameters_manage_didyoumean || CAN_user_parameters_manage_column_config || CAN_user_parameters_manage_audio_alerts || CAN_user_parameters_manage_sms_providers && Koha.Preference('SMSSendDriver') == 'Email' ) || CAN_user_parameters_manage_usage_stats || CAN_user_parameters_manage_additional_fields_baskets || CAN_user_parameters_manage_additional_fields_subscriptions || CAN_user_parameters_manage_mana ) %]
                 <h3>Additional parameters</h3>
                 <dl>
                         <!-- <dt><a href="/cgi-bin/koha/admin/printers.pl">Network Printers</a></dt>
                         <dt><a href="/cgi-bin/koha/admin/share_content.pl">Share content with Mana KB</a></dt>
                         <dd>Share content (subscriptions, reports) with the Koha community</dd>
                     [% END %]
+                    [% IF ( CAN_user_parameters_manage_additional_fields_baskets || CAN_user_parameters_manage_additional_fields_subscriptions ) %]
+                    <dt><a href="/cgi-bin/koha/admin/additional-fields.pl">Additional fields</a></dt>
+                    <dd>Add additional fields to certain tables</dd>
+                    [% END %]
                 </dl>
             [% END %]
             </div>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/add_fields.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/add_fields.tt
deleted file mode 100644 (file)
index 9087712..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-[% USE raw %]
-[% USE Asset %]
-[% USE AuthorisedValues %]
-[% SET footerjs = 1 %]
-[% INCLUDE 'doc-head-open.inc' %]
-<title>Koha &rsaquo; Serials &rsaquo; Manage new fields for subscriptions
-  [% IF op == "list" %] &rsaquo; List of fields
-  [% ELSIF op == "add_form" %]
-    [% IF field %] &rsaquo; Modify field
-    [% ELSE %] &rsaquo; Add field
-    [% END %]
-  [% END %]
-</title>
-[% INCLUDE 'doc-head-close.inc' %]
-</head>
-
-<body id="ser_add_fields" class="ser">
-  [% INCLUDE 'header.inc' %]
-  [% INCLUDE 'serials-search.inc' %]
-
-  <div id="breadcrumbs">
-    <a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/serials/serials-home.pl">Serials</a> &rsaquo; Manage new fields for subscriptions
-  </div>
-
-<div class="main container-fluid">
-    <div class="row">
-        <div class="col-sm-10 col-sm-push-2">
-            <main>
-
-  [% IF op == 'list' %]
-    <div id="toolbar" class="btn-toolbar">
-      <a class="btn btn-default btn-sm" id="newfields" href="/cgi-bin/koha/serials/add_fields.pl?op=add_form"><i class="fa fa-plus"></i> New field</a>
-    </div>
-  [% END %]
-
-  [% IF messages %]
-    [% FOR message IN messages %]
-      [% IF message.code == 'insert' %]
-        [% IF message.number > 0 %]
-          <div class="dialog message">Field created.</div>
-        [% ELSE %]
-          <div class="dialog alert">The field could not be created. Perhaps the name already exists?</div>
-        [% END %]
-      [% ELSIF message.code == 'update' %]
-        [% IF message.number > 0 %]
-          <div class="dialog message">Field updated.</div>
-        [% ELSE %]
-          <div class="dialog alert">The field could not be updated. Perhaps the name already exists?</div>
-        [% END %]
-      [% ELSIF message.code == 'delete' %]
-        [% IF message.number > 0 %]
-          <div class="dialog message">Field deleted.</div>
-        [% ELSE %]
-          <div class="dialog alert">The field could not be deleted. Check the log for errors.</div>
-        [% END %]
-      [% END %]
-    [% END %]
-  [% END %]
-
-  [% IF op == 'list' %]
-    <h3>Additional fields for subscriptions</h3>
-    [% IF fields %]
-      <table id="fieldst">
-        <thead>
-          <tr>
-            <th>Name</th>
-            <th>Authorised value category</th>
-            <th>Marc field</th>
-            <th>Searchable</th>
-            <th>Actions</th>
-          </tr>
-        </thead>
-        <tbody>
-          [% FOR field IN fields %]
-            <tr>
-              <td>[% field.name | html %]</td>
-              <td>[% field.authorised_value_category | html %]</td>
-              <td>[% field.marcfield | html %]</td>
-              <td>
-                [% IF field.searchable %]Yes[% ELSE %]No[% END %]
-              </td>
-              <td class="actions">
-                <a class="btn btn-default btn-xs" href="/cgi-bin/koha/serials/add_fields.pl?op=add_form&amp;field_id=[% field.id | html %]"><i class="fa fa-pencil"></i> Edit</a>
-                <a class="confirmdelete btn btn-default btn-xs" href="/cgi-bin/koha/serials/add_fields.pl?op=delete&amp;field_id=[% field.id | html %]"><i class="fa fa-trash"></i> Delete</a>
-              </td>
-            </tr>
-          [% END %]
-        </tbody>
-      </table>
-    [% ELSE %]
-      There is no field defined.
-    [% END %]
-  [% ELSIF op == 'add_form' %]
-    [% IF field %]
-      <h3>Modify field</h3>
-    [% ELSE %]
-      <h3>Add field</h3>
-    [% END %]
-    <form action="/cgi-bin/koha/serials/add_fields.pl" name="add_form" id="add_field" method="post">
-      <fieldset class="rows">
-        <ol>
-          <li>
-            <label for="name" class="required">Name: </label>
-            <input type="text" name="name" id="name" value="[% field.name | html %]" class="required" required="required" />
-            <span class="required">Required</span>
-          </li>
-          <li>
-            <label for="av">Authorised value category: </label>
-            <select id="av" name="authorised_value_category">
-              <option value="">None</option>
-              [% PROCESS options_for_authorised_value_categories authorised_value_categories => AuthorisedValues.GetCategories( selected => field.authorised_value_category ) %]
-            </select>
-          </li>
-          <li>
-            <label for="marcfield">Marc field: </label>
-            <input type="text" name="marcfield" id="marcfield" value="[% field.marcfield | html %]" />
-          </li>
-          <li>
-            <label for="searchable">Searchable: </label>
-            [% IF field.searchable %]
-              <input type="checkbox" name="searchable" id="searchable" checked="checked" />
-            [% ELSE %]
-              <input type="checkbox" name="searchable" id="searchable" />
-            [% END %]
-          </li>
-        </ol>
-      </fieldset>
-      <fieldset class="action">
-        [% IF field %]
-          <input type="hidden" name="field_id" value="[% field.id | html %]" />
-        [% END %]
-        <input type="hidden" name="op" value="add" />
-        <input type="submit" value="Save" />
-        <a href="/cgi-bin/koha/serials/add_fields.pl" class="cancel">Cancel</a>
-      </fieldset>
-    </form>
-  [% END %]
-
-            </main>
-        </div> <!-- /.col-sm-10.col-sm-push-2 -->
-
-        <div class="col-sm-2 col-sm-pull-10">
-            <aside>
-                [% INCLUDE 'serials-menu.inc' %]
-            </aside>
-        </div> <!-- /.col-sm-2.col-sm-pull-10 -->
-     </div> <!-- /.row -->
-
-[% MACRO jsinclude BLOCK %]
-    [% INCLUDE "datatables.inc" %]
-    <script>
-        $(document).ready(function(){
-
-            $("#fieldst").dataTable($.extend(true, {}, dataTablesDefaults, {
-                'bAutoWidth': false,
-                'sPaginationType': 'four_button',
-                "aoColumnDefs": [
-                    { "aTargets": [ -1 ], "bSortable": false, "bSearchable": false },
-                ]
-            }));
-
-            $(".confirmdelete").click(function(){
-                return confirm(_("Are you sure you want to delete this field?"));
-            });
-
-            $("#add_field").on('submit', function(){
-                if ( $("#marcfield").val().length > 0
-                    && $("select[name='authorised_value_category']" ).val().length > 0 ) {
-                    alert("You cannot select an authorised value category and a marcfield");
-                    return false;
-                }
-                return true;
-            });
-        });
-    </script>
-[% END %]
-
-[% INCLUDE 'intranet-bottom.inc' %]
index ffdcc14..80cf0d6 100644 (file)
                   <label for="to">Expires before:</label>
                   <input type="text" id="to" name="expiration_date_filter" value="[% expiration_date_filter | $KohaDates %]" size="10" maxlength="10" class="datepickerto" />
                 </li>
-                [% FOR field IN additional_fields_for_subscription %]
-                  <li>
-                    <label for="additional_field_[% field.id | html %]"> [% field.name | html %]: </label>
-                    [% IF field.authorised_value_choices %]
-                      <select id="additional_field_[% field.id | html %]" name="additional_field_[% field.id | html %]_filter">
-                        <option value="">All</option>
-                        [% FOREACH av IN field.authorised_value_choices %]
-                          <option value="[% av.authorised_value | html %]">[% av.lib | html %]</option>
-                        [% END %]
-                      </select>
-                    [% ELSE %]
-                      <input id="additional_field_[% field.id | html %]" type="text" value="[% additional_fields.${field.name} | html %]" name="additional_field_[% field.id | html %]_filter" />
-                    [% END %]
-                  </li>
-                [% END %]
+                [% INCLUDE 'additional-fields-entry.inc' available=additional_fields_for_subscription values=additional_field_filters wrap_fieldset=0 %]
               </ol>
               <input type="hidden" name="searched" value="1" />
               [% IF ( mana ) %]<input type="hidden" name="mana" value="1" />[% END %]
index 714bd75..e2f6949 100644 (file)
@@ -451,36 +451,9 @@ fieldset.rows li.radio { width: 100%; } /* override staff-global.css */
                             </fieldset>
 
                             [% IF additional_fields_for_subscription %]
-                              <div id="subscription_additional_fields">
-                                <fieldset class="rows">
-                                  <legend>Additional fields</legend>
-                                  <ol>
-                                    [% FOR field IN additional_fields_for_subscription %]
-                                      <li>
-                                        <label for="additional_field_[% field.id | html %]"> [% field.name | html %]: </label>
-                                        [% IF field.authorised_value_choices %]
-                                          <select name="additional_field_[% field.id | html %]" id="additional_field_[% field.id | html %]">
-                                            [% FOREACH av IN field.authorised_value_choices %]
-                                              [% IF av.authorised_value == additional_fields.${field.name} %]
-                                                <option value="[% av.authorised_value | html %]" selected="selected">[% av.lib | html %]</option>
-                                              [% ELSE %]
-                                                <option value="[% av.authorised_value | html %]">[% av.lib | html %]</option>
-                                              [% END %]
-                                            [% END %]
-                                          </select> (Authorised values for [% field.authorised_value_category | html %])
-                                        [% ELSE %]
-                                          [% IF field.marcfield %]
-                                            <input type="text" value="[% additional_fields.${field.name} | html %]" id="additional_field_[% field.id | html %]" name="additional_field_[% field.id | html %]" readonly="readonly" />
-                                            This value will be filled with the [% field.marcfield | html %] subfield of the selected biblio.
-                                          [% ELSE %]
-                                            <input type="text" value="[% additional_fields.${field.name} | html %]" id="additional_field_[% field.id | html %]" name="additional_field_[% field.id | html %]" />
-                                          [% END %]
-                                        [% END %]
-                                      </li>
-                                    [% END %]
-                                  </ol>
-                                </fieldset>
-                              </div>
+                                <div id="subscription_additional_fields">
+                                    [% INCLUDE 'additional-fields-entry.inc' available=additional_fields_for_subscription values=additional_fields %]
+                                </div>
                             [% END %]
 
                             <input type="hidden" id="mana_id"  name="mana_id" value=""/>
index 5d23f21..976b128 100755 (executable)
@@ -80,19 +80,10 @@ if ( $op and $op eq "close" ) {
 
 
 my $additional_fields = Koha::AdditionalField->all( { tablename => 'subscription', searchable => 1 } );
-my $additional_field_filters;
-for my $field ( @$additional_fields ) {
-    my $filter_value = $query->param('additional_field_' . $field->{id} . '_filter');
-    if ( defined $filter_value and $filter_value ne q|| ) {
-        $additional_field_filters->{ $field->{name} } = {
-            value => $filter_value,
-            authorised_value_category => $field->{authorised_value_category},
-        };
-    }
-    if ( $field->{authorised_value_category} ) {
-        $field->{authorised_value_choices} = GetAuthorisedValues( $field->{authorised_value_category} );
-    }
-}
+my $additional_field_filters = Koha::AdditionalField->get_filters_from_query( {
+    tablename => 'subscription',
+    query => $query,
+} );
 
 my $expiration_date_dt = $expiration_date ? dt_from_string( $expiration_date ) : undef;
 my @subscriptions;
@@ -119,7 +110,7 @@ if ($searched){
             publisher    => $publisher,
             bookseller   => $bookseller,
             branch       => $branch,
-            additional_fields => [ map{ { name => $_, value => $additional_field_filters->{$_}{value}, authorised_value_category => $additional_field_filters->{$_}{authorised_value_category} } } keys %$additional_field_filters ],
+            additional_fields => $additional_field_filters,
             location     => $location,
             expiration_date => $expiration_date_dt,
         });
@@ -197,7 +188,7 @@ else
         branches_loop => \@branches_loop,
         done_searched => $searched,
         routing       => $routing,
-        additional_field_filters => $additional_field_filters,
+        additional_field_filters => Koha::AdditionalField->get_filters_as_values( $additional_field_filters ),
         additional_fields_for_subscription => $additional_fields,
         marcflavour   => (uc(C4::Context->preference("marcflavour"))),
         mana => $mana
index 31198c6..7cc131d 100755 (executable)
@@ -144,14 +144,7 @@ $template->param(
     locations_loop=>$locations_loop,
 );
 
-
-my $additional_fields = Koha::AdditionalField->all( { tablename => 'subscription' } );
-for my $field ( @$additional_fields ) {
-    if ( $field->{authorised_value_category} ) {
-        $field->{authorised_value_choices} = GetAuthorisedValues( $field->{authorised_value_category} );
-    }
-}
-$template->param( additional_fields_for_subscription => $additional_fields );
+$template->param( additional_fields_for_subscription => scalar Koha::AdditionalField->all( { tablename => 'subscription' } ) );
 
 my $typeloop = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } };
 
@@ -376,8 +369,13 @@ sub redirect_add_subscription {
         my $result = Koha::SharedContent::send_entity( $query->param('mana_language') || '', $loggedinuser, $subscriptionid, 'subscription');
         $template->param( mana_msg => $result->{msg} );
     }
-    my $additional_fields = Koha::AdditionalField->all( { tablename => 'subscription' } );
-    insert_additional_fields( $additional_fields, $biblionumber, $subscriptionid );
+
+    Koha::AdditionalField->update_fields_from_query( {
+        tablename => 'subscription',
+        record_id => $subscriptionid,
+        query => $query,
+        marc_record => GetMarcBiblio({ biblionumber => $biblionumber, embed_items => 1 })
+    } );
 
     print $query->redirect("/cgi-bin/koha/serials/subscription-detail.pl?subscriptionid=$subscriptionid");
     return;
@@ -480,34 +478,13 @@ sub redirect_mod_subscription {
         $skip_serialseq, $itemtype, $previousitemtype, $mana_id
     );
 
-    my $additional_fields = Koha::AdditionalField->all( { tablename => 'subscription' } );
-    insert_additional_fields( $additional_fields, $biblionumber, $subscriptionid );
+    Koha::AdditionalField->update_fields_from_query( {
+        tablename => 'subscription',
+        record_id => $subscriptionid,
+        query => $query,
+        marc_record => GetMarcBiblio({ biblionumber => $biblionumber, embed_items => 1 })
+    } );
 
     print $query->redirect("/cgi-bin/koha/serials/subscription-detail.pl?subscriptionid=$subscriptionid");
     return;
 }
-
-sub insert_additional_fields {
-    my ( $additional_fields, $biblionumber, $subscriptionid ) = @_;
-    my $record = GetMarcBiblio({
-        biblionumber => $biblionumber,
-        embed_items  => 1 });
-    for my $field ( @$additional_fields ) {
-        my $af = Koha::AdditionalField->new({ id => $field->{id} })->fetch;
-        if ( $af->{marcfield} ) {
-            my ( $field, $subfield ) = split /\$/, $af->{marcfield};
-            $af->{values} = undef;
-            if ( $field and $subfield ) {
-                my $value = $record->subfield( $field, $subfield );
-                $af->{values} = {
-                    $subscriptionid => $value
-                };
-            }
-        } else {
-            $af->{values} = {
-                $subscriptionid => scalar $query->param('additional_field_' . $field->{id})
-            } if defined $query->param('additional_field_' . $field->{id});
-        }
-        $af->insert_values;
-    }
-}