@@ -, +, @@
- a new DB field items.new.
- a new page to configure this new status
(tools/toggle_new_status.pl).
- a new cronjob script (misc/cronjob/toggle_new_status.pl).
- to know easily what are the new items (with a simple sql query).
- to display an icon in the search results.
- issuing rules can be adapt for new items. Automatically (using the
cronjob script), the status change (depending the configuration) and
the item can be issued, for example.
- a RSS/Atom feeds can be created on these new items.
- log in with a librarian having the tools > items_batchmod permission.
- navigate to Home > Tools > Toggle new status
- click on the edit button
- there are 3 "blocks":
* duration: the duration during an item is considered as new.
* conditions: the status will change only if the conditions are meet.
* substitutions: if there is no substitution, no action will be done.
You can add some change to apply to the matching items.
E.g. ccode=3
new=''
If the value is an empty string (in other words, the input does not
contain anything), the field will be deleted.
You can create as many rules as you want.
- test the interface : add/remove rule, conditions, substitutions,
submit the form, edit, etc.
(There is a looot of JS everywhere, so certainly a looot of bugs...).
- when you have your rules defined, you can now launch the cronjob
script without any parameter.
A report will be displayed with the matching itemnumber and the
substitutions to apply. Verify results are consistent.
- launch the script with the -c argument and verify values have been
modified depending the substitution rules.
---
C4/Items.pm | 91 ++++++-
.../intranet-tmpl/prog/en/css/staff-global.css | 29 ++
.../en/modules/help/tools/toggle_new_status.tt | 45 +++
.../prog/en/modules/tools/toggle_new_status.tt | 294 ++++++++++++++++++++
.../prog/en/modules/tools/tools-home.tt | 5 +
misc/cronjobs/toggle_new_status.pl | 106 +++++++
tools/toggle_new_status.pl | 116 ++++++++
7 files changed, 685 insertions(+), 1 deletions(-)
create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/toggle_new_status.tt
create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/toggle_new_status.tt
create mode 100755 misc/cronjobs/toggle_new_status.pl
create mode 100755 tools/toggle_new_status.pl
--- a/C4/Items.pm
+++ a/C4/Items.pm
@@ -470,6 +470,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,
@@ -2164,7 +2165,8 @@ sub _koha_new_item {
enumchron = ?,
more_subfields_xml = ?,
copynumber = ?,
- stocknumber = ?
+ stocknumber = ?,
+ new = ?
";
my $sth = $dbh->prepare($query);
my $today = C4::Dates->today('iso');
@@ -2207,6 +2209,7 @@ sub _koha_new_item {
$item->{'more_subfields_xml'},
$item->{'copynumber'},
$item->{'stocknumber'},
+ $item->{'new'},
);
my $itemnumber;
@@ -3056,4 +3059,90 @@ 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 {
+ # Pure ANSI SQL goodness.
+ my $sql = 'SELECT * FROM items WHERE 1=0;';
+
+ # Get the database handle.
+ my $dbh = C4::Context->dbh;
+
+ # Run the SQL statement to load STH's readonly properties.
+ my $sth = $dbh->prepare($sql);
+ my $rv = $sth->execute();
+
+ # This only fails if the table doesn't exist.
+ # This will always be called AFTER an install or upgrade,
+ # so borrowers will exist!
+ my @data;
+ if ($sth->{NUM_OF_FIELDS}>0) {
+ @data = @{$sth->{NAME}};
+ }
+ else {
+ @data = ();
+ }
+ return @data;
+}
+
+sub ToggleNewStatus {
+ my ( $params ) = @_;
+ my @rules = @{ $params->{rules} };
+ my $report_only = $params->{report_only};
+
+ my $dbh = C4::Context->dbh;
+ my @errors;
+ my @items_columns = C4::Items::columns;
+ my $report;
+ for my $rule ( @rules ) {
+ my $duration = $rule->{duration};
+ my $conditions = $rule->{conditions};
+ my $substitutions = $rule->{substitutions};
+ my @params;
+
+ my $query = q|SELECT biblionumber, itemnumber FROM items WHERE 1 |;
+ for my $condition ( @$conditions ) {
+ if ( grep {/^$condition->{field}$/} @items_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 $duration ) {
+ $query .= q| AND TO_DAYS(NOW()) - TO_DAYS(dateaccessioned) >= ? |;
+ push @params, $duration;
+ }
+ 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;
--- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css
+++ a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css
@@ -2758,3 +2758,32 @@ span.onsite_checkout {
border-radius: 4px;
border : 1px solid #FFF2CE;
}
+
+/* Tools > toggle_new_status */
+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;
+}
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/toggle_new_status.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/toggle_new_status.tt
@@ -0,0 +1,45 @@
+[% INCLUDE 'help-top.inc' %]
+
Toggle new status configuration
+
+
This configuration page allows to configure the rules for the toggle new status 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/toggle_new_status.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' %]
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/toggle_new_status.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/toggle_new_status.tt
@@ -0,0 +1,294 @@
+[% INCLUDE 'doc-head-open.inc' %]
+Koha › Tools › Toggle new status
+[% INCLUDE 'doc-head-close.inc' %]
+
+
+
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'cat-search.inc' %]
+
+ [% IF rule.duration.defined and rule.duration.length > 0 %]
+ [% rule.duration %] days
+ [% ELSE %]
+ There is no duration 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 %]
+
Export bibliographic, holdings, and authority records
--- a/misc/cronjobs/toggle_new_status.pl
+++ a/misc/cronjobs/toggle_new_status.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('toggle_new_status_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
+
+toggle_new_status.pl
+
+=head1 SYNOPSIS
+
+./toggle_new_status.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
--- a/tools/toggle_new_status.pl
+++ a/tools/toggle_new_status.pl
@@ -0,0 +1,116 @@
+#!/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
+
+toggle_new_status.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/toggle_new_status.tt",
+ query => $cgi,
+ type => "intranet",
+ authnotrequired => 0,
+ flagsrequired => { tools => 'items_batchmod' },
+ }
+);
+
+my $op = $cgi->param('op') // 'show';
+
+my $syspref_name = q|toggle_new_status_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->{duration} = $cgi->param("duration_$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;
+}
+
+$template->param(
+ op => $op,
+ messages => \@messages,
+ item_fields => [ C4::Items::columns ],
+ rules => $rules,
+);
+
+output_html_with_http_headers $cgi, $cookie, $template->output;
--