diff --git a/C4/Items.pm b/C4/Items.pm
index 26e9342a6b..51479ecfeb 100644
--- a/C4/Items.pm
+++ b/C4/Items.pm
@@ -35,6 +35,7 @@ use DateTime::Format::MySQL;
use Data::Dumper; # used as part of logging item record changes, not just for
# debugging; so please don't remove this
use Koha::DateUtils qw/dt_from_string/;
+use Koha::Database;
use Koha::Database;
@@ -473,6 +474,7 @@ sub _build_default_values_for_mod_marc {
location => undef,
permanent_location => undef,
materials => undef,
+ new => undef,
notforloan => 0,
# paidfor => undef, # commented, see bug 12817
price => undef,
@@ -2198,7 +2200,8 @@ sub _koha_new_item {
enumchron = ?,
more_subfields_xml = ?,
copynumber = ?,
- stocknumber = ?
+ stocknumber = ?,
+ new = ?
";
my $sth = $dbh->prepare($query);
my $today = output_pref({ dt => dt_from_string, dateformat => 'iso', dateonly => 1 });
@@ -2242,6 +2245,7 @@ sub _koha_new_item {
$item->{'more_subfields_xml'},
$item->{'copynumber'},
$item->{'stocknumber'},
+ $item->{'new'},
);
my $itemnumber;
@@ -3135,4 +3139,94 @@ sub PrepareItemrecordDisplay {
};
}
+=head2 columns
+
+ my @columns = C4::Items::columns();
+
+Returns an array of items' table columns on success,
+and an empty array on failure.
+
+=cut
+
+sub columns {
+ my $rs = Koha::Database->new->schema->resultset('Item');
+ return $rs->result_source->columns;
+}
+
+=head2 biblioitems_columns
+
+ my @columns = C4::Items::biblioitems_columns();
+
+Returns an array of biblioitems' table columns on success,
+and an empty array on failure.
+
+=cut
+
+sub biblioitems_columns {
+ my $rs = Koha::Database->new->schema->resultset('Biblioitem');
+ return $rs->result_source->columns;
+}
+
+sub ToggleNewStatus {
+ my ( $params ) = @_;
+ my @rules = @{ $params->{rules} };
+ my $report_only = $params->{report_only};
+
+ my $dbh = C4::Context->dbh;
+ my @errors;
+ my @item_columns = map { "items.$_" } C4::Items::columns;
+ my @biblioitem_columns = map { "biblioitems.$_" } C4::Items::biblioitems_columns;
+ my $report;
+ for my $rule ( @rules ) {
+ my $age = $rule->{age};
+ my $conditions = $rule->{conditions};
+ my $substitutions = $rule->{substitutions};
+ my @params;
+
+ my $query = q|
+ SELECT items.biblionumber, items.itemnumber
+ FROM items
+ LEFT JOIN biblioitems ON biblioitems.biblionumber = items.biblionumber
+ WHERE 1
+ |;
+ for my $condition ( @$conditions ) {
+ if (
+ grep {/^$condition->{field}$/} @item_columns
+ or grep {/^$condition->{field}$/} @biblioitem_columns
+ ) {
+ if ( $condition->{value} =~ /\|/ ) {
+ my @values = split /\|/, $condition->{value};
+ $query .= qq| AND $condition->{field} IN (|
+ . join( ',', ('?') x scalar @values )
+ . q|)|;
+ push @params, @values;
+ } else {
+ $query .= qq| AND $condition->{field} = ?|;
+ push @params, $condition->{value};
+ }
+ }
+ }
+ if ( defined $age ) {
+ $query .= q| AND TO_DAYS(NOW()) - TO_DAYS(dateaccessioned) >= ? |;
+ push @params, $age;
+ }
+ my $sth = $dbh->prepare($query);
+ $sth->execute( @params );
+ while ( my $values = $sth->fetchrow_hashref ) {
+ my $biblionumber = $values->{biblionumber};
+ my $itemnumber = $values->{itemnumber};
+ my $item = C4::Items::GetItem( $itemnumber );
+ for my $substitution ( @$substitutions ) {
+ next unless $substitution->{field};
+ C4::Items::ModItem( {$substitution->{field} => $substitution->{value}}, $biblionumber, $itemnumber )
+ unless $report_only;
+ push @{ $report->{$itemnumber} }, $substitution;
+ }
+ }
+ }
+
+ return $report;
+}
+
+
1;
diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css
index b8a857d47c..23283048d2 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css
+++ b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css
@@ -2815,6 +2815,7 @@ span.onsite_checkout {
border-radius: 4px;
border : 1px solid #FFF2CE;
}
+
div.lastchecked {
padding : .2em 1em;
border: 2px solid #BCDB89;
@@ -2845,3 +2846,32 @@ div#cn_browser_table_wrapper > table#cn_browser_table {
margin: auto;
width:90%;
}
+
+/* Tools > automatic_item_modification_by_age */
+div.rules {
+ display: block;
+}
+div#new_rule, div.rule {
+ background-color: #F4F8F9;
+ border: 2px solid #B9D8D9;
+ border-radius: 5px;
+ margin: .3em;
+ padding: .3em;
+}
+
+div.duration, div.blocks {
+ border: 2px solid #B9D8D9;
+ border-radius: 5px 5px 5px 5px;
+ margin: .3em;
+ padding: 0 .3em .3em .3em;
+}
+
+div.duration h5, div.blocks h5 {
+ padding-bottom: 4px;
+ padding-left: 0.2em;
+ background-color: #E6F0F2;
+ border-radius: 1px;
+}
+div.duration span, div.blocks div {
+ display:block;
+}
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/automatic_item_modification_by_age.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/automatic_item_modification_by_age.tt
new file mode 100644
index 0000000000..8fdda1ba4e
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/automatic_item_modification_by_age.tt
@@ -0,0 +1,45 @@
+[% INCLUDE 'help-top.inc' %]
+
Automatic item modifications by age configuration
+
+This configuration page allows to configure the rules for the automatic item modifications by age cronjob script.
+
+Libraries can manage the 'new' status for items. With this script, it will be possible to:
+
+ - know easily what are the new items in the catalogue.
+ - display an icon in the search results for new items.
+ - configure issuing rules depending the 'new' status.
+ - get a RSS/Atom feeds on these new items.
+
+
+How to work the configuration page?
+There are 3 values to define:
+The duration
+This value corresponds to the duration an item is considered as new.
+The conditions
+Conditions should be defined if you want to test some values before to substitute fields in the items.
+They are cumulatives but you can separate with a pipe '|' for a field with several values.
+The substitutions
+Substitutions are changes to apply to the matching items.
+At least one substitution must be defined, else there is no sense to launch the script.
+If the value is an empty string, the field will be deleted.
+Examples
+You want to remove the items.new value for items created 10 days ago:
+
+ - Duration: 10 days
+ - No condition
+ - Substitution: items.new = '' (no value in the input)
+
+
+You want to change the items.ccode=1 to items.ccode=2 for items created 7 days ago.
+
+ - Duration: 7 days
+ - Condition: items.ccode = 1
+ - Substitution: items.ccode = 2
+
+
+How to execute the cronjob script?
+The cronjob script is misc/cronjobs/automatic_item_modification_by_age.pl.
+Try the -h parameter in order to see the help.
+Without any parameter, the script will be launched in a dry-run mode. If the -c (or --confirm) flag is given, the script will apply the changes.
+
+[% INCLUDE 'help-bottom.inc' %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/automatic_item_modification_by_age.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/automatic_item_modification_by_age.tt
new file mode 100644
index 0000000000..a08e96d022
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/automatic_item_modification_by_age.tt
@@ -0,0 +1,294 @@
+[% INCLUDE 'doc-head-open.inc' %]
+Koha › Tools › Automatic item modifications by age
+[% INCLUDE 'doc-head-close.inc' %]
+
+
+
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'cat-search.inc' %]
+
+
+
+
+
+
+
Automatic item modifications by age
+
+ [% FOR message IN messages %]
+ [% IF message.type == "error" %]
+
+ [% END %]
+ [% IF message.code == "unable_to_load_configuration" %]
+ An error occurs: Unable to load the configuration.
+ [% END %]
+
+ [% END %]
+
+ [% IF op == 'edit_form' %]
+
+
Add a new rule
+
+
+
+
Age
+ days
+
+
+
Conditions
+
+
+ =
+
+
+
+
+
+
+
Substitutions
+
+
+ =
+
+
+
+
+
+
Add this rule
+
Remove this rule
+
+ [% ELSIF rules and op == 'show' %]
+
+
List of rules
+ [% FOR rule IN rules %]
+
+
+
Age
+ [% IF rule.age.defined and rule.age.length > 0 %]
+ [% rule.age %] days
+ [% ELSE %]
+ There is no age for this rule.
+ [% END %]
+
+
+
Conditions
+ [% FOR condition IN rule.conditions %]
+ [% IF condition.field %]
+
+ [% condition.field %] = [% condition.value %]
+
+ [% ELSE %]
+ There is no condition for this rule.
+ [% END %]
+ [% END %]
+
+
+
Substitutions
+ [% FOR substitution IN rule.substitutions %]
+
+ [% substitution.field %] = [% substitution.value %]
+
+ [% END %]
+
+
+ [% END %]
+
+ [% ELSE %]
+ There is no rule defined. Please click on the edit button.
+ [% END %]
+
+
+
+
+ [% INCLUDE 'tools-menu.inc' %]
+
+
+[% INCLUDE 'intranet-bottom.inc' %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt
index 629ce84726..bb54f54642 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt
@@ -129,6 +129,11 @@
Modify a batch of records (biblios or authorities)
[% END %]
+ [% IF ( CAN_user_tools_items_batchmod ) %]
+
Automatic item modifications by age
+
Define rules to modify items by age
+ [% END %]
+
[% IF ( CAN_user_tools_export_catalog ) %]
Export data
Export bibliographic, holdings, and authority records
diff --git a/misc/cronjobs/automatic_item_modification_by_age.pl b/misc/cronjobs/automatic_item_modification_by_age.pl
new file mode 100755
index 0000000000..51effd32b1
--- /dev/null
+++ b/misc/cronjobs/automatic_item_modification_by_age.pl
@@ -0,0 +1,106 @@
+#!/usr/bin/perl
+
+use Modern::Perl;
+
+use Getopt::Long;
+use Pod::Usage;
+use JSON;
+
+use C4::Context;
+use C4::Items;
+
+# Getting options
+my ( $verbose, $help, $confirm );
+my $result = GetOptions(
+ 'h|help' => \$help,
+ 'v|verbose' => \$verbose,
+ 'c|confirm' => \$confirm,
+);
+
+pod2usage(1) if $help;
+$verbose = 1 unless $confirm;
+
+# Load configuration from the syspref
+my $syspref_content = C4::Context->preference('automatic_item_modification_by_age_configuration');
+my $rules = eval { JSON::from_json( $syspref_content ) };
+pod2usage({ -message => "Unable to load the configuration : $@", -exitval => 1 })
+ if $@;
+
+my $report = C4::Items::ToggleNewStatus( { rules => $rules, report_only => not $confirm } );
+
+if ( $verbose ) {
+ if ( $report ) {
+ say "Item to modify:";
+ while ( my ( $itemnumber, $substitutions ) = each %$report ) {
+ for my $substitution ( @$substitutions ) {
+ if ( defined $substitution->{value} and $substitution->{value} ne q|| ) {
+ say "\titemnumber $itemnumber: $substitution->{field}=$substitution->{value}";
+ } else {
+ say "\titemnumber $itemnumber: field $substitution->{field} to delete";
+ }
+ }
+ }
+ } else {
+ say "There is no item to modify";
+ }
+}
+
+exit(0);
+
+__END__
+
+=head1 NAME
+
+automatic_item_modification_by_age.pl
+
+=head1 SYNOPSIS
+
+./automatic_item_modification_by_age.pl -h
+
+Toggle recent acquisitions status.
+Use this script to delete "new" status for items.
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-h|--help>
+
+Prints this help message.
+
+=item B<-v|--verbose>
+
+Set the verbose flag.
+
+=item B<-c|--confirm>
+
+The script will modify the items.
+
+=back
+
+=head1 AUTHOR
+
+Jonathan Druart
+
+=head1 COPYRIGHT
+
+Copyright 2013 BibLibre
+
+=head1 LICENSE
+
+This file is part of Koha.
+
+Koha is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+Koha is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Koha; if not, see .
+
+=cut
diff --git a/t/db_dependent/Items/AutomaticItemModificationByAge.t b/t/db_dependent/Items/AutomaticItemModificationByAge.t
new file mode 100644
index 0000000000..3f2943c942
--- /dev/null
+++ b/t/db_dependent/Items/AutomaticItemModificationByAge.t
@@ -0,0 +1,283 @@
+#!/usr/bin/perl
+
+use Modern::Perl;
+use Test::More tests => 16;
+use MARC::Record;
+use MARC::Field;
+use DateTime;
+use DateTime::Duration;
+
+use C4::Biblio;
+use C4::Context;
+use C4::Items;
+use Koha::DateUtils;
+
+my $dbh = C4::Context->dbh;
+$dbh->{AutoCommit} = 0;
+$dbh->{RaiseError} = 1;
+
+$dbh->do(q|
+ DELETE FROM marc_subfield_structure
+ WHERE kohafield = 'items.new' OR kohafield = 'items.stocknumber'
+|);
+
+my $new_tagfield = 'i';
+$dbh->do(qq|
+ INSERT INTO marc_subfield_structure(tagfield, tagsubfield, kohafield, frameworkcode)
+ VALUES ( 952, '$new_tagfield', 'items.new', '' )
+|);
+
+my $record = MARC::Record->new();
+$record->append_fields(
+ MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
+ MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
+ MARC::Field->new('942', ' ', ' ', c => 'ITEMTYPE_T'),
+);
+my ($biblionumber, undef) = C4::Biblio::AddBiblio($record, '');
+
+my ($item_bibnum, $item_bibitemnum, $itemnumber) = C4::Items::AddItem(
+ {
+ homebranch => 'CPL',
+ holdingbranch => 'CPL',
+ new => 'new_value',
+ ccode => 'FIC',
+ },
+ $biblionumber
+);
+
+my $item = C4::Items::GetItem( $itemnumber );
+is ( $item->{new}, 'new_value', q|AddItem insert the 'new' field| );
+
+my ( $tagfield, undef ) = GetMarcFromKohaField('items.itemnumber', '');
+my $marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
+is( $marc_item->subfield($tagfield, $new_tagfield), 'new_value', q|Koha mapping is correct|);
+
+# Update the items.new field if items.ccode eq 'FIC' => should be updated
+my @rules = (
+ {
+ conditions => [
+ {
+ field => 'items.ccode',
+ value => 'FIC',
+ },
+ ],
+ substitutions => [
+ {
+ field => 'items.new',
+ value => 'updated_value',
+ },
+ ],
+ age => '0',
+ },
+);
+
+C4::Items::ToggleNewStatus( { rules => \@rules } );
+
+my $modified_item = C4::Items::GetItem( $itemnumber );
+is( $modified_item->{new}, 'updated_value', q|ToggleNewStatus: The new value is updated|);
+$marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
+is( $marc_item->subfield($tagfield, $new_tagfield), 'updated_value', q|ToggleNewStatus: The new value is updated| );
+
+# Update the items.new field if items.ccode eq 'DONT_EXIST' => should not be updated
+@rules = (
+ {
+ conditions => [
+ {
+ field => 'items.ccode',
+ value => 'DONT_EXIST',
+ },
+ ],
+ substitutions => [
+ {
+ field => 'items.new',
+ value => 'new_updated_value',
+ },
+ ],
+ age => '0',
+ },
+);
+
+C4::Items::ToggleNewStatus( { rules => \@rules } );
+
+$modified_item = C4::Items::GetItem( $itemnumber );
+is( $modified_item->{new}, 'updated_value', q|ToggleNewStatus: The new value is not updated|);
+$marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
+is( $marc_item->subfield($tagfield, $new_tagfield), 'updated_value', q|ToggleNewStatus: The new value is not updated| );
+
+# Play with age
+$item = C4::Items::GetItem( $itemnumber );
+my $dt_today = dt_from_string;
+my $days5ago = $dt_today->add_duration( DateTime::Duration->new( days => -5 ) );
+
+C4::Items::ModItem( { dateaccessioned => $days5ago }, $biblionumber, $itemnumber );
+$item = C4::Items::GetItem( $itemnumber );
+
+@rules = (
+ {
+ conditions => [
+ {
+ field => 'items.ccode',
+ value => 'FIC',
+ },
+ ],
+ substitutions => [
+ {
+ field => 'items.new',
+ value => 'new_updated_value',
+ },
+ ],
+ age => '10',
+ },
+);
+C4::Items::ToggleNewStatus( { rules => \@rules } );
+$modified_item = C4::Items::GetItem( $itemnumber );
+is( $modified_item->{new}, 'updated_value', q|ToggleNewStatus: Age = 10 : The new value is not updated|);
+
+$rules[0]->{age} = 5;
+$rules[0]->{substitutions}[0]{value} = 'new_updated_value5';
+C4::Items::ToggleNewStatus( { rules => \@rules } );
+$modified_item = C4::Items::GetItem( $itemnumber );
+is( $modified_item->{new}, 'new_updated_value5', q|ToggleNewStatus: Age = 5 : The new value is updated|);
+
+$rules[0]->{age} = '';
+$rules[0]->{substitutions}[0]{value} = 'new_updated_value_empty_string';
+C4::Items::ToggleNewStatus( { rules => \@rules } );
+$modified_item = C4::Items::GetItem( $itemnumber );
+is( $modified_item->{new}, 'new_updated_value_empty_string', q|ToggleNewStatus: Age = '' : The new value is updated|);
+
+$rules[0]->{age} = undef;
+$rules[0]->{substitutions}[0]{value} = 'new_updated_value_undef';
+C4::Items::ToggleNewStatus( { rules => \@rules } );
+$modified_item = C4::Items::GetItem( $itemnumber );
+is( $modified_item->{new}, 'new_updated_value_undef', q|ToggleNewStatus: Age = undef : The new value is updated|);
+
+# Field deletion
+@rules = (
+ {
+ conditions => [
+ {
+ field => 'items.ccode',
+ value => 'FIC',
+ },
+ ],
+ substitutions => [
+ {
+ field => 'items.new',
+ value => '',
+ },
+ ],
+ age => '0',
+ },
+);
+
+C4::Items::ToggleNewStatus( { rules => \@rules } );
+
+$modified_item = C4::Items::GetItem( $itemnumber );
+is( $modified_item->{new}, '', q|ToggleNewStatus: The new value is empty|);
+$marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
+is( $marc_item->subfield($tagfield, $new_tagfield), undef, q|ToggleNewStatus: The new field is removed from the item marc| );
+
+# conditions multiple
+@rules = (
+ {
+ conditions => [
+ {
+ field => 'items.ccode',
+ value => 'FIC',
+ },
+ {
+ field => 'items.homebranch',
+ value => 'CPL',
+ },
+ ],
+ substitutions => [
+ {
+ field => 'items.new',
+ value => 'new_value',
+ },
+ ],
+ age => '0',
+ },
+);
+
+C4::Items::ToggleNewStatus( { rules => \@rules } );
+
+$modified_item = C4::Items::GetItem( $itemnumber );
+is( $modified_item->{new}, 'new_value', q|ToggleNewStatus: conditions multiple: all match, the new value is updated|);
+
+@rules = (
+ {
+ conditions => [
+ {
+ field => 'items.ccode',
+ value => 'FIC',
+ },
+ {
+ field => 'items.homebranch',
+ value => 'DONT_EXIST',
+ },
+ ],
+ substitutions => [
+ {
+ field => 'items.new',
+ value => 'new_updated_value',
+ },
+ ],
+ age => '0',
+ },
+);
+
+C4::Items::ToggleNewStatus( { rules => \@rules } );
+
+$modified_item = C4::Items::GetItem( $itemnumber );
+is( $modified_item->{new}, 'new_value', q|ToggleNewStatus: conditions multiple: at least 1 condition does not match, the new value is not updated|);
+
+@rules = (
+ {
+ conditions => [
+ {
+ field => 'items.ccode',
+ value => 'FIC|NFIC',
+ },
+ {
+ field => 'items.homebranch',
+ value => 'MPL|CPL',
+ },
+ ],
+ substitutions => [
+ {
+ field => 'items.new',
+ value => 'new_updated_value',
+ },
+ ],
+ age => '0',
+ },
+);
+
+C4::Items::ToggleNewStatus( { rules => \@rules } );
+
+$modified_item = C4::Items::GetItem( $itemnumber );
+is( $modified_item->{new}, 'new_updated_value', q|ToggleNewStatus: conditions multiple: the 2 conditions match, the new value is updated|);
+
+@rules = (
+ {
+ conditions => [
+ {
+ field => 'biblioitems.itemtype',
+ value => 'ITEMTYPE_T',
+ },
+ ],
+ substitutions => [
+ {
+ field => 'items.new',
+ value => 'another_new_updated_value',
+ },
+ ],
+ age => '0',
+ },
+);
+
+C4::Items::ToggleNewStatus( { rules => \@rules } );
+
+$modified_item = C4::Items::GetItem( $itemnumber );
+is( $modified_item->{new}, 'another_new_updated_value', q|ToggleNewStatus: conditions on biblioitems|);
diff --git a/tools/automatic_item_modification_by_age.pl b/tools/automatic_item_modification_by_age.pl
new file mode 100755
index 0000000000..eca339cb39
--- /dev/null
+++ b/tools/automatic_item_modification_by_age.pl
@@ -0,0 +1,119 @@
+#!/usr/bin/perl
+
+# This file is part of Koha.
+#
+# Copyright 2013 BibLibre
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see .
+
+=head1 NAME
+
+automatic_item_modification_by_age.pl: Update new status for items.
+
+=cut
+
+=head1 DESCRIPTION
+
+This script allows a user to update the new status for items.
+
+=cut
+
+use Modern::Perl;
+
+use CGI;
+use JSON qw( to_json from_json );
+
+use C4::Auth;
+use C4::Context;
+use C4::Items;
+use C4::Output;
+use C4::Koha;
+
+my $cgi = new CGI;
+
+# open template
+my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
+ {
+ template_name => "tools/automatic_item_modification_by_age.tt",
+ query => $cgi,
+ type => "intranet",
+ authnotrequired => 0,
+ flagsrequired => { tools => 'items_batchmod' },
+ }
+);
+
+my $op = $cgi->param('op') // 'show';
+
+my $syspref_name = q|automatic_item_modification_by_age_configuration|;
+if ( $op eq 'update' ) {
+ my @rules;
+ my @unique_ids = $cgi->param('unique_id');
+ for my $unique_id ( @unique_ids ) {
+ my @substitution_fields = $cgi->param("substitution_field_$unique_id");
+ my @substitution_values = $cgi->param("substitution_value_$unique_id");
+ my @condition_fields = $cgi->param("condition_field_$unique_id");
+ my @condition_values = $cgi->param("condition_value_$unique_id");
+ my $rule = {
+ substitutions => [],
+ conditions => [],
+ };
+ for my $value ( @substitution_values ) {
+ my $field = shift @substitution_fields;
+ last unless $field;
+ push @{ $rule->{substitutions} }, { field => $field, value => $value };
+ }
+ push @{ $rule->{substitutions} }, {}
+ unless @{ $rule->{substitutions} };
+ for my $value ( @condition_values ) {
+ my $field = shift @condition_fields;
+ last unless $field;
+ push @{ $rule->{conditions} }, { field => $field, value => $value };
+ }
+ push @{ $rule->{conditions} }, {}
+ unless @{ $rule->{conditions} };
+ $rule->{age} = $cgi->param("age_$unique_id");
+ push @rules, $rule;
+ }
+ my $syspref_content = to_json( \@rules );
+ C4::Context->set_preference($syspref_name, $syspref_content);
+
+ $op = 'show';
+}
+
+my @messages;
+my $syspref_content = C4::Context->preference($syspref_name);
+my $rules;
+$rules = eval { JSON::from_json( $syspref_content ) }
+ if $syspref_content;
+if ( $@ ) {
+ push @messages, {
+ type => 'error',
+ code => 'unable_to_load_configuration'
+ };
+ $template->param( messages => \@messages );
+ output_html_with_http_headers $cgi, $cookie, $template->output;
+ exit;
+}
+
+my @item_fields = map { "items.$_" } C4::Items::columns;
+my @biblioitem_fields = map { "biblioitems.$_" } C4::Items::biblioitems_columns;
+$template->param(
+ op => $op,
+ messages => \@messages,
+ condition_fields => [ @item_fields, @biblioitem_fields ],
+ substitution_fields => \@item_fields,
+ rules => $rules,
+);
+
+output_html_with_http_headers $cgi, $cookie, $template->output;