From colin.campbell at ptfs-europe.com Fri Jun 1 09:15:37 2012 From: colin.campbell at ptfs-europe.com (Colin Campbell) Date: Fri, 1 Jun 2012 08:15:37 +0100 Subject: [Koha-patches] [PATCH] Bug 8176 Assign an intial value to $sqlwhere Message-ID: <1338534937-4852-1-git-send-email-colin.campbell@ptfs-europe.com> warnings in log because of undefined value in string concatenation variable should be initialized to empty string rather than left undefined --- C4/Serials.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/C4/Serials.pm b/C4/Serials.pm index 20ad706..af5c833 100644 --- a/C4/Serials.pm +++ b/C4/Serials.pm @@ -566,7 +566,7 @@ sub GetSubscriptions { LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber ); my @bind_params; - my $sqlwhere; + my $sqlwhere = q{}; if ($biblionumber) { $sqlwhere = " WHERE biblio.biblionumber=?"; push @bind_params, $biblionumber; -- 1.7.11.rc0 From dpavlin at rot13.org Fri Jun 1 15:27:22 2012 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Fri, 1 Jun 2012 15:27:22 +0200 Subject: [Koha-patches] [PATCH] Bug 8178 - circ/circulation.pl under plack duplicates checkout rows Message-ID: <1338557242-19145-1-git-send-email-dpavlin@rot13.org> Bug 7851 introduced our scoping for vairables, unfortunatly it has side-effect that checkout rows accumulate on page reloads instead of being initialized to empty array (which this patch fixes) Test scenario: 1. start intranet under plack 2. open /cgi-bin/koha/circ/circulation.pl and reload page few time confirming that rows gets duplicated 3. apply patch and reload page to verify that it works --- circ/circulation.pl | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/circ/circulation.pl b/circ/circulation.pl index c89abff..fdad5f2 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -417,10 +417,10 @@ if ($borrowernumber) { # make the issued books table. my $todaysissues = ''; my $previssues = ''; -our @todaysissues; -our @previousissues; -our @relissues; -our @relprevissues; +our @todaysissues = (); +our @previousissues = (); +our @relissues = (); +our @relprevissues = (); my $displayrelissues; our $totalprice = 0; -- 1.7.2.5 From dpavlin at rot13.org Fri Jun 1 15:40:26 2012 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Fri, 1 Jun 2012 15:40:26 +0200 Subject: [Koha-patches] [PATCH] Bug 7844 - plack intranet tooling for developers Message-ID: <1338558026-22809-1-git-send-email-dpavlin@rot13.org> koha.psgi example and plackup.sh script to run any Koha site intranet or opac interface under plack with optional multi-process Starman server plackup.sh site-name [intranet] site-name is used to find config /etc/koha/sites/site-name/koha-conf.xml All configuration is specified in koha.psgi, which you are welcomed to edit and tune according to your development needs. When you are happy with it, rename it to site name and save it for safe-keeping. Test scenario: 1. install plack and dependencies, as documented at http://wiki.koha-community.org/wiki/Plack 2. start ./plackup.sh sitename 3. open intranet page http://localhost:5001/cgi-bin/koha/mainpage.pl and verify that it works 4. start ./plackup.sh sitename i[ntranet] 5. open OPAC http://localhost:5000/cgi-bin/koha/opac-main.pl and verify that it works 6. next step is to take a look into koha.psgi and enable additional debug modules, save file and reload page (plackup will reload code automatically) --- misc/plack/README.plack | 32 +++++++++++++++++++ misc/plack/koha.psgi | 78 +++++++++++++++++++++++++++++++++++++++++++++++ misc/plack/plackup.sh | 53 ++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 0 deletions(-) create mode 100644 misc/plack/README.plack create mode 100644 misc/plack/koha.psgi create mode 100755 misc/plack/plackup.sh diff --git a/misc/plack/README.plack b/misc/plack/README.plack new file mode 100644 index 0000000..71593f4 --- /dev/null +++ b/misc/plack/README.plack @@ -0,0 +1,32 @@ +Bug 7844 - plack intranet tooling for developers + +koha.psgi example and plackup.sh script to run any Koha site +intranet or opac interface under plack with optional multi-process +Starman server + + plackup.sh site-name [intranet] + +site-name is used to find config /etc/koha/sites/site-name/koha-conf.xml + +All configuration is specified in koha.psgi, which you are welcomed to edit +and tune according to your development needs. + +When you are happy with it, rename it to site name and save it for safe-keeping. + +Test scenario: +1. install plack and dependencies, as documented at + http://wiki.koha-community.org/wiki/Plack + +2. start ./plackup.sh sitename + +3. open intranet page http://localhost:5001/cgi-bin/koha/mainpage.pl + and verify that it works + +4. start ./plackup.sh sitename i[ntranet] + +5. open OPAC http://localhost:5000/cgi-bin/koha/opac-main.pl + and verify that it works + +6. next step is to take a look into koha.psgi and enable additional + debug modules, save file and reload page (plackup will reload + code automatically) diff --git a/misc/plack/koha.psgi b/misc/plack/koha.psgi new file mode 100644 index 0000000..e388dae --- /dev/null +++ b/misc/plack/koha.psgi @@ -0,0 +1,78 @@ +#!/usr/bin/perl +use Plack::Builder; +use Plack::App::CGIBin; +use lib qw( ./lib ); +use Plack::Middleware::Debug; +use Plack::App::Directory; + +BEGIN { + +# override configuration from startup script below: +# (requires --reload option) + +$ENV{PLACK_DEBUG} = 1; # toggle debugging + +# memcache change requires restart +$ENV{MEMCACHED_SERVERS} = "localhost:11211"; +#$ENV{MEMCACHED_DEBUG} = 0; + +$ENV{PROFILE_PER_PAGE} = 1; # reset persistant and profile counters after each page, like CGI +#$ENV{INTRANET} = 1; # usually passed from script + +#$ENV{DBI_AUTOPROXY}='dbi:Gofer:transport=null;cache=DBI::Util::CacheMemory' + +} # BEGIN + +use C4::Context; +use C4::Languages; +use C4::Members; +use C4::Dates; +use C4::Boolean; +use C4::Letters; +use C4::Koha; +use C4::XSLT; +use C4::Branch; +use C4::Category; +=for preload +use C4::Tags; # FIXME +=cut + +use Devel::Size 0.77; # 0.71 doesn't work for Koha +my $watch_capture_regex = '(C4|Koha)'; + +sub watch_for_size { + my @watch = + map { s/^.*$watch_capture_regex/$1/; s/\//::/g; s/\.pm$//; $_ } # fix paths + grep { /$watch_capture_regex/ } + keys %INC + ; + warn "# watch_for_size ",join(' ', at watch); + return @watch; +}; + +my $CGI_ROOT = $ENV{INTRANET} ? $ENV{INTRANETDIR} : $ENV{OPACDIR}; +warn "# using Koha ", $ENV{INTRANET} ? 'intranet' : 'OPAC', " CGI from $CGI_ROOT\n"; +my $app=Plack::App::CGIBin->new(root => $CGI_ROOT); + +builder { + + enable_if { $ENV{PLACK_DEBUG} } 'Debug', panels => [ + qw(Koha Persistant), + qw(Environment Response Timer Memory), + # optional plugins (uncomment to enable) are sorted according to performance implact +# [ 'Devel::Size', for => \&watch_for_size ], # https://github.com/dpavlin/p5-plack-devel-debug-devel-size +# [ 'DBIProfile', profile => 2 ], +# [ 'DBITrace', level => 1 ], # a LOT of fine-graded SQL trace +# [ 'Profiler::NYTProf', exclude => [qw(.*\.css .*\.png .*\.ico .*\.js .*\.gif)] ], + ]; + + enable_if { $ENV{PLACK_DEBUG} } 'StackTrace'; + + enable_if { $ENV{INTRANETDIR} } "Plack::Middleware::Static", + path => qr{^/(intranet|opac)-tmpl/}, + root => "$ENV{INTRANETDIR}/koha-tmpl/"; + + mount "/cgi-bin/koha" => $app; + +}; + diff --git a/misc/plack/plackup.sh b/misc/plack/plackup.sh new file mode 100755 index 0000000..35fcf0f --- /dev/null +++ b/misc/plack/plackup.sh @@ -0,0 +1,53 @@ +#!/bin/sh -xe + +# This is plack startup script for Koha + +# ./plackup.sh [site] [intranet] + +site=$1 +test ! -z "$site" && shift || site=srvgit # default + +export KOHA_CONF=/etc/koha/sites/$site/koha-conf.xml +export LOGDIR="$( sudo -u $site-koha xmlstarlet sel -t -v 'yazgfs/config/logdir' $KOHA_CONF )" +export INTRANETDIR="$( sudo -u $site-koha xmlstarlet sel -t -v 'yazgfs/config/intranetdir' $KOHA_CONF )" +export OPACDIR="$( sudo -u $site-koha xmlstarlet sel -t -v 'yazgfs/config/opacdir' $KOHA_CONF | sed 's,/cgi-bin/opac,,' )" + +dir=`dirname $0` + +# enable memcache - it's safe even on installation which don't have it +# since Koha has check on C4::Context +#export MEMCACHED_SERVERS=localhost:11211 +# pass site name as namespace to perl code +export MEMCACHED_NAMESPACE=$site +#export MEMCACHED_DEBUG=1 + +if [ ! -e "$INTRANETDIR/C4" ] ; then + echo "intranetdir in $KOHA_CONF doesn't point to Koha git checkout" + exit 1 +fi + +if [ -z "$1" ] ; then # type anything after site name for intranet! + INTRANET=0 + PORT=5000 +else + INTRANET=1 + PORT=5001 + shift # pass rest of arguments to plackup +fi +export INTRANET # pass to plack + +# uncomment to enable logging +#opt="$opt --access-log $LOGDIR/opac-access.log --error-log $LOGDIR/opac-error.log" + +# --max-requests 50 decreased from 1000 to keep memory usage sane +# --workers 4 number of cores on machine +#test "$INTRANET" != 1 && \ # don't use Starman for intranet +opt="$opt --server Starman -M FindBin --max-requests 50 --workers 4" + +# -E deployment turn off access log on STDOUT +opt="$opt -E deployment" + +# comment out reload in production! +opt="$opt --reload -R $INTRANETDIR/C4 -R $INTRANETDIR/Koha" + +sudo -E -u $site-koha plackup --port $PORT -I $INTRANETDIR -I $INTRANETDIR/installer $opt $* $dir/koha.psgi -- 1.7.2.5 From christophe.croullebois at biblibre.com Fri Jun 1 16:10:50 2012 From: christophe.croullebois at biblibre.com (Christophe Croullebois) Date: Fri, 1 Jun 2012 16:10:50 +0200 Subject: [Koha-patches] [PATCH 1/1] Bug 7351 : Patch for minor visual changes Message-ID: <1338559850-10238-1-git-send-email-christophe.croullebois@biblibre.com> I have just put a space between the radio button and the text for the new lines.. And I have replaced tabulations by space. You must have applied before : "[SIGN OFF]Bug 7351 : feature that allows to delete a range of dates" "Patch for minor textual changes" --- .../prog/en/modules/tools/holidays.tt | 66 +++++++++++--------- 1 files changed, 36 insertions(+), 30 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt index aa578cf..1cf239c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt @@ -215,36 +215,42 @@ - -
  • - - [?] -
    You can make an exception for this holiday rule. This means that you will be able to say that for a repeatable holiday there is one day which is going to be an exception.
    -
  • -
  • - . - [?] -
    You can make an exception on a range of dates repeated yearly.
    -
  • -
  • - [?] -
    This will delete this holiday rule. If it is a repeatable holiday, this option checks for possible exceptions. If an exception exists, this option will remove the exception and set the date to a regular holiday.
  • -
  • . - [?] -
    This will delete the single holidays rules only. The repeatable holidays and exceptions will not be deleted.
    -
  • -
  • . - [?] -
    This will delete the repeated holidays rules only. The repeatable holidays will be deleted but not the exceptions.
    -
  • -
  • . - [?] -
    This will delete the exceptions inside a given range. Be careful about your scope range. If it is oversized, you could slow down Koha.
    -
  • -
  • - [?] -
    This will save changes to the holiday's title and description. If the information for a repeatable holiday is modified, it affects all of the dates on which the holiday is repeated.
  • - + +
  • + + + [?] +
    You can make an exception for this holiday rule. This means that you will be able to say that for a repeatable holiday there is one day which is going to be an exception.
    +
  • +
  • + . + [?] +
    You can make an exception on a range of dates repeated yearly.
    +
  • +
  • + + [?] +
    This will delete this holiday rule. If it is a repeatable holiday, this option checks for possible exceptions. If an exception exists, this option will remove the exception and set the date to a regular holiday.
  • +
  • + . + [?] +
    This will delete the single holidays rules only. The repeatable holidays and exceptions will not be deleted.
    + /li> +
  • + . + [?] +
    This will delete the repeated holidays rules only. The repeatable holidays will be deleted but not the exceptions.
    +
  • +
  • + . + [?] +
    This will delete the exceptions inside a given range. Be careful about your scope range. If it is oversized, you could slow down Koha.
    +
  • +
  • + + [?] +
    This will save changes to the holiday's title and description. If the information for a repeatable holiday is modified, it affects all of the dates on which the holiday is repeated.
  • +
    Cancel -- 1.7.0.4 From oleonard at myacpl.org Fri Jun 1 16:19:01 2012 From: oleonard at myacpl.org (Owen Leonard) Date: Fri, 1 Jun 2012 10:19:01 -0400 Subject: [Koha-patches] [PATCH] Bug 7747 [FOLLOW-UP] Replace YUI autocomplete with jQueryUI Message-ID: This patch removes the template calls to the now-obsolete YUI JS dependencies and removes the relevant YUI files themselves. Patch is attached since it contains long lines. -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-Bug-7747-FOLLOW-UP-Replace-YUI-autocomplete-with-jQu.patch Type: application/octet-stream Size: 494156 bytes Desc: not available URL: From dpavlin at rot13.org Fri Jun 1 16:40:13 2012 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Fri, 1 Jun 2012 16:40:13 +0200 Subject: [Koha-patches] [PATCH] Bug 8180 - cataloguing/additem.pl plack scoping Message-ID: <1338561613-31786-1-git-send-email-dpavlin@rot13.org> $dbh needs our scoping when using "Add item" to prevent error Can't call method "prepare" on an undefined value at /srv/koha/cataloguing/additem.pl line 88. Test scenario: 1. start intranet with plack 2. select one Edit items on one record 3. fill in new item and click on "Add item" --- cataloguing/additem.pl | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/cataloguing/additem.pl b/cataloguing/additem.pl index f970890..deb0208 100755 --- a/cataloguing/additem.pl +++ b/cataloguing/additem.pl @@ -37,7 +37,7 @@ use C4::Search; use MARC::File::XML; use URI::Escape; -my $dbh = C4::Context->dbh; +our $dbh = C4::Context->dbh; sub find_value { my ($tagfield,$insubfield,$record) = @_; -- 1.7.2.5 From dpavlin at rot13.org Fri Jun 1 17:45:40 2012 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Fri, 1 Jun 2012 17:45:40 +0200 Subject: [Koha-patches] [PATCH] Bug 8178 - circ/circulation.pl under plack duplicates checkout rows Message-ID: <1338565540-9071-1-git-send-email-dpavlin@rot13.org> Bug 7851 introduced our scoping for vairables, unfortunatly it has side-effect that checkout rows accumulate on page reloads instead of being initialized to empty array (which this patch fixes) This also fixes %renew_failed initialization on each request. Test scenario: 1. start intranet under plack 2. open /cgi-bin/koha/circ/circulation.pl and reload page few time confirming that rows gets duplicated 3. apply patch and reload page to verify that it works --- circ/circulation.pl | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/circ/circulation.pl b/circ/circulation.pl index c89abff..858bfe5 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -94,7 +94,7 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user ( my $branches = GetBranches(); my @failedrenews = $query->param('failedrenew'); # expected to be itemnumbers -our %renew_failed; +our %renew_failed = {}; for (@failedrenews) { $renew_failed{$_} = 1; } my $findborrower = $query->param('findborrower'); @@ -417,10 +417,10 @@ if ($borrowernumber) { # make the issued books table. my $todaysissues = ''; my $previssues = ''; -our @todaysissues; -our @previousissues; -our @relissues; -our @relprevissues; +our @todaysissues = (); +our @previousissues = (); +our @relissues = (); +our @relprevissues = (); my $displayrelissues; our $totalprice = 0; -- 1.7.2.5 From oleonard at myacpl.org Fri Jun 1 18:24:16 2012 From: oleonard at myacpl.org (Owen Leonard) Date: Fri, 1 Jun 2012 12:24:16 -0400 Subject: [Koha-patches] [PATCH] Bug 8143 - Upgrade jQuery tabs to current jQueryUI version Message-ID: Current jQuery-driven tabs are done using a very old version of the tabs plugin. This patch upgrades jQueryUI to the latest version and adds the tabs widget dependency to the jqueryui js file and updates the syntax for existing tabs: - $("#foo > ul").tabs(); changes to $("#foo").tabs(); - Remove full URL from tab links (use #anchor only). Pages with "static" tabs (tabs which are built in the markup rather than generated by the plugin) have been modified to use their own style. Examples: pay.tt in the staff client and opac-readingrecord.tt in the OPAC. Patch is attached because it contains long lines. -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-Bug-8143-Upgrade-jQuery-tabs-to-current-jQueryUI-ver.patch Type: application/octet-stream Size: 263732 bytes Desc: not available URL: From dpavlin at rot13.org Fri Jun 1 21:12:01 2012 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Fri, 1 Jun 2012 21:12:01 +0200 Subject: [Koha-patches] [PATCH] Bug 8183 - acqui/parcels.pl plack scoping Message-ID: <1338577921-9623-1-git-send-email-dpavlin@rot13.org> Scope our $template for plack to prevent following error: Can't call method "param" on an undefined value at /srv/koha_ffzg/acqui/parcels.pl line 177. Test scenario: 1. Home > Acquisitions > Search for vendor 2. click on "Receive shipment" --- acqui/parcels.pl | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/acqui/parcels.pl b/acqui/parcels.pl index 173c0c8..fdb46d5 100755 --- a/acqui/parcels.pl +++ b/acqui/parcels.pl @@ -86,7 +86,7 @@ my $dateto = $input->param('dateto'); my $resultsperpage = $input->param('resultsperpage'); $resultsperpage ||= 20; -my ( $template, $loggedinuser, $cookie ) = get_template_and_user( +our ( $template, $loggedinuser, $cookie ) = get_template_and_user( { template_name => 'acqui/parcels.tmpl', query => $input, type => 'intranet', -- 1.7.2.5 From dpavlin at rot13.org Fri Jun 1 21:24:52 2012 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Fri, 1 Jun 2012 21:24:52 +0200 Subject: [Koha-patches] [PATCH] Bug 7952 - PDF::Reuse under plack writes to console STDOUT instead to browser Message-ID: <1338578692-11411-1-git-send-email-dpavlin@rot13.org> Without name option to prFile, PDF::Reuse opens '-' file which is real console STDOUT on plack so pdf file gets emited to terminal instead of sending it to browser. This change creates temporary file using File::Temp, pass it to PDF::Reuse and then reads it back and prints it out for plack (or CGI) to pick up. DEBUG=1 it will debugging output Test secenario: 1. Home ? Tools ? Patron Card Creator ? Manage Card Batches 2. select batch checkbox and click Export 3. select template and click Export 4. click on pdf file to download it --- C4/Creators/PDF.pm | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-) diff --git a/C4/Creators/PDF.pm b/C4/Creators/PDF.pm index 0aae09c..b3dd1dd 100644 --- a/C4/Creators/PDF.pm +++ b/C4/Creators/PDF.pm @@ -21,6 +21,7 @@ use strict; use warnings; use PDF::Reuse; use PDF::Reuse::Barcode; +use File::Temp; BEGIN { use version; our $VERSION = qv('1.0.0_1'); @@ -42,7 +43,13 @@ sub new { delete($opts{InitVars}); prDocDir($opts{'DocDir'}) if $opts{'DocDir'}; delete($opts{'DocDir'}); - prFile(%opts); + + my $fh = File::Temp->new( UNLINK => 0, SUFFIX => '.pdf' ); + $opts{Name} = $self->{filename} = "$fh"; # filename + close $fh; # we need just filename + warn "## Name [$opts{Name}] $fh"; + + prFile(\%opts); bless ($self, $type); return $self; } @@ -52,6 +59,13 @@ sub End { # if the pdf stream is utf8, explicitly set it to utf8; this avoids at lease some wide character errors -chris_n utf8::encode($PDF::Reuse::stream) if utf8::is_utf8($PDF::Reuse::stream); prEnd(); + + # slurp temporary filename and print it out for plack to pick up + local $/ = undef; + open(my $fh, '<', $self->{filename}) || die "$self->{filename}: $!"; + print <$fh>; + close $fh; + unlink $self->{filename}; } sub Add { -- 1.7.2.5 From amit.gupta at osslabs.biz Mon Jun 4 06:12:05 2012 From: amit.gupta at osslabs.biz (Amit Gupta) Date: Mon, 4 Jun 2012 09:42:05 +0530 Subject: [Koha-patches] [PATCH] Bug 7910 - Batch renewal of serials Message-ID: <1338783125-1862-1-git-send-email-amit.gupta@osslabs.biz> To Test: 1) Go to Serials click on Check expiration link. 2) Search some subscription which have to expire it will give some result. 3) Select atleast one subscription which you want to renew. 4) Check the expiration date after renew. --- .../prog/en/modules/serials/checkexpiration.tt | 34 ++++++++++++++++++-- serials/subscription-renew.pl | 28 +++++++++++++--- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/checkexpiration.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/checkexpiration.tt index 272f19e..6163c76 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/checkexpiration.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/checkexpiration.tt @@ -25,7 +25,23 @@ // ]]> - + [% INCLUDE 'header.inc' %] @@ -83,8 +99,15 @@ [% END %] will expire before [% date %]

    +
    + + + + - + + @@ -97,6 +120,9 @@ [% ELSE %] [% END %] + @@ -117,7 +143,9 @@ [% END %] -
    ISSN Title Note
    + + [% subscriptions_loo.issn %] Renew
    +
    + +
    [% ELSE %]

    No results for your query

    [% END %] diff --git a/serials/subscription-renew.pl b/serials/subscription-renew.pl index 48861bc..815d910 100755 --- a/serials/subscription-renew.pl +++ b/serials/subscription-renew.pl @@ -61,7 +61,8 @@ my $dbh = C4::Context->dbh; my $mode = $query->param('mode'); my $op = $query->param('op') || q{}; -my $subscriptionid = $query->param('subscriptionid'); +my @subscriptionid = $query->param('subscriptionid'); +my $date = $query->param('date'); my $done = 0; # for after form has been submitted my ( $template, $loggedinuser, $cookie ) = get_template_and_user( { @@ -75,17 +76,32 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( ); if ( $op eq "renew" ) { ReNewSubscription( - $subscriptionid, $loggedinuser, + @subscriptionid, $loggedinuser, C4::Dates->new($query->param('startdate'))->output('iso'), $query->param('numberlength'), $query->param('weeklength'), $query->param('monthlength'), $query->param('note') ); } -my $subscription = GetSubscription($subscriptionid); +my $subid; +if ( $op eq "renewall" ) { + foreach $subid (@subscriptionid){ + next unless $subid; + my $data = GetSubscription($subid); + my $length = $data->{numberlength}; + my $weeklength = $data->{weeklength}; + my $monthlength = $data->{monthlength}; + my $note = $data->{note}; + my $startdate = $data->{enddate} || POSIX::strftime( "%Y-%m-%d", localtime ); + ReNewSubscription( $subid,$loggedinuser,$startdate,$length,$weeklength, $monthlength, $note); + } + print $query->redirect("/cgi-bin/koha/serials/checkexpiration.pl?date=$date"); +} + +my $subscription = GetSubscription(@subscriptionid); if ($subscription->{'cannotedit'}){ - carp "Attempt to renew subscription $subscriptionid by ".C4::Context->userenv->{'id'}." not allowed"; - print $query->redirect("/cgi-bin/koha/serials/subscription-detail.pl?subscriptionid=$subscriptionid"); + carp "Attempt to renew subscription @subscriptionid by ".C4::Context->userenv->{'id'}." not allowed"; + print $query->redirect("/cgi-bin/koha/serials/subscription-detail.pl?subscriptionid=@subscriptionid"); } $template->param( @@ -96,7 +112,7 @@ $template->param( numberlength => $subscription->{numberlength}, weeklength => $subscription->{weeklength}, monthlength => $subscription->{monthlength}, - subscriptionid => $subscriptionid, + subscriptionid => @subscriptionid, bibliotitle => $subscription->{bibliotitle}, $op => 1, popup => ($query->param('mode')eq "popup"), -- 1.6.4.2 From oleonard at myacpl.org Mon Jun 4 21:24:48 2012 From: oleonard at myacpl.org (Owen Leonard) Date: Mon, 4 Jun 2012 15:24:48 -0400 Subject: [Koha-patches] [PATCH] Bug 8171 - Improper escaping of quotes during z39.50 queries leads to broken html Message-ID: <1338837889-11278-1-git-send-email-oleonard@myacpl.org> Implementing fix as suggested by Chris Cormack: http://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=8171#c4 --- .../prog/en/modules/cataloguing/z3950_search.tt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_search.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_search.tt index 3db24d3..ffd29d2 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_search.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_search.tt @@ -91,7 +91,7 @@ tr.selected { background-color : #FFFFCC; } tr.selected td { background-color :
    -
    1. +
      1. -- 1.7.9.5 From oleonard at myacpl.org Tue Jun 5 18:26:35 2012 From: oleonard at myacpl.org (Owen Leonard) Date: Tue, 5 Jun 2012 12:26:35 -0400 Subject: [Koha-patches] [PATCH] Bug 8187 - Batch patron modification missing from tools sidebar menu Message-ID: <1338913595-15057-1-git-send-email-oleonard@myacpl.org> Adding a link to the tools sidebar menu for batch patron modification. Also changing the link text on the Tools home page to make it somewhat clearer. --- .../intranet-tmpl/prog/en/includes/tools-menu.inc | 3 +++ .../prog/en/modules/tools/tools-home.tt | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc index b70ffd4..0c3ac93 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc @@ -34,6 +34,9 @@ [% IF ( CAN_user_tools_delete_anonymize_patrons ) %]
      2. Patrons (anonymize, bulk-delete)
      3. [% END %] + [% IF ( CAN_user_tools_edit_patrons ) %] +
      4. Batch patron modification
      5. + [% END %] [% IF ( CAN_user_tools_moderate_tags ) %]
      6. Tag moderation
      7. [% END %] 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 3c8d641..1f4e1e2 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 @@ -46,8 +46,8 @@ [% END %] [% IF ( CAN_user_tools_edit_patrons ) %] -
        Patrons (Modification)
        -
        Modify patrons
        +
        Batch patron modification
        +
        Modify patrons in batch
        [% END %] [% IF ( CAN_user_tools_moderate_tags ) %] -- 1.7.9.5 From oleonard at myacpl.org Tue Jun 5 18:58:19 2012 From: oleonard at myacpl.org (Owen Leonard) Date: Tue, 5 Jun 2012 12:58:19 -0400 Subject: [Koha-patches] [PATCH] Bug 8184 - Duplicate budget page lacks heading and breadcrumbs Message-ID: <1338915499-15825-1-git-send-email-oleonard@myacpl.org> Adding title, heading, and breadcrumbs for "duplicate a budget" operation. Also: - adding cancel link for duplicate and edit - correcting the CSS so that the "edit" menu button is styled like an edit button. operations. --- .../intranet-tmpl/prog/en/css/staff-global.css | 5 +++-- .../prog/en/modules/admin/aqbudgetperiods.tt | 12 ++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) 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 e591a73..96c8b7e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css @@ -905,7 +905,7 @@ fieldset.rows .inputnote { visibility:visible; /* you propably don't need to change this one */ display:block; } -#newbiblio a, #addchild a, #newentry a, #newshelf a, #newmenuc .first-child, #newsupplier .first-child, #newlabel a, #newtemplate a, #newlabelbatch a, #newpatroncardbatch a, #newprofile a, #newsubscription a, #newdictionary a, #newbasket a, #newrootbudget-button, #budgets_menuc .first-child, #periods_menuc .first-child { +#newbiblio a, #addchild a, #newentry a, #newshelf a, #newmenuc .first-child, #newsupplier .first-child, #newlabel a, #newtemplate a, #newlabelbatch a, #newpatroncardbatch a, #newprofile a, #newsubscription a, #newdictionary a, #newbasket a, #newrootbudget-button, #budgets_menuc .first-child { padding-left : 34px; background-image: url("../../img/toolbar-new.gif"); background-position : center left; @@ -943,7 +943,8 @@ fieldset.rows .inputnote { #managelabel a, #managetemplate a, #managelabelbatch a, -#manageprofile a { +#manageprofile a, +#periods_menuc .first-child { padding-left : 34px; background-image: url("../../img/toolbar-edit.gif"); background-position : center left; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgetperiods.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgetperiods.tt index aae5925..4b25992 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgetperiods.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgetperiods.tt @@ -89,7 +89,7 @@ Add budget [% END %] [% END %] - + [% IF ( duplicate_form ) %]› Duplicate budget[% END %] [% IF ( delete_confirm ) %]› Delete budget '[% budget_period_description %]'? [% END %] @@ -136,7 +136,10 @@ Delete budget '[% budget_period_description %]'? [% END %] [% END %] - + + [% IF ( duplicate_form ) %] + Budgets › Duplicate budget + [% END %] [% IF ( else ) %] @@ -152,6 +155,7 @@ [% INCLUDE 'budgets-admin-toolbar.inc' %] [% IF ( duplicate_form ) %] +

        Duplicate budget

        @@ -195,7 +199,7 @@
        - + Cancel
        @@ -287,7 +291,7 @@ - + [% IF ( budget_period_id ) %]Cancel[% END %]
    -- 1.7.9.5 From amit.gupta at osslabs.biz Wed Jun 6 14:09:00 2012 From: amit.gupta at osslabs.biz (Amit Gupta) Date: Wed, 6 Jun 2012 17:39:00 +0530 Subject: [Koha-patches] [PATCH] Bug 7911 Greater flexibility in auto barcode number Message-ID: <1338984540-6115-1-git-send-email-amit.gupta@osslabs.biz> Add option to generate autoBarcode with itemtype as prefix To Test: 1) Go to More->Adminstration->Global system preferences 2) Choose (generated in the form itemtypecode) under autobarcode option. 3) Create one bibliographic record and add item. 4) Click on barcode field it will generate barcode automatically for ex: BK0001 --- cataloguing/value_builder/barcode.pl | 25 ++++++++++++++++++++ installer/data/mysql/sysprefs.sql | 1 + installer/data/mysql/updatedatabase.pl | 7 +++++ .../en/modules/admin/preferences/cataloguing.pref | 1 + 4 files changed, 34 insertions(+), 0 deletions(-) diff --git a/cataloguing/value_builder/barcode.pl b/cataloguing/value_builder/barcode.pl index c5e1fd3..cb6abb0 100755 --- a/cataloguing/value_builder/barcode.pl +++ b/cataloguing/value_builder/barcode.pl @@ -60,6 +60,7 @@ sub plugin_javascript { my ($year, $mon, $day) = split('-', C4::Dates->today('iso')); my ($tag,$subfield) = GetMarcFromKohaField("items.barcode", ''); my ($loctag,$locsubfield) = GetMarcFromKohaField("items.homebranch", ''); + my ($itypetag,$itypesubfield) = GetMarcFromKohaField("items.itype", ''); my $nextnum; my $query; @@ -122,6 +123,30 @@ sub plugin_javascript { \$('#' + id).val(document.f.field_value[fnum].value + '$nextnum'); } "; + } + elsif ($autoBarcodeType eq 'itypeincr') { # Generates a barcode where itype = Itemtype, incr = incremental number + + $query = "SELECT MAX(CAST(SUBSTRING(barcode,-4) AS signed)) AS number FROM items WHERE barcode REGEXP ?"; + my $sth = $dbh->prepare($query); + $sth->execute(); + while (my ($count)= $sth->fetchrow_array) { + $nextnum = $count if $count; + $nextnum = 0 if $nextnum == 9999; # this sequence only allows for cataloging 10000 books per month + warn "Existing incremental number = $nextnum" if $DEBUG; + } + $nextnum++; + $nextnum = sprintf("%0*d", "4",$nextnum); + warn "New itypeincr Barcode = $nextnum" if $DEBUG; + $scr = " + for (i=0 ; ipreference("Version") < TransformToNum($DBversion)) { SetVersion ($DBversion); } +$DBversion = "3.09.00.XXX"; +if (C4::Context->preference("Version") < TransformToNum($DBversion)) { + $dbh->do("update systempreferences set options='incremental|annual|hbyymmincr|itypeincr|OFF', explanation= 'Used to autogenerate a barcode: incremental will be of the form 1, 2, 3; annual of the form 2007-0001, 2007-0002; hbyymmincr of the form HB08010001 where HB=Home Branch; itypeincr of the form BK0001 where itype=Item type.' where variable='autobarcode'"); + print "Upgrade to $DBversion done (Add option to generate autoBarcode with itemtype as prefix)\n"; + SetVersion ($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref index 10e1d13..68c1820 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref @@ -89,6 +89,7 @@ Cataloging: incremental: generated in the form 1, 2, 3. annual: generated in the form <year>-0001, <year>-0002. hbyymmincr: generated in the form <branchcode>yymm0001. + itypeincr: generated in the form <itemtypecode>0001. "OFF": not generated automatically. Display: - -- 1.6.4.2 From christophe.croullebois at biblibre.com Wed Jun 6 16:16:23 2012 From: christophe.croullebois at biblibre.com (christophe croullebois) Date: Wed, 6 Jun 2012 16:16:23 +0200 Subject: [Koha-patches] [PATCH 1/1] Bug 8197 : Software error when you have cleaned cookies and try to past the url to opac-topissues.pl Message-ID: <1338992183-12295-1-git-send-email-christophe.croullebois@biblibre.com> Try to delete cookies and paste the url to opac-topissues.pl. Without the patch we have a Software error. --- opac/opac-topissues.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opac/opac-topissues.pl b/opac/opac-topissues.pl index 6ecc6ad..7fb902e 100755 --- a/opac/opac-topissues.pl +++ b/opac/opac-topissues.pl @@ -129,7 +129,7 @@ $template->param(do_it => 1, results_loop => \@results, ); -$template->param( branchloop => GetBranchesLoop(C4::Context->userenv->{'branch'})); +$template->param( branchloop => GetBranchesLoop(C4::Context->userenv?C4::Context->userenv->{'branch'}:'')); # the index parameter is different for item-level itemtypes my $itype_or_itemtype = (C4::Context->preference("item-level_itypes"))?'itype':'itemtype'; -- 1.7.9.5 From jonathan.druart at biblibre.com Wed Jun 6 16:37:01 2012 From: jonathan.druart at biblibre.com (Jonathan Druart) Date: Wed, 6 Jun 2012 16:37:01 +0200 Subject: [Koha-patches] [PATCH 1/1] Bug 8199 : Replace table in opac-results with div Message-ID: <1338993421-32181-1-git-send-email-jonathan.druart@biblibre.com> Test plan: launch a query from your opac search form and compare results before and after applying this patch. Normally, You don't show a lot of differences. --- koha-tmpl/opac-tmpl/prog/en/css/opac.css | 44 ++ .../opac-tmpl/prog/en/modules/opac-results.tt | 520 +++++++++++-------- 2 files changed, 345 insertions(+), 219 deletions(-) diff --git a/koha-tmpl/opac-tmpl/prog/en/css/opac.css b/koha-tmpl/opac-tmpl/prog/en/css/opac.css index ea538aa..0bf2421 100644 --- a/koha-tmpl/opac-tmpl/prog/en/css/opac.css +++ b/koha-tmpl/opac-tmpl/prog/en/css/opac.css @@ -1169,6 +1169,50 @@ a.cancel { margin : 0 0 0 0; } +.searchresults .controls { + background-color : #EEE; + border : 1px solid #E8E8E8; + vertical-align : middle; + padding : 3px 3px 5px 5px; +} + +.searchresults .controls { + font-size: 90%; +} + +.searchresults .controls img { + vertical-align: middle; +} + +.searchresults .controls select { + font-size: 90%; +} + +.searchresults .controls label { + font-weight : bold; + margin-left : .5em; +} + +.result { + overflow: hidden; + border-bottom: 1px solid #DDDDDD; + padding: 5px 10px 0; +} +.all_results>div.odd { + background-color: #F3F3F3; +} + +.result > input{ + float: left; +} +.result > span { + float: left; + margin-left: 5px; +} +.result > span.image { + float: right; +} + #CheckAll, #CheckNone { font-weight : normal; margin : 0 .5em; diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt index 67b1686..cd1b873 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt @@ -285,7 +285,6 @@ $(document).ready(function(){
    [% END %] - [% IF ( total ) %] [% IF ( scan ) %]

    Scan index:

    @@ -345,7 +344,7 @@ $(document).ready(function(){ [% ELSE %]
    -
    + [% IF ( searchdesc ) %] [% FOREACH QUERY_INPUT IN QUERY_INPUTS %] @@ -355,79 +354,92 @@ $(document).ready(function(){ [% END %] [% END %] - - - - - [% FOREACH SEARCH_RESULT IN SEARCH_RESULTS %] +
    + + [% FOREACH SEARCH_RESULT IN SEARCH_RESULTS %] [% UNLESS ( loop.odd ) %] -
    +
    [% ELSE %] -
    +
    [% END %] + [% IF ( opacbookbag ) %] + + [% ELSE %] + [% IF ( virtualshelves ) %] + + [% ELSE %] + [% IF ( RequestOnOpac ) %] + [% UNLESS ( SEARCH_RESULT.norequests ) %] + [% IF ( opacuserlogin ) %] + + [% END %] + [% END %] + [% END %] + [% END %] + [% END %] + [% UNLESS suppress_result_number %] + [% SEARCH_RESULT.result_number %]. + [% END %] -
    - - - [% UNLESS ( item_level_itypes ) %] + [% UNLESS ( item_level_itypes ) %] [% UNLESS ( noItemTypeImages ) %] - - - [% END %] + + [% IF ( SEARCH_RESULT.imageurl ) %] + [% SEARCH_RESULT.description %] + [% END %] + [% IF ( SEARCH_RESULT.score_avg ) %] + + [% END %] + [% END %] + [% END %] - [% IF ( SEARCH_RESULT.AuthorisedValueImages ) %] - - [% END %] + [% IF ( SEARCH_RESULT.AuthorisedValueImages ) %] + + [% FOREACH authorised_value_image IN SEARCH_RESULT.authorised_value_images %] + [% authorised_value_image.label %] + [% END %] + + [% END %] - - + [% IF ( BakerTaylorEnabled ) %] + [% IF ( SEARCH_RESULT.normalized_isbn ) %] + See Baker & Taylor + [% ELSE %] + No cover image available + [% END %] [% END %] -
    -
    -
    - - - - [% IF ( OpacHighlightedWords ) %] - Unhighlight - Highlight - [% END %] - [% IF ( opacbookbag || virtualshelves ) %] - - [% END %] - -
    - - [% IF ( opacuserlogin ) %][% IF ( loggedinusername ) %][% IF ( TagsEnabled ) %] - [% IF ( TagsInputOnList ) %] - - [% IF ( loggedinusername ) %] - - +
    +
    + +
    +
    + + + + [% IF ( OpacHighlightedWords ) %] + Unhighlight + Highlight + [% END %] + [% IF ( opacbookbag || virtualshelves ) %] + + [% END %] + +
    + + [% IF ( opacuserlogin ) %][% IF ( loggedinusername ) %][% IF ( TagsEnabled ) %] + [% IF ( TagsInputOnList ) %] + + [% IF ( loggedinusername ) %] + + + [% END %] [% END %] - [% END %] - [% END %][% END %][% END %] + [% END %][% END %][% END %] +
    -
    [% IF ( opacbookbag ) %] [% ELSE %] -[% IF ( virtualshelves ) %] [% ELSE %] -[% IF ( RequestOnOpac ) %][% UNLESS ( SEARCH_RESULT.norequests ) %][% IF ( opacuserlogin ) %] [% END %][% END %][% END %][% END %][% END %][% UNLESS suppress_result_number %][% SEARCH_RESULT.result_number %].[% END %] - [% IF ( SEARCH_RESULT.imageurl ) %] - [% SEARCH_RESULT.description %] - [% END %] - [% IF ( SEARCH_RESULT.score_avg ) %] - - [% END %] - - [% FOREACH authorised_value_image IN SEARCH_RESULT.authorised_value_images %] - [% authorised_value_image.label %] - [% END %] - + [% IF ( COinSinOPACResults ) %] [% IF ( SEARCH_RESULT.coins ) %] @@ -435,204 +447,274 @@ $(document).ready(function(){ [% END %] [% IF ( OPACXSLTResultsDisplay ) %] - [% SEARCH_RESULT.XSLTResultsRecord %] + [% SEARCH_RESULT.XSLTResultsRecord %] [% ELSE %] - [% IF ( BiblioDefaultViewmarc ) %] - [% ELSE %] - [% IF ( BiblioDefaultViewisbd ) %] - [% ELSE %] - [% END %] - [% END %] - [% IF ( SEARCH_RESULT.title ) %][% SEARCH_RESULT.title |html %][% ELSE %]No title[% END %] [% FOREACH subtitl IN SEARCH_RESULT.subtitle %], [% subtitl.subfield|html %][% END %] - [% IF ( SEARCH_RESULT.author ) %]by [% SEARCH_RESULT.author %] - [% ELSE %]  - [% END %] - Publication: - [% IF ( SEARCH_RESULT.place ) %][% SEARCH_RESULT.place %] [% END %][% IF ( SEARCH_RESULT.publishercode ) %][% SEARCH_RESULT.publishercode|html %][% END %][% IF ( SEARCH_RESULT.publicationyear ) %] [% SEARCH_RESULT.publicationyear %] - [% ELSE %][% IF ( SEARCH_RESULT.copyrightdate ) %] [% SEARCH_RESULT.copyrightdate %][% END %][% END %] - [% IF ( SEARCH_RESULT.pages ) %]. [% SEARCH_RESULT.pages %][% END %] - [% IF ( SEARCH_RESULT.notes ) %], [% SEARCH_RESULT.notes|html %][% END %] - [% IF ( SEARCH_RESULT.size ) %] [% SEARCH_RESULT.size %][% END %] - [% IF ( SEARCH_RESULT.timestamp ) %] (modified on [% SEARCH_RESULT.timestamp %])[% END %] - - [% IF ( SEARCH_RESULT.summary ) %] - - [% SEARCH_RESULT.summary %] - - [% END %] - [% IF ( SEARCH_RESULT.copyrightdate ) %]Date:[% SEARCH_RESULT.copyrightdate %][% END %] - - - Availability: - [% IF ( SEARCH_RESULT.available_items_loop.0 ) %] - Copies available: - [% FOREACH available_items_loo IN SEARCH_RESULT.available_items_loop %] - [% UNLESS ( available_items_loo.hideatopac ) %] - [% IF ( singleBranchMode ) %] - [% available_items_loo.location %] + [% IF ( BiblioDefaultViewmarc ) %] + + [% ELSE %] + [% IF ( BiblioDefaultViewisbd ) %] + [% ELSE %] - [% available_items_loo.branchname %] + [% END %] - - [% IF ( OPACItemsResultsDisplay ) %] - [% UNLESS ( singleBranchMode ) %][% available_items_loo.location %][% END %] - [% IF ( available_items_loo.itemcallnumber ) %][[% available_items_loo.itemcallnumber %]][% END %] - [% END %] - ([% available_items_loo.count %]), + [% END %] + [% IF ( SEARCH_RESULT.title ) %] + [% SEARCH_RESULT.title |html %] + [% ELSE %] + No title + [% END %] + [% FOREACH subtitl IN SEARCH_RESULT.subtitle %], [% subtitl.subfield|html %][% END %] + [% IF ( SEARCH_RESULT.author ) %] + by [% SEARCH_RESULT.author %] + [% ELSE %] +   + [% END %] + + Publication: + [% IF ( SEARCH_RESULT.place ) %] + [% SEARCH_RESULT.place %] [% END %] + [% IF ( SEARCH_RESULT.publishercode ) %] + [% SEARCH_RESULT.publishercode|html %] [% END %] - + [% IF ( SEARCH_RESULT.publicationyear ) %] + [% SEARCH_RESULT.publicationyear %] [% ELSE %] - [% IF ( SEARCH_RESULT.ALTERNATEHOLDINGS ) %] - [% FOREACH ALTERNATEHOLDING IN SEARCH_RESULT.ALTERNATEHOLDINGS %] -  [% ALTERNATEHOLDING.holding %], + [% IF ( SEARCH_RESULT.copyrightdate ) %] + [% SEARCH_RESULT.copyrightdate %] + [% END %] [% END %] + [% IF ( SEARCH_RESULT.pages ) %]. [% SEARCH_RESULT.pages %][% END %] + [% IF ( SEARCH_RESULT.notes ) %], [% SEARCH_RESULT.notes|html %][% END %] + [% IF ( SEARCH_RESULT.size ) %] [% SEARCH_RESULT.size %][% END %] + [% IF ( SEARCH_RESULT.timestamp ) %] (modified on [% SEARCH_RESULT.timestamp %])[% END %] + + [% IF ( SEARCH_RESULT.summary ) %] + + [% SEARCH_RESULT.summary %] + + [% END %] + [% IF ( SEARCH_RESULT.copyrightdate ) %] + Date:[% SEARCH_RESULT.copyrightdate %] + [% END %] + + + Availability: + [% IF ( SEARCH_RESULT.available_items_loop.0 ) %] + + Copies available: + [% FOREACH available_items_loo IN SEARCH_RESULT.available_items_loop %] + [% UNLESS ( available_items_loo.hideatopac ) %] + [% IF ( singleBranchMode ) %] + [% available_items_loo.location %] + [% ELSE %] + [% available_items_loo.branchname %] + [% END %] + + [% IF ( OPACItemsResultsDisplay ) %] + [% UNLESS ( singleBranchMode ) %][% available_items_loo.location %][% END %] + [% IF ( available_items_loo.itemcallnumber ) %] + [[% available_items_loo.itemcallnumber %]] + [% END %] + [% END %] + ([% available_items_loo.count %]), + [% END %] + [% END %] + [% ELSE %] + [% IF ( SEARCH_RESULT.ALTERNATEHOLDINGS ) %] + [% FOREACH ALTERNATEHOLDING IN SEARCH_RESULT.ALTERNATEHOLDINGS %] +  [% ALTERNATEHOLDING.holding %], + [% END %] + [% ELSE %] No items available: - [% END %] + [% END %] [% END %] - [% IF ( SEARCH_RESULT.onloancount ) %] Checked out ([% SEARCH_RESULT.onloancount %]), [% END %] - [% IF ( SEARCH_RESULT.wthdrawncount ) %] Withdrawn ([% SEARCH_RESULT.wthdrawncount %]), [% END %] - [% UNLESS ( SEARCH_RESULT.hidelostitems ) %][% IF ( SEARCH_RESULT.itemlostcount ) %] Lost ([% SEARCH_RESULT.itemlostcount %]),[% END %][% END %] - [% IF ( SEARCH_RESULT.damagedcount ) %] Damaged ([% SEARCH_RESULT.damagedcount %]),[% END %] - [% IF ( SEARCH_RESULT.orderedcount ) %] On order ([% SEARCH_RESULT.orderedcount %]),[% END %] - [% IF ( SEARCH_RESULT.onholdcount ) %] On hold ([% SEARCH_RESULT.onholdcount %]),[% END %] - [% IF ( SEARCH_RESULT.intransitcount ) %] In transit ([% SEARCH_RESULT.intransitcount %]),[% END %] + [% IF ( SEARCH_RESULT.onloancount ) %] Checked out ([% SEARCH_RESULT.onloancount %]), [% END %] + [% IF ( SEARCH_RESULT.wthdrawncount ) %] Withdrawn ([% SEARCH_RESULT.wthdrawncount %]), [% END %] + [% UNLESS ( SEARCH_RESULT.hidelostitems ) %][% IF ( SEARCH_RESULT.itemlostcount ) %] Lost ([% SEARCH_RESULT.itemlostcount %]),[% END %][% END %] + [% IF ( SEARCH_RESULT.damagedcount ) %] Damaged ([% SEARCH_RESULT.damagedcount %]),[% END %] + [% IF ( SEARCH_RESULT.orderedcount ) %] On order ([% SEARCH_RESULT.orderedcount %]),[% END %] + [% IF ( SEARCH_RESULT.onholdcount ) %] On hold ([% SEARCH_RESULT.onholdcount %]),[% END %] + [% IF ( SEARCH_RESULT.intransitcount ) %] In transit ([% SEARCH_RESULT.intransitcount %]),[% END %] - + [% END %] [% IF ( SEARCH_RESULT.score_avg ) %] - - [% SEARCH_RESULT.score_avg %] / 5 (on [% SEARCH_RESULT.num_scores %] rates) - [% IF ( SEARCH_RESULT.num_critics ) %] - - [% END %] - [% IF ( SEARCH_RESULT.num_critics_pro ) %] - - [% END %] - [% IF ( SEARCH_RESULT.num_videos ) %] - - [% END %] - [% IF ( SEARCH_RESULT.num_quotations ) %] - - [% END %] - + + + [% SEARCH_RESULT.score_avg %] / 5 (on [% SEARCH_RESULT.num_scores %] rates) + [% IF ( SEARCH_RESULT.num_critics ) %] + + [% END %] + [% IF ( SEARCH_RESULT.num_critics_pro ) %] + + [% END %] + [% IF ( SEARCH_RESULT.num_videos ) %] + + [% END %] + [% IF ( SEARCH_RESULT.num_quotations ) %] + + [% END %] + [% END %] [% IF ( LibraryThingForLibrariesID ) %]
    [% END %] - [% IF ( opacuserlogin ) %][% IF ( TagsEnabled ) %] - [% IF ( TagsShowOnList ) %] - [% IF ( SEARCH_RESULT.TagLoop.size ) %] -
    Tags: -
      [% FOREACH TagLoo IN SEARCH_RESULT.TagLoop %]
    • [% TagLoo.term %] ([% TagLoo.weight_total %])
    • - [% END %] -
    - [% END %] - [% IF ( SEARCH_RESULT.TagLoop.size ) %] -
    [% END %] - [% END %] - [% END %][% END %] - [% IF ( SEARCH_RESULT.searchhighlightblob ) %]Match: [% SEARCH_RESULT.searchhighlightblob %][% END %] - - - - - [% IF ( OpacStarRatings == 'all' ) %] -
    - -[% FOREACH i IN [ 1 2 3 4 5 ] %] - -[% IF ( SEARCH_RESULT.rating_avg == i ) %] - -[% ELSE %] - -[% END %] - -[% END %] - - - - [% IF ( SEARCH_RESULT.rating_total ) > 0 %] -   ([% SEARCH_RESULT.rating_total %] votes) - [% ELSE %] -
    + [% IF ( opacuserlogin ) %] + [% IF ( TagsEnabled ) %] + [% IF ( TagsShowOnList ) %] + [% IF ( SEARCH_RESULT.TagLoop.size ) %] +
    + Tags: +
      + [% FOREACH TagLoo IN SEARCH_RESULT.TagLoop %] +
    • + [% TagLoo.term %] + ([% TagLoo.weight_total %]) +
    • + [% END %] +
    +
    + [% END %] + [% END %] + [% END %] [% END %] + [% IF ( SEARCH_RESULT.searchhighlightblob ) %] + Match: [% SEARCH_RESULT.searchhighlightblob %] + [% END %] + [% IF ( OpacStarRatings == 'all' ) %] +
    + + [% FOREACH i IN [ 1 2 3 4 5 ] %] + [% IF ( SEARCH_RESULT.rating_avg == i ) %] + + [% ELSE %] + + [% END %] + [% END %] + + -
    + [% IF ( SEARCH_RESULT.rating_total ) > 0 %] +   ([% SEARCH_RESULT.rating_total %] votes) + [% ELSE %] +
    + [% END %] +
    [% END %] -Actions: - [% IF ( RequestOnOpac ) %] + + Actions: + [% IF ( RequestOnOpac ) %] [% UNLESS ( SEARCH_RESULT.norequests ) %] - [% IF ( opacuserlogin ) %] - [% IF ( AllowOnShelfHolds ) %] - Place hold - [% ELSE %] - [% IF ( SEARCH_RESULT.itemsissued ) %] - Place hold - [% END %] - [% END %] + [% IF ( opacuserlogin ) %] + [% IF ( AllowOnShelfHolds ) %] + Place hold + [% ELSE %] + [% IF ( SEARCH_RESULT.itemsissued ) %] + Place hold + [% END %] [% END %] + [% END %] [% END %] - [% END %] + [% END %] - [% IF ( TagsInputOnList ) %] + [% IF ( TagsInputOnList ) %] [% IF ( loggedinusername ) %] - Add tag - - Cancel + Add tag + + + + + Cancel - [% ELSIF ( loop.first ) %]Log in to add tags. + Tag status here. + + + [% ELSIF ( loop.first ) %] + Log in to add tags. [% END %] - [% END %] + [% END %] - [% IF ( opacuserlogin ) %][% IF ( loggedinusername ) %][% IF ( virtualshelves ) %]Save to Lists - [% END %][% END %][% END %] - [% IF ( opacbookbag ) %] + [% IF ( opacuserlogin ) %] + [% IF ( loggedinusername ) %] + [% IF ( virtualshelves ) %] + Save to Lists + [% END %] + [% END %] + [% END %] + [% IF ( opacbookbag ) %] [% IF ( SEARCH_RESULT.incart ) %] - In your cart (remove) + In your cart (remove) [% ELSE %] - Add to cart + Add to cart [% END %] - [% END %] + [% END %] -
    - - [% IF ( OPACLocalCoverImages ) %][% END %] - [% IF ( OPACAmazonEnabled ) %][% IF ( OPACAmazonCoverImages ) %][% IF ( SEARCH_RESULT.normalized_isbn ) %][% ELSE %]No cover image available[% END %][% END %][% END %] - - [% IF ( SyndeticsEnabled ) %] + + + + + [% IF ( OPACLocalCoverImages ) %] + + [% END %] + [% IF ( OPACAmazonEnabled ) %] + [% IF ( OPACAmazonCoverImages ) %] + [% IF ( SEARCH_RESULT.normalized_isbn ) %] + + [% ELSE %] + No cover image available + [% END %] + [% END %] + [% END %] + [% IF ( SyndeticsEnabled ) %] [% IF ( SyndeticsCoverImages ) %] - [% IF SEARCH_RESULT.normalized_isbn %] - [% IF ( using_https ) %] - + [% IF SEARCH_RESULT.normalized_isbn %] + [% IF ( using_https ) %] + [% ELSE %] - - [% END %] - [% ELSE %] + + [% END %] + [% ELSE %] No cover image available + [% END %] [% END %] - [% END %] - [% END %] + [% END %] - [% IF ( GoogleJackets ) %][% IF ( SEARCH_RESULT.normalized_isbn ) %][% ELSE %]No cover image available[% END %][% END %] - [% IF OpenLibraryCovers %][% IF SEARCH_RESULT.normalized_isbn %][% ELSE %]No cover image available[% END %][% END %] + [% IF ( GoogleJackets ) %] + [% IF ( SEARCH_RESULT.normalized_isbn ) %] + + [% ELSE %] + No cover image available + [% END %] + [% END %] + [% IF OpenLibraryCovers %] + [% IF SEARCH_RESULT.normalized_isbn %] + + [% ELSE %] + No cover image available + [% END %] + [% END %] - [% IF ( BakerTaylorEnabled ) %][% IF ( SEARCH_RESULT.normalized_isbn ) %]See Baker & Taylor[% ELSE %]No cover image available[% END %][% END %] -
    -
    -
    + +
    + [% END %] +
    + +
    -
    - + + [% END %] [% INCLUDE 'page-numbers.inc' %] -- 1.7.7.3 From dpavlin at rot13.org Wed Jun 6 17:40:21 2012 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Wed, 6 Jun 2012 17:40:21 +0200 Subject: [Koha-patches] [PATCH] Bug 7961 - Local cover images should support CSV link files Message-ID: <1338997221-25147-1-git-send-email-dpavlin@rot13.org> Corrent code doesn't have support for filenames which contain spaces or commans which breaks CSV files saved from spreadsheet similar to: 12345, "conver image, with spaces.jpg" This patch tweaks file parsing a bit. We are always splitting line to only two values (to support commas as part of filename) and removing spaces only on beginning and end of filename (to cover space after comma in CSV example above while preserving spaces in filename). With this change only invalid character in picture filename left are quotes (") which are commonly used to quote strings with spaces. Covers added will be logged in action_log, using CATALOGUING / MODIFY action (which is shown as "Catalog" in tools > Log viewer) Test scenario: 1. collect pictures with spaces and commas in name 2. dump file list into CSV file and add biblio number as first column (name of file is idlink.txt or datalink.txt) 3. create zip with CSV file and pictures 4. verify that all pictures got uploaded and linked to biblio records 5. verify that modification log includes cover image name --- tools/upload-cover-image.pl | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/upload-cover-image.pl b/tools/upload-cover-image.pl index 7552e28..f73e7cd 100755 --- a/tools/upload-cover-image.pl +++ b/tools/upload-cover-image.pl @@ -48,6 +48,7 @@ use C4::Auth; use C4::Output; use C4::Images; use C4::UploadedFile; +use C4::Log; my $debug = 1; @@ -143,10 +144,13 @@ if ($fileID) { $error = 'DELERR'; } else { - ( $biblionumber, $filename ) = split $delim, $line; + ( $biblionumber, $filename ) = split $delim, $line, 2; $biblionumber =~ s/[\"\r\n]//g; # remove offensive characters - $filename =~ s/[\"\r\n\s]//g; + $filename =~ s/[\"\r\n]//g; + $filename =~ s/^\s+//; + $filename =~ s/\s+$//; + logaction('CATALOGUING', 'MODIFY', $biblionumber, "cover image: $filename"); my $srcimage = GD::Image->new("$dir/$filename"); if ( defined $srcimage ) { $total++; -- 1.7.2.5 From amit.gupta at osslabs.biz Fri Jun 8 13:21:18 2012 From: amit.gupta at osslabs.biz (Amit Gupta) Date: Fri, 8 Jun 2012 16:51:18 +0530 Subject: [Koha-patches] [PATCH 3/3] Bug 6813: Acquistions duplicate search across orders, suggestions and catalog Message-ID: <1339154478-6788-1-git-send-email-amit.gupta@osslabs.biz> To Test: Create a an suggestion, order and catalog record for a certain title. Use the duplicate search tool available in the acquisitions menu (left navigation bar) to search and find the suggestion, order and catalog record matching the search term. Enter one or more of title, author and ISBN in the search criteria. --- C4/Biblio.pm | 55 ++++++++ C4/Suggestions.pm | 54 +++++++ acqui/duplicatesearch.pl | 105 ++++++++++++++ .../prog/en/includes/acquisitions-menu.inc | 1 + .../prog/en/modules/acqui/duplicatesearch.tt | 145 ++++++++++++++++++++ 5 files changed, 360 insertions(+), 0 deletions(-) create mode 100755 acqui/duplicatesearch.pl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/acqui/duplicatesearch.tt diff --git a/C4/Biblio.pm b/C4/Biblio.pm index 2aa17d5..637c1a3 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -97,6 +97,7 @@ BEGIN { &CountBiblioInOrders &GetSubscriptionsId &GetHolds + &FindBiblios ); # To modify something @@ -3700,6 +3701,60 @@ sub GetHolds { return ($holds); } +=head2 FindBiblios + +Find biblios matching title, author, isbn and return a array containing details of matching biblios. + +=cut + +sub FindBiblios { + my $dbh = C4::Context->dbh; + my %params = @_; + my $title = $params{title}; + my $author = $params{author}; + my $isbn = $params{isbn}; + my $query = "SELECT title, author, isbn, biblio.biblionumber FROM biblio LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber"; + $query .= " WHERE 1 "; + my @query_params = (); + + if ( defined $title ) { + if ( $title eq ""){ + + } else { + $query .= " AND biblio.title LIKE ? "; + $title =~ s/\s+/%/g; + push @query_params, "%$title%"; + } + } + + if ( defined $author ) { + if( $author eq ""){ + + } else { + $query .= " AND biblio.author LIKE ? "; + push @query_params, "%$author%"; + } + } + + if ( defined $isbn) { + if ( $isbn eq ""){ + + } else { + $query .= " AND biblioitems.isbn LIKE ? "; + push @query_params, "%$isbn%"; + } + } + + my $sth = $dbh->prepare($query); + $sth->execute( @query_params ); + my @bib_loop; + while (my $data=$sth->fetchrow_hashref){ + push @bib_loop,$data; + } + + return \@bib_loop; +} + =head2 prepare_host_field $marcfield = prepare_host_field( $hostbiblioitem, $marcflavour ); diff --git a/C4/Suggestions.pm b/C4/Suggestions.pm index 60d0e99..635b338 100644 --- a/C4/Suggestions.pm +++ b/C4/Suggestions.pm @@ -47,6 +47,7 @@ our @EXPORT = qw< NewSuggestion SearchSuggestion DelSuggestionsOlderThan + FindSuggestions >; =head1 NAME @@ -448,6 +449,59 @@ sub ModSuggestion { return $status_update_table; } +=head2 FindSuggestions + +Find Suggestions matching title, author, isbn and return a array containing details of matching Suggestions. + +=cut + +sub FindSuggestions { + my $dbh = C4::Context->dbh; + my %params = @_; + my $title = $params{title}; + my $author = $params{author}; + my $isbn = $params{isbn}; + my $querysug="SELECT title, author, isbn, STATUS, suggestionid FROM suggestions"; + $querysug .=" WHERE 1"; + my @query_sug = (); + + if ( defined $title ) { + if ( $title eq ""){ + + } else { + $querysug .= " AND suggestions.title LIKE ? "; + $title =~ s/\s+/%/g; + push @query_sug, "%$title%"; + } + } + + if ( defined $author ) { + if( $author eq ""){ + + } else { + $querysug .= " AND suggestions.author LIKE ? "; + push @query_sug, "%$author%"; + } + } + + if ( defined $isbn) { + if ( $isbn eq ""){ + + } else { + $querysug .= " AND suggestions.isbn LIKE ? "; + push @query_sug, "%$isbn%"; + } + } + my $sth = $dbh->prepare($querysug); + $sth->execute( @query_sug ); + my @sugg_loop; + while (my $data=$sth->fetchrow_hashref){ + push (@sugg_loop,$data); + } + + return \@sugg_loop; +} + =head2 ConnectSuggestionAndBiblio &ConnectSuggestionAndBiblio($ordernumber,$biblionumber) diff --git a/acqui/duplicatesearch.pl b/acqui/duplicatesearch.pl new file mode 100755 index 0000000..532bd91 --- /dev/null +++ b/acqui/duplicatesearch.pl @@ -0,0 +1,105 @@ +#!/usr/bin/perl + +#script to duplicate search (Orders, suggestions, bibliographic records) +#written by amit.gupta at osslabs.biz 08/06/2012 + +# Copyright 2012 Nucsoft Osslabs +# +# 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 2 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +=head1 NAME + +duplicatesearch.pl + +=head1 DESCRIPTION + +This script is used to search duplicate orders, suggestions and catalog records + +=cut + +use strict; +use warnings; +use CGI; +use C4::Auth; # get_template_and_user +use C4::Output; +use C4::Acquisition; +use C4::Suggestions; +use C4::Biblio; +use C4::Debug; +use C4::Search; + +my $input = new CGI; +my $title = $input->param( 'title'); +my $author = $input->param('author'); +my $isbn = $input->param('isbn'); +my $op = $input->param('op'); + +# getting the template +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "acqui/duplicatesearch.tmpl", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => { acquisition => 'group_manage', acquisition => 'order_manage', acquisition => 'order_receive' }, + debug => 1, + } +); + + +if ($op eq "result"){ + my ( $order_loop, $total_qty, $total_price, $total_qtyreceived ) = GetHistory( + title => $title, + author => $author, + isbn => $isbn, + name => undef, + from_placed_on => undef, + to_placed_on => undef, + basket => undef, + booksellerinvoicenumber => undef, + ); + + my $sugg_loop = FindSuggestions( + title => $title, + author => $author, + isbn => $isbn, + ); + + my $bib_loop = FindBiblios( + title => $title, + author => $author, + isbn => $isbn + ); + + + $template->param( + result => 1, + orders_loop => $order_loop, + sugg_loop => $sugg_loop, + bib_loop => $bib_loop, + numresults_order => scalar(@$order_loop), + numresults_sugg => scalar(@$sugg_loop), + numresults_bib => scalar(@$bib_loop), + ); +} + +$template->param( + title => $title, + author => $author, + isbn => $isbn, +); + +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc index ac1a7a4..38cdf44 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc @@ -4,6 +4,7 @@ [% IF ( CAN_user_acquisition_budget_manage ) %]
  • Budgets
  • Funds
  • +
  • Duplicate Search
  • [% END %] [% IF ( CAN_user_parameters ) %]
  • Currencies
  • diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/duplicatesearch.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/duplicatesearch.tt new file mode 100644 index 0000000..711d780 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/duplicatesearch.tt @@ -0,0 +1,145 @@ +[% USE KohaDates %] +[% INCLUDE 'doc-head-open.inc' %] +Koha › Acquisitions › Duplicate Search +[% INCLUDE 'doc-head-close.inc' %] + + + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'acquisitions-search.inc' %] + + +
    +
    +
    +
    + +

    Duplicate Search

    +
    + [% IF ( result ) %] +
    + +
    + [% IF (numresults_order) %] + [% INCLUDE 'table-pager.inc' perpage='10' %] + + [% ELSE %] +
    + [% END %] + + + + + + + + + [% FOREACH orders_loo IN orders_loop %] + + + + + + + [% END %] +
    Basket NameOrder NumberSummaryVendor
    [% orders_loo.basketname %][% orders_loo.ordernumber %][% orders_loo.title |html %]
    [% orders_loo.author %]
    [% orders_loo.name %]
    +
    +
    +

    Suggestion Search Results

    + [% IF (numresults_sugg) %] + [% INCLUDE 'table-pager.inc' perpage='10' %] + + [% ELSE %] +
    + [% END %] + + + + + + + + + [% FOREACH sugg_loo IN sugg_loop %] + + + + + + + [% END %] +
    TitleAuthorISBNStatus
    [% sugg_loo.title %][% sugg_loo.author %][% sugg_loo.isbn %][% sugg_loo.STATUS %]
    +
    +
    +

    Catalog Search Results

    + [% IF (numresults_bib) %] + [% INCLUDE 'table-pager.inc' perpage='10' %] + + [% ELSE %] +
    + [% END %] + + + + + + + + [% FOREACH bib_loo IN bib_loop %] + + + + + + [% END %] +
    TitleAuthorISBN
    [% bib_loo.title %][% bib_loo.author %][% bib_loo.isbn %]
    +
    +
    +[% ELSE %] +

    No Result

    +[% END %] + +
    +
    +
    +
    +
    + +
    +

    Filter Results:

    +
      +
    1. +
    2. +
    3. +
    4. +
    5. +
    6. +
    7. +
    8. + +
    + Clear All +
    +
    +[% INCLUDE 'acquisitions-menu.inc' %] +
    +
    +[% INCLUDE 'intranet-bottom.inc' %] -- 1.6.4.2 From martin.renvoize at ptfs-europe.com Sat Jun 9 11:56:02 2012 From: martin.renvoize at ptfs-europe.com (Martin Renvoize) Date: Sat, 9 Jun 2012 10:56:02 +0100 Subject: [Koha-patches] [PATCH] Bug 3708 - Add another customizable region to the OPAC: right sidebar Message-ID: <1339235762-13630-1-git-send-email-martin.renvoize@ptfs-europe.com> From: Owen Leonard This patch creates a new system preference, OpacRightSidebar, in which the librarian can add HTML which will appear on the OPAC main page under the login form. If the user is logged in the content will appear in place of the login form. Signed-off-by: Martin Renvoize --- C4/Auth.pm | 2 + installer/data/mysql/sysprefs.sql | 1 + installer/data/mysql/updatedatabase.pl | 8 ++++++ .../prog/en/modules/admin/preferences/opac.pref | 5 ++++ koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt | 25 +++++++++---------- 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/C4/Auth.pm b/C4/Auth.pm index ffee1bb..302178b 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -426,6 +426,7 @@ sub get_template_and_user { OpacKohaUrl => C4::Context->preference("OpacKohaUrl"), OpacMainUserBlock => "" . C4::Context->preference("OpacMainUserBlock"), OpacNav => "" . C4::Context->preference("OpacNav"), + OpacRightSidebar => "" . C4::Context->preference("OpacRightSidebar"), OpacNavBottom => "" . C4::Context->preference("OpacNavBottom"), OpacPasswordChange => C4::Context->preference("OpacPasswordChange"), OPACPatronDetails => C4::Context->preference("OPACPatronDetails"), @@ -962,6 +963,7 @@ sub checkauth { LibraryName => C4::Context->preference("LibraryName"), opacuserlogin => C4::Context->preference("opacuserlogin"), OpacNav => C4::Context->preference("OpacNav"), + OpacRightSidebar => C4::Context->preference("OpacRightSidebar"), OpacNavBottom => C4::Context->preference("OpacNavBottom"), opaccredits => C4::Context->preference("opaccredits"), OpacFavicon => C4::Context->preference("OpacFavicon"), diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index 2ffe2df..e863255 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -82,6 +82,7 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OpacMaintenance',0,'If ON, enables maintenance warning in OPAC','','YesNo'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OpacMainUserBlock','Welcome to Koha...\r\n
    ','A user-defined block of HTML in the main content area of the opac main page','70|10','Textarea'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OpacNav','Important links here.','Use HTML tags to add navigational links to the left-hand navigational bar in OPAC','70|10','Textarea'); +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacRightSidebar','','Show the following HTML in the right hand column of the main page under the main login form','70|10','Textarea'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OpacNavBottom','Important links here.','Use HTML tags to add navigational links to the left-hand navigational bar in OPAC','70|10','Textarea'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OPACNoResultsFound','','Display this HTML when no results are found for a search in the OPAC','70|10','Textarea'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OpacPasswordChange',1,'If ON, enables patron-initiated password change in OPAC (disable it when using LDAP auth)',NULL,'YesNo'); diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index dbbdee3..3f55a31 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -5308,6 +5308,14 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) { SetVersion ($DBversion); } + +$DBversion = "3.09.00.XXX"; +if (C4::Context->preference("Version") < TransformToNum($DBversion)) { + $dbh->do("INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacRightSidebar', '', '70|10', 'Show the following HTML in the right hand column of the main page under the main login form', 'Textarea');"); + print "Upgrade to $DBversion done (Add customizable OpacRightSidebar region to the OPAC main page)\n"; + SetVersion ($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref index e4ea15b..ef763c3 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -165,6 +165,11 @@ OPAC: type: textarea class: code - + - "Show the following HTML in the right hand column of the main page under the main login form:" + - pref: OpacRightSidebar + type: textarea + class: code + - - "Show the following HTML on the left hand column of the main page and patron account on the OPAC, after OpacNav, and before patron account links if available:" - pref: OpacNavBottom type: textarea diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt index a89c473..b8680d3 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt @@ -12,17 +12,14 @@
    [% IF ( opacuserlogin ) %] [% IF ( loggedinusername ) %] -
    -
    +
    [% ELSE %] -
    -
    +
    [% END %] [% ELSE %] -
    -
    +
    [% END %] - +
    [% IF ( koha_news_count ) %]
    @@ -43,11 +40,12 @@ - [% IF ( opacuserlogin ) %] + [% IF ( opacuserlogin || OpacRightSidebar ) %] +
    + [% IF ( opacuserlogin ) %] [% UNLESS ( loggedinusername ) %] [% UNLESS ( casAuthentication ) %] -
    -
    +
    @@ -60,11 +58,12 @@
    -
    [% END %] [% END %] - -[% END %] + [% END %] + [% IF ( OpacRightSidebar ) %]
    [% OpacRightSidebar %]
    [% END %] +
    + [% END %]
    -- 1.7.2.5 From martin.renvoize at ptfs-europe.com Sat Jun 9 12:16:31 2012 From: martin.renvoize at ptfs-europe.com (Martin Renvoize) Date: Sat, 9 Jun 2012 11:16:31 +0100 Subject: [Koha-patches] [PATCH] Bug 8197 : Software error when you have cleaned cookies and try to past the url to opac-topissues.pl Message-ID: <1339236991-13851-1-git-send-email-martin.renvoize@ptfs-europe.com> From: christophe croullebois Try to delete cookies and paste the url to opac-topissues.pl. Without the patch we have a Software error. Signed-off-by: Martin Renvoize --- opac/opac-topissues.pl | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/opac/opac-topissues.pl b/opac/opac-topissues.pl index 6ecc6ad..7fb902e 100755 --- a/opac/opac-topissues.pl +++ b/opac/opac-topissues.pl @@ -129,7 +129,7 @@ $template->param(do_it => 1, results_loop => \@results, ); -$template->param( branchloop => GetBranchesLoop(C4::Context->userenv->{'branch'})); +$template->param( branchloop => GetBranchesLoop(C4::Context->userenv?C4::Context->userenv->{'branch'}:'')); # the index parameter is different for item-level itemtypes my $itype_or_itemtype = (C4::Context->preference("item-level_itypes"))?'itype':'itemtype'; -- 1.7.2.5 From martin.renvoize at ptfs-europe.com Sat Jun 9 12:42:18 2012 From: martin.renvoize at ptfs-europe.com (Martin Renvoize) Date: Sat, 9 Jun 2012 11:42:18 +0100 Subject: [Koha-patches] [PATCH] Bug 8184 - Duplicate budget page lacks heading and breadcrumbs Message-ID: <1339238538-14032-1-git-send-email-martin.renvoize@ptfs-europe.com> From: Owen Leonard Adding title, heading, and breadcrumbs for "duplicate a budget" operation. Also: - adding cancel link for duplicate and edit - correcting the CSS so that the "edit" menu button is styled like an edit button. operations. Signed-off-by: Martin Renvoize --- .../intranet-tmpl/prog/en/css/staff-global.css | 5 +++-- .../prog/en/modules/admin/aqbudgetperiods.tt | 12 ++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) 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 e591a73..96c8b7e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css @@ -905,7 +905,7 @@ fieldset.rows .inputnote { visibility:visible; /* you propably don't need to change this one */ display:block; } -#newbiblio a, #addchild a, #newentry a, #newshelf a, #newmenuc .first-child, #newsupplier .first-child, #newlabel a, #newtemplate a, #newlabelbatch a, #newpatroncardbatch a, #newprofile a, #newsubscription a, #newdictionary a, #newbasket a, #newrootbudget-button, #budgets_menuc .first-child, #periods_menuc .first-child { +#newbiblio a, #addchild a, #newentry a, #newshelf a, #newmenuc .first-child, #newsupplier .first-child, #newlabel a, #newtemplate a, #newlabelbatch a, #newpatroncardbatch a, #newprofile a, #newsubscription a, #newdictionary a, #newbasket a, #newrootbudget-button, #budgets_menuc .first-child { padding-left : 34px; background-image: url("../../img/toolbar-new.gif"); background-position : center left; @@ -943,7 +943,8 @@ fieldset.rows .inputnote { #managelabel a, #managetemplate a, #managelabelbatch a, -#manageprofile a { +#manageprofile a, +#periods_menuc .first-child { padding-left : 34px; background-image: url("../../img/toolbar-edit.gif"); background-position : center left; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgetperiods.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgetperiods.tt index aae5925..4b25992 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgetperiods.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgetperiods.tt @@ -89,7 +89,7 @@ Add budget [% END %] [% END %] - + [% IF ( duplicate_form ) %]› Duplicate budget[% END %] [% IF ( delete_confirm ) %]› Delete budget '[% budget_period_description %]'? [% END %] @@ -136,7 +136,10 @@ Delete budget '[% budget_period_description %]'? [% END %] [% END %] - + + [% IF ( duplicate_form ) %] + Budgets › Duplicate budget + [% END %] [% IF ( else ) %] @@ -152,6 +155,7 @@ [% INCLUDE 'budgets-admin-toolbar.inc' %] [% IF ( duplicate_form ) %] +

    Duplicate budget

    @@ -195,7 +199,7 @@
    - + Cancel
    @@ -287,7 +291,7 @@ - + [% IF ( budget_period_id ) %]Cancel[% END %] -- 1.7.2.5 From colin.campbell at ptfs-europe.com Sat Jun 9 12:44:10 2012 From: colin.campbell at ptfs-europe.com (Colin Campbell) Date: Sat, 9 Jun 2012 11:44:10 +0100 Subject: [Koha-patches] [PATCH] Bug 8216: Allow SIP modules to pass critic tests Message-ID: <1339238650-6255-1-git-send-email-colin.campbell@ptfs-europe.com> Add C4/SIP to perlcritic tests. Fix those issues that were generating perlcritic errors --- C4/SIP/ILS/Item.pm | 25 +++++++++++++------------ C4/SIP/ILS/Patron.pm | 9 ++++++--- C4/SIP/ILS/Transaction/Checkout.pm | 3 +-- C4/SIP/ILS/Transaction/Hold.pm | 3 +-- C4/SIP/ILS/Transaction/Renew.pm | 5 ++--- C4/SIP/ILS/Transaction/RenewAll.pm | 3 +-- C4/SIP/SIPServer.pm | 2 +- C4/SIP/Sip/Checksum.pm | 6 ------ C4/SIP/Sip/Configuration.pm | 9 --------- C4/SIP/Sip/MsgType.pm | 10 +++++----- C4/SIP/t/SIPtest.pm | 20 ++++++++------------ t/00-testcritic.t | 2 +- 12 files changed, 39 insertions(+), 58 deletions(-) diff --git a/C4/SIP/ILS/Item.pm b/C4/SIP/ILS/Item.pm index 1e900bd..ef812e6 100644 --- a/C4/SIP/ILS/Item.pm +++ b/C4/SIP/ILS/Item.pm @@ -86,7 +86,7 @@ sub new { if (! $item) { syslog("LOG_DEBUG", "new ILS::Item('%s'): not found", $item_id); warn "new ILS::Item($item_id) : No item '$item_id'."; - return undef; + return; } $item->{ 'itemnumber' } = $itemnumber; $item->{ 'id' } = $item->{barcode}; # to SIP, the barcode IS the id. @@ -347,25 +347,26 @@ sub available { return 0; } -sub _barcode_to_borrowernumber ($) { +sub _barcode_to_borrowernumber { my $known = shift; - (defined($known)) or return undef; - my $member = GetMember(cardnumber=>$known) or return undef; + return unless defined $known; + my $member = GetMember(cardnumber=>$known) or return; return $member->{borrowernumber}; } -sub barcode_is_borrowernumber ($$$) { # because hold_queue only has borrowernumber... +sub barcode_is_borrowernumber { # because hold_queue only has borrowernumber... my $self = shift; # not really used my $barcode = shift; - my $number = shift or return undef; # can't be zero - (defined($barcode)) or return undef; # might be 0 or 000 or 000000 - my $converted = _barcode_to_borrowernumber($barcode) or return undef; - return ($number eq $converted); # even though both *should* be numbers, eq is safer. + my $number = shift or return; # can't be zero + return unless defined $barcode; # might be 0 or 000 or 000000 + my $converted = _barcode_to_borrowernumber($barcode); + return unless $converted; + return ($number == $converted); } -sub fill_reserve ($$) { +sub fill_reserve { my $self = shift; - my $hold = shift or return undef; + my $hold = shift or return; foreach (qw(biblionumber borrowernumber reservedate)) { - $hold->{$_} or return undef; + $hold->{$_} or return; } return ModReserveFill($hold); } diff --git a/C4/SIP/ILS/Patron.pm b/C4/SIP/ILS/Patron.pm index 99fd6e7..005c524 100644 --- a/C4/SIP/ILS/Patron.pm +++ b/C4/SIP/ILS/Patron.pm @@ -41,7 +41,7 @@ sub new { $debug and warn "new Patron (GetMember): " . Dumper($kp); unless (defined $kp) { syslog("LOG_DEBUG", "new ILS::Patron(%s): no such patron", $patron_id); - return undef; + return; } $kp = GetMemberDetails(undef,$patron_id); $debug and warn "new Patron (GetMemberDetails): " . Dumper($kp); @@ -207,7 +207,10 @@ sub check_password { # A few special cases, not in AUTOLOADed %fields sub fee_amount { my $self = shift; - return $self->{fines} || undef; + if ( $self->{fines} ) { + return $self->{fines}; + } + return; } sub fines_amount { @@ -231,7 +234,7 @@ sub expired { # sub drop_hold { my ($self, $item_id) = @_; - $item_id or return undef; + return if !$item_id; my $result = 0; foreach (qw(hold_items unavail_holds)) { $self->{$_} or next; diff --git a/C4/SIP/ILS/Transaction/Checkout.pm b/C4/SIP/ILS/Transaction/Checkout.pm index d483e16..026f778 100644 --- a/C4/SIP/ILS/Transaction/Checkout.pm +++ b/C4/SIP/ILS/Transaction/Checkout.pm @@ -38,8 +38,7 @@ my %fields = ( sub new { my $class = shift;; my $self = $class->SUPER::new(); - my $element; - foreach $element (keys %fields) { + foreach my $element (keys %fields) { $self->{_permitted}->{$element} = $fields{$element}; } @{$self}{keys %fields} = values %fields; diff --git a/C4/SIP/ILS/Transaction/Hold.pm b/C4/SIP/ILS/Transaction/Hold.pm index 22abf65..6900ef8 100644 --- a/C4/SIP/ILS/Transaction/Hold.pm +++ b/C4/SIP/ILS/Transaction/Hold.pm @@ -29,8 +29,7 @@ my %fields = ( sub new { my $class = shift; my $self = $class->SUPER::new(); - my $element; - foreach $element (keys %fields) { + foreach my $element (keys %fields) { $self->{_permitted}->{$element} = $fields{$element}; } @{$self}{keys %fields} = values %fields; diff --git a/C4/SIP/ILS/Transaction/Renew.pm b/C4/SIP/ILS/Transaction/Renew.pm index d7f949b..5d9bfb2 100644 --- a/C4/SIP/ILS/Transaction/Renew.pm +++ b/C4/SIP/ILS/Transaction/Renew.pm @@ -22,9 +22,8 @@ my %fields = ( sub new { my $class = shift; my $self = $class->SUPER::new(); - my $element; - foreach $element (keys %fields) { + foreach my $element (keys %fields) { $self->{_permitted}->{$element} = $fields{$element}; } @@ -32,7 +31,7 @@ sub new { return bless $self, $class; } -sub do_renew_for ($$) { +sub do_renew_for { my $self = shift; my $borrower = shift; my ($renewokay,$renewerror) = CanBookBeRenewed($borrower->{borrowernumber},$self->{item}->{itemnumber}); diff --git a/C4/SIP/ILS/Transaction/RenewAll.pm b/C4/SIP/ILS/Transaction/RenewAll.pm index 10fb27d..bd92415 100644 --- a/C4/SIP/ILS/Transaction/RenewAll.pm +++ b/C4/SIP/ILS/Transaction/RenewAll.pm @@ -23,9 +23,8 @@ my %fields = ( sub new { my $class = shift; my $self = $class->SUPER::new(); - my $element; - foreach $element (keys %fields) { + foreach my $element (keys %fields) { $self->{_permitted}->{$element} = $fields{$element}; } diff --git a/C4/SIP/SIPServer.pm b/C4/SIP/SIPServer.pm index c6de11e..86bf9e1 100644 --- a/C4/SIP/SIPServer.pm +++ b/C4/SIP/SIPServer.pm @@ -161,7 +161,7 @@ sub raw_transport { syslog("LOG_INFO", "raw_transport: shutting down"); } -sub get_clean_string ($) { +sub get_clean_string { my $string = shift; if (defined $string) { syslog("LOG_DEBUG", "get_clean_string pre-clean(length %s): %s", length($string), $string); diff --git a/C4/SIP/Sip/Checksum.pm b/C4/SIP/Sip/Checksum.pm index ed102c7..6932000 100644 --- a/C4/SIP/Sip/Checksum.pm +++ b/C4/SIP/Sip/Checksum.pm @@ -36,12 +36,6 @@ sub verify_cksum { return (($cksum + $shortsum) & 0xFFFF) == 0; } -{ - no warnings qw(once); - eval join('',) || die $@ unless caller(); - # FIXME: what the heck is this? -} - 1; __END__ diff --git a/C4/SIP/Sip/Configuration.pm b/C4/SIP/Sip/Configuration.pm index e0616ae..662e24c 100644 --- a/C4/SIP/Sip/Configuration.pm +++ b/C4/SIP/Sip/Configuration.pm @@ -80,15 +80,6 @@ sub find_service { return $self->{listeners}->{$portstr}; } -# -# Testing -# - -{ - no warnings qw(once); - eval join('',) || die $@ unless caller(); -} - 1; __END__ diff --git a/C4/SIP/Sip/MsgType.pm b/C4/SIP/Sip/MsgType.pm index c3914c0..1cfb67e 100644 --- a/C4/SIP/Sip/MsgType.pm +++ b/C4/SIP/Sip/MsgType.pm @@ -293,11 +293,11 @@ sub new { if (!exists($handlers{$msgtag})) { syslog("LOG_WARNING", "new Sip::MsgType: Skipping message of unknown type '%s' in '%s'", $msgtag, $msg); - return(undef); + return; } elsif (!exists($handlers{$msgtag}->{protocol}->{$protocol_version})) { syslog("LOG_WARNING", "new Sip::MsgType: Skipping message '%s' unsupported by protocol rev. '%d'", $msgtag, $protocol_version); - return(undef); + return; } bless $self, $class; @@ -405,7 +405,7 @@ sub handle { } unless ($self->{handler}) { syslog("LOG_WARNING", "No handler defined for '%s'", $msg); - return undef; + return; } return($self->{handler}->($self, $server)); # FIXME # FIXME: Use of uninitialized value in subroutine entry @@ -794,8 +794,8 @@ sub handle_request_acs_resend { return REQUEST_ACS_RESEND; } -sub login_core ($$$) { - my $server = shift or return undef; +sub login_core { + my $server = shift or return; my $uid = shift; my $pwd = shift; my $status = 1; # Assume it all works diff --git a/C4/SIP/t/SIPtest.pm b/C4/SIP/t/SIPtest.pm index 0504d23..df2dcd7 100644 --- a/C4/SIP/t/SIPtest.pm +++ b/C4/SIP/t/SIPtest.pm @@ -14,22 +14,18 @@ BEGIN { auth => [qw(&api_auth)], basic => [qw($datepat $textpat $login_test $sc_status_test $instid $instid2 $currency $server $username $password)], + # duplicate user1 and item1 as user2 and item2 + # w/ tags like $user2_pin instead of $user_pin user1 => [qw($user_barcode $user_pin $user_fullname $user_homeaddr $user_email $user_phone $user_birthday $user_ptype $user_inet)], + user2 => [qw($user2_barcode $user._pin $user2_fullname $user2_homeaddr $user2_email + $user2_phone $user2_birthday $user2_ptype $user2_inet)], item1 => [qw($item_barcode $item_title $item_owner )], + item2 => [qw($item2_barcode $item2_title $item2_owner )], + # we've got item3_* also + item3 => [qw($item3_barcode $item3_title $item3_owner )], diacritic => [qw($item_diacritic_barcode $item_diacritic_title $item_diacritic_owner)], ); - # duplicate user1 and item1 as user2 and item2 - # w/ tags like $user2_pin instead of $user_pin - foreach my $tag (qw(user item)) { - my @tags = @{$EXPORT_TAGS{$tag.'1'}}; # fresh array avoids side affect in map - push @{$EXPORT_TAGS{$tag.'2'}}, map {s/($tag)\_/${1}2_/;$_} @tags; - } - # we've got item3_* also - foreach my $tag (qw(item)) { - my @tags = @{$EXPORT_TAGS{$tag.'1'}}; # fresh array avoids side affect in map - push @{$EXPORT_TAGS{$tag.'3'}}, map {s/($tag)\_/${1}3_/;$_} @tags; - } # From perldoc Exporter # Add all the other ":class" tags to the ":all" class, deleting duplicates my %seen; @@ -241,7 +237,7 @@ sub one_msg { return; } -sub api_auth() { +sub api_auth { # AUTH $ENV{REMOTE_USER} = $username; my $query = CGI->new(); diff --git a/t/00-testcritic.t b/t/00-testcritic.t index d628035..caa95d6 100755 --- a/t/00-testcritic.t +++ b/t/00-testcritic.t @@ -17,7 +17,7 @@ labels members misc offline_circ opac patroncards reports reserve reviews rotati serials sms suggestion t tags test tools virtualshelves Koha); my @dirs = qw( acqui admin authorities basket catalogue cataloguing circ debian errors labels - members offline_circ reserve reviews rotating_collections serials sms virtualshelves Koha); + members offline_circ reserve reviews rotating_collections serials sms virtualshelves Koha C4/SIP); if ( not $ENV{TEST_QA} ) { my $msg = 'Author test. Set $ENV{TEST_QA} to a true value to run'; -- 1.7.11.rc0 From adrien.saurat at biblibre.com Sat Jun 9 12:46:33 2012 From: adrien.saurat at biblibre.com (Adrien Saurat) Date: Sat, 9 Jun 2012 11:46:33 +0100 Subject: [Koha-patches] [PATCH] Bug 8217: Focus on search box in staff detail page Message-ID: <1339238793-27287-1-git-send-email-adrien.saurat@biblibre.com> --- .../prog/en/modules/catalogue/detail.tt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt index c92a891..cd203c6 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt @@ -45,7 +45,7 @@ function verify_images() { - + [% INCLUDE 'header.inc' %] [% INCLUDE 'cat-search.inc' %] -- 1.7.4.1 From martin.renvoize at ptfs-europe.com Sat Jun 9 13:13:23 2012 From: martin.renvoize at ptfs-europe.com (Martin Renvoize) Date: Sat, 9 Jun 2012 12:13:23 +0100 Subject: [Koha-patches] [PATCH] Bug 8005 - Lost item is not anonymized when checked in Message-ID: <1339240403-14364-1-git-send-email-martin.renvoize@ptfs-europe.com> From: Kyle M Hall This bug is caused by the subroutine C4::Circulation::LostItem not passing the privacy parameter when calling C4::Circulation::MarkIssueReturned. This issue is actually anonymized when the item is marked as lost, not when the item is checked in. Note, even if the issue is anonymized, the fine charged for lost items still contains a description of the lost item, which is required for the ability to forgive fees for lost items that are later found. Signed-off-by: Martin Renvoize --- C4/Circulation.pm | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/C4/Circulation.pm b/C4/Circulation.pm index c26de76..00d2793 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -1525,6 +1525,7 @@ patron who last borrowed the book. sub AddReturn { my ( $barcode, $branch, $exemptfine, $dropbox ) = @_; + if ($branch and not GetBranchDetail($branch)) { warn "AddReturn error: branch '$branch' not found. Reverting to " . C4::Context->userenv->{'branch'}; undef $branch; @@ -1757,6 +1758,7 @@ routine in C. sub MarkIssueReturned { my ( $borrowernumber, $itemnumber, $dropbox_branch, $returndate, $privacy ) = @_; + my $dbh = C4::Context->dbh; my $query = 'UPDATE issues SET returndate='; my @bind; @@ -3098,12 +3100,13 @@ sub LostItem{ # if a borrower lost the item, add a replacement cost to the their record if ( my $borrowernumber = $issues->{borrowernumber} ){ - + my $borrower = C4::Members::GetMemberDetails( $borrowernumber ); + C4::Accounts::chargelostitem($borrowernumber, $itemnumber, $issues->{'replacementprice'}, "Lost Item $issues->{'title'} $issues->{'barcode'}") if $charge_fee; #FIXME : Should probably have a way to distinguish this from an item that really was returned. #warn " $issues->{'borrowernumber'} / $itemnumber "; - MarkIssueReturned($borrowernumber,$itemnumber) if $mark_returned; + MarkIssueReturned($borrowernumber,$itemnumber,undef,undef,$borrower->{'privacy'}) if $mark_returned; } } -- 1.7.2.5 From martin.renvoize at ptfs-europe.com Sat Jun 9 15:08:10 2012 From: martin.renvoize at ptfs-europe.com (Martin Renvoize) Date: Sat, 9 Jun 2012 14:08:10 +0100 Subject: [Koha-patches] [PATCH] Bug 7671 : add a real primary key accountlinesid in accountlines Message-ID: <1339247290-14804-1-git-send-email-martin.renvoize@ptfs-europe.com> From: St?phane Delaune Signed-off-by: St?phane Delaune --- C4/Accounts.pm | 114 ++++++++++---------- C4/Circulation.pm | 16 ++-- installer/data/mysql/kohastructure.sql | 2 + installer/data/mysql/updatedatabase.pl | 7 ++ .../prog/en/modules/members/boraccount.tt | 6 +- .../intranet-tmpl/prog/en/modules/members/pay.tt | 1 + .../prog/en/modules/members/paycollect.tt | 2 + members/boraccount.pl | 2 +- members/pay.pl | 45 +++++++- members/paycollect.pl | 8 +- members/printinvoice.pl | 1 + 11 files changed, 127 insertions(+), 77 deletions(-) diff --git a/C4/Accounts.pm b/C4/Accounts.pm index b7aef01..2824cdf 100644 --- a/C4/Accounts.pm +++ b/C4/Accounts.pm @@ -72,7 +72,7 @@ patron. Record payment by a patron. C<$borrowernumber> is the patron's borrower number. C<$payment> is a floating-point number, giving the -amount that was paid. +amount that was paid. Amounts owed are paid off oldest first. That is, if the patron has a $1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment @@ -113,12 +113,12 @@ sub recordpayment { $newamtos = $accdata->{'amountoutstanding'} - $amountleft; $amountleft = 0; } - my $thisacct = $accdata->{accountno}; + my $thisacct = $accdata->{accountlinesid}; my $usth = $dbh->prepare( "UPDATE accountlines SET amountoutstanding= ? - WHERE (borrowernumber = ?) AND (accountno=?)" + WHERE (accountlinesid = ?)" ); - $usth->execute( $newamtos, $borrowernumber, $thisacct ); + $usth->execute( $newamtos, $thisacct ); $usth->finish; # $usth = $dbh->prepare( # "INSERT INTO accountoffsets @@ -144,7 +144,7 @@ sub recordpayment { =head2 makepayment - &makepayment($borrowernumber, $acctnumber, $amount, $branchcode); + &makepayment($accountlinesid, $borrowernumber, $acctnumber, $amount, $branchcode); Records the fact that a patron has paid off the entire amount he or she owes. @@ -165,7 +165,7 @@ sub makepayment { #here we update both the accountoffsets and the account lines #updated to check, if they are paying off a lost item, we return the item # from their card, and put a note on the item record - my ( $borrowernumber, $accountno, $amount, $user, $branch ) = @_; + my ( $accountlinesid, $borrowernumber, $accountno, $amount, $user, $branch ) = @_; my $dbh = C4::Context->dbh; my $manager_id = 0; $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; @@ -173,10 +173,8 @@ sub makepayment { # begin transaction my $nextaccntno = getnextacctno($borrowernumber); my $newamtos = 0; - my $sth = - $dbh->prepare( - "SELECT * FROM accountlines WHERE borrowernumber=? AND accountno=?"); - $sth->execute( $borrowernumber, $accountno ); + my $sth = $dbh->prepare("SELECT * FROM accountlines WHERE accountlinesid=?"); + $sth->execute( $accountlinesid ); my $data = $sth->fetchrow_hashref; $sth->finish; @@ -185,22 +183,20 @@ sub makepayment { $dbh->prepare( "UPDATE accountlines SET amountoutstanding = 0, description = 'Payment,thanks' - WHERE borrowernumber = ? - AND accountno = ? + WHERE accountlinesid = ? " ); - $udp->execute($borrowernumber, $accountno ); + $udp->execute($accountlinesid); $udp->finish; }else{ my $udp = $dbh->prepare( "UPDATE accountlines SET amountoutstanding = 0 - WHERE borrowernumber = ? - AND accountno = ? + WHERE accountlinesid = ? " ); - $udp->execute($borrowernumber, $accountno ); + $udp->execute($accountlinesid); $udp->finish; # create new line @@ -227,6 +223,11 @@ sub makepayment { if ( $data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L' ) { C4::Circulation::ReturnLostItem( $borrowernumber, $data->{'itemnumber'} ); } + my $sthr = $dbh->prepare("SELECT max(accountlinesid) AS lastinsertid FROM accountlines"); + $sthr->execute(); + my $datalastinsertid = $sthr->fetchrow_hashref; + $sthr->finish; + return $datalastinsertid->{'lastinsertid'}; } =head2 getnextacctno @@ -254,18 +255,17 @@ sub getnextacctno ($) { =head2 fixaccounts (removed) - &fixaccounts($borrowernumber, $accountnumber, $amount); + &fixaccounts($accountlinesid, $borrowernumber, $accountnumber, $amount); #' # FIXME - I don't understand what this function does. sub fixaccounts { - my ( $borrowernumber, $accountno, $amount ) = @_; + my ( $accountlinesid, $borrowernumber, $accountno, $amount ) = @_; my $dbh = C4::Context->dbh; my $sth = $dbh->prepare( - "SELECT * FROM accountlines WHERE borrowernumber=? - AND accountno=?" + "SELECT * FROM accountlines WHERE accountlinesid=?" ); - $sth->execute( $borrowernumber, $accountno ); + $sth->execute( $accountlinesid ); my $data = $sth->fetchrow_hashref; # FIXME - Error-checking @@ -277,8 +277,7 @@ sub fixaccounts { UPDATE accountlines SET amount = '$amount', amountoutstanding = '$outstanding' - WHERE borrowernumber = $borrowernumber - AND accountno = $accountno + WHERE accountlinesid = $accountlinesid EOT # FIXME: exceedingly bad form. Use prepare with placholders ("?") in query and execute args. } @@ -456,12 +455,12 @@ sub fixcredit { $newamtos = $accdata->{'amountoutstanding'} - $amountleft; $amountleft = 0; } - my $thisacct = $accdata->{accountno}; + my $thisacct = $accdata->{accountlinesid}; my $usth = $dbh->prepare( "UPDATE accountlines SET amountoutstanding= ? - WHERE (borrowernumber = ?) AND (accountno=?)" + WHERE (accountlinesid = ?)" ); - $usth->execute( $newamtos, $borrowernumber, $thisacct ); + $usth->execute( $newamtos, $thisacct ); $usth->finish; $usth = $dbh->prepare( "INSERT INTO accountoffsets @@ -495,12 +494,12 @@ sub fixcredit { $newamtos = $accdata->{'amountoutstanding'} - $amountleft; $amountleft = 0; } - my $thisacct = $accdata->{accountno}; + my $thisacct = $accdata->{accountlinesid}; my $usth = $dbh->prepare( "UPDATE accountlines SET amountoutstanding= ? - WHERE (borrowernumber = ?) AND (accountno=?)" + WHERE (accountlinesid = ?)" ); - $usth->execute( $newamtos, $borrowernumber, $thisacct ); + $usth->execute( $newamtos, $thisacct ); $usth->finish; $usth = $dbh->prepare( "INSERT INTO accountoffsets @@ -561,12 +560,12 @@ sub refund { } # print $amountleft; - my $thisacct = $accdata->{accountno}; + my $thisacct = $accdata->{accountlinesid}; my $usth = $dbh->prepare( "UPDATE accountlines SET amountoutstanding= ? - WHERE (borrowernumber = ?) AND (accountno=?)" + WHERE (accountlinesid = ?)" ); - $usth->execute( $newamtos, $borrowernumber, $thisacct ); + $usth->execute( $newamtos, $thisacct ); $usth->finish; $usth = $dbh->prepare( "INSERT INTO accountoffsets @@ -599,10 +598,10 @@ sub getcharges { } sub ModNote { - my ( $borrowernumber, $accountno, $note ) = @_; + my ( $accountlinesid, $note ) = @_; my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare('UPDATE accountlines SET note = ? WHERE borrowernumber = ? AND accountno = ?'); - $sth->execute( $note, $borrowernumber, $accountno ); + my $sth = $dbh->prepare('UPDATE accountlines SET note = ? WHERE accountlinesid = ?'); + $sth->execute( $note, $accountlinesid ); } sub getcredits { @@ -647,21 +646,21 @@ sub getrefunds { } sub ReversePayment { - my ( $borrowernumber, $accountno ) = @_; - my $dbh = C4::Context->dbh; - - my $sth = $dbh->prepare('SELECT amountoutstanding FROM accountlines WHERE borrowernumber = ? AND accountno = ?'); - $sth->execute( $borrowernumber, $accountno ); - my $row = $sth->fetchrow_hashref(); - my $amount_outstanding = $row->{'amountoutstanding'}; - - if ( $amount_outstanding <= 0 ) { - $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = amount * -1, description = CONCAT( description, " Reversed -" ) WHERE borrowernumber = ? AND accountno = ?'); - $sth->execute( $borrowernumber, $accountno ); - } else { - $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = 0, description = CONCAT( description, " Reversed -" ) WHERE borrowernumber = ? AND accountno = ?'); - $sth->execute( $borrowernumber, $accountno ); - } + my ( $accountlinesid ) = @_; + my $dbh = C4::Context->dbh; + + my $sth = $dbh->prepare('SELECT amountoutstanding FROM accountlines WHERE accountlinesid = ?'); + $sth->execute( $accountlinesid ); + my $row = $sth->fetchrow_hashref(); + my $amount_outstanding = $row->{'amountoutstanding'}; + + if ( $amount_outstanding <= 0 ) { + $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = amount * -1, description = CONCAT( description, " Reversed -" ) WHERE accountlinesid = ?'); + $sth->execute( $accountlinesid ); + } else { + $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding = 0, description = CONCAT( description, " Reversed -" ) WHERE accountlinesid = ?'); + $sth->execute( $accountlinesid ); + } } =head2 recordpayment_selectaccts @@ -703,7 +702,7 @@ sub recordpayment_selectaccts { # offset transactions my $sth = $dbh->prepare('UPDATE accountlines SET amountoutstanding= ? ' . - 'WHERE (borrowernumber = ?) AND (accountno=?)'); + 'WHERE accountlinesid=?'); for my $accdata ( @{$rows} ) { if ($amountleft == 0) { last; @@ -716,8 +715,8 @@ sub recordpayment_selectaccts { $newamtos = $accdata->{amountoutstanding} - $amountleft; $amountleft = 0; } - my $thisacct = $accdata->{accountno}; - $sth->execute( $newamtos, $borrowernumber, $thisacct ); + my $thisacct = $accdata->{accountlinesid}; + $sth->execute( $newamtos, $thisacct ); } # create new line @@ -732,7 +731,7 @@ sub recordpayment_selectaccts { # makepayment needs to be fixed to handle partials till then this separate subroutine # fills in sub makepartialpayment { - my ( $borrowernumber, $accountno, $amount, $user, $branch ) = @_; + my ( $accountlinesid, $borrowernumber, $accountno, $amount, $user, $branch ) = @_; my $manager_id = 0; $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; if (!$amount || $amount < 0) { @@ -744,12 +743,11 @@ sub makepartialpayment { my $newamtos = 0; my $data = $dbh->selectrow_hashref( - 'SELECT * FROM accountlines WHERE borrowernumber=? AND accountno=?',undef,$borrowernumber,$accountno); + 'SELECT * FROM accountlines WHERE accountlinesid=?',undef,$accountlinesid); my $new_outstanding = $data->{amountoutstanding} - $amount; - my $update = 'UPDATE accountlines SET amountoutstanding = ? WHERE borrowernumber = ? ' - . ' AND accountno = ?'; - $dbh->do( $update, undef, $new_outstanding, $borrowernumber, $accountno); + my $update = 'UPDATE accountlines SET amountoutstanding = ? WHERE accountlinesid = ? '; + $dbh->do( $update, undef, $new_outstanding, $accountlinesid); # create new line my $insert = 'INSERT INTO accountlines (borrowernumber, accountno, date, amount, ' diff --git a/C4/Circulation.pm b/C4/Circulation.pm index c26de76..4b25d47 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -1894,7 +1894,7 @@ sub _FixOverduesOnReturn { return 0 unless $data; # no warning, there's just nothing to fix my $uquery; - my @bind = ($borrowernumber, $item, $data->{'accountno'}); + my @bind = ($data->{'accountlinesid'}); if ($exemptfine) { $uquery = "update accountlines set accounttype='FFOR', amountoutstanding=0"; if (C4::Context->preference("FinesLog")) { @@ -1914,7 +1914,7 @@ sub _FixOverduesOnReturn { } else { $uquery = "update accountlines set accounttype='F' "; } - $uquery .= " where (borrowernumber = ?) and (itemnumber = ?) and (accountno = ?)"; + $uquery .= " where (accountlinesid = ?)"; my $usth = $dbh->prepare($uquery); return $usth->execute(@bind); } @@ -1957,9 +1957,8 @@ sub _FixAccountForLostAndReturned { $amountleft = $data->{'amountoutstanding'} - $amount; # Um, isn't this the same as ZERO? We just tested those two things are == } my $usth = $dbh->prepare("UPDATE accountlines SET accounttype = 'LR',amountoutstanding='0' - WHERE (borrowernumber = ?) - AND (itemnumber = ?) AND (accountno = ?) "); - $usth->execute($data->{'borrowernumber'},$itemnumber,$acctno); # We might be adjusting an account for some OTHER borrowernumber now. Not the one we passed in. + WHERE (accountlinesid = ?)"); + $usth->execute($data->{'accountlinesid'}); # We might be adjusting an account for some OTHER borrowernumber now. Not the one we passed in. #check if any credit is left if so writeoff other accounts my $nextaccntno = getnextacctno($data->{'borrowernumber'}); $amountleft *= -1 if ($amountleft < 0); @@ -1978,12 +1977,11 @@ sub _FixAccountForLostAndReturned { $newamtos = $accdata->{'amountoutstanding'} - $amountleft; $amountleft = 0; } - my $thisacct = $accdata->{'accountno'}; + my $thisacct = $accdata->{'accountlinesid'}; # FIXME: move prepares outside while loop! my $usth = $dbh->prepare("UPDATE accountlines SET amountoutstanding= ? - WHERE (borrowernumber = ?) - AND (accountno=?)"); - $usth->execute($newamtos,$data->{'borrowernumber'},'$thisacct'); # FIXME: '$thisacct' is a string literal! + WHERE (accountlinesid = ?)"); + $usth->execute($newamtos,'$thisacct'); # FIXME: '$thisacct' is a string literal! $usth = $dbh->prepare("INSERT INTO accountoffsets (borrowernumber, accountno, offsetaccount, offsetamount) VALUES diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 3137f38..a4464f1 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -2457,6 +2457,7 @@ CREATE TABLE `messages` ( -- circulation messages left via the patron's check ou DROP TABLE IF EXISTS `accountlines`; CREATE TABLE `accountlines` ( + `accountlinesid` int(11) NOT NULL AUTO_INCREMENT, `borrowernumber` int(11) NOT NULL default 0, `accountno` smallint(6) NOT NULL default 0, `itemnumber` int(11) default NULL, @@ -2472,6 +2473,7 @@ CREATE TABLE `accountlines` ( `notify_level` int(2) NOT NULL default 0, `note` text NULL default NULL, `manager_id` int(11) NULL, + PRIMARY KEY (`accountlinesid`), KEY `acctsborridx` (`borrowernumber`), KEY `timeidx` (`timestamp`), KEY `itemnumber` (`itemnumber`), diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index dbbdee3..696cf26 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -5308,6 +5308,13 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) { SetVersion ($DBversion); } +$DBversion = "XXX"; +if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { + $dbh->do("ALTER TABLE `accountlines` ADD `accountlinesid` INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;"); + print "Upgrade to $DBversion done (adding accountlinesid field in accountlines table)\n"; + SetVersion($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt index 995ea8c..fd12197 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/boraccount.tt @@ -51,7 +51,7 @@ [% IF ( reverse_col ) %]
    diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt index fb06325..246290e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt @@ -73,6 +73,7 @@ + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt index d5102cc..31aed6e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/paycollect.tt @@ -102,6 +102,7 @@ function moneyFormat(textObj) { +
    @@ -157,6 +158,7 @@ function moneyFormat(textObj) { +
    [% IF ( account.payment ) %] - Reverse + Reverse [% ELSE %]   [% END %] @@ -59,9 +59,9 @@ [% END %] [% IF ( account.payment ) %] - Print + Print [% ELSE %] - Print + Print [% END %]
    diff --git a/members/boraccount.pl b/members/boraccount.pl index 44db953..a0aed2f 100755 --- a/members/boraccount.pl +++ b/members/boraccount.pl @@ -53,7 +53,7 @@ my $action = $input->param('action') || ''; my $data=GetMember('borrowernumber' => $borrowernumber); if ( $action eq 'reverse' ) { - ReversePayment( $borrowernumber, $input->param('accountno') ); + ReversePayment( $input->param('accountlinesid') ); } if ( $data->{'category_type'} eq 'C') { diff --git a/members/pay.pl b/members/pay.pl index 8f5233c..cd71c5e 100755 --- a/members/pay.pl +++ b/members/pay.pl @@ -83,11 +83,11 @@ my $writeoff_all = $input->param('woall'); # writeoff all fines if ($writeoff_all) { writeoff_all(@names); } elsif ($writeoff_item) { - my $accountno = $input->param('accountno'); + my $accountlinesid = $input->param('accountlinesid'); my $itemno = $input->param('itemnumber'); my $account_type = $input->param('accounttype'); my $amount = $input->param('amountoutstanding'); - WriteOffFee( $borrowernumber, $accountno, $itemno, $account_type, $amount, $branch ); + WriteOffFee( $borrowernumber, $accountlinesid, $itemno, $account_type, $amount, $branch ); } for (@names) { @@ -106,6 +106,23 @@ add_accounts_to_template(); output_html_with_http_headers $input, $cookie, $template->output; +sub writeoff { + my ( $accountlinesid, $itemnum, $accounttype, $amount ) = @_; + my $manager_id = 0; + $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; + + # if no item is attached to fine, make sure to store it as a NULL + $itemnum ||= undef; + get_writeoff_sth(); + $writeoff_sth->execute( $accountlinesid ); + + my $acct = getnextacctno($borrowernumber); + $add_writeoff_sth->execute( $borrowernumber, $acct, $itemnum, $amount, $manager_id ); + + UpdateStats( $branch, 'writeoff', $amount, q{}, q{}, q{}, $borrowernumber ); + + return; +} sub add_accounts_to_template { @@ -167,6 +184,7 @@ sub redirect_to_paycollect { $redirect .= get_for_redirect( 'itemnumber', "itemnumber$line_no", 0 ); $redirect .= get_for_redirect( 'notify_id', "notify_id$line_no", 0 ); $redirect .= get_for_redirect( 'notify_level', "notify_level$line_no", 0 ); + $redirect .= get_for_redirect( 'accountlinesid', "accountlinesid$line_no", 0 ); $redirect .= '&remote_user='; $redirect .= $user; return print $input->redirect($redirect); @@ -184,7 +202,8 @@ sub writeoff_all { my $itemno = $input->param("itemnumber$value"); my $amount = $input->param("amountoutstanding$value"); my $accountno = $input->param("accountno$value"); - WriteOffFee( $borrowernumber, $accountno, $itemno, $accounttype, $amount, $branch ); + my $accountlinesid = $input->param("accountlinesid$value"); + WriteOffFee( $borrowernumber, $accountlinesid, $itemno, $accounttype, $amount, $branch ); } } @@ -250,3 +269,23 @@ sub payselected { print $input->redirect($redirect); return; } + +sub get_writeoff_sth { + + # lets prepare these statement handles only once + if ($writeoff_sth) { + return; + } else { + my $dbh = C4::Context->dbh; + + # Do we need to validate accounttype + my $sql = 'Update accountlines set amountoutstanding=0 ' + . 'WHERE accountlinesid=?'; + $writeoff_sth = $dbh->prepare($sql); + my $insert = +q{insert into accountlines (borrowernumber,accountno,itemnumber,date,amount,description,accounttype,manager_id)} + . q{values (?,?,?,now(),?,'Writeoff','W',?)}; + $add_writeoff_sth = $dbh->prepare($insert); + } + return; +} diff --git a/members/paycollect.pl b/members/paycollect.pl index 7dfb622..8eb03b0 100755 --- a/members/paycollect.pl +++ b/members/paycollect.pl @@ -56,7 +56,7 @@ my $writeoff = $input->param('writeoff_individual'); my $select_lines = $input->param('selected'); my $select = $input->param('selected_accts'); my $accountno; - +my $accountlinesid; if ( $individual || $writeoff ) { if ($individual) { $template->param( pay_individual => 1 ); @@ -64,6 +64,7 @@ if ( $individual || $writeoff ) { $template->param( writeoff_individual => 1 ); } my $accounttype = $input->param('accounttype'); + $accountlinesid = $input->param('accountlinesid'); my $amount = $input->param('amount'); my $amountoutstanding = $input->param('amountoutstanding'); $accountno = $input->param('accountno'); @@ -75,6 +76,7 @@ if ( $individual || $writeoff ) { $total_due = $amountoutstanding; $template->param( accounttype => $accounttype, + accountlinesid => $accountlinesid, accountno => $accountno, amount => $amount, amountoutstanding => $amountoutstanding, @@ -101,10 +103,10 @@ if ( $total_paid and $total_paid ne '0.00' ) { } else { if ($individual) { if ( $total_paid == $total_due ) { - makepayment( $borrowernumber, $accountno, $total_paid, $user, + makepayment( $accountlinesid, $borrowernumber, $accountno, $total_paid, $user, $branch ); } else { - makepartialpayment( $borrowernumber, $accountno, $total_paid, + makepartialpayment( $accountlinesid, $borrowernumber, $accountno, $total_paid, $user, $branch ); } print $input->redirect( diff --git a/members/printinvoice.pl b/members/printinvoice.pl index 039132f..1bfe632 100755 --- a/members/printinvoice.pl +++ b/members/printinvoice.pl @@ -48,6 +48,7 @@ my ($template, $loggedinuser, $cookie) my $borrowernumber=$input->param('borrowernumber'); my $action = $input->param('action') || ''; my $accountno = $input->param('accountno'); +my $accountlinesid = $input->param('accountlinesid'); #get borrower details my $data=GetMember('borrowernumber' => $borrowernumber); -- 1.7.2.5 From colin.campbell at ptfs-europe.com Sat Jun 9 16:35:10 2012 From: colin.campbell at ptfs-europe.com (Colin Campbell) Date: Sat, 9 Jun 2012 15:35:10 +0100 Subject: [Koha-patches] [PATCH] Bug 7619 Use CRLF as default terminator Message-ID: <1339252510-3527-1-git-send-email-colin.campbell@ptfs-europe.com> Most units require or tolerate CRLF as the terminator Using only \r causes many including 3M units to signal errors due to delay this resets CRLF to be default but adds a single constant variable and explanation so that if you have a "strictly conforming" unit (the 'Baby' is the only I have encountered you know where to make the change --- C4/SIP/Sip.pm | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/C4/SIP/Sip.pm b/C4/SIP/Sip.pm index 4e3f299..85253e1 100644 --- a/C4/SIP/Sip.pm +++ b/C4/SIP/Sip.pm @@ -8,6 +8,7 @@ use strict; use warnings; use English; use Exporter; +use Readonly; use Sys::Syslog qw(syslog); use POSIX qw(strftime); @@ -38,7 +39,16 @@ BEGIN { our $error_detection = 0; our $protocol_version = 1; -our $field_delimiter = '|'; # Protocol Default +our $field_delimiter = '|'; # Protocol Default +# The message terminator for a SIP message is '\r' in the standard doc +# However most sip devices in the wild send a CR LF pair +# This is required by Telnet if that is your carrier mechanism +# On raw connections it may also be required because the buffer is +# only flushed on linefeed and its absence causes enough delay for +# client machines to go into an error state +# The below works for almost all machines if however you have one +# which does not like the additional linefeed change value to $CR +Readonly my $msg_terminator => $CRLF; # We need to keep a copy of the last message we sent to the SC, # in case there's a transmission error and the SC sends us a @@ -234,10 +244,10 @@ sub write_msg { if ($file) { $file->autoflush(1); - print $file "$msg\r"; + print $file $msg, $msg_terminator; } else { STDOUT->autoflush(1); - print $msg, "\r"; + print $msg, $msg_terminator; syslog("LOG_INFO", "OUTPUT MSG: '$msg'"); } -- 1.7.11.rc0 From dpavlin at rot13.org Sun Jun 10 13:02:43 2012 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Sun, 10 Jun 2012 13:02:43 +0200 Subject: [Koha-patches] [PATCH] Bug 7844 - plack intranet tooling for developers Message-ID: <1339326163-10305-1-git-send-email-dpavlin@rot13.org> koha.psgi example and plackup.sh script to run any Koha site intranet or opac interface under plack with optional multi-process Starman server plackup.sh site-name [intranet] site-name is used to find config /etc/koha/sites/site-name/koha-conf.xml All configuration is specified in koha.psgi, which you are welcomed to edit and tune according to your development needs (enable memcache, enable/disable debugging modules for plack and so on). For deployment of opac or intranet you would probably want to take a look in plackup.sh and enable starman as web server (which is pre-forking server written in perl) and put some web server in front of it to serve static web files (e.g. ngnix, apache) When you are happy with it, rename koha.psgi and plackup.sh it to site name and save it for safe-keeping. This version does not have mapping to / of opac or intranet, so you need to use full URLs to pages as specified in test scenario. This will be fixed when we are ready to deploy plack, but for now it's clear indication that this is intended for developers which know what to do anyway. Test scenario: 1. install plack and dependencies, as documented at http://wiki.koha-community.org/wiki/Plack 2. start ./plackup.sh sitename i[ntranet] 3. open intranet page http://localhost:5001/cgi-bin/koha/mainpage.pl and verify that it works 4. start ./plackup.sh sitename 5. open OPAC http://localhost:5000/cgi-bin/koha/opac-main.pl and verify that it works 6. next step is to take a look into koha.psgi and enable additional debug modules, save file and reload page (plackup will reload code automatically) --- misc/plack/README.plack | 45 +++++++++++++++++++++++++++ misc/plack/koha.psgi | 78 +++++++++++++++++++++++++++++++++++++++++++++++ misc/plack/plackup.sh | 53 ++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+), 0 deletions(-) create mode 100644 misc/plack/README.plack create mode 100644 misc/plack/koha.psgi create mode 100755 misc/plack/plackup.sh diff --git a/misc/plack/README.plack b/misc/plack/README.plack new file mode 100644 index 0000000..666d184 --- /dev/null +++ b/misc/plack/README.plack @@ -0,0 +1,45 @@ +Bug 7844 - plack intranet tooling for developers + +koha.psgi example and plackup.sh script to run any Koha site +intranet or opac interface under plack with optional multi-process +Starman server + + plackup.sh site-name [intranet] + +site-name is used to find config /etc/koha/sites/site-name/koha-conf.xml + +All configuration is specified in koha.psgi, which you are welcomed to edit +and tune according to your development needs (enable memcache, enable/disable +debugging modules for plack and so on). + +For deployment of opac or intranet you would probably want to take a look +in plackup.sh and enable starman as web server (which is pre-forking server +written in perl) and put some web server in front of it to serve static web +files (e.g. ngnix, apache) + +When you are happy with it, rename koha.psgi and plackup.sh it to site name +and save it for safe-keeping. + +This version does not have mapping to / of opac or intranet, so you need to +use full URLs to pages as specified in test scenario. This will be fixed when +we are ready to deploy plack, but for now it's clear indication that this +is intended for developers which know what to do anyway. + +Test scenario: +1. install plack and dependencies, as documented at + http://wiki.koha-community.org/wiki/Plack + +2. start ./plackup.sh sitename i[ntranet] + +3. open intranet page http://localhost:5001/cgi-bin/koha/mainpage.pl + and verify that it works + +4. start ./plackup.sh sitename + +5. open OPAC http://localhost:5000/cgi-bin/koha/opac-main.pl + and verify that it works + +6. next step is to take a look into koha.psgi and enable additional + debug modules, save file and reload page (plackup will reload + code automatically) + diff --git a/misc/plack/koha.psgi b/misc/plack/koha.psgi new file mode 100644 index 0000000..e388dae --- /dev/null +++ b/misc/plack/koha.psgi @@ -0,0 +1,78 @@ +#!/usr/bin/perl +use Plack::Builder; +use Plack::App::CGIBin; +use lib qw( ./lib ); +use Plack::Middleware::Debug; +use Plack::App::Directory; + +BEGIN { + +# override configuration from startup script below: +# (requires --reload option) + +$ENV{PLACK_DEBUG} = 1; # toggle debugging + +# memcache change requires restart +$ENV{MEMCACHED_SERVERS} = "localhost:11211"; +#$ENV{MEMCACHED_DEBUG} = 0; + +$ENV{PROFILE_PER_PAGE} = 1; # reset persistant and profile counters after each page, like CGI +#$ENV{INTRANET} = 1; # usually passed from script + +#$ENV{DBI_AUTOPROXY}='dbi:Gofer:transport=null;cache=DBI::Util::CacheMemory' + +} # BEGIN + +use C4::Context; +use C4::Languages; +use C4::Members; +use C4::Dates; +use C4::Boolean; +use C4::Letters; +use C4::Koha; +use C4::XSLT; +use C4::Branch; +use C4::Category; +=for preload +use C4::Tags; # FIXME +=cut + +use Devel::Size 0.77; # 0.71 doesn't work for Koha +my $watch_capture_regex = '(C4|Koha)'; + +sub watch_for_size { + my @watch = + map { s/^.*$watch_capture_regex/$1/; s/\//::/g; s/\.pm$//; $_ } # fix paths + grep { /$watch_capture_regex/ } + keys %INC + ; + warn "# watch_for_size ",join(' ', at watch); + return @watch; +}; + +my $CGI_ROOT = $ENV{INTRANET} ? $ENV{INTRANETDIR} : $ENV{OPACDIR}; +warn "# using Koha ", $ENV{INTRANET} ? 'intranet' : 'OPAC', " CGI from $CGI_ROOT\n"; +my $app=Plack::App::CGIBin->new(root => $CGI_ROOT); + +builder { + + enable_if { $ENV{PLACK_DEBUG} } 'Debug', panels => [ + qw(Koha Persistant), + qw(Environment Response Timer Memory), + # optional plugins (uncomment to enable) are sorted according to performance implact +# [ 'Devel::Size', for => \&watch_for_size ], # https://github.com/dpavlin/p5-plack-devel-debug-devel-size +# [ 'DBIProfile', profile => 2 ], +# [ 'DBITrace', level => 1 ], # a LOT of fine-graded SQL trace +# [ 'Profiler::NYTProf', exclude => [qw(.*\.css .*\.png .*\.ico .*\.js .*\.gif)] ], + ]; + + enable_if { $ENV{PLACK_DEBUG} } 'StackTrace'; + + enable_if { $ENV{INTRANETDIR} } "Plack::Middleware::Static", + path => qr{^/(intranet|opac)-tmpl/}, + root => "$ENV{INTRANETDIR}/koha-tmpl/"; + + mount "/cgi-bin/koha" => $app; + +}; + diff --git a/misc/plack/plackup.sh b/misc/plack/plackup.sh new file mode 100755 index 0000000..35fcf0f --- /dev/null +++ b/misc/plack/plackup.sh @@ -0,0 +1,53 @@ +#!/bin/sh -xe + +# This is plack startup script for Koha + +# ./plackup.sh [site] [intranet] + +site=$1 +test ! -z "$site" && shift || site=srvgit # default + +export KOHA_CONF=/etc/koha/sites/$site/koha-conf.xml +export LOGDIR="$( sudo -u $site-koha xmlstarlet sel -t -v 'yazgfs/config/logdir' $KOHA_CONF )" +export INTRANETDIR="$( sudo -u $site-koha xmlstarlet sel -t -v 'yazgfs/config/intranetdir' $KOHA_CONF )" +export OPACDIR="$( sudo -u $site-koha xmlstarlet sel -t -v 'yazgfs/config/opacdir' $KOHA_CONF | sed 's,/cgi-bin/opac,,' )" + +dir=`dirname $0` + +# enable memcache - it's safe even on installation which don't have it +# since Koha has check on C4::Context +#export MEMCACHED_SERVERS=localhost:11211 +# pass site name as namespace to perl code +export MEMCACHED_NAMESPACE=$site +#export MEMCACHED_DEBUG=1 + +if [ ! -e "$INTRANETDIR/C4" ] ; then + echo "intranetdir in $KOHA_CONF doesn't point to Koha git checkout" + exit 1 +fi + +if [ -z "$1" ] ; then # type anything after site name for intranet! + INTRANET=0 + PORT=5000 +else + INTRANET=1 + PORT=5001 + shift # pass rest of arguments to plackup +fi +export INTRANET # pass to plack + +# uncomment to enable logging +#opt="$opt --access-log $LOGDIR/opac-access.log --error-log $LOGDIR/opac-error.log" + +# --max-requests 50 decreased from 1000 to keep memory usage sane +# --workers 4 number of cores on machine +#test "$INTRANET" != 1 && \ # don't use Starman for intranet +opt="$opt --server Starman -M FindBin --max-requests 50 --workers 4" + +# -E deployment turn off access log on STDOUT +opt="$opt -E deployment" + +# comment out reload in production! +opt="$opt --reload -R $INTRANETDIR/C4 -R $INTRANETDIR/Koha" + +sudo -E -u $site-koha plackup --port $PORT -I $INTRANETDIR -I $INTRANETDIR/installer $opt $* $dir/koha.psgi -- 1.7.2.5 From dpavlin at rot13.org Sun Jun 10 13:29:09 2012 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Sun, 10 Jun 2012 13:29:09 +0200 Subject: [Koha-patches] [PATCH] Bug 7952 - PDF::Reuse under plack writes to console STDOUT instead to browser Message-ID: <1339327749-14141-1-git-send-email-dpavlin@rot13.org> Without name option to prFile, PDF::Reuse opens '-' file which is real console STDOUT on plack so pdf file gets emited to terminal instead of sending it to browser. This change creates temporary file using File::Temp, pass it to PDF::Reuse and then reads it back and prints it out for plack (or CGI) to pick up. Test secenario: 1. Home ? Tools ? Patron Card Creator ? Manage Card Batches 2. select batch checkbox and click Export 3. select template and click Export 4. click on pdf file to download it --- C4/Creators/PDF.pm | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/C4/Creators/PDF.pm b/C4/Creators/PDF.pm index 0aae09c..cbdad7e 100644 --- a/C4/Creators/PDF.pm +++ b/C4/Creators/PDF.pm @@ -21,6 +21,7 @@ use strict; use warnings; use PDF::Reuse; use PDF::Reuse::Barcode; +use File::Temp; BEGIN { use version; our $VERSION = qv('1.0.0_1'); @@ -42,7 +43,12 @@ sub new { delete($opts{InitVars}); prDocDir($opts{'DocDir'}) if $opts{'DocDir'}; delete($opts{'DocDir'}); - prFile(%opts); + + my $fh = File::Temp->new( UNLINK => 0, SUFFIX => '.pdf' ); + $opts{Name} = $self->{filename} = "$fh"; # filename + close $fh; # we need just filename + + prFile(\%opts); bless ($self, $type); return $self; } @@ -52,6 +58,13 @@ sub End { # if the pdf stream is utf8, explicitly set it to utf8; this avoids at lease some wide character errors -chris_n utf8::encode($PDF::Reuse::stream) if utf8::is_utf8($PDF::Reuse::stream); prEnd(); + + # slurp temporary filename and print it out for plack to pick up + local $/ = undef; + open(my $fh, '<', $self->{filename}) || die "$self->{filename}: $!"; + print <$fh>; + close $fh; + unlink $self->{filename}; } sub Add { -- 1.7.2.5 From martin.renvoize at ptfs-europe.com Sun Jun 10 15:10:26 2012 From: martin.renvoize at ptfs-europe.com (Martin Renvoize) Date: Sun, 10 Jun 2012 14:10:26 +0100 Subject: [Koha-patches] [PATCH] Bug 7286: fix rebuild_zebra.pl to add rebuild_zebra_sliced.zsh Message-ID: <1339333826-12693-1-git-send-email-martin.renvoize@ptfs-europe.com> From: St?phane Delaune Signed-off-by: Martin Renvoize --- misc/migration_tools/rebuild_zebra_sliced.zsh | 174 +++++++++++++++++++++++++ 1 files changed, 174 insertions(+), 0 deletions(-) create mode 100755 misc/migration_tools/rebuild_zebra_sliced.zsh diff --git a/misc/migration_tools/rebuild_zebra_sliced.zsh b/misc/migration_tools/rebuild_zebra_sliced.zsh new file mode 100755 index 0000000..c015343 --- /dev/null +++ b/misc/migration_tools/rebuild_zebra_sliced.zsh @@ -0,0 +1,174 @@ +#!/usr/bin/zsh + +# Copyright 2011 BibLibre SARL +# 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 2 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +INCREMENT=$1 +BIBLIOSTART=$2 +BIBLIOEND=$3 +TEMPDIRECTORY=$4 +RMLOGS=$5 + +#echo " | $INCREMENT , $BIBLIOSTART , $BIBLIOEND , $TEMPDIRECTORY , $RMLOGS | "; +# this script rebuild the zebra index recursively +# INCREMENT specify how many records we must try at once +# BIBLIOSTART is the record number to BIBLIOSTART on +# BIBLIOEND is the record number to BIBLIOEND on, if it's greater than the last biblionumber it will be redefine +# TEMPDIRECTORY define a temporary directory to rebuild_zebra +# RMLOGS is used to remove files into logs/, it's use and define by script itself so you have not to define it +# At the BIBLIOEND of each "chunk", this script checks if the indexing process has been OK +# if it hasn't, the slice is splitted in 10, and the reindexing is called again on each smaller chunk +# if the increment goes to 1, it means we tried to reindex 1 by 1, and the failing indexing concern wrong records + +# the logs are stored in a directory called logs/ that must be a subdirectory of reindex.zsh + +# at the BIBLIOEND of the script, just type : +#grep -l "previous transaction" `ls rebuild1.*.err` +# the result contains all the biblios that have not been indexed +# WARNING : the numbers are not the biblionumber but the record number, they can be reached by : +# SELECT biblionumber FROM biblio LIMIT YourNumberHere,1; + +# EXAMPLE to run the script on a 800 000 biblios database : +# ./reindex.zsh 50000 0 800000 +# will reindex the DB, BIBLIOSTARTing with chunks of 50k biblios +#if { grep -E "previous transaction" `dirname $0`/logs/rebuild$INCREMENT.$i.err } ; then + +lastbiblionumber=`perl -e '#!/usr/bin/perl +use C4::Context; +my $dbh = C4::Context->dbh; +my $querylastbiblionumber = "SELECT max(biblionumber) FROM biblio;"; +my $sthlastbiblionumber = $dbh->prepare($querylastbiblionumber); +$sthlastbiblionumber->execute(); +my ( $lastbiblionumber ) = $sthlastbiblionumber->fetchrow_array; print $lastbiblionumber;'` +#echo $lastbiblionumber; +let "maxbiblionumber = $lastbiblionumber + 1" +if [ $# = 4 ] +then + RMLOGS=yes +elif [ $# = 3 ] +then + RMLOGS=yes + TEMPDIRECTORY=/tmp/rebuild +elif [ $# = 2 ] +then + RMLOGS=yes + TEMPDIRECTORY=/tmp/rebuild + BIBLIOEND=$lastbiblionumber +elif [ $# = 1 ] +then + RMLOGS=yes + TEMPDIRECTORY=/tmp/rebuild + BIBLIOSTART=0 + BIBLIOEND=$lastbiblionumber +elif [ $# = 0 ] +then + RMLOGS=yes + TEMPDIRECTORY=/tmp/rebuild + INCREMENT=10000 + BIBLIOSTART=0 + BIBLIOEND=$lastbiblionumber +fi +if [[ $INCREMENT =~ ^10*$ ]] +then +else + echo "The first argument (INCREMENT) must be 1 or a multiple of 10" + exit 2 +fi +if [[ $BIBLIOSTART =~ ^[0-9]*$ ]] +then +else + echo "The second argument (BIBLIOSTART) must be an integer" + exit 2 +fi +if [[ $BIBLIOEND =~ ^[0-9]*$ ]] +then +else + echo "The third argument (BIBLIOEND) must be an integer" + exit 2 +fi +if [ $BIBLIOSTART -ge $BIBLIOEND ] +then + echo "The second argument (BIBLIOSTART) must be lower than the third argument (BIBLIOEND)" + exit 2 +fi +if [[ $maxbiblionumber =~ ^[0-9]*$ ]] +then +else + echo "error : last biblionumber is not an integer" + exit 2 +fi +if [ $BIBLIOEND -gt $lastbiblionumber ]; +then + BIBLIOEND=$lastbiblionumber +fi +ls `dirname $0`/logs/ >/dev/null 2>&1 +if [ $? != 0 ] +then + mkdir `dirname $0`/logs +else + if [ $RMLOGS = "yes" ] + then + rm `dirname $0`/logs/* + fi +fi +ls $TEMPDIRECTORY >/dev/null 2>&1 +if [ $? != 0 ] +then + mkdir $TEMPDIRECTORY + if [ $? != 0 ] + then + echo "can't create dir $TEMPDIRECTORY" + exit 2 + fi +fi +#/home/koha/src/misc/migration_tools/rebuild_zebra.pl -r -b -v -x -nosanitize -length 1 -offset 1 +for ((i=$BIBLIOSTART ; i<=$BIBLIOEND ; i=i+$INCREMENT)) +do + echo "I = " $i "with increment " $INCREMENT + #echo "BIBLIOSTART $BIBLIOSTART INCREMENT $INCREMENT BIBLIOEND $BIBLIOEND i $i" + #echo "`dirname $0`/rebuild_zebra.pl -b -v -x -nosanitize -d $TEMPDIRECTORY -k -length $INCREMENT -offset $i -v log" + `dirname $0`/rebuild_zebra.pl -b -v -v -x -nosanitize -d $TEMPDIRECTORY -k -length $INCREMENT -offset $i > `dirname $0`/logs/rebuild$INCREMENT.$i.log 2> `dirname $0`/logs/rebuild$INCREMENT.$i.err + if (($INCREMENT >1 )); + then + if { grep -q "previous transaction" `dirname $0`/logs/rebuild$INCREMENT.$i.err } ; + then + echo "I must split $i (increment $INCREMENT) because previous transaction didn't reach commit" + ((subincrement=$INCREMENT/10)) + if (($i+$INCREMENT >= $BIBLIOEND )); + then + ((newBIBLIOEND=$BIBLIOEND)) + else + ((newBIBLIOEND=$i+$INCREMENT)) + fi + echo "$0 $subincrement $i $newBIBLIOEND $TEMPDIRECTORY no" + $0 $subincrement $i $newBIBLIOEND $TEMPDIRECTORY no + elif { ! grep -q "Records: $INCREMENT" `dirname $0`/logs/rebuild$INCREMENT.$i.err } ; + then + echo "I must split $i (increment $INCREMENT) because index was uncomplete, less than $INCREMENT records indexed" + ((subincrement=$INCREMENT/10)) + if (($i+$INCREMENT >= $BIBLIOEND )); + then + ((newBIBLIOEND=$BIBLIOEND)) + else + ((newBIBLIOEND=$i+$INCREMENT)) + fi + echo "$0 $subincrement $i $newBIBLIOEND $TEMPDIRECTORY no" + $0 $subincrement $i $newBIBLIOEND $TEMPDIRECTORY no + fi + fi +done +exit 0 -- 1.7.2.5 From dpavlin at rot13.org Sun Jun 10 15:37:26 2012 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Sun, 10 Jun 2012 15:37:26 +0200 Subject: [Koha-patches] [PATCH] Bug 7961 - Local cover images should support CSV link files Message-ID: <1339335446-32177-1-git-send-email-dpavlin@rot13.org> Corrent code doesn't have support for filenames which contain spaces or commans which breaks CSV files saved from spreadsheet similar to: 12345, "conver image, with spaces.jpg" This patch tweaks file parsing a bit. We are always splitting line to only two values (to support commas as part of filename) and removing spaces only on beginning and end of filename (to cover space after comma in CSV example above while preserving spaces in filename). With this change only invalid character in picture filename left are quotes (") which are commonly used to quote strings with spaces. Covers added will be logged in action_log, using CATALOGUING / MODIFY action (which is shown as "Catalog" in tools > Log viewer) Test scenario: 1. collect pictures with spaces and commas in name 2. dump file list into CSV file and add biblio number as first column (name of file is idlink.txt or datalink.txt) 3. create zip with CSV file and pictures 4. verify that all pictures got uploaded and linked to biblio records 5. verify that modification log includes cover image name --- tools/upload-cover-image.pl | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/upload-cover-image.pl b/tools/upload-cover-image.pl index 7552e28..9fe1ad4 100755 --- a/tools/upload-cover-image.pl +++ b/tools/upload-cover-image.pl @@ -48,6 +48,7 @@ use C4::Auth; use C4::Output; use C4::Images; use C4::UploadedFile; +use C4::Log; my $debug = 1; @@ -143,10 +144,15 @@ if ($fileID) { $error = 'DELERR'; } else { - ( $biblionumber, $filename ) = split $delim, $line; + ( $biblionumber, $filename ) = split $delim, $line, 2; $biblionumber =~ s/[\"\r\n]//g; # remove offensive characters - $filename =~ s/[\"\r\n\s]//g; + $filename =~ s/[\"\r\n]//g; + $filename =~ s/^\s+//; + $filename =~ s/\s+$//; + if (C4::Context->preference("CataloguingLog")) { + logaction('CATALOGUING', 'MODIFY', $biblionumber, "cover image: $filename"); + } my $srcimage = GD::Image->new("$dir/$filename"); if ( defined $srcimage ) { $total++; -- 1.7.2.5 From martin.renvoize at ptfs-europe.com Sun Jun 10 15:50:19 2012 From: martin.renvoize at ptfs-europe.com (Martin Renvoize) Date: Sun, 10 Jun 2012 14:50:19 +0100 Subject: [Koha-patches] [PATCH] Bug 7444: Update circ/circulation.pl to use KohaDates TT Plugin Message-ID: <1339336219-13326-1-git-send-email-martin.renvoize@ptfs-europe.com> From: Ian Walls Removes all date formatting done in circ/circulation, and sets any/all date outputs to iso format. The formatting of dates is now handled in the template using the KohaDates plugin. This allows use to remove a dependency on C4/Dates.pm from the script. This patch also removes the usage of C4/Overdues/CheckBorrowerDebarred. Since borrowers.debarred is returned by GetMemberDetails, it doesn't make sense to include another module to run another MySQL query just to fetch the date again. To Test: 1. View the checkout page for a patron with materials checked out today and in days past, as well as items on reserve. 2. View a patron who is nearing their expiry date 3. Renew a patron 4. Renew a material from the checkout page using the renewal date selector 5. Attempt to checkout a book to a patron that is on hold for someone else 6. Attempt to checkout a book that is currently checked out 7. View a debarred patron In all cases, any dates displayed should be in syspref format --- circ/circulation.pl | 28 ++++++++----------- .../prog/en/modules/circ/circulation.tt | 22 ++++++++-------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/circ/circulation.pl b/circ/circulation.pl index c4001d0..4511c84 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -27,11 +27,9 @@ use CGI; use C4::Output; use C4::Print; use C4::Auth qw/:DEFAULT get_session/; -use C4::Dates qw/format_date/; use C4::Branch; # GetBranches use C4::Koha; # GetPrinter use C4::Circulation; -use C4::Overdues qw/CheckBorrowerDebarred/; use C4::Members; use C4::Biblio; use C4::Reserves; @@ -241,7 +239,7 @@ if ($borrowernumber) { flagged => "1", noissues => "1", expired => "1", - renewaldate => format_date("$renew_year-$renew_month-$renew_day") + renewaldate => "$renew_year-$renew_month-$renew_day", ); } # check for NotifyBorrowerDeparture @@ -250,7 +248,7 @@ if ($borrowernumber) { Date_to_Days( $today_year, $today_month, $today_day ) ) { # borrower card soon to expire warn librarian - $template->param("warndeparture" => format_date($borrower->{dateexpiry}), + $template->param("warndeparture" => $borrower->{dateexpiry}, flagged => "1",); if (C4::Context->preference('ReturnBeforeExpiry')){ $template->param("returnbeforeexpiry" => 1); @@ -262,12 +260,12 @@ if ($borrowernumber) { finetotal => $fines ); - my $debar = CheckBorrowerDebarred($borrowernumber); + my $debar = $borrower->{debarred}; if ($debar) { $template->param( 'userdebarred' => 1 ); $template->param( 'debarredcomment' => $borrower->{debarredcomment} ); if ( $debar ne "9999-12-31" ) { - $template->param( 'userdebarreddate' => C4::Dates::format_date($debar) ); + $template->param( 'userdebarreddate' => $debar ); } } @@ -351,7 +349,7 @@ if ($borrowernumber) { $getreserv{transfered} = 0; $getreserv{nottransfered} = 0; - $getreserv{reservedate} = format_date( $num_res->{'reservedate'} ); + $getreserv{reservedate} = $num_res->{'reservedate'}; $getreserv{reservenumber} = $num_res->{'reservenumber'}; $getreserv{title} = $getiteminfo->{'title'}; $getreserv{itemtype} = $itemtypeinfo->{'description'}; @@ -371,7 +369,7 @@ if ($borrowernumber) { $getWaitingReserveInfo{biblionumber} = $getiteminfo->{'biblionumber'}; $getWaitingReserveInfo{itemtype} = $itemtypeinfo->{'description'}; $getWaitingReserveInfo{author} = $getiteminfo->{'author'}; - $getWaitingReserveInfo{reservedate} = format_date( $num_res->{'reservedate'} ); + $getWaitingReserveInfo{reservedate} = $num_res->{'reservedate'}; $getWaitingReserveInfo{waitingat} = GetBranchName( $num_res->{'branchcode'} ); $getWaitingReserveInfo{waitinghere} = 1 if $num_res->{'branchcode'} eq $branch; } @@ -379,7 +377,7 @@ if ($borrowernumber) { if ($transfertwhen) { $getreserv{color} = 'transfered'; $getreserv{transfered} = 1; - $getreserv{datesent} = format_date($transfertwhen); + $getreserv{datesent} = $transfertwhen; $getreserv{frombranch} = GetBranchName($transfertfrom); } elsif ($getiteminfo->{'holdingbranch'} ne $num_res->{'branchcode'}) { $getreserv{nottransfered} = 1; @@ -450,16 +448,14 @@ sub build_issue_data { $it->{'can_renew'} = $can_renew; $it->{'can_confirm'} = !$can_renew && !$restype; $it->{'renew_error'} = $restype; - $it->{'checkoutdate'} = C4::Dates->new($it->{'issuedate'},'iso')->output('syspref'); + $it->{'checkoutdate'} = $it->{'issuedate'}; + $it->{'duedate'} = $it->{'date_due'}; + $it->{'od'} = ( $it->{'date_due'} lt $todaysdate ) ? 1 : 0 ; $it->{'issuingbranchname'} = GetBranchName($it->{'branchcode'}); $totalprice += $it->{'replacementprice'}; $it->{'itemtype'} = $itemtypeinfo->{'description'}; $it->{'itemtype_image'} = $itemtypeinfo->{'imageurl'}; - $it->{'dd'} = output_pref($it->{'date_due'}); - $it->{'displaydate'} = output_pref($it->{'issuedate'}); - #$it->{'od'} = ( $it->{'date_due'} lt $todaysdate ) ? 1 : 0 ; - $it->{'od'} = $it->{'overdue'}; ($it->{'author'} eq '') and $it->{'author'} = ' '; $it->{'renew_failed'} = $renew_failed{$it->{'itemnumber'}}; @@ -673,8 +669,8 @@ $template->param( surname => $borrower->{'surname'}, showname => $borrower->{'showname'}, category_type => $borrower->{'category_type'}, - dateexpiry => format_date($newexpiry), - expiry => format_date($borrower->{'dateexpiry'}), + dateexpiry => $newexpiry, + expiry => $borrower->{'dateexpiry'}, categorycode => $borrower->{'categorycode'}, categoryname => $borrower->{description}, address => $address, diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt index 6877737..248642e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -226,7 +226,7 @@ function refocus(calendar) { -[% IF ( dateexpiry ) %]
    Patron's account has been renewed until [% dateexpiry %]
    [% END %] +[% IF ( dateexpiry ) %]
    Patron's account has been renewed until [% dateexpiry | $KohaDates %]
    [% END %] [% IF additional_materials %]
    Note about the accompanying materials:
    @@ -258,7 +258,7 @@ function refocus(calendar) { [% END %] [% IF ( RESERVED ) %] -
  • Item [% getTitleMessageIteminfo %] ([% getBarcodeMessageIteminfo %]) has been on hold for [% resfirstname %] [% ressurname %] ([% rescardnumber %]) at [% resbranchname %] since [% resreservedate %]
  • +
  • Item [% getTitleMessageIteminfo %] ([% getBarcodeMessageIteminfo %]) has been on hold for [% resfirstname %] [% ressurname %] ([% rescardnumber %]) at [% resbranchname %] since [% resreservedate | $KohaDates %]
  • [% END %] [% IF ( ISSUED_TO_ANOTHER ) %] @@ -554,7 +554,7 @@ No patron matched [% message %] [% IF ( warndeparture ) %]
  • Expiration: Patron's card will expire soon. - Patron's card expires on [% expiry %] Renew or Edit Details + Patron's card expires on [% expiry | $KohaDates %] Renew or Edit Details
  • [% END %] @@ -567,7 +567,7 @@ No patron matched [% message %] [% IF ( expired ) %]
  • Expiration: Patron's card has expired. - [% IF ( expiry ) %]Patron's card expired on [% expiry %][% END %] Renew or Edit Details + [% IF ( expiry ) %]Patron's card expired on [% expiry | $KohaDates %][% END %] Renew or Edit Details
  • [% END %] @@ -582,7 +582,7 @@ No patron matched [% message %] [% IF ( userdebarred ) %]
  • - Restricted: Patron's account is restricted [% IF (userdebarreddate ) %] until [% userdebarreddate %] [% END %] [% IF (debarredcomment ) %] with the comment "[% debarredcomment %]"[% END %] + Restricted: Patron's account is restricted [% IF (userdebarreddate ) %] until [% userdebarreddate | $KohaDates %] [% END %] [% IF (debarredcomment ) %] with the comment "[% debarredcomment %]"[% END %]
    @@ -619,7 +619,7 @@ No patron matched [% message %]

    Holds waiting:

    [% FOREACH WaitingReserveLoo IN WaitingReserveLoop %]
      -
    • [% WaitingReserveLoo.title |html %] ([% WaitingReserveLoo.itemtype %]), [% IF ( WaitingReserveLoo.author ) %]by [% WaitingReserveLoo.author %][% END %] Hold placed on [% WaitingReserveLoo.reservedate %]. +
    • [% WaitingReserveLoo.title |html %] ([% WaitingReserveLoo.itemtype %]), [% IF ( WaitingReserveLoo.author ) %]by [% WaitingReserveLoo.author %][% END %] Hold placed on [% WaitingReserveLoo.reservedate | $KohaDates %]. [% IF ( WaitingReserveLoo.waitingat ) %]
      [% IF ( WaitingReserveLoo.waitinghere ) %][% ELSE %][% END %]Waiting at [% WaitingReserveLoo.waitingat %] [% END %] @@ -724,11 +724,11 @@ No patron matched [% message %]
  • [% END %] [% IF ( todayissue.od ) %] - + [% IF ( todayissue.multiple_borrowers ) %][% END %] @@ -797,13 +797,13 @@ No patron matched [% message %] [% END %] [% IF ( previssue.od ) %] - + [% IF ( previssue.multiple_borrowers ) %][% END %] @@ -965,7 +965,7 @@ No patron matched [% message %] [% FOREACH reservloo IN reservloop %] - + [% END %] [% IF ( todayissue.od ) %] - + [% IF ( todayissue.multiple_borrowers ) %][% END %] @@ -797,13 +797,13 @@ No patron matched [% message %] [% END %] [% IF ( previssue.od ) %] - + [% IF ( previssue.multiple_borrowers ) %][% END %] @@ -965,7 +965,7 @@ No patron matched [% message %] [% FOREACH reservloo IN reservloop %] - +
    [% ELSE %][% END %] - [% todayissue.dd %] + [% todayissue.duedate | $KohaDates %] [% todayissue.title |html %][% IF ( todayissue.author ) %], by [% todayissue.author %][% END %][% IF ( todayissue.itemnotes ) %]- [% todayissue.itemnotes %][% END %] [% todayissue.barcode %] [% UNLESS ( noItemTypeImages ) %] [% IF ( todayissue.itemtype_image ) %][% END %][% END %][% todayissue.itemtype %][% todayissue.checkoutdate %][% todayissue.checkoutdate | $KohaDates %][% todayissue.firstname %] [% todayissue.surname %][% todayissue.issuingbranchname %] [% todayissue.itemcallnumber %]
    [% ELSE %][% END %] - [% previssue.dd %] + [% previssue.duedate | $KohaDates %] [% previssue.title |html %][% IF ( previssue.author ) %], by [% previssue.author %][% END %] [% IF ( previssue.itemnotes ) %]- [% previssue.itemnotes %][% END %] [% previssue.barcode %] [% previssue.itemtype %] [% previssue.displaydate %][% previssue.issuedate | $KohaDates %][% previssue.firstname %] [% previssue.surname %][% previssue.issuingbranchname %] [% previssue.itemcallnumber %]
    [% reservloo.reservedate %][% reservloo.reservedate | $KohaDates %] [% reservloo.title |html %][% IF ( reservloo.author ) %], by [% reservloo.author %][% END %] [% reservloo.itemcallnumber %] [% IF ( reservloo.barcodereserv ) %]Item [% reservloo.barcodereserv %] -- 1.7.2.5 From martin.renvoize at ptfs-europe.com Sun Jun 10 16:08:22 2012 From: martin.renvoize at ptfs-europe.com (Martin Renvoize) Date: Sun, 10 Jun 2012 15:08:22 +0100 Subject: [Koha-patches] [PATCH] Bug 7444: Update circ/circulation.pl to use KohaDates TT Plugin Message-ID: <1339337302-13602-1-git-send-email-martin.renvoize@ptfs-europe.com> From: Ian Walls Removes all date formatting done in circ/circulation, and sets any/all date outputs to iso format. The formatting of dates is now handled in the template using the KohaDates plugin. This allows use to remove a dependency on C4/Dates.pm from the script. This patch also removes the usage of C4/Overdues/CheckBorrowerDebarred. Since borrowers.debarred is returned by GetMemberDetails, it doesn't make sense to include another module to run another MySQL query just to fetch the date again. To Test: 1. View the checkout page for a patron with materials checked out today and in days past, as well as items on reserve. 2. View a patron who is nearing their expiry date 3. Renew a patron 4. Renew a material from the checkout page using the renewal date selector 5. Attempt to checkout a book to a patron that is on hold for someone else 6. Attempt to checkout a book that is currently checked out 7. View a debarred patron In all cases, any dates displayed should be in syspref format Signed-off-by: Martin Renvoize --- circ/circulation.pl | 28 ++++++++----------- .../prog/en/modules/circ/circulation.tt | 22 ++++++++-------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/circ/circulation.pl b/circ/circulation.pl index c4001d0..4511c84 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -27,11 +27,9 @@ use CGI; use C4::Output; use C4::Print; use C4::Auth qw/:DEFAULT get_session/; -use C4::Dates qw/format_date/; use C4::Branch; # GetBranches use C4::Koha; # GetPrinter use C4::Circulation; -use C4::Overdues qw/CheckBorrowerDebarred/; use C4::Members; use C4::Biblio; use C4::Reserves; @@ -241,7 +239,7 @@ if ($borrowernumber) { flagged => "1", noissues => "1", expired => "1", - renewaldate => format_date("$renew_year-$renew_month-$renew_day") + renewaldate => "$renew_year-$renew_month-$renew_day", ); } # check for NotifyBorrowerDeparture @@ -250,7 +248,7 @@ if ($borrowernumber) { Date_to_Days( $today_year, $today_month, $today_day ) ) { # borrower card soon to expire warn librarian - $template->param("warndeparture" => format_date($borrower->{dateexpiry}), + $template->param("warndeparture" => $borrower->{dateexpiry}, flagged => "1",); if (C4::Context->preference('ReturnBeforeExpiry')){ $template->param("returnbeforeexpiry" => 1); @@ -262,12 +260,12 @@ if ($borrowernumber) { finetotal => $fines ); - my $debar = CheckBorrowerDebarred($borrowernumber); + my $debar = $borrower->{debarred}; if ($debar) { $template->param( 'userdebarred' => 1 ); $template->param( 'debarredcomment' => $borrower->{debarredcomment} ); if ( $debar ne "9999-12-31" ) { - $template->param( 'userdebarreddate' => C4::Dates::format_date($debar) ); + $template->param( 'userdebarreddate' => $debar ); } } @@ -351,7 +349,7 @@ if ($borrowernumber) { $getreserv{transfered} = 0; $getreserv{nottransfered} = 0; - $getreserv{reservedate} = format_date( $num_res->{'reservedate'} ); + $getreserv{reservedate} = $num_res->{'reservedate'}; $getreserv{reservenumber} = $num_res->{'reservenumber'}; $getreserv{title} = $getiteminfo->{'title'}; $getreserv{itemtype} = $itemtypeinfo->{'description'}; @@ -371,7 +369,7 @@ if ($borrowernumber) { $getWaitingReserveInfo{biblionumber} = $getiteminfo->{'biblionumber'}; $getWaitingReserveInfo{itemtype} = $itemtypeinfo->{'description'}; $getWaitingReserveInfo{author} = $getiteminfo->{'author'}; - $getWaitingReserveInfo{reservedate} = format_date( $num_res->{'reservedate'} ); + $getWaitingReserveInfo{reservedate} = $num_res->{'reservedate'}; $getWaitingReserveInfo{waitingat} = GetBranchName( $num_res->{'branchcode'} ); $getWaitingReserveInfo{waitinghere} = 1 if $num_res->{'branchcode'} eq $branch; } @@ -379,7 +377,7 @@ if ($borrowernumber) { if ($transfertwhen) { $getreserv{color} = 'transfered'; $getreserv{transfered} = 1; - $getreserv{datesent} = format_date($transfertwhen); + $getreserv{datesent} = $transfertwhen; $getreserv{frombranch} = GetBranchName($transfertfrom); } elsif ($getiteminfo->{'holdingbranch'} ne $num_res->{'branchcode'}) { $getreserv{nottransfered} = 1; @@ -450,16 +448,14 @@ sub build_issue_data { $it->{'can_renew'} = $can_renew; $it->{'can_confirm'} = !$can_renew && !$restype; $it->{'renew_error'} = $restype; - $it->{'checkoutdate'} = C4::Dates->new($it->{'issuedate'},'iso')->output('syspref'); + $it->{'checkoutdate'} = $it->{'issuedate'}; + $it->{'duedate'} = $it->{'date_due'}; + $it->{'od'} = ( $it->{'date_due'} lt $todaysdate ) ? 1 : 0 ; $it->{'issuingbranchname'} = GetBranchName($it->{'branchcode'}); $totalprice += $it->{'replacementprice'}; $it->{'itemtype'} = $itemtypeinfo->{'description'}; $it->{'itemtype_image'} = $itemtypeinfo->{'imageurl'}; - $it->{'dd'} = output_pref($it->{'date_due'}); - $it->{'displaydate'} = output_pref($it->{'issuedate'}); - #$it->{'od'} = ( $it->{'date_due'} lt $todaysdate ) ? 1 : 0 ; - $it->{'od'} = $it->{'overdue'}; ($it->{'author'} eq '') and $it->{'author'} = ' '; $it->{'renew_failed'} = $renew_failed{$it->{'itemnumber'}}; @@ -673,8 +669,8 @@ $template->param( surname => $borrower->{'surname'}, showname => $borrower->{'showname'}, category_type => $borrower->{'category_type'}, - dateexpiry => format_date($newexpiry), - expiry => format_date($borrower->{'dateexpiry'}), + dateexpiry => $newexpiry, + expiry => $borrower->{'dateexpiry'}, categorycode => $borrower->{'categorycode'}, categoryname => $borrower->{description}, address => $address, diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt index 64ca686..1deccb4 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -226,7 +226,7 @@ function refocus(calendar) { -[% IF ( dateexpiry ) %]
    Patron's account has been renewed until [% dateexpiry %]
    [% END %] +[% IF ( dateexpiry ) %]
    Patron's account has been renewed until [% dateexpiry | $KohaDates %]
    [% END %] [% IF additional_materials %]
    Note about the accompanying materials:
    @@ -258,7 +258,7 @@ function refocus(calendar) { [% END %] [% IF ( RESERVED ) %] -
  • Item [% getTitleMessageIteminfo %] ([% getBarcodeMessageIteminfo %]) has been on hold for [% resfirstname %] [% ressurname %] ([% rescardnumber %]) at [% resbranchname %] since [% resreservedate %]
  • +
  • Item [% getTitleMessageIteminfo %] ([% getBarcodeMessageIteminfo %]) has been on hold for [% resfirstname %] [% ressurname %] ([% rescardnumber %]) at [% resbranchname %] since [% resreservedate | $KohaDates %]
  • [% END %] [% IF ( ISSUED_TO_ANOTHER ) %] @@ -554,7 +554,7 @@ No patron matched [% message %] [% IF ( warndeparture ) %]
  • Expiration: Patron's card will expire soon. - Patron's card expires on [% expiry %] Renew or Edit Details + Patron's card expires on [% expiry | $KohaDates %] Renew or Edit Details
  • [% END %] @@ -567,7 +567,7 @@ No patron matched [% message %] [% IF ( expired ) %]
  • Expiration: Patron's card has expired. - [% IF ( expiry ) %]Patron's card expired on [% expiry %][% END %] Renew or Edit Details + [% IF ( expiry ) %]Patron's card expired on [% expiry | $KohaDates %][% END %] Renew or Edit Details
  • [% END %] @@ -582,7 +582,7 @@ No patron matched [% message %] [% IF ( userdebarred ) %]
  • - Restricted: Patron's account is restricted [% IF (userdebarreddate ) %] until [% userdebarreddate %] [% END %] [% IF (debarredcomment ) %] with the comment "[% debarredcomment %]"[% END %] + Restricted: Patron's account is restricted [% IF (userdebarreddate ) %] until [% userdebarreddate | $KohaDates %] [% END %] [% IF (debarredcomment ) %] with the comment "[% debarredcomment %]"[% END %]
    @@ -619,7 +619,7 @@ No patron matched [% message %]

    Holds waiting:

    [% FOREACH WaitingReserveLoo IN WaitingReserveLoop %]
      -
    • [% WaitingReserveLoo.title |html %] ([% WaitingReserveLoo.itemtype %]), [% IF ( WaitingReserveLoo.author ) %]by [% WaitingReserveLoo.author %][% END %] Hold placed on [% WaitingReserveLoo.reservedate %]. +
    • [% WaitingReserveLoo.title |html %] ([% WaitingReserveLoo.itemtype %]), [% IF ( WaitingReserveLoo.author ) %]by [% WaitingReserveLoo.author %][% END %] Hold placed on [% WaitingReserveLoo.reservedate | $KohaDates %]. [% IF ( WaitingReserveLoo.waitingat ) %]
      [% IF ( WaitingReserveLoo.waitinghere ) %][% ELSE %][% END %]Waiting at [% WaitingReserveLoo.waitingat %] [% END %] @@ -724,11 +724,11 @@ No patron matched [% message %]
  • [% ELSE %][% END %] - [% todayissue.dd %] + [% todayissue.duedate | $KohaDates %] [% todayissue.title |html %][% IF ( todayissue.author ) %], by [% todayissue.author %][% END %][% IF ( todayissue.itemnotes ) %]- [% todayissue.itemnotes %][% END %] [% todayissue.barcode %] [% UNLESS ( noItemTypeImages ) %] [% IF ( todayissue.itemtype_image ) %][% END %][% END %][% todayissue.itemtype %][% todayissue.checkoutdate %][% todayissue.checkoutdate | $KohaDates %][% todayissue.firstname %] [% todayissue.surname %][% todayissue.issuingbranchname %] [% todayissue.itemcallnumber %]
    [% ELSE %][% END %] - [% previssue.dd %] + [% previssue.duedate | $KohaDates %] [% previssue.title |html %][% IF ( previssue.author ) %], by [% previssue.author %][% END %] [% IF ( previssue.itemnotes ) %]- [% previssue.itemnotes %][% END %] [% previssue.barcode %] [% previssue.itemtype %] [% previssue.displaydate %][% previssue.issuedate | $KohaDates %][% previssue.firstname %] [% previssue.surname %][% previssue.issuingbranchname %] [% previssue.itemcallnumber %]
    [% reservloo.reservedate %][% reservloo.reservedate | $KohaDates %] [% reservloo.title |html %][% IF ( reservloo.author ) %], by [% reservloo.author %][% END %] [% reservloo.itemcallnumber %] [% IF ( reservloo.barcodereserv ) %]Item [% reservloo.barcodereserv %] -- 1.7.2.5 From amit.gupta at osslabs.biz Mon Jun 11 12:34:16 2012 From: amit.gupta at osslabs.biz (Amit Gupta) Date: Mon, 11 Jun 2012 16:04:16 +0530 Subject: [Koha-patches] [PATCH] Bug 7908 Acquisitions: Maintain payment details against vendors Message-ID: <1339410856-14403-1-git-send-email-amit.gupta@osslabs.biz> New payments button against each vendor. Capture payment details - cheque no, date and notes against one or more invoices that show under section "Pending payments". Once invoices are paid the invoices move to the section "Already paid". Screens are very similar to invoice receiving screens. Currently the "order_receive" permission is used to allow access to this feature, this will be changed in a subsequent patch. --- C4/Acquisition.pm | 82 +++++++++++++ acqui/payment.pl | 84 +++++++++++++ acqui/payments.pl | 110 +++++++++++++++++ installer/data/mysql/kohastructure.sql | 13 ++ installer/data/mysql/updatedatabase.pl | 13 ++ .../prog/en/includes/acquisitions-toolbar.inc | 1 + .../prog/en/modules/acqui/booksellers.tt | 1 + .../intranet-tmpl/prog/en/modules/acqui/payment.tt | 105 ++++++++++++++++ .../prog/en/modules/acqui/payments.tt | 128 ++++++++++++++++++++ 9 files changed, 537 insertions(+), 0 deletions(-) create mode 100755 acqui/payment.pl create mode 100755 acqui/payments.pl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/acqui/payment.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/acqui/payments.tt diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm index 9e077bd..af81244 100644 --- a/C4/Acquisition.pm +++ b/C4/Acquisition.pm @@ -56,6 +56,9 @@ BEGIN { &SearchOrder &GetHistory &GetRecentAcqui &ModReceiveOrder &ModOrderBiblioitemNumber &GetCancelledOrders + &GetPayments + &GetPendingpayments + &AddPayments &NewOrderItem &ModOrderItem &ModItemOrder @@ -158,6 +161,85 @@ sub GetBasket { return ( $basket ); } + +=head3 GetPayments + + $aqpayment = &GetPayments($bookseller,$order, $code, $chequeno); + +get all payments informations in aqpayments for a given vendor + + +=cut + +sub GetPayments { + my ($bookseller,$code, $chequeno) = @_; + my $dbh = C4::Context->dbh; + my @query_params = (); + my $strsth =" + SELECT aqpayments.booksellerinvoicenumber, aqpayments.chequeno,aqpayments.chequedate, aqpayments.notes FROM aqpayments LEFT JOIN aqorders ON aqpayments.booksellerinvoicenumber = aqorders.booksellerinvoicenumber LEFT JOIN aqbasket ON aqorders.basketno = aqbasket.basketno WHERE aqbasket.booksellerid = ? + "; + push @query_params, $bookseller; + + if ( defined $code ) { + $strsth .= " AND aqpayments.booksellerinvoicenumber LIKE ? "; + push @query_params, "$code%"; + } + + if ( defined $chequeno ) { + $strsth .= " AND aqpayments.chequeno LIKE ? "; + push @query_params, "$chequeno%"; + } + + $strsth .= "GROUP BY aqpayments.booksellerinvoicenumber "; + + my $sth = $dbh->prepare($strsth); + + $sth->execute( @query_params ); + my $results = $sth->fetchall_arrayref({}); + $sth->finish; + return @$results; +} + +=head3 GetPendingpayments + + $aqpendingpayment = &GetPendingpayments($supplierid); + +get all pending payments informations in aqpayments for a given vendor + +=cut + +sub GetPendingpayments { + my ($supplierid) = @_; + my $dbh = C4::Context->dbh; + my $strsth = " + SELECT DISTINCT(aqorders.booksellerinvoicenumber) AS booksellerinvoicenumber, aqorders.datereceived FROM aqorders LEFT JOIN aqbasket ON aqorders.basketno= aqbasket.basketno LEFT JOIN aqpayments ON aqorders.booksellerinvoicenumber = aqpayments.booksellerinvoicenumber + WHERE aqbasket.booksellerid=? and aqorders.booksellerinvoicenumber IS NOT NULL AND aqpayments.booksellerinvoicenumber IS NULL"; + my @query_params = ( $supplierid ); + my $sth = $dbh->prepare($strsth); + $sth->execute( @query_params ); + my $results = $sth->fetchall_arrayref({}); + $sth->finish; + return $results; +} + +=head3 AddPayments + + $aqaddpayment = &GetPendingpayments($booksellerinvoicenumber,$chequeno,$chequedate,$notes); + +save all the payments in aqpayments table for a given vendor + +=cut + +sub AddPayments { + my ( $booksellerinvoicenumber, $chequeno,$chequedate,$notes) = @_; + my $dbh = C4::Context->dbh; + my $query = qq| + INSERT INTO aqpayments + (booksellerinvoicenumber,chequeno,chequedate,notes) + VALUES (?,?,?,?) |; + my $sth = $dbh->prepare($query); + $sth->execute( $booksellerinvoicenumber,$chequeno,$chequedate,$notes); +} #------------------------------------------------------------# =head3 NewBasket diff --git a/acqui/payment.pl b/acqui/payment.pl new file mode 100755 index 0000000..66d6af5 --- /dev/null +++ b/acqui/payment.pl @@ -0,0 +1,84 @@ +#!/usr/bin/perl + +#script to Payment Capture against vendor +#written by amit.gupta at osslabs.biz 09/06/2012 + +# Copyright 2012 Nucsoft Osslabs +# +# 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 2 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +=head1 NAME + +payments.pl + +This script is used to capture payments against vendor. + +=cut + +use strict; +use warnings; +use CGI; +use C4::Auth; +use C4::Output; + +use C4::Dates qw/format_date/; +use C4::Acquisition; +use C4::Bookseller qw/ GetBookSellerFromId /; + +my $input = CGI->new; +my $booksellerid = $input->param('booksellerid'); +my $startfrom = $input->param('startfrom'); +my $code = $input->param('filter'); +my $chequeno = $input->param('chequeno'); + + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { template_name => 'acqui/payment.tmpl', + query => $input, + type => 'intranet', + authnotrequired => 0, + flagsrequired => { acquisition => 'order_receive' }, + debug => 1, + } +); + +my $bookseller = GetBookSellerFromId($booksellerid); +my @payments = GetPayments( $booksellerid, $code, $chequeno); +my $count_payments = @payments; +my @loop_received = (); + +for (my $i = 0 ; $i < $count_payments ; $i++) { + my %line; + %line = %{ $payments[$i] }; + $line{booksellerid} = $booksellerid; + $line{chequedate} = format_date($line{chequedate}); + push @loop_received, \%line; + +} + +if ($count_payments) { + $template->param( searchresults => \@loop_received, count => $count_payments, ); +} +$template->param( + chequeno => $chequeno, + name => $bookseller->{'name'}, + datereceived_today => C4::Dates->new()->output(), + booksellerid => $booksellerid, +); + +output_html_with_http_headers $input, $cookie, $template->output; + + diff --git a/acqui/payments.pl b/acqui/payments.pl new file mode 100755 index 0000000..d5fe4de --- /dev/null +++ b/acqui/payments.pl @@ -0,0 +1,110 @@ +#!/usr/bin/perl + +#script to Payment Capture against vendor +#written by amit.gupta at osslabs.biz 09/06/2012 + +# Copyright 2012 Nucsoft Osslabs +# +# 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 2 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +=head1 NAME + +payments.pl + +This script is used to capture payments against vendor. + +=cut + +use strict; +use warnings; +use C4::Auth; +use C4::Acquisition; +use C4::Bookseller qw/ GetBookSellerFromId /; +use CGI; +use C4::Output; +use C4::Dates qw/format_date format_date_in_iso/; + + +my $input=new CGI; +my $booksellerid=$input->param('booksellerid'); +my $bookseller=GetBookSellerFromId($booksellerid); +my $chequeno=$input->param('chequeno') || ''; +my $notes=$input->param('notes') || ''; +my $op = $input->param('op'); + +my $datereceived = ($input->param('op') eq 'new') ? C4::Dates->new($input->param('datereceived')) : C4::Dates->new($input->param('datereceived'), 'iso') ; +$datereceived = C4::Dates->new() unless $datereceived; + +my ($template, $loggedinuser, $cookie) + = get_template_and_user({template_name => "acqui/payments.tmpl", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => {acquisition => 'order_receive'}, + debug => 1, +}); + +my @parcelitems = GetPayments($booksellerid); +my $countlines = scalar @parcelitems; +my @loop_received = (); + +for (my $i = 0 ; $i < $countlines ; $i++) { + my %line; + %line = %{ $parcelitems[$i] }; + $line{booksellerid} = $booksellerid; + $line{chequedate} = format_date($line{chequedate}); + push @loop_received, \%line; + +} + +my $pendingpayments = GetPendingpayments($booksellerid); +my $countpendings = scalar @$pendingpayments; + + +my @loop_orders = (); +for (my $i = 0 ; $i < $countpendings ; $i++) { + my %line; + %line = %{$pendingpayments->[$i]}; + $line{datereceived} = format_date($line{datereceived}); + push @loop_orders, \%line; +} + + +if ($op eq "saveall"){ + my @booksellerinvoicenumber = $input->param( 'booksellerinvoicenumber'); + my $chequedate = $input->param('date'); + foreach my $invoiceno(@booksellerinvoicenumber){ + next unless $invoiceno; + AddPayments( $invoiceno, $chequeno,$chequedate,$notes); + } + my $date = format_date($chequedate); + print $input->redirect("payments.pl?booksellerid=$booksellerid&op=new¬es=$notes&chequeno=$chequeno&datereceived=$date"); +} + + +$template->param( + chequeno => $chequeno, + notes => $notes, + datereceived => $datereceived->output('iso'), + formatteddatereceived => $datereceived->output(), + booksellerid => $booksellerid, + name => $bookseller->{'name'}, + loop_received => \@loop_received, + loop_orders => \@loop_orders, + +); +output_html_with_http_headers $input, $cookie, $template->output; + diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 54498c3..0ddd0fb 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -2846,6 +2846,19 @@ CREATE TABLE `quotes` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- +-- Table structure for table `aqpayments` +-- + +DROP TABLE IF EXISTS aqpayments; +CREATE TABLE `aqpayments` ( + `booksellerinvoicenumber` mediumtext, + `chequeno` varchar(80) default NULL, + `chequedate` date default NULL, + `notes` varchar(80) default NULL, + `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index 62b4372..cfc52ee 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -5343,6 +5343,19 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { SetVersion($DBversion); } +$DBversion ="3.09.00.XXX"; +if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { + $dbh->do("CREATE TABLE `aqpayments` ( + `booksellerinvoicenumber` mediumtext, + `chequeno` varchar(80) default NULL, + `chequedate` date default NULL, + `notes` varchar(80) default NULL, + `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP + ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + print "Upgrade to $DBversion done (New table structure for aqpayments)\n"; + SetVersion ($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-toolbar.inc index 11d7b39..5e2d542 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-toolbar.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-toolbar.inc @@ -26,6 +26,7 @@ { text: _("New basket"), url: "/cgi-bin/koha/acqui/basketheader.pl?booksellerid=[% booksellerid %]&op=add_form"}, { text: _("Baskets"), url: "/cgi-bin/koha/acqui/booksellers.pl?booksellerid=[% booksellerid %]"}, { text: _("Basket groups"), url: "/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=[% booksellerid %]"}, + { text: _("Payment"), url: "/cgi-bin/koha/acqui/payment.pl?booksellerid=[% booksellerid %]"}, [% END %] { text: _("Receive shipments"), url: "/cgi-bin/koha/acqui/parcels.pl?booksellerid=[% booksellerid %]" }, [% IF ( basketno ) %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt index 4077b5d..bc6ea77 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt @@ -81,6 +81,7 @@ $(document).ready(function() { [% END %] [% END %] +
    [% IF ( supplier.loop_basket.size ) %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/payment.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/payment.tt new file mode 100644 index 0000000..c4a20f8 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/payment.tt @@ -0,0 +1,105 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Acquisitions › Payments Details for vendor [% name %] +[% INCLUDE 'doc-head-close.inc' %] +[% INCLUDE 'calendar.inc' %] + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'acquisitions-search.inc' %] + + + +[% IF ( count ) %]
    [% ELSE %]
    [% END %] + +
    +
    +
    + +

    Payments Details for vendor [% name %]

    + +[% IF ( count ) %] + +
    + + + + + + + + + +[% FOREACH searchresult IN searchresults %] +[% UNLESS ( loop.odd ) %] + + [% ELSE %] + + [% END %] + + + + +[% END %] +
    Transaction DateInvoice numberChq No./DD No.
    [% searchresult.chequedate %][% searchresult.booksellerinvoicenumber %][% searchresult.chequeno %]
    +
    +[% END %] +
    + +
    + Payment Details +
    1. + + + + +
    2. +
    3. + + +
    4. +
    5. + + Show Calendar + +
      [% INCLUDE 'date-format.inc' %]
    6. +
    +
    +
    Cancel
    + +
    +
    +
    +
    +[% IF ( count ) %]
    +
    +

    Filter

    +
      +
    1. +
    2. +
    3. +

    4. +
    5. +
    +
    Clear
    +
    +
    [% END %] +
    +
    +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/payments.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/payments.tt new file mode 100644 index 0000000..836602e --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/payments.tt @@ -0,0 +1,128 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Acquisitions › [% IF ( date ) %] + Receipt summary for [% name %] [% IF ( chequeno ) %]invoice [% chequeno %][% END %] on [% formatteddatereceived %][% ELSE %]Receive orders from [% name %][% END %] +[% INCLUDE 'doc-head-close.inc' %] +[% INCLUDE 'greybox.inc' %] + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'acquisitions-search.inc' %] + + + +
    +
    +
    +
    + +
    +

    Chq No./DD No: [% chequeno %] Received by: [% loggedinusername %] Transaction Date: [% formatteddatereceived %]

    +
    + +
    +

    Already Paid

    + [% IF ( loop_received ) %] +
    + + + + + + + + + + + [% FOREACH loop_receive IN loop_received %] + [% UNLESS ( loop.odd ) %] + + [% ELSE %] + + [% END %] + + + + + [% END %] + +
    Invoice NumberChq No./DD No Transaction DateNotes
    [% loop_receive.booksellerinvoicenumber %] + [% loop_receive.chequeno %][% loop_receive.chequedate %][% loop_receive.notes %]
    +
    + [% ELSE %]There are no received payments.[% END %] +
    + +
    + +
    + +
    +
    + +
    +
    +
    +[% INCLUDE 'acquisitions-menu.inc' %] +
    +
    +[% INCLUDE 'intranet-bottom.inc' %] + -- 1.6.4.2 From colin.campbell at ptfs-europe.com Mon Jun 11 12:47:03 2012 From: colin.campbell at ptfs-europe.com (Colin Campbell) Date: Mon, 11 Jun 2012 11:47:03 +0100 Subject: [Koha-patches] [PATCH] Bug 8227 Fix deprecated construct compile time warning in Serials Message-ID: <1339411623-14335-1-git-send-email-colin.campbell@ptfs-europe.com> The perl parser no longer fools itself into sometimes thinking qw( ... ) is a ( qw( ... )) this adds the required parentheses for the foreach expression silencing the compile time warning --- C4/Serials.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/C4/Serials.pm b/C4/Serials.pm index 07f0948..acd48b1 100644 --- a/C4/Serials.pm +++ b/C4/Serials.pm @@ -601,7 +601,7 @@ sub GetSubscriptions { my @sqlstrings; my @strings_to_search; @strings_to_search = map { "$_" } split( / /, $ean ); - foreach my $index qw(biblioitems.ean) { + foreach my $index ( qw(biblioitems.ean) ) { push @bind_params, @strings_to_search; my $tmpstring = "OR $index = ? " x scalar(@strings_to_search); $debug && warn "$tmpstring"; -- 1.7.11.rc0 From adrien.saurat at biblibre.com Mon Jun 11 15:49:57 2012 From: adrien.saurat at biblibre.com (Adrien Saurat) Date: Mon, 11 Jun 2012 14:49:57 +0100 Subject: [Koha-patches] [PATCH] Bug 8231: reminder when checking in for a restricted patron Message-ID: <1339422597-13348-1-git-send-email-adrien.saurat@biblibre.com> From: Lyon3 Team If a patron is restricted, a warning will appear on the return page when checking in. --- C4/Circulation.pm | 6 +++++- circ/returns.pl | 4 ++++ .../intranet-tmpl/prog/en/modules/circ/returns.tt | 3 +++ 3 files changed, 12 insertions(+), 1 deletions(-) diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 9b523e3..74398d6 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -1677,7 +1677,11 @@ sub AddReturn { # fix fine days my $debardate = _FixFineDaysOnReturn( $borrower, $item, $issue->{date_due} ); - $messages->{'Debarred'} = $debardate if ($debardate); + if ($debardate) { + $messages->{'Debarred'} = $debardate; + } elsif ($borrower->{'debarred'}) { + $messages->{'PrevDebarred'} = $borrower->{'debarred'}; + } } # find reserves..... diff --git a/circ/returns.pl b/circ/returns.pl index bd60d42..17b43b2 100755 --- a/circ/returns.pl +++ b/circ/returns.pl @@ -46,6 +46,7 @@ use C4::Koha; # FIXME : is it still useful ? use C4::RotatingCollections; use Koha::DateUtils; use Koha::Calendar; +use C4::Dates qw/format_date/; my $query = new CGI; @@ -470,6 +471,9 @@ foreach my $code ( keys %$messages ) { $err{debarborrowernumber} = $borrower->{borrowernumber}; $err{debarname} = "$borrower->{firstname} $borrower->{surname}"; } + elsif ( $code eq 'PrevDebarred' ) { + $err{prevdebarred} = format_date( $messages->{'PrevDebarred'} ); + } else { die "Unknown error code $code"; # note we need all the (empty) elsif's above, or we die. # This forces the issue of staying in sync w/ Circulation.pm diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt index 835724f..fded74c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt @@ -338,6 +338,9 @@ $(document).ready(function () { [% IF ( errmsgloo.debarred ) %]

    [% errmsgloo.debarname %]([% errmsgloo.debarcardnumber %]) is now debarred until [% errmsgloo.debarred | $KohaDates %]

    [% END %] + [% IF ( errmsgloo.prevdebarred ) %] +

    REMINDER: Patron is restricted until [% errmsgloo.prevdebarred %]

    + [% END %] [% END %] [% IF ( soundon ) %] -- 1.7.4.1 From dpavlin at rot13.org Mon Jun 11 16:56:01 2012 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Mon, 11 Jun 2012 16:56:01 +0200 Subject: [Koha-patches] [PATCH] Bug 7844 - plack intranet tooling for developers Message-ID: <1339426561-24907-1-git-send-email-dpavlin@rot13.org> koha.psgi example and plackup.sh script to run any Koha site intranet or opac interface under plack with optional multi-process Starman server plackup.sh site-name [intranet] site-name is used to find config /etc/koha/sites/site-name/koha-conf.xml All configuration is specified in koha.psgi, which you are welcomed to edit and tune according to your development needs (enable memcache, enable/disable debugging modules for plack and so on). For deployment of opac or intranet you would probably want to take a look in plackup.sh and enable starman as web server (which is pre-forking server written in perl) and put some web server in front of it to serve static web files (e.g. ngnix, apache) When you are happy with it, rename koha.psgi and plackup.sh it to site name and save it for safe-keeping. This version does not have mapping to / of opac or intranet, so you need to use full URLs to pages as specified in test scenario. This will be fixed when we are ready to deploy plack, but for now it's clear indication that this is intended for developers which know what to do anyway. This commit message is included in patch as README.plack because it includes useful information for people using plack for first time. Test scenario: 1. install plack and dependencies, as documented at http://wiki.koha-community.org/wiki/Plack 2. start ./plackup.sh sitename i[ntranet] 3. open intranet page http://localhost:5001/cgi-bin/koha/mainpage.pl and verify that it works 4. start ./plackup.sh sitename 5. open OPAC http://localhost:5000/cgi-bin/koha/opac-main.pl and verify that it works 6. next step is to take a look into koha.psgi and enable additional debug modules, save file and reload page (plackup will reload code automatically) --- misc/plack/README.plack | 48 +++++++++++++++++++++++++++ misc/plack/koha.psgi | 83 +++++++++++++++++++++++++++++++++++++++++++++++ misc/plack/plackup.sh | 54 ++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+), 0 deletions(-) create mode 100644 misc/plack/README.plack create mode 100644 misc/plack/koha.psgi create mode 100755 misc/plack/plackup.sh diff --git a/misc/plack/README.plack b/misc/plack/README.plack new file mode 100644 index 0000000..f539598 --- /dev/null +++ b/misc/plack/README.plack @@ -0,0 +1,48 @@ +Bug 7844 - plack intranet tooling for developers + +koha.psgi example and plackup.sh script to run any Koha site +intranet or opac interface under plack with optional multi-process +Starman server + + plackup.sh site-name [intranet] + +site-name is used to find config /etc/koha/sites/site-name/koha-conf.xml + +All configuration is specified in koha.psgi, which you are welcomed to edit +and tune according to your development needs (enable memcache, enable/disable +debugging modules for plack and so on). + +For deployment of opac or intranet you would probably want to take a look +in plackup.sh and enable starman as web server (which is pre-forking server +written in perl) and put some web server in front of it to serve static web +files (e.g. ngnix, apache) + +When you are happy with it, rename koha.psgi and plackup.sh it to site name +and save it for safe-keeping. + +This version does not have mapping to / of opac or intranet, so you need to +use full URLs to pages as specified in test scenario. This will be fixed when +we are ready to deploy plack, but for now it's clear indication that this +is intended for developers which know what to do anyway. + +This commit message is included in patch as README.plack because it includes +useful information for people using plack for first time. + +Test scenario: +1. install plack and dependencies, as documented at + http://wiki.koha-community.org/wiki/Plack + +2. start ./plackup.sh sitename i[ntranet] + +3. open intranet page http://localhost:5001/cgi-bin/koha/mainpage.pl + and verify that it works + +4. start ./plackup.sh sitename + +5. open OPAC http://localhost:5000/cgi-bin/koha/opac-main.pl + and verify that it works + +6. next step is to take a look into koha.psgi and enable additional + debug modules, save file and reload page (plackup will reload + code automatically) + diff --git a/misc/plack/koha.psgi b/misc/plack/koha.psgi new file mode 100644 index 0000000..904cc72 --- /dev/null +++ b/misc/plack/koha.psgi @@ -0,0 +1,83 @@ +#!/usr/bin/perl +use Plack::Builder; +use Plack::App::CGIBin; +use lib qw( ./lib ); +use Plack::Middleware::Debug; +use Plack::App::Directory; + +BEGIN { + +# override configuration from startup script below: +# (requires --reload option) + +$ENV{PLACK_DEBUG} = 1; # toggle debugging + +# memcache change requires restart +$ENV{MEMCACHED_SERVERS} = "localhost:11211"; +#$ENV{MEMCACHED_DEBUG} = 0; + +$ENV{PROFILE_PER_PAGE} = 1; # reset persistant and profile counters after each page, like CGI +#$ENV{INTRANET} = 1; # usually passed from script + +#$ENV{DBI_AUTOPROXY}='dbi:Gofer:transport=null;cache=DBI::Util::CacheMemory' + +} # BEGIN + +use C4::Context; +use C4::Languages; +use C4::Members; +use C4::Dates; +use C4::Boolean; +use C4::Letters; +use C4::Koha; +use C4::XSLT; +use C4::Branch; +use C4::Category; +=for preload +use C4::Tags; # FIXME +=cut + +use Devel::Size 0.77; # 0.71 doesn't work for Koha +my $watch_capture_regex = '(C4|Koha)'; + +sub watch_for_size { + my @watch = + map { s/^.*$watch_capture_regex/$1/; s/\//::/g; s/\.pm$//; $_ } # fix paths + grep { /$watch_capture_regex/ } + keys %INC + ; + warn "# watch_for_size ",join(' ', at watch); + return @watch; +}; + +my $CGI_ROOT = $ENV{INTRANET} ? $ENV{INTRANETDIR} : $ENV{OPACDIR}; +warn "# using Koha ", $ENV{INTRANET} ? 'intranet' : 'OPAC', " CGI from $CGI_ROOT\n"; +my $app=Plack::App::CGIBin->new(root => $CGI_ROOT); + +builder { + + # please don't use plugins which are under enable_if $ENV{PLACK_DEBUG} in production! + # they are known to leek memory + enable_if { $ENV{PLACK_DEBUG} } 'Debug', panels => [ + qw(Environment Response Timer Memory), + # optional plugins (uncomment to enable) are sorted according to performance implact +# [ 'Devel::Size', for => \&watch_for_size ], # https://github.com/dpavlin/p5-plack-devel-debug-devel-size +# [ 'DBIProfile', profile => 2 ], +# [ 'DBITrace', level => 1 ], # a LOT of fine-graded SQL trace +# [ 'Profiler::NYTProf', exclude => [qw(.*\.css .*\.png .*\.ico .*\.js .*\.gif)] ], + ]; + + # don't enable this plugin in production, since stack traces reveal too much information + # about system to potential attackers! + enable_if { $ENV{PLACK_DEBUG} } 'StackTrace'; + + # this enables plackup or starman to serve static files and provide working plack + # setup without need for front-end web server to serve static files + enable_if { $ENV{INTRANETDIR} } "Plack::Middleware::Static", + path => qr{^/(intranet|opac)-tmpl/}, + root => "$ENV{INTRANETDIR}/koha-tmpl/"; + + mount "/cgi-bin/koha" => $app; + +}; + diff --git a/misc/plack/plackup.sh b/misc/plack/plackup.sh new file mode 100755 index 0000000..9546bd7 --- /dev/null +++ b/misc/plack/plackup.sh @@ -0,0 +1,54 @@ +#!/bin/sh -xe + +# This is plack startup script for Koha + +# ./plackup.sh [site] [intranet] + +site=$1 +test ! -z "$site" && shift || site=srvgit # default + +# extract useful paths from koha-conf.xml +export KOHA_CONF=/etc/koha/sites/$site/koha-conf.xml +export LOGDIR="$( sudo -u $site-koha xmlstarlet sel -t -v 'yazgfs/config/logdir' $KOHA_CONF )" +export INTRANETDIR="$( sudo -u $site-koha xmlstarlet sel -t -v 'yazgfs/config/intranetdir' $KOHA_CONF )" +export OPACDIR="$( sudo -u $site-koha xmlstarlet sel -t -v 'yazgfs/config/opacdir' $KOHA_CONF | sed 's,/cgi-bin/opac,,' )" + +dir=`dirname $0` + +# enable memcache - it's safe even on installation which don't have it +# since Koha has check on C4::Context +#export MEMCACHED_SERVERS=localhost:11211 +# pass site name as namespace to perl code +export MEMCACHED_NAMESPACE=$site +#export MEMCACHED_DEBUG=1 + +if [ ! -e "$INTRANETDIR/C4" ] ; then + echo "intranetdir in $KOHA_CONF doesn't point to Koha git checkout" + exit 1 +fi + +if [ -z "$1" ] ; then # type anything after site name for intranet! + INTRANET=0 + PORT=5000 +else + INTRANET=1 + PORT=5001 + shift # pass rest of arguments to plackup +fi +export INTRANET # pass to plack + +# uncomment to enable logging +#opt="$opt --access-log $LOGDIR/opac-access.log --error-log $LOGDIR/opac-error.log" + +# --max-requests 50 decreased from 1000 to keep memory usage sane +# --workers 4 number of cores on machine +#test "$INTRANET" != 1 && \ # don't use Starman for intranet +opt="$opt --server Starman -M FindBin --max-requests 50 --workers 4" + +# -E deployment turn off access log on STDOUT +opt="$opt -E deployment" + +# comment out reload in production! +opt="$opt --reload -R $INTRANETDIR/C4 -R $INTRANETDIR/Koha" + +sudo -E -u $site-koha plackup --port $PORT -I $INTRANETDIR -I $INTRANETDIR/installer $opt $* $dir/koha.psgi -- 1.7.2.5 From adrien.saurat at biblibre.com Mon Jun 11 17:36:39 2012 From: adrien.saurat at biblibre.com (Adrien Saurat) Date: Mon, 11 Jun 2012 16:36:39 +0100 Subject: [Koha-patches] [PATCH] Bug 8236: prevent renewing if overdue or restriction Message-ID: <1339428999-17149-1-git-send-email-adrien.saurat@biblibre.com> From: Lyon3 Team --- C4/Circulation.pm | 8 ++++++++ .../prog/en/modules/circ/circulation.tt | 12 ++++++++++++ 2 files changed, 20 insertions(+), 0 deletions(-) diff --git a/C4/Circulation.pm b/C4/Circulation.pm index d4329a7..064cc57 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -2322,6 +2322,14 @@ sub CanBookBeRenewed { } } + my ( $blocktype, $count ) = C4::Members::IsMemberBlocked($borrowernumber); + if ( $blocktype == -1 && ! defined($override_limit) ) { + $renewokay=0; + $error="overdue"; + } elsif ( $blocktype == 1 && ! defined($override_limit) ) { + $renewokay=0; + $error="restriction"; + } return ($renewokay,$error); } diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt index 64ca686..2d1256c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -762,6 +762,12 @@ No patron matched [% message %] [% IF ( todayissue.renew_error_too_many ) %] Not renewable [% END %] + [% IF ( todayissue.renew_error_overdue ) %] + Overdues + [% END %] + [% IF ( todayissue.renew_error_restriction ) %] + Patron is restricted + [% END %] [% IF ( todayissue.can_confirm ) %] [% END %] @@ -837,6 +843,12 @@ No patron matched [% message %] [% IF ( previssue.renew_error_too_many ) %] Not renewable [% END %] + [% IF ( previssue.renew_error_overdue ) %] + Not Renewable (Overdue) + [% END %] + [% IF ( previssue.renew_error_restriction ) %] + Patron is restricted + [% END %] [% IF ( previssue.can_confirm ) %] [% END %] -- 1.7.4.1 From srdjan at catalyst.net.nz Tue Jun 12 04:23:08 2012 From: srdjan at catalyst.net.nz (Srdjan) Date: Tue, 12 Jun 2012 14:23:08 +1200 Subject: [Koha-patches] [PATCH] bug_5911: make perlcdritic happy, shut up warnings In-Reply-To: References: Message-ID: <1339467788-4153-1-git-send-email-srdjan@catalyst.net.nz> --- C4/HoldsQueue.pm | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/C4/HoldsQueue.pm b/C4/HoldsQueue.pm index fcb3c14..05095d8 100755 --- a/C4/HoldsQueue.pm +++ b/C4/HoldsQueue.pm @@ -564,11 +564,18 @@ sub debug { # warn @_; } +sub _trim { + return $_[0] unless $_[0]; + $_[0] =~ s/^\s+//; + $_[0] =~ s/\s+$//; + $_[0]; +} + sub load_branches_to_pull_from { my $static_branch_list = C4::Context->preference("StaticHoldsQueueWeight") or return; - my @branches_to_use = map { s/^\s+//; s/\s+$//; $_; } split /,/, $static_branch_list; + my @branches_to_use = map _trim($_), split /,/, $static_branch_list; @branches_to_use = shuffle(@branches_to_use) if C4::Context->preference("RandomizeHoldsQueueWeight"); @@ -590,6 +597,7 @@ sub least_cost_branch { next if $cell->{disable_transfer}; my $cost = $cell->{cost}; + next unless defined $cost; # XXX should this be reported? unless (defined $least_cost) { $least_cost = $cost; -- 1.7.9.5 From oleonard at myacpl.org Tue Jun 12 17:34:16 2012 From: oleonard at myacpl.org (Owen Leonard) Date: Tue, 12 Jun 2012 11:34:16 -0400 Subject: [Koha-patches] [PATCH] Bug 8241 - Remove stray references to YUI autocomplete Message-ID: <1339515257-31479-1-git-send-email-oleonard@myacpl.org> - Removing unused references to YUI assets in authorities/auth_finder.tt - Removing unneeded call to autocomplete JS in help-top.inc and adding new jQuery dependencies. - Minor HTML markup corrections to auth-finder-search.inc discovered in debugging the patch. --- .../prog/en/includes/auth-finder-search.inc | 10 ++++------ .../intranet-tmpl/prog/en/includes/help-top.inc | 4 ++-- .../prog/en/modules/authorities/auth_finder.tt | 4 ---- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/auth-finder-search.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/auth-finder-search.inc index 81e410a..a6d55df 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/auth-finder-search.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/auth-finder-search.inc @@ -89,7 +89,6 @@ $(document).ready(function(){ -
    @@ -128,11 +127,11 @@ $(document).ready(function(){
  • - + - @@ -141,11 +140,11 @@ $(document).ready(function(){
  • - + - @@ -162,4 +161,3 @@ $(document).ready(function(){
  • Cancel
    -
    diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/help-top.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/help-top.inc index 13ec5cf..0c545a4 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/help-top.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/help-top.inc @@ -2,6 +2,7 @@ Online Help + [% IF ( intranetstylesheet ) %] @@ -9,7 +10,7 @@ [% END %] - + [% IF ( intranetcolorstylesheet ) %] @@ -17,7 +18,6 @@ [% END %] -[% IF ( CircAutocompl ) %] [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/auth_finder.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/auth_finder.tt index b67da76..b1d9971 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/auth_finder.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/auth_finder.tt @@ -4,10 +4,6 @@ - - - - -- 1.7.9.5 From oleonard at myacpl.org Tue Jun 12 18:55:59 2012 From: oleonard at myacpl.org (Owen Leonard) Date: Tue, 12 Jun 2012 12:55:59 -0400 Subject: [Koha-patches] [PATCH] Bug 8186 - Form structure problem in serials claims filter Message-ID: <1339520159-31919-1-git-send-email-oleonard@myacpl.org> Correcting form markup so that form fields and buttons are properly spaced. --- .../prog/en/modules/serials/claims.tt | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/claims.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/claims.tt index 399c933..cbf11b2 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/claims.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/claims.tt @@ -192,9 +192,8 @@ - [% IF ( missingissues ) %] -

    Missing issues

    -
    + [% IF ( missingissues ) %] +
    Filters : @@ -214,6 +213,8 @@
  • +
  • +
  • - -
  • - -
  • -
    +
    + + +
    +
    - +
    - + Missing issues @@ -328,8 +328,8 @@ [% END %] - + [% END %] [% ELSE %] -- 1.7.9.5 From oleonard at myacpl.org Wed Jun 13 16:12:11 2012 From: oleonard at myacpl.org (Owen Leonard) Date: Wed, 13 Jun 2012 10:12:11 -0400 Subject: [Koha-patches] Bug 8181 - Replace DynArch calendar widget with jQueryUI version Message-ID: Patch has long lines, so it's attached. -- Owen -- Web Developer Athens County Public Libraries http://www.myacpl.org -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-Bug-8181-Replace-DynArch-calendar-widget-with-jQuery.patch Type: application/octet-stream Size: 644029 bytes Desc: not available URL: From jcamins at cpbibliography.com Thu Jun 14 00:01:30 2012 From: jcamins at cpbibliography.com (Jared Camins-Esakov) Date: Wed, 13 Jun 2012 18:01:30 -0400 Subject: [Koha-patches] =?utf-8?q?=5BPATCH=5D_Bug_7943=3A_Authority_search?= =?utf-8?q?_results_are_untranslatable?= Message-ID: <1339624890-2715-1-git-send-email-jcamins@cpbibliography.com> The HTML for authority search results was previously generated in C4::AuthoritiesMarc::BuildSummary, which meant that it couldn't be translated. This patch moves the HTML generation into the templates by introducing a new authorities-search-results.inc include file for both the OPAC and the Intranet which contains a Template::Toolkit BLOCK for rendering the authority results. Fixes the authority autocomplete by removing the untranslatable strings, and returning only data from the database. To test: 1. Apply patch. 2. Test authority searching in the authority module in the staff client 3. Test authority searching in the authority control plugin in the cataloguing module (and the plugin for UNIMARC field 210$c, if you can figure out how) 4. Test authority searching in the OPAC --- C4/Auth.pm | 5 +- C4/AuthoritiesMarc.pm | 335 ++++++++++---------- authorities/ysearch.pl | 15 +- cataloguing/addbiblio.pl | 1 - .../intranet-tmpl/prog/en/css/staff-global.css | 9 + .../en/includes/authorities-search-results.inc | 60 ++++ .../modules/authorities/searchresultlist-auth.tt | 3 +- .../en/modules/authorities/searchresultlist.tt | 3 +- .../value_builder/unimarc_field_210c.tt | 3 +- koha-tmpl/opac-tmpl/prog/en/css/opac.css | 9 + .../en/includes/authorities-search-results.inc | 60 ++++ .../prog/en/modules/opac-auth-MARCdetail.tt | 87 +++++ .../prog/en/modules/opac-authoritiesdetail.tt | 85 ----- .../en/modules/opac-authoritiessearchresultlist.tt | 8 +- opac/opac-authoritiesdetail.pl | 29 +- 15 files changed, 426 insertions(+), 286 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/authorities-search-results.inc create mode 100644 koha-tmpl/opac-tmpl/prog/en/includes/authorities-search-results.inc create mode 100644 koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-MARCdetail.tt delete mode 100644 koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiesdetail.tt diff --git a/C4/Auth.pm b/C4/Auth.pm index c97046a..66e70bd 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -315,7 +315,7 @@ sub get_template_and_user { "BiblioDefaultView".C4::Context->preference("BiblioDefaultView") => 1, EnhancedMessagingPreferences => C4::Context->preference('EnhancedMessagingPreferences'), GoogleJackets => C4::Context->preference("GoogleJackets"), - OpenLibraryCovers => C4::Context->preference("OpenLibraryCovers"), + OpenLibraryCovers => C4::Context->preference("OpenLibraryCovers"), KohaAdminEmailAddress => "" . C4::Context->preference("KohaAdminEmailAddress"), LoginBranchcode => (C4::Context->userenv?C4::Context->userenv->{"branch"}:"insecure"), LoginFirstname => (C4::Context->userenv?C4::Context->userenv->{"firstname"}:"Bel"), @@ -328,7 +328,8 @@ sub get_template_and_user { XSLTDetailsDisplay => C4::Context->preference("XSLTDetailsDisplay"), XSLTResultsDisplay => C4::Context->preference("XSLTResultsDisplay"), using_https => $in->{'query'}->https() ? 1 : 0, - noItemTypeImages => C4::Context->preference("noItemTypeImages"), + noItemTypeImages => C4::Context->preference("noItemTypeImages"), + marcflavour => C4::Context->preference("marcflavour"), ); if ( $in->{'type'} eq "intranet" ) { diff --git a/C4/AuthoritiesMarc.pm b/C4/AuthoritiesMarc.pm index 5ea5098..c92c319 100644 --- a/C4/AuthoritiesMarc.pm +++ b/C4/AuthoritiesMarc.pm @@ -46,12 +46,12 @@ BEGIN { &DelAuthority &GetAuthority &GetAuthorityXML - + &CountUsage &CountUsageChildren &SearchAuthorities - &BuildSummary + &BuildSummary &BuildUnimarcHierarchies &BuildUnimarcHierarchy @@ -926,9 +926,9 @@ sub FindDuplicateAuthority { =head2 BuildSummary - $text= &BuildSummary( $record, $authid, $authtypecode) + $summary= &BuildSummary( $record, $authid, $authtypecode) -return HTML encoded Summary +Returns a hashref with a summary of the specified record. Comment : authtypecode can be infered from both record and authid. Moreover, authid can also be inferred from $record. @@ -936,171 +936,176 @@ Would it be interesting to delete those things. =cut -sub BuildSummary{ -## give this a Marc record to return summary - my ($record,$authid,$authtypecode)=@_; - my $dbh=C4::Context->dbh; - my $summary; - # handle $authtypecode is NULL or eq "" - if ($authtypecode) { - my $authref = GetAuthType($authtypecode); - $summary = $authref->{summary}; - } - # FIXME: should use I18N.pm - my %language; - $language{'fre'}="Fran?ais"; - $language{'eng'}="Anglais"; - $language{'ger'}="Allemand"; - $language{'ita'}="Italien"; - $language{'spa'}="Espagnol"; - my %thesaurus; - $thesaurus{'1'}="Peuples"; - $thesaurus{'2'}="Anthroponymes"; - $thesaurus{'3'}="Oeuvres"; - $thesaurus{'4'}="Chronologie"; - $thesaurus{'5'}="Lieux"; - $thesaurus{'6'}="Sujets"; - #thesaurus a remplir - my @fields = $record->fields(); - my $reported_tag; - # if the library has a summary defined, use it. Otherwise, build a standard one - # FIXME - it appears that the summary field in the authority frameworks - # can work as a display template. However, this doesn't - # suit the MARC21 version, so for now the "templating" - # feature will be enabled only for UNIMARC for backwards - # compatibility. - if ($summary and C4::Context->preference('marcflavour') eq 'UNIMARC') { - my @fields = $record->fields(); - # $reported_tag = '$9'.$result[$counter]; - my @stringssummary; - foreach my $field (@fields) { - my $tag = $field->tag(); - my $tagvalue = $field->as_string(); - my $localsummary= $summary; - $localsummary =~ s/\[(.?.?.?.?)$tag\*(.*?)\]/$1$tagvalue$2\[$1$tag$2\]/g; - if ($tag<10) { - if ($tag eq '001') { - $reported_tag.='$3'.$field->data(); - } - } else { - my @subf = $field->subfields; - for my $i (0..$#subf) { - my $subfieldcode = $subf[$i][0]; - my $subfieldvalue = $subf[$i][1]; - my $tagsubf = $tag.$subfieldcode; - $localsummary =~ s/\[(.?.?.?.?)$tagsubf(.*?)\]/$1$subfieldvalue$2\[$1$tagsubf$2\]/g; - } - } - push @stringssummary, $localsummary if ($localsummary ne $summary); +sub BuildSummary { + ## give this a Marc record to return summary + my ($record,$authid,$authtypecode)=@_; + my $dbh=C4::Context->dbh; + my %summary; + # handle $authtypecode is NULL or eq "" + if ($authtypecode) { + my $authref = GetAuthType($authtypecode); + $summary{authtypecode} = $authref->{authtypecode}; + $summary{type} = $authref->{authtypetext}; + $summary{summary} = $authref->{summary}; } - my $resultstring; - $resultstring = join(" -- ", at stringssummary); - $resultstring =~ s/\[(.*?)\]//g; - $resultstring =~ s/\n//g; - $summary = $resultstring; - } else { - my $heading = ''; - my $altheading = ''; - my $seealso = ''; - my $broaderterms = ''; - my $narrowerterms = ''; - my $see = ''; - my $seeheading = ''; - my $notes = ''; + my $marc21subfields = 'abcdfghjklmnopqrstuvxyz'; + my %marc21controlrefs = ( 'a' => 'earlier', + 'b' => 'later', + 'd' => 'acronym', + 'f' => 'musical', + 'g' => 'broader', + 'h' => 'narrower', + 'i' => 'subfi', + 't' => 'parent' + ); + my %thesaurus; + $thesaurus{'1'}="Peuples"; + $thesaurus{'2'}="Anthroponymes"; + $thesaurus{'3'}="Oeuvres"; + $thesaurus{'4'}="Chronologie"; + $thesaurus{'5'}="Lieux"; + $thesaurus{'6'}="Sujets"; + #thesaurus a remplir my @fields = $record->fields(); - if (C4::Context->preference('marcflavour') eq 'UNIMARC') { - # construct UNIMARC summary, that is quite different from MARC21 one - # accepted form - foreach my $field ($record->field('2..')) { - $heading.= $field->as_string('abcdefghijlmnopqrstuvwxyz'); - } - # rejected form(s) - foreach my $field ($record->field('3..')) { - $notes.= ''.$field->subfield('a')."\n"; - } - foreach my $field ($record->field('4..')) { - if ($field->subfield('2')) { - my $thesaurus = "thes. : ".$thesaurus{"$field->subfield('2')"}." : "; - $see.= ''.$thesaurus.$field->as_string('abcdefghijlmnopqrstuvwxyz')." -- \n"; + my $reported_tag; +# if the library has a summary defined, use it. Otherwise, build a standard one +# FIXME - it appears that the summary field in the authority frameworks +# can work as a display template. However, this doesn't +# suit the MARC21 version, so for now the "templating" +# feature will be enabled only for UNIMARC for backwards +# compatibility. + if ($summary{summary} and C4::Context->preference('marcflavour') eq 'UNIMARC') { + my @fields = $record->fields(); +# $reported_tag = '$9'.$result[$counter]; + my @stringssummary; + foreach my $field (@fields) { + my $tag = $field->tag(); + my $tagvalue = $field->as_string(); + my $localsummary= $summary{summary}; + $localsummary =~ s/\[(.?.?.?.?)$tag\*(.*?)\]/$1$tagvalue$2\[$1$tag$2\]/g; + if ($tag<10) { + if ($tag eq '001') { + $reported_tag.='$3'.$field->data(); + } + } else { + my @subf = $field->subfields; + for my $i (0..$#subf) { + my $subfieldcode = $subf[$i][0]; + my $subfieldvalue = $subf[$i][1]; + my $tagsubf = $tag.$subfieldcode; + $localsummary =~ s/\[(.?.?.?.?)$tagsubf(.*?)\]/$1$subfieldvalue$2\[$1$tagsubf$2\]/g; + } + } + push @stringssummary, $localsummary if ($localsummary ne $summary{summary}); } - } - # see : - foreach my $field ($record->field('5..')) { - - if (($field->subfield('5')) && ($field->subfield('a')) && ($field->subfield('5') eq 'g')) { - $broaderterms.= ' '.$field->as_string('abcdefgjxyz')." -- \n"; - } elsif (($field->subfield('5')) && ($field->as_string) && ($field->subfield('5') eq 'h')){ - $narrowerterms.= ''.$field->as_string('abcdefgjxyz')." -- \n"; - } elsif ($field->subfield('a')) { - $seealso.= ''.$field->as_string('abcdefgxyz')." -- \n"; + my $resultstring; + $resultstring = join(" -- ", at stringssummary); + $resultstring =~ s/\[(.*?)\]//g; + $resultstring =~ s/\n/
    /g; + $summary{summary} = $resultstring; + } else { + my @authorized; + my @notes; + my @seefrom; + my @seealso; + my @otherscript; + my @fields = $record->fields(); + if (C4::Context->preference('marcflavour') eq 'UNIMARC') { +# construct UNIMARC summary, that is quite different from MARC21 one +# accepted form + foreach my $field ($record->field('2..')) { + push @authorized, $field->as_string('abcdefghijlmnopqrstuvwxyz'); + } +# rejected form(s) + foreach my $field ($record->field('3..')) { + push @notes, $field->subfield('a'); + } + foreach my $field ($record->field('4..')) { + my $thesaurus = $field->subfield('2') ? "thes. : ".$thesaurus{"$field->subfield('2')"}." : " : ''; + push @seefrom, { heading => $thesaurus . $field->as_string('abcdefghijlmnopqrstuvwxyz'), type => 'seefrom' }; + } +# see : + foreach my $field ($record->field('5..')) { + if (($field->subfield('5')) && ($field->subfield('a')) && ($field->subfield('5') eq 'g')) { + push @seealso, { $field->as_string('abcdefgjxyz'), type => 'broader' }; + } elsif (($field->subfield('5')) && ($field->as_string) && ($field->subfield('5') eq 'h')){ + push @seealso, { heading => $field->as_string('abcdefgjxyz'), type => 'narrower' }; + } elsif ($field->subfield('a')) { + push @seealso, { heading => $field->as_string('abcdefgxyz'), type => 'seealso' }; + } + } +# // form + foreach my $field ($record->field('7..')) { + my $lang = substr($field->subfield('8'),3,3); + push @otherscript, { lang => $lang, term => $field->subfield('a') }; + } + } else { +# construct MARC21 summary +# FIXME - looping over 1XX is questionable +# since MARC21 authority should have only one 1XX + foreach my $field ($record->field('1..')) { + my $tag = $field->tag(); + next if "152" eq $tag; +# FIXME - 152 is not a good tag to use +# in MARC21 -- purely local tags really ought to be +# 9XX + if ($tag eq '100') { + push @authorized, $field->as_string('abcdefghjklmnopqrstvxyz68'); + } elsif ($tag eq '110') { + push @authorized, $field->as_string('abcdefghklmnoprstvxyz68'); + } elsif ($tag eq '111') { + push @authorized, $field->as_string('acdefghklnpqstvxyz68'); + } elsif ($tag eq '130') { + push @authorized, $field->as_string('adfghklmnoprstvxyz68'); + } elsif ($tag eq '148') { + push @authorized, $field->as_string('abvxyz68'); + } elsif ($tag eq '150') { + push @authorized, $field->as_string('abvxyz68'); + } elsif ($tag eq '151') { + push @authorized, $field->as_string('avxyz68'); + } elsif ($tag eq '155') { + push @authorized, $field->as_string('abvxyz68'); + } elsif ($tag eq '180') { + push @authorized, $field->as_string('vxyz68'); + } elsif ($tag eq '181') { + push @authorized, $field->as_string('vxyz68'); + } elsif ($tag eq '182') { + push @authorized, $field->as_string('vxyz68'); + } elsif ($tag eq '185') { + push @authorized, $field->as_string('vxyz68'); + } else { + push @authorized, $field->as_string(); + } + } #See From + foreach my $field ($record->field('4..')) { + my $type = 'seefrom'; + $type = $marc21controlrefs{substr $field->subfield('w'), '0'} if ($field->subfield('w')); + if ($type eq 'subfi') { + push @seefrom, { heading => $field->as_string($marc21subfields), type => $field->subfield('i') }; + } else { + push @seefrom, { heading => $field->as_string($marc21subfields), type => $type }; + } + } #See Also + foreach my $field ($record->field('5..')) { + my $type = 'seealso'; + $type = $marc21controlrefs{substr $field->subfield('w'), '0'} if ($field->subfield('w')); + if ($type eq 'subfi') { + push @seealso, { heading => $field->as_string($marc21subfields), type => $field->subfield('i') }; + } else { + push @seealso, { heading => $field->as_string($marc21subfields), type => $type }; + } + } + foreach my $field ($record->field('6..')) { + push @notes, $field->as_string(); + } } - } - # // form - foreach my $field ($record->field('7..')) { - my $lang = substr($field->subfield('8'),3,3); - $seeheading.= ' En '.$language{$lang}.' : '.$field->subfield('a')."
    \n"; - } - $broaderterms =~s/-- \n$//; - $narrowerterms =~s/-- \n$//; - $seealso =~s/-- \n$//; - $see =~s/-- \n$//; - $summary = $heading."
    ".($notes?"$notes
    ":""); - $summary.= '

    TG : '.$broaderterms.'

    ' if ($broaderterms); - $summary.= '

    TS : '.$narrowerterms.'

    ' if ($narrowerterms); - $summary.= '

    TA : '.$seealso.'

    ' if ($seealso); - $summary.= '

    EP : '.$see.'

    ' if ($see); - $summary.= '

    '.$seeheading.'

    ' if ($seeheading); - } else { - # construct MARC21 summary - # FIXME - looping over 1XX is questionable - # since MARC21 authority should have only one 1XX - foreach my $field ($record->field('1..')) { - next if "152" eq $field->tag(); # FIXME - 152 is not a good tag to use - # in MARC21 -- purely local tags really ought to be - # 9XX - if ($record->field('100')) { - $heading.= $field->as_string('abcdefghjklmnopqrstvxyz68'); - } elsif ($record->field('110')) { - $heading.= $field->as_string('abcdefghklmnoprstvxyz68'); - } elsif ($record->field('111')) { - $heading.= $field->as_string('acdefghklnpqstvxyz68'); - } elsif ($record->field('130')) { - $heading.= $field->as_string('adfghklmnoprstvxyz68'); - } elsif ($record->field('148')) { - $heading.= $field->as_string('abvxyz68'); - } elsif ($record->field('150')) { - $heading.= $field->as_string('abvxyz68'); - #$heading.= $field->as_formatted(); - my $tag=$field->tag(); - $heading=~s /^$tag//g; - $heading =~s /\_/\$/g; - } elsif ($record->field('151')) { - $heading.= $field->as_string('avxyz68'); - } elsif ($record->field('155')) { - $heading.= $field->as_string('abvxyz68'); - } elsif ($record->field('180')) { - $heading.= $field->as_string('vxyz68'); - } elsif ($record->field('181')) { - $heading.= $field->as_string('vxyz68'); - } elsif ($record->field('182')) { - $heading.= $field->as_string('vxyz68'); - } elsif ($record->field('185')) { - $heading.= $field->as_string('vxyz68'); - } else { - $heading.= $field->as_string(); - } - } #See From - foreach my $field ($record->field('4..')) { - $seeheading.= "
          used for/see from: ".$field->as_string(); - } #See Also - foreach my $field ($record->field('5..')) { - $altheading.= "
          see also: ".$field->as_string(); - } - $summary .= ": " if $summary; - $summary.=$heading.$seeheading.$altheading; - } - } - return $summary; + $summary{authorized} = \@authorized; + $summary{notes} = \@notes; + $summary{seefrom} = \@seefrom; + $summary{seealso} = \@seealso; + $summary{otherscript} = \@otherscript; + } + return \%summary; } =head2 BuildUnimarcHierarchies diff --git a/authorities/ysearch.pl b/authorities/ysearch.pl index 1f7e5ef..c9e7c47 100755 --- a/authorities/ysearch.pl +++ b/authorities/ysearch.pl @@ -66,14 +66,15 @@ if ( $auth_status ne "ok" ) { print "["; my $i = 0; - foreach (@$results) { + foreach my $result (@$results) { if($i > 0){ print ","; } - my ($value) = $_->{'summary'}; - # Removes new lines - $value =~ s/
    / /g; - $value =~ s/\n//g; - $value = "{\"summary\":\"" . $value . "\"" . "}"; + my $value = ''; + my $authorized = $result->{'summary'}->{authorized}; + foreach my $heading (@$authorized) { + $value .= $heading . ' '; + } + $value = "{\"summary\":\"" . $value . "\"" . "}"; print nsb_clean($value) . "\n"; $i++; } -print "]"; \ No newline at end of file +print "]"; diff --git a/cataloguing/addbiblio.pl b/cataloguing/addbiblio.pl index d5778a4..643fc53 100755 --- a/cataloguing/addbiblio.pl +++ b/cataloguing/addbiblio.pl @@ -984,7 +984,6 @@ $template->param( frameworkcode => $frameworkcode, itemtype => $frameworkcode, borrowernumber => $loggedinuser, - marcflavour => C4::Context->preference("marcflavour"), ); output_html_with_http_headers $input, $cookie, $template->output; 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 555005b..7513a6f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css @@ -2364,3 +2364,12 @@ ul.ui-tabs-nav li { #header_search .ui-corner-top { border-radius: 0 0 4px 4px; } + + +.authref { + text-indent: 2em; +} + +.authref .label { + font-style: italic; +} diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/authorities-search-results.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/authorities-search-results.inc new file mode 100644 index 0000000..44ea78c --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/authorities-search-results.inc @@ -0,0 +1,60 @@ +[% BLOCK showreference %] + [% IF marcflavour == 'UNIMARC' %] + [% SWITCH type %] + [% CASE 'broader' %] + [% heading %] -- + [% CASE 'narrower' %] + [% heading %] -- + [% CASE 'narrower' %] + [% heading %] -- + [% CASE 'seefrom' %] + [% heading %] -- + [% CASE 'seealso' %] + [% heading %] -- + [% END %] + [% ELSE %] + [% IF ( label ) %][% label %][% END %] + [% heading %] + [% UNLESS ( type=='seefrom' || type=='seealso' ) %][% SWITCH type %] + [% CASE 'earlier' %](Earlier heading) + [% CASE 'later' %](Later heading) + [% CASE 'acronym' %](Acronym) + [% CASE 'musical' %](Musical composition) + [% CASE 'broader' %](Broader heading) + [% CASE 'narrower' %](Narrower heading) + [% CASE %]([% type %]) + [% END %][% END %] + [% END %] +[% END %] +[% BLOCK authresult %] + [% IF ( summary.summary ) %][% summary.summary %]:[% END %] + [% UNLESS ( summary.summaryonly ) %] + [% FOREACH authorize IN summary.authorized %] + [% authorize %] + [% END %] + [% IF ( marcflavour == 'UNIMARC' ) %] + [% FOREACH note IN summary.notes %] + [% note %] + [% END %] + [% FOREACH seefro IN summary.seefrom %] + [% PROCESS showreference heading=seefro.heading label="" type=seefro.type %] + [% END %] + [% ELSE %] + [% IF ( summary.seefrom ) %] + [% FOREACH seefro IN summary.seefrom %] +
    + [% PROCESS showreference heading=seefro.heading label="used for/see from:" type=seefro.type %] +
    + [% END %] + [% END %] + [% IF ( summary.seealso ) %] + [% FOREACH seeals IN summary.seealso %] +
    + [% PROCESS showreference heading=seeals.heading label="see also:" type=seeals.type %] +
    + [% END %] + [% END %] + [% END %] + [% END %] +[% END %] + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist-auth.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist-auth.tt index 7fd5607..2881710 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist-auth.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist-auth.tt @@ -1,3 +1,4 @@ +[% PROCESS 'authorities-search-results.inc' %] [% INCLUDE 'doc-head-open.inc' %] Koha › Cataloging authority plugin [% INCLUDE 'doc-head-close.inc' %] @@ -67,7 +68,7 @@ function jumpfull(page)
    [% FOREACH resul IN result %] - + [% END %] - + [% UNLESS ( resul.isEDITORS ) %] [% FOREACH resul IN result %] - + [% END %] - - - + + [% UNLESS ( resul.isEDITORS ) %] [% UNLESS ( resul.isEDITORS ) %] [% END %] - - - - + + + + -- 1.7.2.3 From nengard at bywatersolutions.com Tue Jun 26 07:58:49 2012 From: nengard at bywatersolutions.com (Nicole C. Engard) Date: Tue, 26 Jun 2012 01:58:49 -0400 Subject: [Koha-patches] [PATCH] Bug 8321: Fix OPACShowBarcode description Message-ID: <1340690329-5133-1-git-send-email-nengard@bywatersolutions.com> This preference had a few grammar errors and repeated the word 'show.' This patch resolves those issues. --- .../prog/en/modules/admin/preferences/opac.pref | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref index 7ca4692..cd0c845 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -113,7 +113,7 @@ OPAC: choices: yes: Show no: "Don't show" - - Show items barcode in holding tab. + - the item's barcode on the holdings tab. - - pref: OpacHighlightedWords choices: -- 1.7.2.3 From colin.campbell at ptfs-europe.com Fri Jun 29 19:51:51 2012 From: colin.campbell at ptfs-europe.com (Colin Campbell) Date: Fri, 29 Jun 2012 18:51:51 +0100 Subject: [Koha-patches] [PATCH] Bug 8336 Support Sip Renewal Transaction Message-ID: <1340992311-24877-1-git-send-email-colin.campbell@ptfs-europe.com> Renewals were being rejected for incorrect reasons Checking was being done against the wrong object Add more informative messages on failure Correctly set due_date for renewal response --- C4/SIP/ILS.pm | 15 +++++---------- C4/SIP/ILS/Transaction/Renew.pm | 23 +++++++++++++++-------- C4/SIP/Sip/MsgType.pm | 6 +++++- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/C4/SIP/ILS.pm b/C4/SIP/ILS.pm index f046568..5d59850 100644 --- a/C4/SIP/ILS.pm +++ b/C4/SIP/ILS.pm @@ -428,17 +428,12 @@ sub renew { if (!defined($item)) { $trans->screen_msg("Item not checked out to " . $patron->name); # not checked out to $patron_id $trans->ok(0); - } elsif (!$item->available($patron_id)) { - $trans->screen_msg("Item unavailable due to outstanding holds"); - $trans->ok(0); } else { - $trans->renewal_ok(1); - $trans->desensitize(0); # It's already checked out - $trans->do_renew(); - syslog("LOG_DEBUG", "done renew (ok:%s): %s renews %s", $trans->renewal_ok, $patron_id, $item_id); - -# $item->{due_date} = $nb_due_date if $no_block eq 'Y'; -# $item->{sip_item_properties} = $item_props if $item_props; + $trans->do_renew(); + if ($trans->renewal_ok()) { + $item->{due_date} = $trans->{due}; + $trans->desensitize(0); + } } return $trans; diff --git a/C4/SIP/ILS/Transaction/Renew.pm b/C4/SIP/ILS/Transaction/Renew.pm index 57db003..2344c77 100644 --- a/C4/SIP/ILS/Transaction/Renew.pm +++ b/C4/SIP/ILS/Transaction/Renew.pm @@ -36,21 +36,28 @@ sub do_renew_for { my $borrower = shift; my ($renewokay,$renewerror) = CanBookBeRenewed($borrower->{borrowernumber},$self->{item}->{itemnumber}); if ($renewokay){ - $self->{due} = AddIssue( $borrower, $self->{item}->id, undef, 0 ); - $self->renewal_ok(1); + $self->{due} = undef; + my $due_date = AddIssue( $borrower, $self->{item}->id, undef, 0 ); + if ($due_date) { + $self->{due} = $due_date; + } + $self->renewal_ok(1); } else { - $self->screen_msg(($self->screen_msg || '') . " " . $renewerror); + $renewerror=~s/on_reserve/Item unavailable due to outstanding holds/; + $renewerror=~s/too_many/Item has reached maximum renewals/; + #$self->screen_msg(($self->screen_msg || '') . " " . $renewerror); + $self->screen_msg($renewerror); $self->renewal_ok(0); } - $! and warn "do_renew_for error: $!"; - $self->ok(1) unless $!; - return $self; + $self->ok(1); + return; } sub do_renew { my $self = shift; my $borrower = GetMember( 'cardnumber'=>$self->{patron}->id); - return $self->do_renew_for($borrower); -} + $self->do_renew_for($borrower); + return $self; +} 1; diff --git a/C4/SIP/Sip/MsgType.pm b/C4/SIP/Sip/MsgType.pm index f37b342..c986fe2 100644 --- a/C4/SIP/Sip/MsgType.pm +++ b/C4/SIP/Sip/MsgType.pm @@ -1357,7 +1357,11 @@ sub handle_renew { $resp .= add_field(FID_PATRON_ID, $patron->id); $resp .= add_field(FID_ITEM_ID, $item->id); $resp .= add_field(FID_TITLE_ID, $item->title_id); - $resp .= add_field(FID_DUE_DATE, Sip::timestamp($item->due_date)); + if ($item->due_date) { + $resp .= add_field(FID_DUE_DATE, Sip::timestamp($item->due_date)); + } else { + $resp .= add_field(FID_DUE_DATE, q{}); + } if ($ils->supports('security inhibit')) { $resp .= add_field(FID_SECURITY_INHIBIT, $status->security_inhibit); -- 1.7.11.1.104.ge7b44f1
    [% resul.summary %][% PROCESS authresult summary=resul.summary %] [% resul.used %] times [% IF resul.repets %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist.tt index 1131871..038959f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist.tt @@ -1,3 +1,4 @@ +[% PROCESS 'authorities-search-results.inc' %] [% INCLUDE 'doc-head-open.inc' %] Koha › Authorities › Authority search results [% INCLUDE 'doc-head-close.inc' %] @@ -63,7 +64,7 @@ function searchauthority() { [% ELSE %]
    [% resul.summary %][% PROCESS authresult summary=resul.summary %] Details diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_210c.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_210c.tt index 5306146..043e700 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_210c.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/unimarc_field_210c.tt @@ -1,3 +1,4 @@ +[% PROCESS 'authorities-search-results.inc' %] [% INCLUDE 'doc-head-open.inc' %] UNIMARC field 210c builder [% INCLUDE 'doc-head-close.inc' %] @@ -59,7 +60,7 @@
    [% resul.summary %][% PROCESS authresult summary=resul.summary %] [% resul.used %] times [% IF ( resul.to_report ) %] diff --git a/koha-tmpl/opac-tmpl/prog/en/css/opac.css b/koha-tmpl/opac-tmpl/prog/en/css/opac.css index 6223025..e2996a9 100644 --- a/koha-tmpl/opac-tmpl/prog/en/css/opac.css +++ b/koha-tmpl/opac-tmpl/prog/en/css/opac.css @@ -2585,6 +2585,15 @@ ul.ui-tabs-nav li { color: #222222; } +.authref { + text-indent: 2em; +} + +.authref .label { + font-style: italic; +} + + /* ## BABELTHEQUE ##?*/ /* Uncomment if babeltheque configuration no contains these lines */ /* diff --git a/koha-tmpl/opac-tmpl/prog/en/includes/authorities-search-results.inc b/koha-tmpl/opac-tmpl/prog/en/includes/authorities-search-results.inc new file mode 100644 index 0000000..44ea78c --- /dev/null +++ b/koha-tmpl/opac-tmpl/prog/en/includes/authorities-search-results.inc @@ -0,0 +1,60 @@ +[% BLOCK showreference %] + [% IF marcflavour == 'UNIMARC' %] + [% SWITCH type %] + [% CASE 'broader' %] + [% heading %] -- + [% CASE 'narrower' %] + [% heading %] -- + [% CASE 'narrower' %] + [% heading %] -- + [% CASE 'seefrom' %] + [% heading %] -- + [% CASE 'seealso' %] + [% heading %] -- + [% END %] + [% ELSE %] + [% IF ( label ) %][% label %][% END %] + [% heading %] + [% UNLESS ( type=='seefrom' || type=='seealso' ) %][% SWITCH type %] + [% CASE 'earlier' %](Earlier heading) + [% CASE 'later' %](Later heading) + [% CASE 'acronym' %](Acronym) + [% CASE 'musical' %](Musical composition) + [% CASE 'broader' %](Broader heading) + [% CASE 'narrower' %](Narrower heading) + [% CASE %]([% type %]) + [% END %][% END %] + [% END %] +[% END %] +[% BLOCK authresult %] + [% IF ( summary.summary ) %][% summary.summary %]:[% END %] + [% UNLESS ( summary.summaryonly ) %] + [% FOREACH authorize IN summary.authorized %] + [% authorize %] + [% END %] + [% IF ( marcflavour == 'UNIMARC' ) %] + [% FOREACH note IN summary.notes %] + [% note %] + [% END %] + [% FOREACH seefro IN summary.seefrom %] + [% PROCESS showreference heading=seefro.heading label="" type=seefro.type %] + [% END %] + [% ELSE %] + [% IF ( summary.seefrom ) %] + [% FOREACH seefro IN summary.seefrom %] +
    + [% PROCESS showreference heading=seefro.heading label="used for/see from:" type=seefro.type %] +
    + [% END %] + [% END %] + [% IF ( summary.seealso ) %] + [% FOREACH seeals IN summary.seealso %] +
    + [% PROCESS showreference heading=seeals.heading label="see also:" type=seeals.type %] +
    + [% END %] + [% END %] + [% END %] + [% END %] +[% END %] + diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-MARCdetail.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-MARCdetail.tt new file mode 100644 index 0000000..8e87d71 --- /dev/null +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-MARCdetail.tt @@ -0,0 +1,87 @@ +[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Entry +[% INCLUDE 'doc-head-close.inc' %] +[% IF ( displayhierarchy ) %] + + +[% END %] + + + +
    +
    +[% INCLUDE 'masthead.inc' %] +
    +
    +
    + +[% IF ( displayhierarchy ) %] + +
    +[% FOREACH loophierarchie IN loophierarchies %] +
    + [% FOREACH loopelemen IN loophierarchie.loopelement %] +
    + [% IF ( loopelemen.current_value ) %] + [% loopelemen.value %] + [% ELSE %] + [% loopelemen.value %] + [% END %] + [% IF ( loopelemen.ifchildren ) %] + +
    + [% FOREACH loopchildre IN loopelemen.loopchildren %] + + [% END %] + [% END %] +
    + [% END %] + +
    +[% END %] +
    +[% END %] +

    Entry [% authtypetext %]

    +

    Used in [% count %] records

    + [% FOREACH Tag0X IN Tab0XX %] +

    [% Tag0X.tag %]

    +
      + [% FOREACH subfiel IN Tag0X.subfield %] +

      [% subfiel.marc_lib %]: + [% IF subfiel.isurl %][% subfiel.marc_value %] + [% ELSE %][% subfiel.marc_value %][% END %]

      + [% END %] +
    + [% END %] +
    + +
    +
    +
    +[% IF ( OpacNav ) %] +
    +
    +[% INCLUDE 'navigation.inc' %] +
    +
    [% END %] +
    +[% INCLUDE 'opac-bottom.inc' %] diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiesdetail.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiesdetail.tt deleted file mode 100644 index 287f6d1..0000000 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiesdetail.tt +++ /dev/null @@ -1,85 +0,0 @@ -[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Entry -[% INCLUDE 'doc-head-close.inc' %] -[% IF ( displayhierarchy ) %] - - -[% END %] - - - -
    -
    -[% INCLUDE 'masthead.inc' %] -
    -
    -
    - -[% IF ( displayhierarchy ) %] - -
    -[% FOREACH loophierarchie IN loophierarchies %] -
    - [% FOREACH loopelemen IN loophierarchie.loopelement %] -
    - [% IF ( loopelemen.current_value ) %] - [% loopelemen.value %] - [% ELSE %] - [% loopelemen.value %] - [% END %] - [% IF ( loopelemen.ifchildren ) %] - +
    - [% FOREACH loopchildre IN loopelemen.loopchildren %] - - [% END %] - [% END %] -
    - [% END %] - -
    -[% END %] -
    -[% END %] -

    Entry [% authtypetext %]

    -

    Used in [% count %] records

    - [% FOREACH Tag0X IN Tab0XX %] -

    [% Tag0X.tag %]

    -
      - [% FOREACH subfiel IN Tag0X.subfield %] -

      [% subfiel.marc_lib %]: [% subfiel.marc_value %]

      - [% END %] -
    - [% END %] -
    - -
    -
    -
    -[% IF ( OpacNav ) %] -
    -
    -[% INCLUDE 'navigation.inc' %] -
    -
    [% END %] -
    -[% INCLUDE 'opac-bottom.inc' %] diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt index 5fdfb27..a27480a 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt @@ -1,3 +1,4 @@ +[% PROCESS 'authorities-search-results.inc' %] [% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › [% IF ( total ) %]Authority search result[% ELSE %]No results found[% END %] [% INCLUDE 'doc-head-close.inc' %] @@ -52,11 +53,8 @@ [% ELSE %]
    [% resul.summary %] - [% authtypetext %] - [% PROCESS authresult summary=resul.summary %][% authtypetext %] [% resul.used %] biblios diff --git a/opac/opac-authoritiesdetail.pl b/opac/opac-authoritiesdetail.pl index 6610dfd..41b994f 100755 --- a/opac/opac-authoritiesdetail.pl +++ b/opac/opac-authoritiesdetail.pl @@ -52,9 +52,8 @@ my $query = new CGI; my $dbh = C4::Context->dbh; -my $authid = $query->param('authid'); -my $authtypecode = &GetAuthTypeCode( $authid ); -my $tagslib = &GetTagsLabels( 1, $authtypecode ); +my $display_hierarchy = C4::Context->preference("AuthDisplayHierarchy"); +my $show_marc = $query->param('marc') || 1; # Currently only MARC view is available # open template my ( $template, $loggedinuser, $cookie ) = get_template_and_user( @@ -67,8 +66,13 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( } ); +my $authid = $query->param('authid'); +my $authtypecode = &GetAuthTypeCode( $authid ); +my $tagslib = &GetTagsLabels( 0, $authtypecode ); + + my $record; -if (C4::Context->preference("AuthDisplayHierarchy")){ +if ($display_hierarchy){ my $trees=BuildUnimarcHierarchies($authid); my @trees = split /;/,$trees ; push @trees,$trees unless (@trees); @@ -88,7 +92,7 @@ if (C4::Context->preference("AuthDisplayHierarchy")){ push @loophierarchies, { 'loopelement' =>\@loophierarchy}; } $template->param( - 'displayhierarchy' =>C4::Context->preference("AuthDisplayHierarchy"), + 'displayhierarchy' => $display_hierarchy, 'loophierarchies' =>\@loophierarchies, ); } @@ -145,15 +149,10 @@ foreach my $field (@fields) { my %subfield_data; $subfield_data{marc_lib} = $tagslib->{ $field->tag() }->{ $subf[$i][0] }->{lib}; - if ( $tagslib->{ $field->tag() }->{ $subf[$i][0] }->{isurl} ) { - $subfield_data{marc_value} = - "$subf[$i][1]"; - } - else { - $subfield_data{marc_value} = $subf[$i][1]; - } $subfield_data{marc_subfield} = $subf[$i][0]; $subfield_data{marc_tag} = $field->tag(); + $subfield_data{isurl} = $tagslib->{ $field->tag() }->{ $subf[$i][0] }->{isurl}; + $subfield_data{marc_value} = $subf[$i][1]; push( @subfields_data, \%subfield_data ); } } @@ -186,12 +185,6 @@ $template->param( biblio_fields => $biblio_fields, authtypetext => $authtypes->{$authtypecode}{'authtypetext'}, authtypesloop => \@authtypesloop, - LibraryName => C4::Context->preference("LibraryName"), - OpacNav => C4::Context->preference("OpacNav"), - opaccredits => C4::Context->preference("opaccredits"), - opacsmallimage => C4::Context->preference("opacsmallimage"), - opaclayoutstylesheet => C4::Context->preference("opaclayoutstylesheet"), - opaccolorstylesheet => C4::Context->preference("opaccolorstylesheet"), ); output_html_with_http_headers $query, $cookie, $template->output; -- 1.7.2.5 From jcamins at cpbibliography.com Thu Jun 14 00:24:30 2012 From: jcamins at cpbibliography.com (Jared Camins-Esakov) Date: Wed, 13 Jun 2012 18:24:30 -0400 Subject: [Koha-patches] [PATCH] Bug 7475: Enable authority overlay Message-ID: <1339626270-3587-1-git-send-email-jcamins@cpbibliography.com> This patch does the following: * Completes authority support within Koha's import batch code * Completes authority support in Koha's matching rule code * Exposes the ability to stage and commit batches of authorities using the renamed scripts misc/stage_file.pl and misc/commit_file.pl To test: 1. Find a file of authorities (a sample file with MARC21 authorities is attached to bug 7475) and download it to your server 2. Stage the file using the following command (replace with the name of the file you saved in step 1): > misc/stage_file.pl --file --authorities 3. Note the batch number the script assigns to your batch 4. Commit the records using the following command (replace with the batch number you made note of in step 3): > misc/commit_file.pl --batch-number 5. Index the authorities Zebraqueue (or wait) 6. Confirm that the new authorities appear. 7. Revert the import with the following command: > misc/commit_file.pl --batch-number --revert 8. Index the authorities Zebraqueue (or wait) 9. Confirm that the records have been removed --- C4/ImportBatch.pm | 304 +++++++++++++------- C4/Matcher.pm | 73 ++++- admin/matching-rules.pl | 12 +- .../data/mysql/atomicupdate/importauthorities.pl | 19 ++ installer/data/mysql/kohastructure.sql | 15 + .../prog/en/modules/admin/matching-rules.tt | 11 + misc/commit_biblios_file.pl | 119 -------- misc/commit_file.pl | 151 ++++++++++ misc/cronjobs/import_webservice_batch.pl | 2 +- misc/stage_biblios_file.pl | 185 ------------ misc/stage_file.pl | 197 +++++++++++++ svc/import_bib | 2 +- tools/manage-marc-import.pl | 4 +- 13 files changed, 667 insertions(+), 427 deletions(-) create mode 100755 installer/data/mysql/atomicupdate/importauthorities.pl delete mode 100755 misc/commit_biblios_file.pl create mode 100755 misc/commit_file.pl delete mode 100755 misc/stage_biblios_file.pl create mode 100755 misc/stage_file.pl diff --git a/C4/ImportBatch.pm b/C4/ImportBatch.pm index 5bf79bf..a62f15d 100644 --- a/C4/ImportBatch.pm +++ b/C4/ImportBatch.pm @@ -1,6 +1,6 @@ package C4::ImportBatch; -# Copyright (C) 2007 LibLime +# Copyright (C) 2007 LibLime, 2012 C & P Bibliography Services # # This file is part of Koha. # @@ -40,14 +40,16 @@ BEGIN { GetImportRecordMarcXML AddImportBatch GetImportBatch + AddAuthorityToBatch AddBiblioToBatch AddItemsToImportBiblio + ModAuthorityInBatch ModBiblioInBatch BatchStageMarcRecords - BatchFindBibDuplicates - BatchCommitBibRecords - BatchRevertBibRecords + BatchFindDuplicates + BatchCommitRecords + BatchRevertRecords CleanBatch GetAllImportBatches @@ -272,10 +274,43 @@ sub ModBiblioInBatch { } +=head2 AddAuthToBatch + + my $import_record_id = AddAuthToBatch($batch_id, $record_sequence, + $marc_record, $encoding, $z3950random, $update_counts); + +=cut + +sub AddAuthToBatch { + my $batch_id = shift; + my $record_sequence = shift; + my $marc_record = shift; + my $encoding = shift; + my $z3950random = shift; + my $update_counts = @_ ? shift : 1; + + my $import_record_id = _create_import_record($batch_id, $record_sequence, $marc_record, 'auth', $encoding, $z3950random); + _update_batch_record_counts($batch_id) if $update_counts; + return $import_record_id; +} + +=head2 ModAuthInBatch + + ModAuthInBatch($import_record_id, $marc_record); + +=cut + +sub ModAuthInBatch { + my ($import_record_id, $marc_record) = @_; + + _update_import_record_marc($import_record_id, $marc_record); + +} + =head2 BatchStageMarcRecords ($batch_id, $num_records, $num_items, @invalid_records) = - BatchStageMarcRecords($encoding, $marc_records, $file_name, + BatchStageMarcRecords($record_type, $encoding, $marc_records, $file_name, $comments, $branch_code, $parse_items, $leave_as_staging, $progress_interval, $progress_callback); @@ -283,6 +318,7 @@ sub ModBiblioInBatch { =cut sub BatchStageMarcRecords { + my $record_type = shift; my $encoding = shift; my $marc_records = shift; my $file_name = shift; @@ -338,10 +374,14 @@ sub BatchStageMarcRecords { push @invalid_records, $marc_blob; } else { $num_valid++; - $import_record_id = AddBiblioToBatch($batch_id, $rec_num, $marc_record, $encoding, int(rand(99999)), 0); - if ($parse_items) { - my @import_items_ids = AddItemsToImportBiblio($batch_id, $import_record_id, $marc_record, 0); - $num_items += scalar(@import_items_ids); + if ($record_type eq 'biblio') { + $import_record_id = AddBiblioToBatch($batch_id, $rec_num, $marc_record, $encoding, int(rand(99999)), 0); + if ($parse_items) { + my @import_items_ids = AddItemsToImportBiblio($batch_id, $import_record_id, $marc_record, 0); + $num_items += scalar(@import_items_ids); + } + } elsif ($record_type eq 'auth') { + $import_record_id = AddAuthToBatch($batch_id, $rec_num, $marc_record, $encoding, int(rand(99999)), 0); } } } @@ -392,9 +432,9 @@ sub AddItemsToImportBiblio { return @import_items_ids; } -=head2 BatchFindBibDuplicates +=head2 BatchFindDuplicates - my $num_with_matches = BatchFindBibDuplicates($batch_id, $matcher, + my $num_with_matches = BatchFindDuplicates($batch_id, $matcher, $max_matches, $progress_interval, $progress_callback); Goes through the records loaded in the batch and attempts to @@ -412,7 +452,7 @@ singular argument. =cut -sub BatchFindBibDuplicates { +sub BatchFindDuplicates { my $batch_id = shift; my $matcher = shift; my $max_matches = @_ ? shift : 10; @@ -430,9 +470,10 @@ sub BatchFindBibDuplicates { my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("SELECT import_record_id, marc + my $sth = $dbh->prepare("SELECT import_records.import_record_id, record_type, marc FROM import_records - JOIN import_biblios USING (import_record_id) + LEFT JOIN import_auths ON (import_records.import_record_id=import_auths.import_record_id) + LEFT JOIN import_biblios ON (import_records.import_record_id=import_biblios.import_record_id) WHERE import_batch_id = ?"); $sth->execute($batch_id); my $num_with_matches = 0; @@ -460,15 +501,15 @@ sub BatchFindBibDuplicates { return $num_with_matches; } -=head2 BatchCommitBibRecords +=head2 BatchCommitRecords - my ($num_added, $num_updated, $num_items_added, $num_items_errored, - $num_ignored) = BatchCommitBibRecords($batch_id, $framework, - $progress_interval, $progress_callback); + my ($num_added, $num_updated, $num_items_added, $num_items_errored, $num_ignored) = + BatchCommitRecords($batch_id, $framework, + $progress_interval, $progress_callback); =cut -sub BatchCommitBibRecords { +sub BatchCommitRecords { my $batch_id = shift; my $framework = shift; @@ -483,25 +524,29 @@ sub BatchCommitBibRecords { $progress_interval = 0 unless 'CODE' eq ref $progress_callback; } + my $record_type; my $num_added = 0; my $num_updated = 0; my $num_items_added = 0; my $num_items_errored = 0; my $num_ignored = 0; # commit (i.e., save, all records in the batch) - # FIXME biblio only at the moment SetImportBatchStatus('importing'); my $overlay_action = GetImportBatchOverlayAction($batch_id); my $nomatch_action = GetImportBatchNoMatchAction($batch_id); my $item_action = GetImportBatchItemAction($batch_id); + my $item_tag; + my $item_subfield; my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("SELECT import_record_id, status, overlay_status, marc, encoding + my $sth = $dbh->prepare("SELECT import_records.import_record_id, record_type, status, overlay_status, marc, encoding FROM import_records - JOIN import_biblios USING (import_record_id) + LEFT JOIN import_auths ON (import_records.import_record_id=import_auths.import_record_id) + LEFT JOIN import_biblios ON (import_records.import_record_id=import_biblios.import_record_id) WHERE import_batch_id = ?"); $sth->execute($batch_id); my $rec_num = 0; while (my $rowref = $sth->fetchrow_hashref) { + $record_type = $rowref->{'record_type'}; $rec_num++; if ($progress_interval and (0 == ($rec_num % $progress_interval))) { &$progress_callback($rec_num); @@ -513,67 +558,87 @@ sub BatchCommitBibRecords { my $marc_record = MARC::Record->new_from_usmarc($rowref->{'marc'}); - # remove any item tags - rely on BatchCommitItems - my ($item_tag,$item_subfield) = &GetMarcFromKohaField("items.itemnumber",''); - foreach my $item_field ($marc_record->field($item_tag)) { - $marc_record->delete_field($item_field); + if ($record_type eq 'biblio') { + # remove any item tags - rely on BatchCommitItems + ($item_tag,$item_subfield) = &GetMarcFromKohaField("items.itemnumber",''); + foreach my $item_field ($marc_record->field($item_tag)) { + $marc_record->delete_field($item_field); + } } - # decide what what to do with the bib and item records - my ($bib_result, $item_result, $bib_match) = + my ($record_result, $item_result, $record_match) = _get_commit_action($overlay_action, $nomatch_action, $item_action, - $rowref->{'overlay_status'}, $rowref->{'import_record_id'}); + $rowref->{'overlay_status'}, $rowref->{'import_record_id'}, $record_type); - if ($bib_result eq 'create_new') { + my $recordid; + my $query; + if ($record_result eq 'create_new') { $num_added++; - my ($biblionumber, $biblioitemnumber) = AddBiblio($marc_record, $framework); - my $sth = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?"); - $sth->execute($biblionumber, $rowref->{'import_record_id'}); - $sth->finish(); - if ($item_result eq 'create_new') { - my ($bib_items_added, $bib_items_errored) = BatchCommitItems($rowref->{'import_record_id'}, $biblionumber); - $num_items_added += $bib_items_added; - $num_items_errored += $bib_items_errored; + if ($record_type eq 'biblio') { + my $biblioitemnumber; + ($recordid, $biblioitemnumber) = AddBiblio($marc_record, $framework); + $query = "UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?"; + if ($item_result eq 'create_new') { + my ($bib_items_added, $bib_items_errored) = BatchCommitItems($rowref->{'import_record_id'}, $recordid); + $num_items_added += $bib_items_added; + $num_items_errored += $bib_items_errored; + } + } else { + my $authid = AddAuthority($marc_record, undef, GuessAuthTypeCode($marc_record)); + $query = "UPDATE import_auths SET matched_authid = ? WHERE import_record_id = ?"; } + my $sth = $dbh->prepare_cached($query); + $sth->execute($recordid, $rowref->{'import_record_id'}); + $sth->finish(); SetImportRecordStatus($rowref->{'import_record_id'}, 'imported'); - } elsif ($bib_result eq 'replace') { + } elsif ($record_result eq 'replace') { $num_updated++; - my $biblionumber = $bib_match; - my ($count, $oldbiblio) = GetBiblio($biblionumber); - my $oldxml = GetXmlBiblio($biblionumber); - - # remove item fields so that they don't get - # added again if record is reverted - my $old_marc = MARC::Record->new_from_xml(StripNonXmlChars($oldxml), 'UTF-8', $rowref->{'encoding'}); - foreach my $item_field ($old_marc->field($item_tag)) { - $old_marc->delete_field($item_field); - } + $recordid = $record_match; + my $oldxml; + if ($record_type eq 'biblio') { + my ($count, $oldbiblio) = GetBiblio($recordid); + $oldxml = GetXmlBiblio($recordid); + + # remove item fields so that they don't get + # added again if record is reverted + my $old_marc = MARC::Record->new_from_xml(StripNonXmlChars($oldxml), 'UTF-8', $rowref->{'encoding'}); + foreach my $item_field ($old_marc->field($item_tag)) { + $old_marc->delete_field($item_field); + } + $oldxml = $old_marc->as_xml(); + + ModBiblio($marc_record, $recordid, $oldbiblio->{'frameworkcode'}); + $query = "UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?"; + + if ($item_result eq 'create_new') { + my ($bib_items_added, $bib_items_errored) = BatchCommitItems($rowref->{'import_record_id'}, $recordid); + $num_items_added += $bib_items_added; + $num_items_errored += $bib_items_errored; + } + } else { + my $oldxml = GetAuthorityXML($recordid); - ModBiblio($marc_record, $biblionumber, $oldbiblio->{'frameworkcode'}); + ModAuthority($recordid, $marc_record, GuessAuthTypeCode($marc_record)); + $query = "UPDATE import_auths SET matched_authid = ? WHERE import_record_id = ?"; + } my $sth = $dbh->prepare_cached("UPDATE import_records SET marcxml_old = ? WHERE import_record_id = ?"); - $sth->execute($old_marc->as_xml(), $rowref->{'import_record_id'}); + $sth->execute($oldxml, $rowref->{'import_record_id'}); $sth->finish(); - my $sth2 = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?"); - $sth2->execute($biblionumber, $rowref->{'import_record_id'}); + my $sth2 = $dbh->prepare_cached($query); + $sth2->execute($recordid, $rowref->{'import_record_id'}); $sth2->finish(); - if ($item_result eq 'create_new') { - my ($bib_items_added, $bib_items_errored) = BatchCommitItems($rowref->{'import_record_id'}, $biblionumber); - $num_items_added += $bib_items_added; - $num_items_errored += $bib_items_errored; - } SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'match_applied'); SetImportRecordStatus($rowref->{'import_record_id'}, 'imported'); - } elsif ($bib_result eq 'ignore') { + } elsif ($record_result eq 'ignore') { $num_ignored++; - my $biblionumber = $bib_match; - if (defined $biblionumber and $item_result eq 'create_new') { - my ($bib_items_added, $bib_items_errored) = BatchCommitItems($rowref->{'import_record_id'}, $biblionumber); + if ($record_type eq 'biblio' and defined $recordid and $item_result eq 'create_new') { + my ($bib_items_added, $bib_items_errored) = BatchCommitItems($rowref->{'import_record_id'}, $recordid); $num_items_added += $bib_items_added; $num_items_errored += $bib_items_errored; # still need to record the matched biblionumber so that the # items can be reverted my $sth2 = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?"); - $sth2->execute($biblionumber, $rowref->{'import_record_id'}); + $sth2->execute($recordid, $rowref->{'import_record_id'}); SetImportRecordOverlayStatus($rowref->{'import_record_id'}, 'match_applied'); } SetImportRecordStatus($rowref->{'import_record_id'}, 'ignored'); @@ -632,62 +697,82 @@ sub BatchCommitItems { return ($num_items_added, $num_items_errored); } -=head2 BatchRevertBibRecords +=head2 BatchRevertRecords my ($num_deleted, $num_errors, $num_reverted, $num_items_deleted, - $num_ignored) = BatchRevertBibRecords($batch_id); + $num_ignored) = BatchRevertRecords($batch_id); =cut -sub BatchRevertBibRecords { +sub BatchRevertRecords { my $batch_id = shift; + my $record_type; my $num_deleted = 0; my $num_errors = 0; my $num_reverted = 0; - my $num_items_deleted = 0; my $num_ignored = 0; + my $num_items_deleted = 0; # commit (i.e., save, all records in the batch) - # FIXME biblio only at the moment SetImportBatchStatus('reverting'); my $overlay_action = GetImportBatchOverlayAction($batch_id); my $nomatch_action = GetImportBatchNoMatchAction($batch_id); my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("SELECT import_record_id, status, overlay_status, marcxml_old, encoding, matched_biblionumber + my $sth = $dbh->prepare("SELECT import_records.import_record_id, record_type, status, overlay_status, marcxml_old, encoding, matched_biblionumber, matched_authid FROM import_records - JOIN import_biblios USING (import_record_id) + LEFT JOIN import_auths ON (import_records.import_record_id=import_auths.import_record_id) + LEFT JOIN import_biblios ON (import_records.import_record_id=import_biblios.import_record_id) WHERE import_batch_id = ?"); $sth->execute($batch_id); while (my $rowref = $sth->fetchrow_hashref) { + $record_type = $rowref->{'record_type'}; if ($rowref->{'status'} eq 'error' or $rowref->{'status'} eq 'reverted') { $num_ignored++; next; } - my $bib_result = _get_revert_action($overlay_action, $rowref->{'overlay_status'}, $rowref->{'status'}); + my $record_result = _get_revert_action($overlay_action, $rowref->{'overlay_status'}, $rowref->{'status'}); - if ($bib_result eq 'delete') { - $num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'}); - my $error = DelBiblio($rowref->{'matched_biblionumber'}); + if ($record_result eq 'delete') { + my $error = undef; + if ($record_type eq 'biblio') { + $num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'}); + $error = DelBiblio($rowref->{'matched_biblionumber'}); + } else { + my $deletedauthid = DelAuthority($rowref->{'matched_authid'}); + } if (defined $error) { $num_errors++; } else { $num_deleted++; SetImportRecordStatus($rowref->{'import_record_id'}, 'reverted'); } - } elsif ($bib_result eq 'restore') { + } elsif ($record_result eq 'restore') { $num_reverted++; my $old_record = MARC::Record->new_from_xml(StripNonXmlChars($rowref->{'marcxml_old'}), 'UTF-8', $rowref->{'encoding'}); - my $biblionumber = $rowref->{'matched_biblionumber'}; - my ($count, $oldbiblio) = GetBiblio($biblionumber); - $num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'}); - ModBiblio($old_record, $biblionumber, $oldbiblio->{'frameworkcode'}); + if ($record_type eq 'biblio') { + my $biblionumber = $rowref->{'matched_biblionumber'}; + my ($count, $oldbiblio) = GetBiblio($biblionumber); + $num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'}); + ModBiblio($old_record, $biblionumber, $oldbiblio->{'frameworkcode'}); + } else { + my $authid = $rowref->{'matched_authid'}; + ModAuthority($authid, $old_record, GuessAuthTypeCode($old_record)); + } SetImportRecordStatus($rowref->{'import_record_id'}, 'reverted'); - } elsif ($bib_result eq 'ignore') { - $num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'}); + } elsif ($record_result eq 'ignore') { + if ($record_type eq 'biblio') { + $num_items_deleted += BatchRevertItems($rowref->{'import_record_id'}, $rowref->{'matched_biblionumber'}); + } SetImportRecordStatus($rowref->{'import_record_id'}, 'reverted'); } - my $sth2 = $dbh->prepare_cached("UPDATE import_biblios SET matched_biblionumber = NULL WHERE import_record_id = ?"); + my $query; + if ($record_type eq 'biblio') { + $query = "UPDATE import_biblios SET matched_biblionumber = NULL WHERE import_record_id = ?"; + } else { + $query = "UPDATE import_auths SET matched_authid = NULL WHERE import_record_id = ?"; + } + my $sth2 = $dbh->prepare_cached($query); $sth2->execute($rowref->{'import_record_id'}); } @@ -1305,26 +1390,45 @@ sub _update_batch_record_counts { } sub _get_commit_action { - my ($overlay_action, $nomatch_action, $item_action, $overlay_status, $import_record_id) = @_; + my ($overlay_action, $nomatch_action, $item_action, $overlay_status, $import_record_id, $record_type) = @_; - my ($bib_result, $bib_match, $item_result); - - if ($overlay_status ne 'no_match') { - $bib_match = GetBestRecordMatch($import_record_id); - if ($overlay_action eq 'replace') { - $bib_result = defined($bib_match) ? 'replace' : 'create_new'; - } elsif ($overlay_action eq 'create_new') { - $bib_result = 'create_new'; - } elsif ($overlay_action eq 'ignore') { - $bib_result = 'ignore'; - } - $item_result = ($item_action eq 'always_add' or $item_action eq 'add_only_for_matches') ? 'create_new' : 'ignore'; - } else { - $bib_result = $nomatch_action; - $item_result = ($item_action eq 'always_add' or $item_action eq 'add_only_for_new') ? 'create_new' : 'ignore'; - } + if ($record_type eq 'biblio') { + my ($bib_result, $bib_match, $item_result); + + if ($overlay_status ne 'no_match') { + $bib_match = GetBestRecordMatch($import_record_id); + if ($overlay_action eq 'replace') { + $bib_result = defined($bib_match) ? 'replace' : 'create_new'; + } elsif ($overlay_action eq 'create_new') { + $bib_result = 'create_new'; + } elsif ($overlay_action eq 'ignore') { + $bib_result = 'ignore'; + } + $item_result = ($item_action eq 'always_add' or $item_action eq 'add_only_for_matches') ? 'create_new' : 'ignore'; + } else { + $bib_result = $nomatch_action; + $item_result = ($item_action eq 'always_add' or $item_action eq 'add_only_for_new') ? 'create_new' : 'ignore'; + } + return ($bib_result, $item_result, $bib_match); + } else { # must be auths + my ($auth_result, $auth_match); + + if ($overlay_status ne 'no_match') { + $auth_match = GetBestRecordMatch($import_record_id); + if ($overlay_action eq 'replace') { + $auth_result = defined($auth_match) ? 'replace' : 'create_new'; + } elsif ($overlay_action eq 'create_new') { + $auth_result = 'create_new'; + } elsif ($overlay_action eq 'ignore') { + $auth_result = 'ignore'; + } + } else { + $auth_result = $nomatch_action; + } + + return ($auth_result, undef, $auth_match); - return ($bib_result, $item_result, $bib_match); + } } sub _get_revert_action { diff --git a/C4/Matcher.pm b/C4/Matcher.pm index 59b5876..c9f418d 100644 --- a/C4/Matcher.pm +++ b/C4/Matcher.pm @@ -1,6 +1,6 @@ package C4::Matcher; -# Copyright (C) 2007 LibLime +# Copyright (C) 2007 LibLime, 2012 C & P Bibliography Services # # This file is part of Koha. # @@ -22,8 +22,6 @@ use warnings; use C4::Context; use MARC::Record; -use C4::Search; -use C4::Biblio; use vars qw($VERSION); @@ -384,6 +382,20 @@ sub delete { $sth->execute($matcher_id); # relying on cascading deletes to clean up everything } +=head2 record_type + + $matcher->record_type('biblio'); + my $record_type = $matcher->record_type(); + +Accessor method. + +=cut + +sub record_type { + my $self = shift; + @_ ? $self->{'record_type'} = shift : $self->{'record_type'}; +} + =head2 threshold $matcher->threshold(1000); @@ -582,7 +594,7 @@ sub add_simple_required_check { ); } -=head2 find_matches +=head2 get_matches my @matches = $matcher->get_matches($marc_record, $max_matches); foreach $match (@matches) { @@ -618,9 +630,34 @@ sub get_matches { my @source_keys = _get_match_keys($source_record, $matchpoint); next if scalar(@source_keys) == 0; # build query - my $query = join(" or ", map { "$matchpoint->{'index'}=$_" } @source_keys); - # FIXME only searching biblio index at the moment - my ($error, $searchresults, $total_hits) = SimpleSearch($query, 0, $max_matches); + my $query; + my $error; + my $searchresults; + my $total_hits; + if ($self->{'record_type'} eq 'biblio') { + $query = join(" or ", map { "$matchpoint->{'index'}=$_" } @source_keys); +# FIXME only searching biblio index at the moment + require C4::Search; + ($error, $searchresults, $total_hits) = C4::Search::SimpleSearch($query, 0, $max_matches); + } elsif ($self->{'record_type'} eq 'authority') { + my $authresults; + my @marclist; + my @and_or; + my @excluding = []; + my @operator; + my @value; + foreach my $key (@source_keys) { + push @marclist, $matchpoint->{'index'}; + push @and_or, 'or'; + push @operator, 'exact'; + push @value, $key; + } + require C4::AuthoritiesMarc; + ($searchresults, $total_hits) = C4::AuthoritiesMarc::SearchAuthorities( + \@marclist, \@and_or, \@excluding, \@operator, + \@value, 0, 20, undef, 'AuthidAsc', 1 + ); + } if (defined $error ) { warn "search failed ($query) $error"; @@ -639,13 +676,20 @@ sub get_matches { keys %matches; my @results = (); - foreach my $marcblob (keys %matches) { - my $target_record = MARC::Record->new_from_usmarc($marcblob); - my $result = TransformMarcToKoha(C4::Context->dbh, $target_record, ''); - # FIXME - again, bibliospecific - # also, can search engine be induced to give just the number in the first place? - my $record_number = $result->{'biblionumber'}; - push @results, { 'record_id' => $record_number, 'score' => $matches{$marcblob} }; + if ($self->{'record_type'} eq 'biblio') { + require C4::Biblio; + foreach my $marcblob (keys %matches) { + my $target_record = MARC::Record->new_from_usmarc($marcblob); + my $record_number; + my $result = C4::Biblio::TransformMarcToKoha(C4::Context->dbh, $target_record, ''); + $record_number = $result->{'biblionumber'}; + push @results, { 'record_id' => $record_number, 'score' => $matches{$marcblob} }; + } + } elsif ($self->{'record_type'} eq 'authority') { + require C4::AuthoritiesMarc; + foreach my $authid (keys %matches) { + push @results, { 'record_id' => $authid, 'score' => $matches{$authid} }; + } } @results = sort { $b->{'score'} cmp $a->{'score'} } @results; if (scalar(@results) > $max_matches) { @@ -673,6 +717,7 @@ sub dump { $result->{'matcher_id'} = $self->{'id'}; $result->{'code'} = $self->{'code'}; $result->{'description'} = $self->{'description'}; + $result->{'record_type'} = $self->{'record_type'}; $result->{'matchpoints'} = []; foreach my $matchpoint (@{ $self->{'matchpoints'} }) { diff --git a/admin/matching-rules.pl b/admin/matching-rules.pl index b167026..e682fb5 100755 --- a/admin/matching-rules.pl +++ b/admin/matching-rules.pl @@ -92,9 +92,10 @@ sub add_matching_rule_form { sub add_update_matching_rule { my $template = shift; my $matcher_id = shift; + my $record_type = $input->param('record_type') || 'biblio'; # do parsing - my $matcher = C4::Matcher->new('biblio', 1000); # FIXME biblio only for now + my $matcher = C4::Matcher->new($record_type, 1000); $matcher->code($input->param('code')); $matcher->description($input->param('description')); $matcher->threshold($input->param('threshold')); @@ -203,10 +204,11 @@ sub edit_matching_rule_form { my $matcher = C4::Matcher->fetch($matcher_id); - $template->param(matcher_id => $matcher_id); - $template->param(code => $matcher->code()); - $template->param(description => $matcher->description()); - $template->param(threshold => $matcher->threshold()); + $template->{VARS}->{'matcher_id'} = $matcher_id; + $template->{VARS}->{'code'} = $matcher->code(); + $template->{VARS}->{'description'} = $matcher->description(); + $template->{VARS}->{'threshold'} = $matcher->threshold(); + $template->{VARS}->{'record_type'} = $matcher->record_type(); my $matcher_info = $matcher->dump(); my @matchpoints = (); diff --git a/installer/data/mysql/atomicupdate/importauthorities.pl b/installer/data/mysql/atomicupdate/importauthorities.pl new file mode 100755 index 0000000..f242f61 --- /dev/null +++ b/installer/data/mysql/atomicupdate/importauthorities.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use C4::Context; +my $dbh = C4::Context->dbh; + +$dbh->do( +q|CREATE TABLE `import_auths` ( + `import_record_id` int(11) NOT NULL, + `matched_authid` int(11) default NULL, + `control_number` varchar(25) default NULL, + `original_source` varchar(25) default NULL, + CONSTRAINT `import_auths_ibfk_1` FOREIGN KEY (`import_record_id`) + REFERENCES `import_records` (`import_record_id`) ON DELETE CASCADE ON UPDATE CASCADE, + KEY `matched_authid` (`matched_authid`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8;| +); +print "Upgrade done (Added support for staging authorities)\n"; diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 54498c3..13864ce 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -909,6 +909,21 @@ CREATE TABLE `import_record_matches` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- +-- Table structure for table `import_auths` +-- + +DROP TABLE IF EXISTS `import_auths`; +CREATE TABLE `import_auths` ( + `import_record_id` int(11) NOT NULL, + `matched_authid` int(11) default NULL, + `control_number` varchar(25) default NULL, + `original_source` varchar(25) default NULL, + CONSTRAINT `import_auths_ibfk_1` FOREIGN KEY (`import_record_id`) + REFERENCES `import_records` (`import_record_id`) ON DELETE CASCADE ON UPDATE CASCADE, + KEY `matched_authid` (`matched_authid`), +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -- Table structure for table `import_biblios` -- diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/matching-rules.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/matching-rules.tt index 5835244..2bd8aaf 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/matching-rules.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/matching-rules.tt @@ -220,6 +220,17 @@ function CheckRuleForm(f) { Required +
  • + Required +
  • diff --git a/misc/commit_biblios_file.pl b/misc/commit_biblios_file.pl deleted file mode 100755 index b4be670..0000000 --- a/misc/commit_biblios_file.pl +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/perl - -use strict; -#use warnings; FIXME - Bug 2505 -BEGIN { - # find Koha's Perl modules - # test carefully before changing this - use FindBin; - eval { require "$FindBin::Bin/kohalib.pl" }; -} - -use C4::Context; -use C4::ImportBatch; -use Getopt::Long; - -$| = 1; - -# command-line parameters -my $batch_number = ""; -my $list_batches = 0; -my $want_help = 0; - -my $result = GetOptions( - 'batch-number:s' => \$batch_number, - 'list-batches' => \$list_batches, - 'h|help' => \$want_help -); - -if ($want_help or (not $batch_number and not $list_batches)) { - print_usage(); - exit 0; -} - -if ($list_batches) { - list_batches(); - exit 0; -} - -# FIXME dummy user so that logging won't fail -# in future, probably should tie to a real user account -C4::Context->set_userenv(0, 'batch', 0, 'batch', 'batch', 'batch', 'batch', 'batch'); - -my $dbh = C4::Context->dbh; -$dbh->{AutoCommit} = 0; -if ($batch_number =~ /^\d+$/ and $batch_number > 0) { - my $batch = GetImportBatch($batch_number); - die "$0: import batch $batch_number does not exist in database\n" unless defined $batch; - die "$0: import batch $batch_number status is '" . $batch->{'import_status'} . "', and therefore cannot be imported\n" - unless $batch->{'import_status'} eq "staged" or $batch->{'import_status'} eq "reverted"; - process_batch($batch_number); - $dbh->commit(); -} else { - die "$0: please specify a numeric batch ID\n"; -} - -exit 0; - -sub list_batches { - my $results = GetAllImportBatches(); - print sprintf("%5.5s %-25.25s %-25.25s %-10.10s\n", "#", "File name", "Batch comments", "Status"); - print '-' x 5, ' ' , '-' x 25, ' ', '-' x 25, ' ', '-' x 10, "\n" ; - foreach my $batch (@{ $results}) { - if ($batch->{'import_status'} eq "staged" or $batch->{'import_status'} eq "reverted") { - print sprintf("%5.5s %-25.25s %-25.25s %-10.10s\n", - $batch->{'import_batch_id'}, - $batch->{'file_name'}, - $batch->{'comments'}, - $batch->{'import_status'}); - } - } -} - -sub process_batch { - my ($import_batch_id) = @_; - - print "... importing MARC records -- please wait\n"; - my ($num_added, $num_updated, $num_items_added, $num_items_errored, $num_ignored) = - BatchCommitBibRecords($import_batch_id, '', 100, \&print_progress_and_commit); - print "... finished importing MARC records\n"; - - print <<_SUMMARY_; - -MARC record import report ----------------------------------------- -Batch number: $import_batch_id -Number of new bibs added: $num_added -Number of bibs replaced: $num_updated -Number of bibs ignored: $num_ignored -Number of items added: $num_items_added -Number of items ignored: $num_items_errored - -Note: an item is ignored if its barcode is a -duplicate of one already in the database. -_SUMMARY_ -} - -sub print_progress_and_commit { - my $recs = shift; - print "... processed $recs records\n"; - $dbh->commit(); -} - -sub print_usage { - print <<_USAGE_; -$0: import a batch of staged MARC records into database. - -Use this batch job to complete the import of a batch of -MARC records that was staged either by the batch job -stage_biblios_file.pl or by the Koha Tools option -"Stage MARC Records for Import". - -Parameters: - --batch-number <#> number of the record batch - to import - --list-batches print a list of record batches - available to commit - --help or -h show this message. -_USAGE_ -} diff --git a/misc/commit_file.pl b/misc/commit_file.pl new file mode 100755 index 0000000..1f54faf --- /dev/null +++ b/misc/commit_file.pl @@ -0,0 +1,151 @@ +#!/usr/bin/perl + +use strict; +#use warnings; FIXME - Bug 2505 +BEGIN { + # find Koha's Perl modules + # test carefully before changing this + use FindBin; + eval { require "$FindBin::Bin/kohalib.pl" }; +} + +use C4::Context; +use C4::ImportBatch; +use Getopt::Long; + +$| = 1; + +# command-line parameters +my $batch_number = ""; +my $list_batches = 0; +my $revert = 0; +my $want_help = 0; + +my $result = GetOptions( + 'batch-number:s' => \$batch_number, + 'list-batches' => \$list_batches, + 'revert' => \$revert, + 'h|help' => \$want_help +); + +if ($want_help or (not $batch_number and not $list_batches)) { + print_usage(); + exit 0; +} + +if ($list_batches) { + list_batches(); + exit 0; +} + +# FIXME dummy user so that logging won't fail +# in future, probably should tie to a real user account +C4::Context->set_userenv(0, 'batch', 0, 'batch', 'batch', 'batch', 'batch', 'batch'); + +my $dbh = C4::Context->dbh; +$dbh->{AutoCommit} = 0; +if ($batch_number =~ /^\d+$/ and $batch_number > 0) { + my $batch = GetImportBatch($batch_number); + die "$0: import batch $batch_number does not exist in database\n" unless defined $batch; + if ($revert) { + die "$0: import batch $batch_number status is '" . $batch->{'import_status'} . "', and therefore cannot be imported\n" + unless $batch->{'import_status'} eq "imported"; + revert_batch($batch_number); + } else { + die "$0: import batch $batch_number status is '" . $batch->{'import_status'} . "', and therefore cannot be imported\n" + unless $batch->{'import_status'} eq "staged" or $batch->{'import_status'} eq "reverted"; + process_batch($batch_number); + } + $dbh->commit(); +} else { + die "$0: please specify a numeric batch ID\n"; +} + +exit 0; + +sub list_batches { + my $results = GetAllImportBatches(); + print sprintf("%5.5s %-25.25s %-25.25s %-10.10s\n", "#", "File name", "Batch comments", "Status"); + print '-' x 5, ' ' , '-' x 25, ' ', '-' x 25, ' ', '-' x 10, "\n" ; + foreach my $batch (@{ $results}) { + if ($batch->{'import_status'} eq "staged" or $batch->{'import_status'} eq "reverted") { + print sprintf("%5.5s %-25.25s %-25.25s %-10.10s\n", + $batch->{'import_batch_id'}, + $batch->{'file_name'}, + $batch->{'comments'}, + $batch->{'import_status'}); + } + } +} + +sub process_batch { + my ($import_batch_id) = @_; + + print "... importing MARC records -- please wait\n"; + my ($num_added, $num_updated, $num_items_added, $num_items_errored, $num_ignored) = + BatchCommitRecords($import_batch_id, '', 100, \&print_progress_and_commit); + print "... finished importing MARC records\n"; + + print <<_SUMMARY_; + +MARC record import report +---------------------------------------- +Batch number: $import_batch_id +Number of new records added: $num_added +Number of records replaced: $num_updated +Number of records ignored: $num_ignored +Number of items added: $num_items_added +Number of items ignored: $num_items_errored + +Note: an item is ignored if its barcode is a +duplicate of one already in the database. +_SUMMARY_ +} + +sub revert_batch { + my ($import_batch_id) = @_; + + print "... reverting batch -- please wait\n"; + my ($num_deleted, $num_errors, $num_reverted, $num_items_deleted, $num_ignored) = + BatchRevertRecords($import_batch_id, 100, \&print_progress_and_commit); + print "... finished reverting batch\n"; + + print <<_SUMMARY_; + +MARC record import report +---------------------------------------- +Batch number: $import_batch_id +Number of records deleted: $num_deleted +Number of errors: $num_errors +Number of records reverted: $num_reverted +Number of records ignored: $num_ignored +Number of items added: $num_items_deleted + +_SUMMARY_ +} + + +sub print_progress_and_commit { + my $recs = shift; + print "... processed $recs records\n"; + $dbh->commit(); +} + +sub print_usage { + print <<_USAGE_; +$0: import a batch of staged MARC records into database. + +Use this batch job to complete the import of a batch of +MARC records that was staged either by the batch job +stage_file.pl or by the Koha Tools option +"Stage MARC Records for Import". + +Parameters: + --batch-number <#> number of the record batch + to import + --list-batches print a list of record batches + available to commit + --revert revert a batch instead of importing it + --help or -h show this message. +_USAGE_ +} diff --git a/misc/cronjobs/import_webservice_batch.pl b/misc/cronjobs/import_webservice_batch.pl index d1b30ef..3f57779 100755 --- a/misc/cronjobs/import_webservice_batch.pl +++ b/misc/cronjobs/import_webservice_batch.pl @@ -54,4 +54,4 @@ EOF my $batch_ids = GetStagedWebserviceBatches() or exit; $framework ||= ''; -BatchCommitBibRecords($_, $framework) foreach @$batch_ids; +BatchCommitRecords($_, $framework) foreach @$batch_ids; diff --git a/misc/stage_biblios_file.pl b/misc/stage_biblios_file.pl deleted file mode 100755 index 6e2b30c..0000000 --- a/misc/stage_biblios_file.pl +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/perl - -# This file is part of Koha. -# -# Copyright (C) 2007 LibLime -# Parts Copyright BSZ 2011 -# -# 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 2 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 this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -use strict; -use warnings; -BEGIN { - # find Koha's Perl modules - # test carefully before changing this - use FindBin; - eval { require "$FindBin::Bin/kohalib.pl" }; -} - -use C4::Context; -use C4::ImportBatch; -use C4::Matcher; -use Getopt::Long; - -$| = 1; - -# command-line parameters -my $encoding = ""; -my $match_bibs = 0; -my $add_items = 0; -my $input_file = ""; -my $batch_comment = ""; -my $want_help = 0; -my $no_replace ; - -my $result = GetOptions( - 'encoding:s' => \$encoding, - 'file:s' => \$input_file, - 'match-bibs:s' => \$match_bibs, - 'add-items' => \$add_items, - 'no-replace' => \$no_replace, - 'comment:s' => \$batch_comment, - 'h|help' => \$want_help -); - -if ($encoding eq "") { - $encoding = "utf8"; -} - -if (not $result or $input_file eq "" or $want_help) { - print_usage(); - exit 0; -} - -unless (-r $input_file) { - die "$0: cannot open input file $input_file: $!\n"; -} - -my $dbh = C4::Context->dbh; -$dbh->{AutoCommit} = 0; -process_batch($input_file, $match_bibs, $add_items, $batch_comment); -$dbh->commit(); - -exit 0; - -sub process_batch { - my ($input_file, $match_bibs, $add_items, $batch_comment) = @_; - - open IN, "<$input_file" or die "$0: cannot open input file $input_file: $!\n"; - my $marc_records = ""; - $/ = "\035"; - my $num_input_records = 0; - while () { - s/^\s+//; - s/\s+$//; - next unless $_; # skip if record has only whitespace, as might occur - # if file includes newlines between each MARC record - $marc_records .= $_; # FIXME - this sort of string concatenation - # is probably rather inefficient - $num_input_records++; - } - close IN; - - print "... staging MARC records -- please wait\n"; - my ($batch_id, $num_valid, $num_items, @import_errors) = - BatchStageMarcRecords($encoding, $marc_records, $input_file, $batch_comment, '', $add_items, 0, - 100, \&print_progress_and_commit); - print "... finished staging MARC records\n"; - - my $num_with_matches = 0; - if ($match_bibs) { - my $matcher = C4::Matcher->fetch($match_bibs) ; - if (! defined $matcher) { - $matcher = C4::Matcher->new('biblio'); - $matcher->add_simple_matchpoint('isbn', 1000, '020', 'a', -1, 0, ''); - $matcher->add_simple_required_check('245', 'a', -1, 0, '', - '245', 'a', -1, 0, ''); - } else { - SetImportBatchMatcher($batch_id, $match_bibs); - } - # set default record overlay behavior - SetImportBatchOverlayAction($batch_id, ($no_replace) ? 'ignore' : 'replace'); - SetImportBatchNoMatchAction($batch_id, 'create_new'); - SetImportBatchItemAction($batch_id, 'always_add'); - print "... looking for matches with records already in database\n"; - $num_with_matches = BatchFindBibDuplicates($batch_id, $matcher, 10, 100, \&print_progress_and_commit); - print "... finished looking for matches\n"; - } - - my $num_invalid_bibs = scalar(@import_errors); - print <<_SUMMARY_; - -MARC record staging report ------------------------------------- -Input file: $input_file -Number of input bibs: $num_input_records -Number of valid bibs: $num_valid -Number of invalid bibs: $num_invalid_bibs -_SUMMARY_ - if ($match_bibs) { - print "Number of bibs matched: $num_with_matches\n"; - } else { - print "Incoming bibs not matched against existing bibs (--match-bibs option not supplied)\n"; - } - if ($add_items) { - print "Number of items parsed: $num_items\n"; - } else { - print "No items parsed (--add-items option not supplied)\n"; - } - - print "\n"; - print "Batch number assigned: $batch_id\n"; - print "\n"; -} - -sub print_progress_and_commit { - my $recs = shift; - $dbh->commit(); - print "... processed $recs records\n"; -} - -sub print_usage { - print <<_USAGE_; -$0: stage MARC bib file into reservoir. - -Use this batch job to load a file of MARC bibliographic records -(with optional item information) into the Koha reservoir. - -After running this program to stage your file, you can use -either the batch job commit_biblios_file.pl or the Koha -Tools option "Manage Staged MARC Records" to load the -records into the main Koha database. - -Parameters: - --file name of input MARC bib file - --encoding encoding of MARC records, default is utf8. - Other possible options are: MARC-8, - ISO_5426, ISO_6937, ISO_8859-1, EUC-KR - --match-bibs use this option to match bibs - in the file with bibs already in - the database for future overlay. - If isn't defined, a default - MARC21 ISBN & title match rule will be applied. - --add-items use this option to specify that - item data is embedded in the MARC - bibs and should be parsed. - --no-replace overlay action for bib record: default is to - replace extant bib with the imported record. - --comment optional comment to describe - the record batch; if the comment - has spaces in it, surround the - comment with quotation marks. - --help or -h show this message. -_USAGE_ -} diff --git a/misc/stage_file.pl b/misc/stage_file.pl new file mode 100755 index 0000000..3cf6309 --- /dev/null +++ b/misc/stage_file.pl @@ -0,0 +1,197 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Copyright (C) 2007 LibLime +# Parts Copyright BSZ 2011 +# Parts Copyright C & P Bibliography Services 2012 +# +# 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 2 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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use strict; +use warnings; +BEGIN { + # find Koha's Perl modules + # test carefully before changing this + use FindBin; + eval { require "$FindBin::Bin/kohalib.pl" }; +} + +use C4::Context; +use C4::ImportBatch; +use C4::Matcher; +use Getopt::Long; + +$| = 1; + +# command-line parameters +my $record_type = "biblio"; +my $encoding = ""; +my $authorities = 0; +my $match = 0; +my $add_items = 0; +my $input_file = ""; +my $batch_comment = ""; +my $want_help = 0; +my $no_replace ; + +my $result = GetOptions( + 'encoding:s' => \$encoding, + 'file:s' => \$input_file, + 'match|match-bibs:s' => \$match, + 'add-items' => \$add_items, + 'no-replace' => \$no_replace, + 'comment:s' => \$batch_comment, + 'authorities' => \$authorities, + 'h|help' => \$want_help +); + +$record_type = 'biblio' if ($authorities); + +if ($encoding eq "") { + $encoding = "utf8"; +} + +if (not $result or $input_file eq "" or $want_help) { + print_usage(); + exit 0; +} + +unless (-r $input_file) { + die "$0: cannot open input file $input_file: $!\n"; +} + +my $dbh = C4::Context->dbh; +$dbh->{AutoCommit} = 0; +process_batch($input_file, $record_type, $match, $add_items, $batch_comment); +$dbh->commit(); + +exit 0; + +sub process_batch { + my ($input_file, $record_type, $match, $add_items, $batch_comment) = @_; + + open IN, "<$input_file" or die "$0: cannot open input file $input_file: $!\n"; + my $marc_records = ""; + $/ = "\035"; + my $num_input_records = 0; + while () { + s/^\s+//; + s/\s+$//; + next unless $_; # skip if record has only whitespace, as might occur + # if file includes newlines between each MARC record + $marc_records .= $_; # FIXME - this sort of string concatenation + # is probably rather inefficient + $num_input_records++; + } + close IN; + + print "... staging MARC records -- please wait\n"; + my ($batch_id, $num_valid_records, $num_items, @import_errors) = + BatchStageMarcRecords($record_type, $encoding, $marc_records, $input_file, $batch_comment, '', $add_items, 0, + 100, \&print_progress_and_commit); + print "... finished staging MARC records\n"; + + my $num_with_matches = 0; + if ($match) { + my $matcher = C4::Matcher->fetch($match) ; + if (defined $matcher) { + SetImportBatchMatcher($batch_id, $match); + } elsif ($record_type eq 'biblio') { + $matcher = C4::Matcher->new($record_type); + $matcher->add_simple_matchpoint('isbn', 1000, '020', 'a', -1, 0, ''); + $matcher->add_simple_required_check('245', 'a', -1, 0, '', + '245', 'a', -1, 0, ''); + } + # set default record overlay behavior + SetImportBatchOverlayAction($batch_id, ($no_replace) ? 'ignore' : 'replace'); + SetImportBatchNoMatchAction($batch_id, 'create_new'); + SetImportBatchItemAction($batch_id, 'always_add'); + print "... looking for matches with records already in database\n"; + $num_with_matches = BatchFindDuplicates($batch_id, $matcher, 10, 100, \&print_progress_and_commit); + print "... finished looking for matches\n"; + } + + my $num_invalid_records = scalar(@import_errors); + print <<_SUMMARY_; + +MARC record staging report +------------------------------------ +Input file: $input_file +Record type: $record_type +Number of input records: $num_input_records +Number of valid records: $num_valid_records +Number of invalid records: $num_invalid_records +_SUMMARY_ + if ($match) { + print "Number of records matched: $num_with_matches\n"; + } else { + print "Incoming records not matched against existing records (--match option not supplied)\n"; + } + if ($record_type eq 'biblio') { + if ($add_items) { + print "Number of items parsed: $num_items\n"; + } else { + print "No items parsed (--add-items option not supplied)\n"; + } + } + + print "\n"; + print "Batch number assigned: $batch_id\n"; + print "\n"; +} + +sub print_progress_and_commit { + my $recs = shift; + $dbh->commit(); + print "... processed $recs records\n"; +} + +sub print_usage { + print <<_USAGE_; +$0: stage MARC file into reservoir. + +Use this batch job to load a file of MARC bibliographic +(with optional item information) or authority records into +the Koha reservoir. + +After running this program to stage your file, you can use +either the batch job commit_file.pl or the Koha +Tools option "Manage Staged MARC Records" to load the +records into the main Koha database. + +Parameters: + --file name of input MARC bib file + --authorities stage authority records instead of bibs + --encoding encoding of MARC records, default is utf8. + Other possible options are: MARC-8, + ISO_5426, ISO_6937, ISO_8859-1, EUC-KR + --match use this option to match records + in the file with records already in + the database for future overlay. + If isn't defined, a default + MARC21 ISBN & title match rule will be applied + for bib imports. + --add-items use this option to specify that + item data is embedded in the MARC + bibs and should be parsed. + --no-replace overlay action for record: default is to + replace extant with the imported record. + --comment optional comment to describe + the record batch; if the comment + has spaces in it, surround the + comment with quotation marks. + --help or -h show this message. +_USAGE_ +} diff --git a/svc/import_bib b/svc/import_bib index 5e7e493..c130204 100755 --- a/svc/import_bib +++ b/svc/import_bib @@ -92,7 +92,7 @@ sub import_bib { $marcxml =~ s/<\?xml.*?\?>//i; # XXX we are ignoring the result of this; - BatchCommitBibRecords($batch_id, $framework) if lc($import_mode) eq 'direct'; + BatchCommitRecords($batch_id, $framework) if lc($import_mode) eq 'direct'; $result->{'status'} = "ok"; $result->{'import_batch_id'} = $batch_id; diff --git a/tools/manage-marc-import.pl b/tools/manage-marc-import.pl index 8a8d9e8..7346c59 100755 --- a/tools/manage-marc-import.pl +++ b/tools/manage-marc-import.pl @@ -244,7 +244,7 @@ sub commit_batch { $callback = progress_callback($job, $dbh); } my ($num_added, $num_updated, $num_items_added, $num_items_errored, $num_ignored) = - BatchCommitBibRecords($import_batch_id, $framework, 50, $callback); + BatchCommitRecords($import_batch_id, $framework, 50, $callback); $dbh->commit(); my $results = { @@ -273,7 +273,7 @@ sub revert_batch { $callback = progress_callback($job, $dbh); } my ($num_deleted, $num_errors, $num_reverted, $num_items_deleted, $num_ignored) = - BatchRevertBibRecords($import_batch_id, 50, $callback); + BatchRevertRecords($import_batch_id, 50, $callback); $dbh->commit(); my $results = { -- 1.7.2.5 From jcamins at cpbibliography.com Thu Jun 14 01:27:41 2012 From: jcamins at cpbibliography.com (Jared Camins-Esakov) Date: Wed, 13 Jun 2012 19:27:41 -0400 Subject: [Koha-patches] [PATCH] Bug 6720: Display the authority type in OPAC Message-ID: <1339630061-3991-1-git-send-email-jcamins@cpbibliography.com> Due to a peculiarity in the way SearchAuthorities worked, the authority search results on the OPAC always listed the authority type that the user searched for, rather than the authority type of the results. --- C4/AuthoritiesMarc.pm | 1 + .../en/modules/opac-authoritiessearchresultlist.tt | 2 +- 2 files changed, 2 insertions(+), 1 deletions(-) diff --git a/C4/AuthoritiesMarc.pm b/C4/AuthoritiesMarc.pm index 5ea5098..405e689 100644 --- a/C4/AuthoritiesMarc.pm +++ b/C4/AuthoritiesMarc.pm @@ -351,6 +351,7 @@ sub SearchAuthorities { $reported_tag .= '$' . $_->[0] . $_->[1]; } } + $newline{authtype} = GetAuthType(GetAuthTypeCode($authid))->{'summary'}; $newline{summary} = $summary; $newline{even} = $counter % 2; $newline{reported_tag} = $reported_tag; diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt index 5fdfb27..ecd345d 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt @@ -55,7 +55,7 @@
    [% resul.summary %] - [% authtypetext %] + [% resul.authtype %] -- 1.7.2.5 From jcamins at cpbibliography.com Thu Jun 14 01:29:27 2012 From: jcamins at cpbibliography.com (Jared Camins-Esakov) Date: Wed, 13 Jun 2012 19:29:27 -0400 Subject: [Koha-patches] [PATCH] Bug 8206: Specify index in OPAC authority search Message-ID: <1339630167-4040-1-git-send-email-jcamins@cpbibliography.com> Adds a dropdown to allow the user to choose to search the 'mainentry,' 'match-heading,' and 'see-from' indexes, in addition to the 'any' index which is the default. To test (you will need authority records with see-from and see-also headings): 1. Go to the browse subjects and authors section in the OPAC 2. Do a search for a fairly generic term that is used as a see-also term in a lot of records. Note that your search results include both the record that you wanted and all the other records that refer to it. 3. Apply the patch. 4. Repeat the search from step 2. Notice there is no change to the results. 5. Repeat the search from step 2, but choose "in main entry" and observe that you are now only seeing authority records with the search entered in their main entry. 6. Repeat the search from step 2, but choose "in any heading" and observe that the results are the same as in step 2. This is intentional, so that in the future notes in authorities can be made searchable. 7. Search for an obsolete form of heading with the "in keyword" option selected. Notice what results you get. 8. Repeat the search from step 7 with the "in see from heading" option selected, and notice that the results are more specific (at least if the term you are searching for is generic enough to find false positives in keyword searches on current headings) --- .../prog/en/modules/opac-authorities-home.tt | 16 +++++++++++----- opac/opac-authorities-home.pl | 20 ++++++-------------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-authorities-home.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-authorities-home.tt index 04d5a8c..8357fe7 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-authorities-home.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-authorities-home.tt @@ -22,15 +22,21 @@ [% END %] [% END %] - - - - - + + + + +
  • -
    Serials planning @@ -1371,7 +1370,7 @@ $(document).ready(function() {
  • - +
    @@ -1441,7 +1440,7 @@ $(document).ready(function() { - + -- 1.7.9.5 From jcamins at cpbibliography.com Fri Jun 15 20:00:26 2012 From: jcamins at cpbibliography.com (Jared Camins-Esakov) Date: Fri, 15 Jun 2012 14:00:26 -0400 Subject: [Koha-patches] [PATCH] Bug 8255: allow local cover images to be cached Message-ID: <1339783226-3751-1-git-send-email-jcamins@cpbibliography.com> --- catalogue/image.pl | 3 +-- opac/opac-image.pl | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/catalogue/image.pl b/catalogue/image.pl index 4fa77e9..ff74cbe 100755 --- a/catalogue/image.pl +++ b/catalogue/image.pl @@ -92,8 +92,7 @@ if ( C4::Context->preference("LocalCoverImages") ) { } print $data->header( -type => $mimetype, - -'Cache-Control' => 'no-store', - -expires => 'now', + -expires => '+30m', -Content_Length => length($image) ), $image; diff --git a/opac/opac-image.pl b/opac/opac-image.pl index ba554c7..e2dc556 100755 --- a/opac/opac-image.pl +++ b/opac/opac-image.pl @@ -92,8 +92,7 @@ if ( C4::Context->preference("OPACLocalCoverImages") ) { } print $data->header( -type => $mimetype, - -'Cache-Control' => 'no-store', - -expires => 'now', + -expires => '+30m', -Content_Length => length($image) ), $image; -- 1.7.2.5 From tomascohen at gmail.com Fri Jun 15 20:02:01 2012 From: tomascohen at gmail.com (Tomas Cohen Arazi) Date: Fri, 15 Jun 2012 15:02:01 -0300 Subject: [Koha-patches] [PATCH] Bug 8251 - Patrons get incorrectly debarred Message-ID: <1339783321-9722-1-git-send-email-tomascohen@gmail.com> Patrons get incorrectly debarred because of the use of Datetime->delta_days wich happens to always return a positive number. Also changed the use of Datetime->truncate function so it follows the docs, using 'day' instead of 'days' (which is used in DateTime::Duration). This patch has been tested against master. --- Koha/Calendar.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Koha/Calendar.pm b/Koha/Calendar.pm index f63e7eb..dc132cd 100644 --- a/Koha/Calendar.pm +++ b/Koha/Calendar.pm @@ -173,9 +173,9 @@ sub days_between { my $dateend_temp = $end_dt->clone(); # start and end should not be closed days - my $duration = $dateend_temp->delta_days($datestart_temp); - $datestart_temp->truncate( to => 'days' ); - $dateend_temp->truncate( to => 'days' ); + $datestart_temp->truncate( to => 'day' ); + $dateend_temp->truncate( to => 'day' ); + my $duration = $dateend_temp - $datestart_temp; while ( DateTime->compare( $datestart_temp, $dateend_temp ) == -1 ) { $datestart_temp->add( days => 1 ); if ( $self->is_holiday($datestart_temp) ) { -- 1.7.9.5 From jcamins at cpbibliography.com Fri Jun 15 20:46:22 2012 From: jcamins at cpbibliography.com (Jared Camins-Esakov) Date: Fri, 15 Jun 2012 14:46:22 -0400 Subject: [Koha-patches] [PATCH] Bug 8256: Teach webservice to select reports by name Message-ID: <1339785982-4046-1-git-send-email-jcamins@cpbibliography.com> Adds the ability to pass a hash to C4::Reports::Guided::get_saved_report which specifies a name or id to select the report. --- C4/Reports/Guided.pm | 26 +++++++++++++++++++++----- opac/svc/report | 11 ++++++----- svc/report | 25 ++++++++++++++++++++----- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/C4/Reports/Guided.pm b/C4/Reports/Guided.pm index f1ebe0c..5e44824 100644 --- a/C4/Reports/Guided.pm +++ b/C4/Reports/Guided.pm @@ -607,13 +607,29 @@ sub get_saved_reports { } sub get_saved_report { - my ($id) = @_; my $dbh = C4::Context->dbh(); - my $query = " SELECT * FROM saved_sql WHERE id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($id); + my $query; + my $sth; + my $report_arg; + if ($#_ == 0 && ref $_[0] eq 'SCALAR') { + ($report_arg) = @_; + $query = " SELECT * FROM saved_sql WHERE id = ?"; + } elsif (ref $_[0] eq 'HASH') { + my ($selector) = @_; + if ($selector->{name}) { + $query = " SELECT * FROM saved_sql WHERE report_name LIKE ?"; + $report_arg = $selector->{name}; + } elsif ($selector->{id} || $selector->{id} eq '0') { + $query = " SELECT * FROM saved_sql WHERE id = ?"; + $report_arg = $selector->{id}; + } + } else { + return; + } + $sth = $dbh->prepare($query); + $sth->execute($report_arg); my $data = $sth->fetchrow_hashref(); - return ( $data->{'savedsql'}, $data->{'type'}, $data->{'report_name'}, $data->{'notes'}, $data->{'cache_expiry'}, $data->{'public'} ); + return ( $data->{'savedsql'}, $data->{'type'}, $data->{'report_name'}, $data->{'notes'}, $data->{'cache_expiry'}, $data->{'public'}, $data->{'id'} ); } =item create_compound($masterID,$subreportID) diff --git a/opac/svc/report b/opac/svc/report index 0f9d5fb..c02a2eb 100755 --- a/opac/svc/report +++ b/opac/svc/report @@ -28,18 +28,19 @@ use CGI; use Koha::Cache; my $query = CGI->new(); -my $report = $query->param('id'); +my $report_id = $query->param('id'); +my $report_name = $query->param('name'); my $cache; -my ( $sql, $type, $name, $notes, $cache_expiry, $public ) = - get_saved_report($report); +my ( $sql, $type, $report_name, $notes, $cache_expiry, $public, $report_id ) = + get_saved_report($report_name ? { 'name' => $report_name } : { 'id' => $report_id } ); die "Sorry this report is not public\n" unless $public; if (Koha::Cache->is_cache_active) { $cache = Koha::Cache->new( ); - my $page = $cache->get_from_cache("opac:report:$report"); + my $page = $cache->get_from_cache("opac:report:$report_id"); if ($page) { print $query->header; print $page; @@ -56,5 +57,5 @@ my $json_text = to_json($lines); print $json_text; if (Koha::Cache->is_cache_active) { - $cache->set_in_cache( "opac:report:$report", $json_text, $cache_expiry ); + $cache->set_in_cache( "opac:report:$report_id", $json_text, $cache_expiry ); } diff --git a/svc/report b/svc/report index 18e1986..9917df3 100755 --- a/svc/report +++ b/svc/report @@ -30,9 +30,15 @@ use Koha::Cache; my $query = CGI->new(); -my $report = $query->param('id'); +my $report_id = $query->param('id'); +my $report_name = $query->param('name'); my $cache; +my $sql; +my $type; +my $notes; +my $cache_expiry; +my $public; my ( $template, $loggedinuser, $cookie ) = get_template_and_user( { @@ -45,8 +51,15 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( ); if (Koha::Cache->is_cache_active) { + if ($report_name) { # When retrieving by name, we have to hit the + # database to get the ID before we can check + # the cache. Yuck. + ( $sql, $type, $report_name, $notes, $cache_expiry, $public, $report_id ) = + get_saved_report( { 'name' => $report_name } ); + } + $cache = Koha::Cache->new(); - my $page = $cache->get_from_cache("intranet:report:$report"); + my $page = $cache->get_from_cache("intranet:report:$report_id"); if ($page) { print $query->header; print $page; @@ -57,8 +70,10 @@ if (Koha::Cache->is_cache_active) { print $query->header; # $public isnt used for intranet -my ( $sql, $type, $name, $notes, $cache_expiry, $public ) = - get_saved_report($report); +unless ($sql) { + ( $sql, $type, $report_name, $notes, $cache_expiry, $public, $report_id ) = + get_saved_report($report_name ? { 'name' => $report_name } : { 'id' => $report_id } ); +} my $offset = 0; my $limit = C4::Context->preference("SvcMaxReportRows") || 10; my ( $sth, $errors ) = execute_query( $sql, $offset, $limit ); @@ -67,5 +82,5 @@ my $json_text = to_json($lines); print $json_text; if (Koha::Cache->is_cache_active) { - $cache->set_in_cache( "intranet:report:$report", $json_text, $cache_expiry ); + $cache->set_in_cache( "intranet:report:$report_id", $json_text, $cache_expiry ); } -- 1.7.2.5 From Katrin.Fischer.83 at web.de Sat Jun 16 14:21:37 2012 From: Katrin.Fischer.83 at web.de (Katrin Fischer) Date: Sat, 16 Jun 2012 14:21:37 +0200 Subject: [Koha-patches] [PATCH] Bug 7905: Follow up - Multi-line subscription notes Message-ID: <1339849297-10955-1-git-send-email-Katrin.Fischer.83@web.de> This patch adds the TT filter to other places where we are displaying the subscription notes: - OPAC detail page, subscription tab - OPAC subscription brief history page - Staff detail page, subscription tab --- .../prog/en/modules/catalogue/detail.tt | 2 +- koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt | 4 ++-- .../prog/en/modules/opac-serial-issues.tt | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt index ce52040..df0ffe2 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt @@ -478,7 +478,7 @@ function verify_images() { [% FOREACH subscription IN subscriptions %] [% IF ( subscription.branchname ) %]

    At library: [% subscription.branchname %]

    [% ELSE %] [% IF ( subscription.branchcode ) %]

    At library: [% subscription.branchcode %]

    [% END %][% END %] - [% IF ( subscription.subscriptionnotes ) %]

    [% subscription.subscriptionnotes %]

    [% END %] + [% IF ( subscription.subscriptionnotes ) %]

    [% subscription.subscriptionnotes FILTER html_line_break %]

    [% END %] [% IF ( subscription.latestserials ) %]

    The [% subscription.staffdisplaycount %] latest issues related to this subscription:

    diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt index 776f82f..1d00422 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt @@ -956,10 +956,10 @@ YAHOO.util.Event.onContentReady("furtherm", function () { [% FOREACH subscription IN subscriptions %] [% IF ( subscription.branchname ) %]

    At library: [% subscription.branchname %]

    [% ELSE %] [% IF ( subscription.branchcode ) %]

    At library: [% subscription.branchcode %]

    [% END %][% END %] - [% IF ( subscription.subscriptionnotes ) %]

    [% subscription.subscriptionnotes %]

    [% END %] + [% IF ( subscription.subscriptionnotes ) %]

    [% subscription.subscriptionnotes FILTER html_line_break %]

    [% END %]

    Subscription from: [% subscription.histstartdate | $KohaDates %] to:[% IF ( subscription.histenddate ) %] [% subscription.histenddate | $KohaDates %] [% ELSE %] now (current)[% END %]

    [% IF ( subscription.missinglist ) %]

    Missing issues: [% subscription.missinglist %]

    [% END %] - [% IF ( subscription.opacnote ) %]

    ([% subscription.opacnote %])

    [% END %] + [% IF ( subscription.opacnote ) %]

    [% subscription.opacnote FILTER html_line_break %]

    [% END %] [% IF ( subscription.latestserials ) %]

    The [% subscription.opacdisplaycount %] latest issues for this subscription:

    diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-serial-issues.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-serial-issues.tt index 790aa48..b0d0db7 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-serial-issues.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-serial-issues.tt @@ -89,7 +89,10 @@

    The subscription expired on [% subscription_LOO.histenddate %]

    [% END %]

    -

    [% subscription_LOO.branchname %] [% subscription_LOO.notes %]

    +

    [% subscription_LOO.branchname %]

    + [% IF ( subscription_LOO.notes ) %] +

    [% subscription_LOO.notes FILTER html_line_break %]

    + [% END %] [% IF ( subscription_LOO.recievedlist ) %]
    Available issues

    @@ -105,7 +108,7 @@ [% IF ( subscription_LOO.opacnote ) %]

    Issues summary

    - [% subscription_LOO.opacnote %] + [% subscription_LOO.opacnote FILTER html_line_break %]

    [% END %] [% IF ( subscription_LOO.letter ) %] -- 1.7.9.5 From colin.campbell at ptfs-europe.com Mon Jun 18 12:33:47 2012 From: colin.campbell at ptfs-europe.com (Colin Campbell) Date: Mon, 18 Jun 2012 11:33:47 +0100 Subject: [Koha-patches] [PATCH] Bug 6939 DefaultClassificationSource should be default in 942 Message-ID: <1340015627-7913-1-git-send-email-colin.campbell@ptfs-europe.com> A logic bug in the original code adding DefaultClassificationSource caused the default not to be used (the last used value was used instead) The bug was fixed in additem by bug 2398 but addbiblio's use of the code was not fixed. --- cataloguing/addbiblio.pl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cataloguing/addbiblio.pl b/cataloguing/addbiblio.pl index d5778a4..d9edf7a 100755 --- a/cataloguing/addbiblio.pl +++ b/cataloguing/addbiblio.pl @@ -215,10 +215,8 @@ sub build_authorized_values_list { ($class_source eq $default_source); push @authorised_values, $class_source; $authorised_lib{$class_source} = $class_sources->{$class_source}->{'description'}; - $value = $class_source unless ($value); - $value = $default_source unless ($value); } - #---- "true" authorised value + $value = $default_source unless $value; } else { $authorised_values_sth->execute( -- 1.7.11 From jcamins at cpbibliography.com Mon Jun 18 23:47:06 2012 From: jcamins at cpbibliography.com (Jared Camins-Esakov) Date: Mon, 18 Jun 2012 17:47:06 -0400 Subject: [Koha-patches] [PATCH] Bug 8268: Add database dump to export tool Message-ID: <1340056026-3901-1-git-send-email-jcamins@cpbibliography.com> This patch builds on work by Lars Wirzenius for the Koha packages. To date, the only way for a Koha librarian to obtain a complete backup of their system has been to log into the system via SSH (or FTP) to download the mysqldump file. This patch makes it possible for superlibrarians in properly configured systems to download night backups via the staff client's Export tool. Recognizing that this is functionality with potentially very grave security implications, system administrators must manually enable these features in the koha-conf.xml configuration file. The following configuration settings have been added to the koha-conf.xml file: * backupdir => directory where backups should be stored. * backup_db_via_tools => whether to allow superlibrarians to download database backups via the Export tool. The default is disabled, and there is no way -- by design -- to enable this option without manually editing koha-conf.xml. * backup_conf_via_tools => whether to allow superlibrarians to download configuration backups via the Export tool (this may be applicable to packages only). The default is disabled, and there is no way -- by design -- to enable this option without manually editing koha-conf.xml. This commit modifies the following scripts to make use of the new backupdir configuration option: * koha-dump and koha-run-backups in the Debian packages * The sample backup script misc/cronjobs/backup.sh Note that for security reasons, superlibrarians will not be allowed to download files that are not owned by the web server's effective user. This imposes a de facto dependency on ITK (for Apache) or running the web server as the Koha user (as is done with Plack). To test: 1. Apply patch. 2. Go to export page as a superlibrarian. Notice that no additional export options appear because they have not been enabled. 3. Add $KOHADEV/var/spool to the section of your koha-conf.xml (note that you will need to adjust that so that it is pointing at a logical directory). 4. Create the aforementioned directory. 5. Go to export page as a superlibrarian. Notice that no additional export options appear because they have not been enabled. 6. Add 1 to the section of your koha-conf.xml 7. Go to the export page as a superlibrarian. Notice the new tab. 8. Go to the export page as a non-superlibrarian. Notice there is no new tab. 9. Run: mysqldump -u koha -p koha | gzip > $BACKUPDIR/backup.sql.gz (substituting appropriate user, password, and database name) 10. Go to the export page as a superlibrarian, and look at the "Export database" tab. If you are running the web server as your Koha user, and ran the above command as your Koha user, you should now see the file listed as an option for download. 11. If you *did* see the file listed, change the ownership to something else: sudo chown root:root $BACKUPDIR/backup.sql.gz 11a. Confirm that you no longer see the file listed when you look at the "Export database" tab. 12. Change the ownership on the file to your web server (or Koha) user: sudo chown www-data:www-data backup.sql.gz 13. Go to the export page as a superlibrarian, and look at the "Export database" tab. You should now see backup.sql.gz listed. 14. Choose to download backup.sql.gz 15. Confirm that the downloaded file is what you were expecting. If you are interested, you can repeat the above steps but replace with , and instead of creating an sql file, create a tar file. To test packaging: run koha-dump, confirm that it still creates a usable backup. --- Makefile.PL | 9 ++ debian/scripts/koha-dump | 6 +- debian/scripts/koha-run-backups | 13 ++- debian/templates/koha-conf-site.xml.in | 6 ++ etc/koha-conf.xml | 6 ++ .../intranet-tmpl/prog/en/modules/tools/export.tt | 54 ++++++++++++ misc/cronjobs/backup.sh | 18 ++--- tools/export.pl | 89 +++++++++++++++++++- 8 files changed, 181 insertions(+), 20 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 9ac1474..46a3524 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -226,6 +226,10 @@ command-line, e.g., READMEs. Directory for Apache and Zebra logs produced by Koha. +=item BACKUP_DIR + +Directory for backup files produced by Koha. + =item PAZPAR2_CONF_DIR Directory for PazPar2 configuration files. @@ -293,6 +297,7 @@ my $target_map = { './services' => 'INTRANET_CGI_DIR', './skel' => 'NONE', './skel/var/log/koha' => { target => 'LOG_DIR', trimdir => -1 }, + './skel/var/spool/koha' => { target => 'BACKUP_DIR', trimdir => -1 }, './skel/var/run/koha/zebradb' => { target => 'ZEBRA_RUN_DIR', trimdir => -1 }, './skel/var/lock/koha/zebradb/authorities' => { target => 'ZEBRA_LOCK_DIR', trimdir => 6 }, './skel/var/lib/koha/zebradb/authorities/key' => { target => 'ZEBRA_DATA_DIR', trimdir => 6 }, @@ -548,6 +553,7 @@ my %test_suite_override_dirs = ( KOHA_CONF_DIR => ['etc'], ZEBRA_CONF_DIR => ['etc', 'zebradb'], LOG_DIR => ['var', 'log'], + BACKUP_DIR => ['var', 'spool'], SCRIPT_DIR => ['bin'], ZEBRA_LOCK_DIR => ['var', 'lock', 'zebradb'], ZEBRA_DATA_DIR => ['var', 'lib', 'zebradb'], @@ -1227,6 +1233,7 @@ sub get_target_directories { $dirmap{'DOC_DIR'} = File::Spec->catdir(@basedir, $package, 'doc'); $dirmap{'ZEBRA_LOCK_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'lock', 'zebradb'); $dirmap{'LOG_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'log'); + $dirmap{'BACKUP_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'spool'); $dirmap{'ZEBRA_DATA_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'lib', 'zebradb'); $dirmap{'ZEBRA_RUN_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'run', 'zebradb'); } elsif ($mode eq 'dev') { @@ -1256,6 +1263,7 @@ sub get_target_directories { $dirmap{'DOC_DIR'} = File::Spec->catdir(@basedir, $package, 'doc'); $dirmap{'ZEBRA_LOCK_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'lock', 'zebradb'); $dirmap{'LOG_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'log'); + $dirmap{'BACKUP_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'spool'); $dirmap{'ZEBRA_DATA_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'lib', 'zebradb'); $dirmap{'ZEBRA_RUN_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'run', 'zebradb'); } else { @@ -1277,6 +1285,7 @@ sub get_target_directories { $dirmap{'DOC_DIR'} = File::Spec->catdir(@basedir, $package, 'doc'); $dirmap{'ZEBRA_LOCK_DIR'} = File::Spec->catdir(File::Spec->rootdir(), 'var', 'lock', $package, 'zebradb'); $dirmap{'LOG_DIR'} = File::Spec->catdir(File::Spec->rootdir(), 'var', 'log', $package); + $dirmap{'BACKUP_DIR'} = File::Spec->catdir(File::Spec->rootdir(), 'var', 'spool', $package); $dirmap{'ZEBRA_DATA_DIR'} = File::Spec->catdir(File::Spec->rootdir(), 'var', 'lib', $package, 'zebradb'); $dirmap{'ZEBRA_RUN_DIR'} = File::Spec->catdir(File::Spec->rootdir(), 'var', 'run', $package, 'zebradb'); } diff --git a/debian/scripts/koha-dump b/debian/scripts/koha-dump index 99c3894..2fe9edd 100755 --- a/debian/scripts/koha-dump +++ b/debian/scripts/koha-dump @@ -44,7 +44,9 @@ mysqlhost="$( xmlstarlet sel -t -v 'yazgfs/config/hostname' $kohaconfig )" mysqldb="$( xmlstarlet sel -t -v 'yazgfs/config/database' $kohaconfig )" mysqluser="$( xmlstarlet sel -t -v 'yazgfs/config/user' $kohaconfig )" mysqlpass="$( xmlstarlet sel -t -v 'yazgfs/config/pass' $kohaconfig )" -dbdump="/var/spool/koha/$name/$name-$date.sql.gz" +backupdir="$( xmlstarlet sel -t -v 'yazgfs/config/backupdir' $kohaconfig )" +[ -z "$backupdir" ] && backupdir="/var/spool/koha/$name" +dbdump="$backupdir/$name-$date.sql.gz" echo "* DB to $dbdump" mysqldump --databases --host="$mysqlhost" \ --user="$mysqluser" --password="$mysqlpass" "$mysqldb" | @@ -54,7 +56,7 @@ chmod g+r "$dbdump" # Dump configs, logs, etc. -metadump="/var/spool/koha/$name/$name-$date.tar.gz" +metadump="$backupdir/$name-$date.tar.gz" echo "* configs, logs to $metadump" tar -C / -czf "$metadump" \ "etc/koha/sites/$name" \ diff --git a/debian/scripts/koha-run-backups b/debian/scripts/koha-run-backups index 7bf39c5..9675f89 100755 --- a/debian/scripts/koha-run-backups +++ b/debian/scripts/koha-run-backups @@ -17,7 +17,7 @@ # Daily cron job for koha. # - dump all sites, except one called 'demo' -dirname="/var/spool/koha" +dirname="" days="2" show_help() { @@ -58,10 +58,15 @@ done for name in $(koha-list --enabled | grep -Fxv demo) do koha-dump "$name" > /dev/null + if [ -z "$dirname"]; then + backupdir="$( xmlstarlet sel -t -v 'yazgfs/config/backupdir' /etc/koha/sites/$name/koha-conf.xml )"; + else + backupdir="$dirname/$name"; + fi # Remove old dump files. # FIXME: This could probably be replaced by one line of perl. - ls "$dirname/$name/" | + ls "$backupdir/" | sed "s:^$name-\([0-9-]*\)\.\(sql\|tar\)\.gz$:\1:" | sort -u | tac | @@ -69,8 +74,8 @@ do tac | while read date do - tardump="$dirname/$name/$name-$date.tar.gz" - sqldump="$dirname/$name/$name-$date.sql.gz" + tardump="$backupdir/$name-$date.tar.gz" + sqldump="$backupdir/$name-$date.sql.gz" if [ -e "$tardump" ] && [ -e "$sqldump" ] then rm "$tardump" diff --git a/debian/templates/koha-conf-site.xml.in b/debian/templates/koha-conf-site.xml.in index a440c96..d8fbd7c 100644 --- a/debian/templates/koha-conf-site.xml.in +++ b/debian/templates/koha-conf-site.xml.in @@ -263,6 +263,12 @@ /usr/share/koha/intranet/htdocs/intranet-tmpl /usr/share/koha/intranet/htdocs/intranet-tmpl/prog/en/includes/ /var/log/koha/__KOHASITE__ + /var/lib/koha/__KOHASITE__ + + 0 + 0 /usr/share/koha/misc/koha-install-log 0 diff --git a/etc/koha-conf.xml b/etc/koha-conf.xml index f31e31c..bb79355 100644 --- a/etc/koha-conf.xml +++ b/etc/koha-conf.xml @@ -282,6 +282,12 @@ __PAZPAR2_TOGGLE_XML_POST__ __INTRANET_TMPL_DIR__ __INTRANET_TMPL_DIR__/prog/en/includes/ __LOG_DIR__ + __BACKUP_DIR__ + + 0 + 0 http://__PAZPAR2_HOST__:__PAZPAR2_PORT__/search.pz2 __MISC_DIR__/koha-install-log 0 diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt index fa98d78..9c27482 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt @@ -29,6 +29,12 @@ $(document).ready(function() {

    @@ -207,6 +213,54 @@ Calendar.setup(

    +[% IF ( allow_db_export ) %] +
    +
    +

    Note : This export file will be very large, and is generated nightly.

    +
    + Choose a file + [% IF ( dbfiles ) %] +
      + [% FOREACH dbfile IN dbfiles %] +
    • [% dbfile %]
    • + [% END %] +
    + [% ELSE %] +

    Unfortunately, no backups are available.

    + [% END %] +
    + + + +
    + +
    +[% END %] + +[% IF ( allow_conf_export ) %] +
    +
    +

    Note : This export file will be very large, and is generated nightly.

    +
    + Choose a file + [% IF ( conffiles ) %] +
      + [% FOREACH conffile IN conffiles %] +
    • [% conffile %]
    • + [% END %] +
    + [% ELSE %] +

    Unfortunately, no backups are available.

    + [% END %] +
    + + + +
    + +
    +[% END %] + diff --git a/misc/cronjobs/backup.sh b/misc/cronjobs/backup.sh index 38026cb..0806c6c 100755 --- a/misc/cronjobs/backup.sh +++ b/misc/cronjobs/backup.sh @@ -1,23 +1,19 @@ #!/bin/sh # Script to create daily backups of the Koha database. # Based on a script by John Pennington +BACKUPDIR=`xmlstarlet sel -t -v 'yazgfs/config/backupdir' $KOHA_CONF` KOHA_DATE=`date '+%y%m%d'` -KOHA_DUMP=/tmp/koha-$KOHA_DATE.dump -KOHA_BACKUP=/tmp/koha-$KOHA_DATE.dump.gz +KOHA_BACKUP=$BACKUPDIR/koha-$KOHA_DATE.sql.gz -mysqldump --single-transaction -u koha -ppassword koha > $KOHA_DUMP && -gzip -f $KOHA_DUMP && -# Creates the dump file and compresses it; -# -u is the Koha user, -p is the password for that user. -# The -f switch on gzip forces it to overwrite the file if one exists. +mysqldump --single-transaction -u koha -ppassword koha | gzip -9 > $KOHA_BACKUP -mv $KOHA_BACKUP /home/kohaadmin && -chown kohaadmin.users /home/kohaadmin/koha-$KOHA_DATE.dump.gz && -chmod 600 /home/kohaadmin/koha-$KOHA_DATE.dump.gz && +#mv $KOHA_BACKUP /home/kohaadmin && +#chown kohaadmin.users /home/kohaadmin/koha-$KOHA_DATE.dump.gz && +#chmod 600 /home/kohaadmin/koha-$KOHA_DATE.dump.gz && # Makes the compressed dump file property of the kohaadmin user. # Make sure that you replace kohaadmin with a real user. -echo "$KOHA_BACKUP was successfully created." | mail kohaadmin -s $KOHA_BACKUP || +[ -f $KOHA_BACKUP] && echo "$KOHA_BACKUP was successfully created." | mail kohaadmin -s $KOHA_BACKUP || echo "$KOHA_BACKUP was NOT successfully created." | mail kohaadmin -s $KOHA_BACKUP # Notifies kohaadmin of (un)successful backup creation # EOF diff --git a/tools/export.pl b/tools/export.pl index b439a8d..88d34b8 100755 --- a/tools/export.pl +++ b/tools/export.pl @@ -33,7 +33,7 @@ my $filename=$query->param("filename"); my $dbh=C4::Context->dbh; my $marcflavour = C4::Context->preference("marcflavour"); -my ($template, $loggedinuser, $cookie) +my ($template, $loggedinuser, $cookie, $flags) = get_template_and_user ( { @@ -57,10 +57,23 @@ my ($template, $loggedinuser, $cookie) $branch = C4::Context->userenv->{'branch'}; } +my $backupdir = C4::Context->config('backupdir'); + if ($op eq "export") { + my $charset = 'utf-8'; + my $mimetype = 'application/octet-stream'; binmode STDOUT, ':encoding(UTF-8)'; - print $query->header( -type => 'application/octet-stream', - -charset => 'utf-8', + if ( $filename =~ m/\.gz$/ ) { + $mimetype = 'application/x-gzip'; + $charset = ''; + binmode STDOUT; + } elsif ( $filename =~ m/\.bz2$/ ) { + $mimetype = 'application/x-bzip2'; + binmode STDOUT; + $charset = ''; + } + print $query->header( -type => $mimetype, + -charset => $charset, -attachment=>$filename); my $record_type = $query->param("record_type"); @@ -159,6 +172,30 @@ if ($op eq "export") { push @sql_params, $authtype; } } + elsif ( $record_type eq 'db' ) { + my $successful_export; + if ( $flags->{superlibrarian} && C4::Context->config('backup_db_via_tools') ) { + $successful_export = download_backup( { directory => "$backupdir", extension => 'sql', filename => "$filename" } ) + } + unless ( $successful_export ) { + warn "A suspicious attempt was made to download the db at '$filename' by someone at " . $query->remote_host() . "\n"; + } + exit; + } + elsif ( $record_type eq 'conf' ) { + my $successful_export; + if ( $flags->{superlibrarian} && C4::Context->config('backup_conf_via_tools') ) { + $successful_export = download_backup( { directory => "$backupdir", extension => 'tar', filename => "$filename" } ) + } + unless ( $successful_export ) { + warn "A suspicious attempt was made to download the configuration at '$filename' by someone at " . $query->remote_host() . "\n"; + } + exit; + } + else { + # Someone is trying to mess us up + exit; + } my $sth = $dbh->prepare($sql_query); $sth->execute(@sql_params); @@ -255,6 +292,16 @@ else { push @authtypesloop, \%row; } + if ( $flags->{superlibrarian} && C4::Context->config('backup_db_via_tools') && $backupdir && -d $backupdir ) { + $template->{VARS}->{'allow_db_export'} = 1; + $template->{VARS}->{'dbfiles'} = getbackupfilelist( { directory => "$backupdir", extension => 'sql' } ); + } + + if ( $flags->{superlibrarian} && C4::Context->config('backup_conf_via_tools') && $backupdir && -d $backupdir ) { + $template->{VARS}->{'allow_conf_export'} = 1; + $template->{VARS}->{'conffiles'} = getbackupfilelist( { directory => "$backupdir", extension => 'tar' } ); + } + $template->param( branchloop => \@branchloop, itemtypeloop => \@itemtypesloop, @@ -264,3 +311,39 @@ else { output_html_with_http_headers $query, $cookie, $template->output; } + +sub getbackupfilelist { + my $args = shift; + my $directory = $args->{directory}; + my $extension = $args->{extension}; + my @files; + + if ( opendir(my $dir, $directory) ) { + while (my $file = readdir($dir)) { + next unless ( $file =~ m/\.$extension(\.(gz|bz2|xz))?/ ); + push @files, $file if ( -f "$backupdir/$file" && -o "$backupdir/$file" ); + } + closedir($dir); + } + + return \@files; +} + +sub download_backup { + my $args = shift; + my $directory = $args->{directory}; + my $extension = $args->{extension}; + my $filename = $args->{filename}; + + return unless ( $directory && -d $directory ); + return unless ( $filename =~ m/$extension(\.(gz|bz2|xz))?$/ && not $filename =~ m#(^\.\.|/)# ); + $filename = "$directory/$filename"; + return unless ( -f $filename && -o $filename ); + return unless ( open(my $dump, '<', $filename) ); + binmode $dump; + while (read($dump, my $data, 64 * 1024)) { + print $data; + } + close ($dump); + return 1; +} -- 1.7.2.5 From marc at msys.ch Tue Jun 19 04:22:39 2012 From: marc at msys.ch (Marc Balmer) Date: Tue, 19 Jun 2012 04:22:39 +0200 Subject: [Koha-patches] [PATCH] Bug 8268: Add database dump to export tool In-Reply-To: <1340056026-3901-1-git-send-email-jcamins@cpbibliography.com> References: <1340056026-3901-1-git-send-email-jcamins@cpbibliography.com> Message-ID: This is a MySQLism and can't go in as is. The script backup.sh should really call backup_mysql.sh or backup_postgresql.sh, depending on whether database is being used. backup_postgresql.sh can be for now, but provisions have to be made to allow for DB independent backup. - Marc -- Marc Balmer micro systems, http://www.msys.ch/ Tel. +41 61 383 05 10, Fax +41 61 383 05 12 Am 18.06.2012 um 23:47 schrieb Jared Camins-Esakov : > This patch builds on work by Lars Wirzenius for the Koha packages. > > To date, the only way for a Koha librarian to obtain a complete backup > of their system has been to log into the system via SSH (or FTP) to > download the mysqldump file. This patch makes it possible for > superlibrarians in properly configured systems to download night backups > via the staff client's Export tool. > > Recognizing that this is functionality with potentially very grave > security implications, system administrators must manually enable these > features in the koha-conf.xml configuration file. > > The following configuration settings have been added to the koha-conf.xml > file: > * backupdir => directory where backups should be stored. > * backup_db_via_tools => whether to allow superlibrarians to download > database backups via the Export tool. The default is disabled, and > there is no way -- by design -- to enable this option without manually > editing koha-conf.xml. > * backup_conf_via_tools => whether to allow superlibrarians to download > configuration backups via the Export tool (this may be applicable to > packages only). The default is disabled, and there is no way -- by > design -- to enable this option without manually editing koha-conf.xml. > > This commit modifies the following scripts to make use of the new > backupdir configuration option: > * koha-dump and koha-run-backups in the Debian packages > * The sample backup script misc/cronjobs/backup.sh > > Note that for security reasons, superlibrarians will not be allowed > to download files that are not owned by the web server's effective user. > This imposes a de facto dependency on ITK (for Apache) or running the > web server as the Koha user (as is done with Plack). > > To test: > 1. Apply patch. > 2. Go to export page as a superlibrarian. Notice that no additional > export options appear because they have not been enabled. > 3. Add $KOHADEV/var/spool to the section > of your koha-conf.xml (note that you will need to adjust that so that > it is pointing at a logical directory). > 4. Create the aforementioned directory. > 5. Go to export page as a superlibrarian. Notice that no additional > export options appear because they have not been enabled. > 6. Add 1 to the > section of your koha-conf.xml > 7. Go to the export page as a superlibrarian. Notice the new tab. > 8. Go to the export page as a non-superlibrarian. Notice there is no > new tab. > 9. Run: mysqldump -u koha -p koha | gzip > $BACKUPDIR/backup.sql.gz > (substituting appropriate user, password, and database name) > 10. Go to the export page as a superlibrarian, and look at the "Export > database" tab. If you are running the web server as your Koha user, > and ran the above command as your Koha user, you should now see the > file listed as an option for download. > 11. If you *did* see the file listed, change the ownership to something > else: sudo chown root:root $BACKUPDIR/backup.sql.gz > 11a. Confirm that you no longer see the file listed when you look at the > "Export database" tab. > 12. Change the ownership on the file to your web server (or Koha) user: > sudo chown www-data:www-data backup.sql.gz > 13. Go to the export page as a superlibrarian, and look at the "Export > database" tab. You should now see backup.sql.gz listed. > 14. Choose to download backup.sql.gz > 15. Confirm that the downloaded file is what you were expecting. > > If you are interested, you can repeat the above steps but replace > with , and instead of > creating an sql file, create a tar file. > > To test packaging: run koha-dump, confirm that it still creates a > usable backup. > --- > Makefile.PL | 9 ++ > debian/scripts/koha-dump | 6 +- > debian/scripts/koha-run-backups | 13 ++- > debian/templates/koha-conf-site.xml.in | 6 ++ > etc/koha-conf.xml | 6 ++ > .../intranet-tmpl/prog/en/modules/tools/export.tt | 54 ++++++++++++ > misc/cronjobs/backup.sh | 18 ++--- > tools/export.pl | 89 +++++++++++++++++++- > 8 files changed, 181 insertions(+), 20 deletions(-) > > diff --git a/Makefile.PL b/Makefile.PL > index 9ac1474..46a3524 100644 > --- a/Makefile.PL > +++ b/Makefile.PL > @@ -226,6 +226,10 @@ command-line, e.g., READMEs. > > Directory for Apache and Zebra logs produced by Koha. > > +=item BACKUP_DIR > + > +Directory for backup files produced by Koha. > + > =item PAZPAR2_CONF_DIR > > Directory for PazPar2 configuration files. > @@ -293,6 +297,7 @@ my $target_map = { > './services' => 'INTRANET_CGI_DIR', > './skel' => 'NONE', > './skel/var/log/koha' => { target => 'LOG_DIR', trimdir => -1 }, > + './skel/var/spool/koha' => { target => 'BACKUP_DIR', trimdir => -1 }, > './skel/var/run/koha/zebradb' => { target => 'ZEBRA_RUN_DIR', trimdir => -1 }, > './skel/var/lock/koha/zebradb/authorities' => { target => 'ZEBRA_LOCK_DIR', trimdir => 6 }, > './skel/var/lib/koha/zebradb/authorities/key' => { target => 'ZEBRA_DATA_DIR', trimdir => 6 }, > @@ -548,6 +553,7 @@ my %test_suite_override_dirs = ( > KOHA_CONF_DIR => ['etc'], > ZEBRA_CONF_DIR => ['etc', 'zebradb'], > LOG_DIR => ['var', 'log'], > + BACKUP_DIR => ['var', 'spool'], > SCRIPT_DIR => ['bin'], > ZEBRA_LOCK_DIR => ['var', 'lock', 'zebradb'], > ZEBRA_DATA_DIR => ['var', 'lib', 'zebradb'], > @@ -1227,6 +1233,7 @@ sub get_target_directories { > $dirmap{'DOC_DIR'} = File::Spec->catdir(@basedir, $package, 'doc'); > $dirmap{'ZEBRA_LOCK_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'lock', 'zebradb'); > $dirmap{'LOG_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'log'); > + $dirmap{'BACKUP_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'spool'); > $dirmap{'ZEBRA_DATA_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'lib', 'zebradb'); > $dirmap{'ZEBRA_RUN_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'run', 'zebradb'); > } elsif ($mode eq 'dev') { > @@ -1256,6 +1263,7 @@ sub get_target_directories { > $dirmap{'DOC_DIR'} = File::Spec->catdir(@basedir, $package, 'doc'); > $dirmap{'ZEBRA_LOCK_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'lock', 'zebradb'); > $dirmap{'LOG_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'log'); > + $dirmap{'BACKUP_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'spool'); > $dirmap{'ZEBRA_DATA_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'lib', 'zebradb'); > $dirmap{'ZEBRA_RUN_DIR'} = File::Spec->catdir(@basedir, $package, 'var', 'run', 'zebradb'); > } else { > @@ -1277,6 +1285,7 @@ sub get_target_directories { > $dirmap{'DOC_DIR'} = File::Spec->catdir(@basedir, $package, 'doc'); > $dirmap{'ZEBRA_LOCK_DIR'} = File::Spec->catdir(File::Spec->rootdir(), 'var', 'lock', $package, 'zebradb'); > $dirmap{'LOG_DIR'} = File::Spec->catdir(File::Spec->rootdir(), 'var', 'log', $package); > + $dirmap{'BACKUP_DIR'} = File::Spec->catdir(File::Spec->rootdir(), 'var', 'spool', $package); > $dirmap{'ZEBRA_DATA_DIR'} = File::Spec->catdir(File::Spec->rootdir(), 'var', 'lib', $package, 'zebradb'); > $dirmap{'ZEBRA_RUN_DIR'} = File::Spec->catdir(File::Spec->rootdir(), 'var', 'run', $package, 'zebradb'); > } > diff --git a/debian/scripts/koha-dump b/debian/scripts/koha-dump > index 99c3894..2fe9edd 100755 > --- a/debian/scripts/koha-dump > +++ b/debian/scripts/koha-dump > @@ -44,7 +44,9 @@ mysqlhost="$( xmlstarlet sel -t -v 'yazgfs/config/hostname' $kohaconfig )" > mysqldb="$( xmlstarlet sel -t -v 'yazgfs/config/database' $kohaconfig )" > mysqluser="$( xmlstarlet sel -t -v 'yazgfs/config/user' $kohaconfig )" > mysqlpass="$( xmlstarlet sel -t -v 'yazgfs/config/pass' $kohaconfig )" > -dbdump="/var/spool/koha/$name/$name-$date.sql.gz" > +backupdir="$( xmlstarlet sel -t -v 'yazgfs/config/backupdir' $kohaconfig )" > +[ -z "$backupdir" ] && backupdir="/var/spool/koha/$name" > +dbdump="$backupdir/$name-$date.sql.gz" > echo "* DB to $dbdump" > mysqldump --databases --host="$mysqlhost" \ > --user="$mysqluser" --password="$mysqlpass" "$mysqldb" | > @@ -54,7 +56,7 @@ chmod g+r "$dbdump" > > > # Dump configs, logs, etc. > -metadump="/var/spool/koha/$name/$name-$date.tar.gz" > +metadump="$backupdir/$name-$date.tar.gz" > echo "* configs, logs to $metadump" > tar -C / -czf "$metadump" \ > "etc/koha/sites/$name" \ > diff --git a/debian/scripts/koha-run-backups b/debian/scripts/koha-run-backups > index 7bf39c5..9675f89 100755 > --- a/debian/scripts/koha-run-backups > +++ b/debian/scripts/koha-run-backups > @@ -17,7 +17,7 @@ > # Daily cron job for koha. > # - dump all sites, except one called 'demo' > > -dirname="/var/spool/koha" > +dirname="" > days="2" > > show_help() { > @@ -58,10 +58,15 @@ done > for name in $(koha-list --enabled | grep -Fxv demo) > do > koha-dump "$name" > /dev/null > + if [ -z "$dirname"]; then > + backupdir="$( xmlstarlet sel -t -v 'yazgfs/config/backupdir' /etc/koha/sites/$name/koha-conf.xml )"; > + else > + backupdir="$dirname/$name"; > + fi > > # Remove old dump files. > # FIXME: This could probably be replaced by one line of perl. > - ls "$dirname/$name/" | > + ls "$backupdir/" | > sed "s:^$name-\([0-9-]*\)\.\(sql\|tar\)\.gz$:\1:" | > sort -u | > tac | > @@ -69,8 +74,8 @@ do > tac | > while read date > do > - tardump="$dirname/$name/$name-$date.tar.gz" > - sqldump="$dirname/$name/$name-$date.sql.gz" > + tardump="$backupdir/$name-$date.tar.gz" > + sqldump="$backupdir/$name-$date.sql.gz" > if [ -e "$tardump" ] && [ -e "$sqldump" ] > then > rm "$tardump" > diff --git a/debian/templates/koha-conf-site.xml.in b/debian/templates/koha-conf-site.xml.in > index a440c96..d8fbd7c 100644 > --- a/debian/templates/koha-conf-site.xml.in > +++ b/debian/templates/koha-conf-site.xml.in > @@ -263,6 +263,12 @@ > /usr/share/koha/intranet/htdocs/intranet-tmpl > /usr/share/koha/intranet/htdocs/intranet-tmpl/prog/en/includes/ > /var/log/koha/__KOHASITE__ > + /var/lib/koha/__KOHASITE__ > + > + 0 > + 0 > > /usr/share/koha/misc/koha-install-log > 0 > diff --git a/etc/koha-conf.xml b/etc/koha-conf.xml > index f31e31c..bb79355 100644 > --- a/etc/koha-conf.xml > +++ b/etc/koha-conf.xml > @@ -282,6 +282,12 @@ __PAZPAR2_TOGGLE_XML_POST__ > __INTRANET_TMPL_DIR__ > __INTRANET_TMPL_DIR__/prog/en/includes/ > __LOG_DIR__ > + __BACKUP_DIR__ > + > + 0 > + 0 > http://__PAZPAR2_HOST__:__PAZPAR2_PORT__/search.pz2 > __MISC_DIR__/koha-install-log > 0 > diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt > index fa98d78..9c27482 100644 > --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt > +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt > @@ -29,6 +29,12 @@ $(document).ready(function() { > >
    >

    > @@ -207,6 +213,54 @@ Calendar.setup( > >

    > > +[% IF ( allow_db_export ) %] > +
    > +
    > +

    Note : This export file will be very large, and is generated nightly.

    > +
    > + Choose a file > + [% IF ( dbfiles ) %] > +
      > + [% FOREACH dbfile IN dbfiles %] > +
    • [% dbfile %]
    • > + [% END %] > +
    > + [% ELSE %] > +

    Unfortunately, no backups are available.

    > + [% END %] > +
    > + > + > + > +
    > + > +
    > +[% END %] > + > +[% IF ( allow_conf_export ) %] > +
    > +
    > +

    Note : This export file will be very large, and is generated nightly.

    > +
    > + Choose a file > + [% IF ( conffiles ) %] > +
      > + [% FOREACH conffile IN conffiles %] > +
    • [% conffile %]
    • > + [% END %] > +
    > + [% ELSE %] > +

    Unfortunately, no backups are available.

    > + [% END %] > +
    > + > + > + > +
    > + > +
    > +[% END %] > + > > > > diff --git a/misc/cronjobs/backup.sh b/misc/cronjobs/backup.sh > index 38026cb..0806c6c 100755 > --- a/misc/cronjobs/backup.sh > +++ b/misc/cronjobs/backup.sh > @@ -1,23 +1,19 @@ > #!/bin/sh > # Script to create daily backups of the Koha database. > # Based on a script by John Pennington > +BACKUPDIR=`xmlstarlet sel -t -v 'yazgfs/config/backupdir' $KOHA_CONF` > KOHA_DATE=`date '+%y%m%d'` > -KOHA_DUMP=/tmp/koha-$KOHA_DATE.dump > -KOHA_BACKUP=/tmp/koha-$KOHA_DATE.dump.gz > +KOHA_BACKUP=$BACKUPDIR/koha-$KOHA_DATE.sql.gz > > -mysqldump --single-transaction -u koha -ppassword koha > $KOHA_DUMP && > -gzip -f $KOHA_DUMP && > -# Creates the dump file and compresses it; > -# -u is the Koha user, -p is the password for that user. > -# The -f switch on gzip forces it to overwrite the file if one exists. > +mysqldump --single-transaction -u koha -ppassword koha | gzip -9 > $KOHA_BACKUP > > -mv $KOHA_BACKUP /home/kohaadmin && > -chown kohaadmin.users /home/kohaadmin/koha-$KOHA_DATE.dump.gz && > -chmod 600 /home/kohaadmin/koha-$KOHA_DATE.dump.gz && > +#mv $KOHA_BACKUP /home/kohaadmin && > +#chown kohaadmin.users /home/kohaadmin/koha-$KOHA_DATE.dump.gz && > +#chmod 600 /home/kohaadmin/koha-$KOHA_DATE.dump.gz && > # Makes the compressed dump file property of the kohaadmin user. > # Make sure that you replace kohaadmin with a real user. > > -echo "$KOHA_BACKUP was successfully created." | mail kohaadmin -s $KOHA_BACKUP || > +[ -f $KOHA_BACKUP] && echo "$KOHA_BACKUP was successfully created." | mail kohaadmin -s $KOHA_BACKUP || > echo "$KOHA_BACKUP was NOT successfully created." | mail kohaadmin -s $KOHA_BACKUP > # Notifies kohaadmin of (un)successful backup creation > # EOF > diff --git a/tools/export.pl b/tools/export.pl > index b439a8d..88d34b8 100755 > --- a/tools/export.pl > +++ b/tools/export.pl > @@ -33,7 +33,7 @@ my $filename=$query->param("filename"); > my $dbh=C4::Context->dbh; > my $marcflavour = C4::Context->preference("marcflavour"); > > -my ($template, $loggedinuser, $cookie) > +my ($template, $loggedinuser, $cookie, $flags) > = get_template_and_user > ( > { > @@ -57,10 +57,23 @@ my ($template, $loggedinuser, $cookie) > $branch = C4::Context->userenv->{'branch'}; > } > > +my $backupdir = C4::Context->config('backupdir'); > + > if ($op eq "export") { > + my $charset = 'utf-8'; > + my $mimetype = 'application/octet-stream'; > binmode STDOUT, ':encoding(UTF-8)'; > - print $query->header( -type => 'application/octet-stream', > - -charset => 'utf-8', > + if ( $filename =~ m/\.gz$/ ) { > + $mimetype = 'application/x-gzip'; > + $charset = ''; > + binmode STDOUT; > + } elsif ( $filename =~ m/\.bz2$/ ) { > + $mimetype = 'application/x-bzip2'; > + binmode STDOUT; > + $charset = ''; > + } > + print $query->header( -type => $mimetype, > + -charset => $charset, > -attachment=>$filename); > > my $record_type = $query->param("record_type"); > @@ -159,6 +172,30 @@ if ($op eq "export") { > push @sql_params, $authtype; > } > } > + elsif ( $record_type eq 'db' ) { > + my $successful_export; > + if ( $flags->{superlibrarian} && C4::Context->config('backup_db_via_tools') ) { > + $successful_export = download_backup( { directory => "$backupdir", extension => 'sql', filename => "$filename" } ) > + } > + unless ( $successful_export ) { > + warn "A suspicious attempt was made to download the db at '$filename' by someone at " . $query->remote_host() . "\n"; > + } > + exit; > + } > + elsif ( $record_type eq 'conf' ) { > + my $successful_export; > + if ( $flags->{superlibrarian} && C4::Context->config('backup_conf_via_tools') ) { > + $successful_export = download_backup( { directory => "$backupdir", extension => 'tar', filename => "$filename" } ) > + } > + unless ( $successful_export ) { > + warn "A suspicious attempt was made to download the configuration at '$filename' by someone at " . $query->remote_host() . "\n"; > + } > + exit; > + } > + else { > + # Someone is trying to mess us up > + exit; > + } > > my $sth = $dbh->prepare($sql_query); > $sth->execute(@sql_params); > @@ -255,6 +292,16 @@ else { > push @authtypesloop, \%row; > } > > + if ( $flags->{superlibrarian} && C4::Context->config('backup_db_via_tools') && $backupdir && -d $backupdir ) { > + $template->{VARS}->{'allow_db_export'} = 1; > + $template->{VARS}->{'dbfiles'} = getbackupfilelist( { directory => "$backupdir", extension => 'sql' } ); > + } > + > + if ( $flags->{superlibrarian} && C4::Context->config('backup_conf_via_tools') && $backupdir && -d $backupdir ) { > + $template->{VARS}->{'allow_conf_export'} = 1; > + $template->{VARS}->{'conffiles'} = getbackupfilelist( { directory => "$backupdir", extension => 'tar' } ); > + } > + > $template->param( > branchloop => \@branchloop, > itemtypeloop => \@itemtypesloop, > @@ -264,3 +311,39 @@ else { > > output_html_with_http_headers $query, $cookie, $template->output; > } > + > +sub getbackupfilelist { > + my $args = shift; > + my $directory = $args->{directory}; > + my $extension = $args->{extension}; > + my @files; > + > + if ( opendir(my $dir, $directory) ) { > + while (my $file = readdir($dir)) { > + next unless ( $file =~ m/\.$extension(\.(gz|bz2|xz))?/ ); > + push @files, $file if ( -f "$backupdir/$file" && -o "$backupdir/$file" ); > + } > + closedir($dir); > + } > + > + return \@files; > +} > + > +sub download_backup { > + my $args = shift; > + my $directory = $args->{directory}; > + my $extension = $args->{extension}; > + my $filename = $args->{filename}; > + > + return unless ( $directory && -d $directory ); > + return unless ( $filename =~ m/$extension(\.(gz|bz2|xz))?$/ && not $filename =~ m#(^\.\.|/)# ); > + $filename = "$directory/$filename"; > + return unless ( -f $filename && -o $filename ); > + return unless ( open(my $dump, '<', $filename) ); > + binmode $dump; > + while (read($dump, my $data, 64 * 1024)) { > + print $data; > + } > + close ($dump); > + return 1; > +} > -- > 1.7.2.5 > > _______________________________________________ > Koha-patches mailing list > Koha-patches at lists.koha-community.org > http://lists.koha-community.org/cgi-bin/mailman/listinfo/koha-patches > website : http://www.koha-community.org/ > git : http://git.koha-community.org/ > bugs : http://bugs.koha-community.org/ From robin at catalyst.net.nz Tue Jun 19 11:23:34 2012 From: robin at catalyst.net.nz (Robin Sheat) Date: Tue, 19 Jun 2012 10:23:34 +0100 Subject: [Koha-patches] [PATCH] Bug 8268: Add database dump to export tool In-Reply-To: References: <1340056026-3901-1-git-send-email-jcamins@cpbibliography.com> Message-ID: <4FE04516.60702@catalyst.net.nz> Op 19-06-12 03:22, Marc Balmer schreef: > This is a MySQLism and can't go in as is. It isn't, and it can (with normal testing, of course.) Robin. From marc at msys.ch Tue Jun 19 11:24:46 2012 From: marc at msys.ch (Marc Balmer) Date: Tue, 19 Jun 2012 11:24:46 +0200 Subject: [Koha-patches] [PATCH] Bug 8268: Add database dump to export tool In-Reply-To: <4FE04516.60702@catalyst.net.nz> References: <1340056026-3901-1-git-send-email-jcamins@cpbibliography.com> <4FE04516.60702@catalyst.net.nz> Message-ID: <4FE0455E.6090809@msys.ch> Am 19.06.12 11:23, schrieb Robin Sheat: > Op 19-06-12 03:22, Marc Balmer schreef: >> This is a MySQLism and can't go in as is. > > It isn't, and it can (with normal testing, of course.) To be correct, it is not a *new* MySQLism, but it still is MySQL only. That said (because it's not new), I not against it anymore. From colin.campbell at ptfs-europe.com Tue Jun 19 12:36:37 2012 From: colin.campbell at ptfs-europe.com (Colin Campbell) Date: Tue, 19 Jun 2012 11:36:37 +0100 Subject: [Koha-patches] [PATCH] Bug 8271 teach SIPServer.pm to set its own lib path Message-ID: <1340102197-8500-1-git-send-email-colin.campbell@ptfs-europe.com> SIPServer.pm requires that C4/SIP is added to its lib path This has been done by passing this directory to it via -I. By using FindBin it can set the path for itself correctly. This will also work if the C4/SIP directory tree is moved to a non-standard location Removed the now redundant -I. from sip_run.sh Added a variable to sip_run.sh for the koha tree to highlight a problem with the script if you have multiple directories in the PERL5LIB environment variable --- C4/SIP/SIPServer.pm | 2 ++ misc/bin/sip_run.sh | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/C4/SIP/SIPServer.pm b/C4/SIP/SIPServer.pm index bab51e8..9245f96 100644 --- a/C4/SIP/SIPServer.pm +++ b/C4/SIP/SIPServer.pm @@ -2,6 +2,8 @@ package SIPServer; use strict; use warnings; +use FindBin qw($Bin); +use lib "$Bin"; # use Exporter; use Sys::Syslog qw(syslog); use Net::Server::PreFork; diff --git a/misc/bin/sip_run.sh b/misc/bin/sip_run.sh index b1bc8d9..c578194 100755 --- a/misc/bin/sip_run.sh +++ b/misc/bin/sip_run.sh @@ -24,7 +24,10 @@ for x in HOME PERL5LIB KOHA_CONF ; do fi; done; unset x; -cd $PERL5LIB/C4/SIP; +# you should hard code this if you have multiple directories +# in your PERL5LIB +PERL_MODULE_DIR=$PERL5LIB +cd $PERL_MODULE_DIR/C4/SIP; echo; sipconfig=${1}; @@ -34,8 +37,8 @@ errfile=${3:-$HOME/sip.err}; if [ $sipconfig ]; then echo "Running with config file located in $sipconfig" ; echo "Calling (backgrounded):"; - echo "perl -I./ ./SIPServer.pm $sipconfig >>$outfile 2>>$errfile"; - perl -I./ ./SIPServer.pm $sipconfig >>$outfile 2>>$errfile & + echo "perl ./SIPServer.pm $sipconfig >>$outfile 2>>$errfile"; + perl ./SIPServer.pm $sipconfig >>$outfile 2>>$errfile & else echo "Please specify a config file and try again." -- 1.7.11 From colin.campbell at ptfs-europe.com Tue Jun 19 13:55:15 2012 From: colin.campbell at ptfs-europe.com (Colin Campbell) Date: Tue, 19 Jun 2012 12:55:15 +0100 Subject: [Koha-patches] [PATCH] Bug 7787: Make the SIP server much more robust. Message-ID: <1340106915-10220-1-git-send-email-colin.campbell@ptfs-europe.com> From: Marc Balmer Be liberal in what we accept, but strict in what we send: Never exit the server process, but send a SC_RESEND message (96) to the client if we received anything we don't understand. This is consistent with SIP server implementations of other ILSs. Signed-off-by: Colin Campbell --- C4/SIP/SIPServer.pm | 55 ++++++++++++++++++--------------------------------- C4/SIP/Sip.pm | 8 -------- C4/SIP/Sip/MsgType.pm | 4 +++- 3 files changed, 22 insertions(+), 45 deletions(-) diff --git a/C4/SIP/SIPServer.pm b/C4/SIP/SIPServer.pm index bab51e8..a23c713 100644 --- a/C4/SIP/SIPServer.pm +++ b/C4/SIP/SIPServer.pm @@ -35,7 +35,6 @@ BEGIN { my %transports = ( RAW => \&raw_transport, telnet => \&telnet_transport, - # http => \&http_transport, # for http just use the OPAC ); # @@ -126,31 +125,18 @@ sub raw_transport { my $self = shift; my ($input); my $service = $self->{service}; - my $strikes = 3; - eval { - local $SIG{ALRM} = sub { die "raw_transport Timed Out!\n"; }; - syslog("LOG_DEBUG", "raw_transport: timeout is %d", $service->{timeout}); - while ($strikes--) { - alarm $service->{timeout}; - $input = Sip::read_SIP_packet(*STDIN); - alarm 0; - if (!$input) { - # EOF on the socket - syslog("LOG_INFO", "raw_transport: shutting down: EOF during login"); - return; - } - $input =~ s/[\r\n]+$//sm; # Strip off trailing line terminator(s) - last if Sip::MsgType::handle($input, $self, LOGIN); - } - }; - - if (length $@) { - syslog("LOG_ERR", "raw_transport: LOGIN ERROR: '$@'"); - die "raw_transport: login error (timeout? $@), exiting"; - } elsif (!$self->{account}) { - syslog("LOG_ERR", "raw_transport: LOGIN FAILED"); - die "raw_transport: Login failed (no account), exiting"; + while (!$self->{account}) { + local $SIG{ALRM} = sub { die "raw_transport Timed Out!\n"; }; + syslog("LOG_DEBUG", "raw_transport: timeout is %d", $service->{timeout}); + $input = Sip::read_SIP_packet(*STDIN); + if (!$input) { + # EOF on the socket + syslog("LOG_INFO", "raw_transport: shutting down: EOF during login"); + return; + } + $input =~ s/[\r\n]+$//sm; # Strip off trailing line terminator(s) + last if Sip::MsgType::handle($input, $self, LOGIN); } syslog("LOG_DEBUG", "raw_transport: uname/inst: '%s/%s'", @@ -269,32 +255,29 @@ sub sip_protocol_loop { # In short, we'll take any valid message here. #my $expect = SC_STATUS; my $expect = ''; - my $strikes = 3; - while ($input = Sip::read_SIP_packet(*STDIN)) { + while (1) { + $input = Sip::read_SIP_packet(*STDIN); + unless ($input) { + return; # EOF + } # begin input hacks ... a cheap stand in for better Telnet layer $input =~ s/^[^A-z0-9]+//s; # Kill leading bad characters... like Telnet handshakers $input =~ s/[^A-z0-9]+$//s; # Same on the end, should get DOSsy ^M line-endings too. while (chomp($input)) {warn "Extra line ending on input";} unless ($input) { - if ($strikes--) { - syslog("LOG_ERR", "sip_protocol_loop: empty input skipped"); - next; - } else { - syslog("LOG_ERR", "sip_protocol_loop: quitting after too many errors"); - die "sip_protocol_loop: quitting after too many errors"; - } + syslog("LOG_ERR", "sip_protocol_loop: empty input skipped"); + print("96$CR"); + next; } # end cheap input hacks my $status = Sip::MsgType::handle($input, $self, $expect); if (!$status) { syslog("LOG_ERR", "sip_protocol_loop: failed to handle %s",substr($input,0,2)); - die "sip_protocol_loop: failed Sip::MsgType::handle('$input', $self, '$expect')"; } next if $status eq REQUEST_ACS_RESEND; if ($expect && ($status ne $expect)) { # We received a non-"RESEND" that wasn't what we were expecting. syslog("LOG_ERR", "sip_protocol_loop: expected %s, received %s, exiting", $expect, $input); - die "sip_protocol_loop: exiting: expected '$expect', received '$status'"; } # We successfully received and processed what we were expecting $expect = ''; diff --git a/C4/SIP/Sip.pm b/C4/SIP/Sip.pm index e9e1392..ba682dd 100644 --- a/C4/SIP/Sip.pm +++ b/C4/SIP/Sip.pm @@ -158,7 +158,6 @@ sub read_SIP_packet { # local $/ = "\r"; # don't need any of these here. use whatever the prevailing $/ is. local $/ = "\015"; # proper SPEC: (octal) \015 = (hex) x0D = (dec) 13 = (ascii) carriage return { # adapted from http://perldoc.perl.org/5.8.8/functions/readline.html - for ( my $tries = 1 ; $tries <= 3 ; $tries++ ) { undef $!; $record = readline($fh); if ( defined($record) ) { @@ -173,14 +172,7 @@ sub read_SIP_packet { while ( chomp($record) ) { 1; } $record and last; # success - } else { - if ($!) { - syslog( "LOG_DEBUG", "read_SIP_packet (try #$tries) ERROR: $! $@" ); - # die "read_SIP_packet ERROR: $!"; - warn "read_SIP_packet ERROR: $! $@"; - } } - } } if ($record) { my $len2 = length($record); diff --git a/C4/SIP/Sip/MsgType.pm b/C4/SIP/Sip/MsgType.pm index cc6b6d5..1682812 100644 --- a/C4/SIP/Sip/MsgType.pm +++ b/C4/SIP/Sip/MsgType.pm @@ -405,7 +405,9 @@ sub handle { } unless ($self->{handler}) { syslog("LOG_WARNING", "No handler defined for '%s'", $msg); - return undef; + $last_response = REQUEST_SC_RESEND; + print("$last_response\r"); + return REQUEST_ACS_RESEND; } return($self->{handler}->($self, $server)); # FIXME # FIXME: Use of uninitialized value in subroutine entry -- 1.7.11 From oleonard at myacpl.org Tue Jun 19 19:09:27 2012 From: oleonard at myacpl.org (Owen Leonard) Date: Tue, 19 Jun 2012 13:09:27 -0400 Subject: [Koha-patches] [PATCH] Bug 8272 - OPAC : date expiration format Message-ID: <1340125767-19355-1-git-send-email-oleonard@myacpl.org> Adding TT date filter to output of expiration date on OPAC user page. --- koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt index 0b8930f..8ae9a77 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt @@ -83,7 +83,7 @@ $.tablesorter.addParser({ [% IF ( BORROWER_INF.warndeparture ) %]
    - Please note: Your card will expire on [% BORROWER_INF.warndeparture %]. Please contact the library for more information. + Please note: Your card will expire on [% BORROWER_INF.warndeparture | $KohaDates %]. Please contact the library for more information. [% IF ( BORROWER_INF.returnbeforeexpiry ) %] Also note that you must return all checked out items before your card expires.[% END %]
    [% END %] -- 1.7.9.5 From srdjan at catalyst.net.nz Thu Jun 21 02:25:04 2012 From: srdjan at catalyst.net.nz (Srdjan) Date: Thu, 21 Jun 2012 12:25:04 +1200 Subject: [Koha-patches] [PATCH] bug_7993: Save reports with Group/Subgroup hierarchy In-Reply-To: References: Message-ID: <1340238304-4348-1-git-send-email-srdjan@catalyst.net.nz> This should make saved reports more manageable. Group/Subgroup hierarchy is stored in authorised_values, categories REPORT_GROUP and REPORT_SUBGROUP, connected by REPORT_SUBGROUP.lib_opac -> REPORT_GROUP.authorised_value Database changes: * authorised_values: expanded category to 16 chars * created default set of REPORT_GROUP authorised values to match hardcoded report areas * reports_dictionary: replaced area int with report_area text, converted values * saved_sql: added report_area, report_group and report_subgroup; report_area is not currently used, saved for the record C4/Reports/Guided.pm: * Replaced Area numeric values with the mnemonic codes * get_report_areas(): returns hardcoded areas list * created get_report_areas(): returns full hierarchy (groups with belonging subgroups) * save_report(): changed iterface, accepts fields hashref as input * update_sql(): changed iterface, accepts id and fields hashref as input * get_saved_reports():] - join to authorised_values to pick group and subgroup name - accept group and subgroup filter params * get_saved_report(): - changed iterface, return record hashref - join to authorised_values to pick group and subgroup name * build_authorised_value_list(): new sub, moved code from reports/guided_reports.pl * Updated interfaces in: cronjobs/runreport.pl, svc/report, opac/svc/report: get_saved_report() reports/dictionary.pl: get_report_areas() reports/guided_reports.pl reports/guided_reports_start.tt: * Reports list: - added group/subgroup filter - display area/group/subgroup for the reports * Create report wizard: - carry area to the end - select group and subgroup when saving the report; group defaults to area, useful when report groups match areas * Update report and Create from SQL: added group/subgroup * Amended reports/guided_reports.pl accordingly Conflicts: C4/Reports/Guided.pm admin/authorised_values.pl installer/data/mysql/kohastructure.sql installer/data/mysql/updatedatabase.pl koha-tmpl/intranet-tmpl/prog/en/modules/reports/dictionary.tmpl koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tmpl misc/cronjobs/runreport.pl reports/dictionary.pl reports/guided_reports.pl --- C4/Reports/Guided.pm | 429 +++++++++++------- admin/authorised_values.pl | 23 +- installer/data/mysql/kohastructure.sql | 11 +- installer/data/mysql/updatedatabase.pl | 32 ++ .../prog/en/modules/reports/dictionary.tt | 4 +- .../en/modules/reports/guided_reports_start.tt | 128 +++++- misc/cronjobs/runreport.pl | 22 +- opac/svc/report | 9 +- reports/dictionary.pl | 292 ++++++------ reports/guided_reports.pl | 472 +++++++++++--------- svc/report | 7 +- 11 files changed, 891 insertions(+), 538 deletions(-) diff --git a/C4/Reports/Guided.pm b/C4/Reports/Guided.pm index f1ebe0c..da7ce56 100644 --- a/C4/Reports/Guided.pm +++ b/C4/Reports/Guided.pm @@ -26,7 +26,8 @@ use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); use C4::Context; use C4::Dates qw/format_date format_date_in_iso/; use C4::Templates qw/themelanguage/; -use C4::Dates; +use C4::Koha; +use C4::Output; use XML::Simple; use XML::Dumper; use C4::Debug; @@ -34,75 +35,82 @@ use C4::Debug; # use Data::Dumper; BEGIN { - # set the version for version checking + # set the version for version checking $VERSION = 3.07.00.049; - require Exporter; - @ISA = qw(Exporter); - @EXPORT = qw( - get_report_types get_report_areas get_columns build_query get_criteria - save_report get_saved_reports execute_query get_saved_report create_compound run_compound - get_column_type get_distinct_values save_dictionary get_from_dictionary - delete_definition delete_report format_results get_sql - nb_rows update_sql - ); + require Exporter; + @ISA = qw(Exporter); + @EXPORT = qw( + get_report_types get_report_areas get_report_groups get_columns build_query get_criteria + save_report get_saved_reports execute_query get_saved_report create_compound run_compound + get_column_type get_distinct_values save_dictionary get_from_dictionary + delete_definition delete_report format_results get_sql + nb_rows update_sql build_authorised_value_list + ); } -our %table_areas; -$table_areas{'1'} = - [ 'borrowers', 'statistics','items', 'biblioitems' ]; # circulation -$table_areas{'2'} = [ 'items', 'biblioitems', 'biblio' ]; # catalogue -$table_areas{'3'} = [ 'borrowers' ]; # patrons -$table_areas{'4'} = ['aqorders', 'biblio', 'items']; # acquisitions -$table_areas{'5'} = [ 'borrowers', 'accountlines' ]; # accounts -our %keys; -$keys{'1'} = [ - 'statistics.borrowernumber=borrowers.borrowernumber', - 'items.itemnumber = statistics.itemnumber', - 'biblioitems.biblioitemnumber = items.biblioitemnumber' -]; -$keys{'2'} = [ - 'items.biblioitemnumber=biblioitems.biblioitemnumber', - 'biblioitems.biblionumber=biblio.biblionumber' -]; -$keys{'3'} = [ ]; -$keys{'4'} = [ - 'aqorders.biblionumber=biblio.biblionumber', - 'biblio.biblionumber=items.biblionumber' -]; -$keys{'5'} = ['borrowers.borrowernumber=accountlines.borrowernumber']; +=item get_report_areas() -# have to do someting here to know if its dropdown, free text, date etc +This will return a list of all the available report areas -our %criteria; -# reports on circulation -$criteria{'1'} = [ - 'statistics.type', 'borrowers.categorycode', - 'statistics.branch', - 'biblioitems.publicationyear|date', - 'items.dateaccessioned|date' -]; -# reports on catalogue -$criteria{'2'} = - [ 'items.itemnumber|textrange', 'items.biblionumber|textrange', 'items.barcode|textrange', - 'biblio.frameworkcode', 'items.holdingbranch', 'items.homebranch', - 'biblio.datecreated|daterange', 'biblio.timestamp|daterange', 'items.onloan|daterange', - 'items.ccode', 'items.itemcallnumber|textrange', 'items.itype', - 'items.itemlost', 'items.location' ]; -# reports on borrowers -$criteria{'3'} = ['borrowers.branchcode', 'borrowers.categorycode']; -# reports on acquisition -$criteria{'4'} = ['aqorders.datereceived|date']; - -# reports on accounting -$criteria{'5'} = ['borrowers.branchcode', 'borrowers.categorycode']; +=cut + +my @REPORT_AREA = ( + [CIRC => "Circulation"], + [CAT => "Catalogue"], + [PAT => "Patrons"], + [ACQ => "Acquisition"], + [ACC => "Accounts"], +); +my $AREA_NAME_SQL_SNIPPET + = "CASE report_area " . + join (" ", map "WHEN '$_->[0]' THEN '$_->[1]'", @REPORT_AREA) . + " END AS areaname"; +sub get_report_areas { + return \@REPORT_AREA +} + +my %table_areas = ( + CIRC => [ 'borrowers', 'statistics', 'items', 'biblioitems' ], + CAT => [ 'items', 'biblioitems', 'biblio' ], + PAT => ['borrowers'], + ACQ => [ 'aqorders', 'biblio', 'items' ], + ACC => [ 'borrowers', 'accountlines' ], +); +my %keys = ( + CIRC => [ 'statistics.borrowernumber=borrowers.borrowernumber', + 'items.itemnumber = statistics.itemnumber', + 'biblioitems.biblioitemnumber = items.biblioitemnumber' ], + CAT => [ 'items.biblioitemnumber=biblioitems.biblioitemnumber', + 'biblioitems.biblionumber=biblio.biblionumber' ], + PAT => [], + ACQ => [ 'aqorders.biblionumber=biblio.biblionumber', + 'biblio.biblionumber=items.biblionumber' ], + ACC => ['borrowers.borrowernumber=accountlines.borrowernumber'], +); + +# have to do someting here to know if its dropdown, free text, date etc +my %criteria = ( + CIRC => [ 'statistics.type', 'borrowers.categorycode', 'statistics.branch', + 'biblioitems.publicationyear|date', 'items.dateaccessioned|date' ], + CAT => [ 'items.itemnumber|textrange', 'items.biblionumber|textrange', + 'items.barcode|textrange', 'biblio.frameworkcode', + 'items.holdingbranch', 'items.homebranch', + 'biblio.datecreated|daterange', 'biblio.timestamp|daterange', + 'items.onloan|daterange', 'items.ccode', + 'items.itemcallnumber|textrange', 'items.itype', 'items.itemlost', + 'items.location' ], + PAT => [ 'borrowers.branchcode', 'borrowers.categorycode' ], + ACQ => ['aqorders.datereceived|date'], + ACC => [ 'borrowers.branchcode', 'borrowers.categorycode' ], +); # Adds itemtypes to criteria, according to the syspref -if (C4::Context->preference('item-level_itypes')) { - unshift @{ $criteria{'1'} }, 'items.itype'; - unshift @{ $criteria{'2'} }, 'items.itype'; +if ( C4::Context->preference('item-level_itypes') ) { + unshift @{ $criteria{'CIRC'} }, 'items.itype'; + unshift @{ $criteria{'CAT'} }, 'items.itype'; } else { - unshift @{ $criteria{'1'} }, 'biblioitems.itemtype'; - unshift @{ $criteria{'2'} }, 'biblioitems.itemtype'; + unshift @{ $criteria{'CIRC'} }, 'biblioitems.itemtype'; + unshift @{ $criteria{'CAT'} }, 'biblioitems.itemtype'; } =head1 NAME @@ -145,26 +153,33 @@ sub get_report_types { } -=item get_report_areas() +=item get_report_groups() -This will return a list of all the available report areas +This will return a list of all the available report areas with groups =cut -sub get_report_areas { +sub get_report_groups { my $dbh = C4::Context->dbh(); - # FIXME these should be in the database - my @reports = ( 'Circulation', 'Catalog', 'Patrons', 'Acquisitions', 'Accounts'); - my @reports2; - for ( my $i = 0 ; $i < 5 ; $i++ ) { - my %hashrep; - $hashrep{id} = $i + 1; - $hashrep{name} = $reports[$i]; - push @reports2, \%hashrep; + my $groups = GetAuthorisedValues('REPORT_GROUP'); + my $subgroups = GetAuthorisedValues('REPORT_SUBGROUP'); + + my %groups_with_subgroups = map { $_->{authorised_value} => { + name => $_->{lib}, + groups => {} + } } @$groups; + foreach (@$subgroups) { + my $sg = $_->{authorised_value}; + my $g = $_->{lib_opac} + or warn( qq{REPORT_SUBGROUP "$sg" without REPORT_GROUP (lib_opac)} ), + next; + my $g_sg = $groups_with_subgroups{$g} + or warn( qq{REPORT_SUBGROUP "$sg" with invalid REPORT_GROUP "$g"} ), + next; + $g_sg->{subgroups}{$sg} = $_->{lib}; } - return ( \@reports2 ); - + return \%groups_with_subgroups } =item get_all_tables() @@ -196,8 +211,10 @@ This will return a list of all columns for a report area sub get_columns { # this calls the internal fucntion _get_columns - my ($area,$cgi) = @_; - my $tables = $table_areas{$area}; + my ( $area, $cgi ) = @_; + my $tables = $table_areas{$area} + or die qq{Unsuported report area "$area"}; + my @allcolumns; my $first = 1; foreach my $table (@$tables) { @@ -472,37 +489,47 @@ Returns id of the newly created report =cut sub save_report { - my ( $borrowernumber, $sql, $name, $type, $notes, $cache_expiry, $public ) = @_; - $cache_expiry ||= 300; + my ($fields) = @_; + my $borrowernumber = $fields->{borrowernumber}; + my $sql = $fields->{sql}; + my $name = $fields->{name}; + my $type = $fields->{type}; + my $notes = $fields->{notes}; + my $area = $fields->{area}; + my $group = $fields->{group}; + my $subgroup = $fields->{subgroup}; + my $cache_expiry = $fields->{cache_expiry} || 300; + my $public = $fields->{public}; + my $dbh = C4::Context->dbh(); - $sql =~ s/(\s*\;\s*)$//; # removes trailing whitespace and /;/ - my $query = -"INSERT INTO saved_sql (borrowernumber,date_created,last_modified,savedsql,report_name,type,notes,cache_expiry, public) VALUES (?,now(),now(),?,?,?,?,?,?)"; - $dbh->do( $query, undef, $borrowernumber, $sql, $name, $type, $notes, $cache_expiry, $public ); + $sql =~ s/(\s*\;\s*)$//; # removes trailing whitespace and /;/ + my $query = "INSERT INTO saved_sql (borrowernumber,date_created,last_modified,savedsql,report_name,report_area,report_group,report_subgroup,type,notes,cache_expiry,public) VALUES (?,now(),now(),?,?,?,?,?,?,?,?,?)"; + $dbh->do($query, undef, $borrowernumber, $sql, $name, $area, $group, $subgroup, $type, $notes, $cache_expiry, $public); + my $id = $dbh->selectrow_array("SELECT max(id) FROM saved_sql WHERE borrowernumber=? AND report_name=?", undef, $borrowernumber, $name); return $id; } sub update_sql { - my $id = shift || croak "No Id given"; - my $sql = shift; - my $reportname = shift; - my $notes = shift; - my $cache_expiry = shift; - my $public = shift; - - # not entirely a magic number, Cache::Memcached::Set assumed any expiry >= (60*60*24*30) is an absolute unix timestamp (rather than relative seconds) + my $id = shift || croak "No Id given"; + my $fields = shift; + my $sql = $fields->{sql}; + my $name = $fields->{name}; + my $notes = $fields->{notes}; + my $group = $fields->{group}; + my $subgroup = $fields->{subgroup}; + my $cache_expiry = $fields->{cache_expiry}; + my $public = $fields->{public}; + if( $cache_expiry >= 2592000 ){ die "Please specify a cache expiry less than 30 days\n"; } - my $dbh = C4::Context->dbh(); - $sql =~ s/(\s*\;\s*)$//; # removes trailing whitespace and /;/ - my $query = "UPDATE saved_sql SET savedsql = ?, last_modified = now(), report_name = ?, notes = ?, cache_expiry = ?, public = ? WHERE id = ? "; - my $sth = $dbh->prepare($query); - $sth->execute( $sql, $reportname, $notes, $cache_expiry, $public, $id ); - $sth->finish(); + my $dbh = C4::Context->dbh(); + $sql =~ s/(\s*\;\s*)$//; # removes trailing whitespace and /;/ + my $query = "UPDATE saved_sql SET savedsql = ?, last_modified = now(), report_name = ?, report_group = ?, report_subgroup = ?, notes = ?, cache_expiry = ?, public = ? WHERE id = ? "; + $dbh->do($query, undef, $sql, $name, $group, $subgroup, $notes, $cache_expiry, $public, $id ); } sub store_results { @@ -549,30 +576,34 @@ sub format_results { } sub delete_report { - my ( $id ) = @_; - my $dbh = C4::Context->dbh(); - my $query = "DELETE FROM saved_sql WHERE id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($id); + my ($id) = @_; + my $dbh = C4::Context->dbh(); + my $query = "DELETE FROM saved_sql WHERE id = ?"; + my $sth = $dbh->prepare($query); + $sth->execute($id); } -# $filter is either { date => $d, author => $a, keyword => $kw } -# or $keyword. Optional. + +my $SAVED_REPORTS_BASE_QRY = < $d, author => $a, keyword => $kw, } +# or $keyword. Optional. my ($filter) = @_; $filter = { keyword => $filter } if $filter && !ref( $filter ); + my ($group, $subgroup) = @_; my $dbh = C4::Context->dbh(); + my $query = $SAVED_REPORTS_BASE_QRY; my (@cond, at args); - my $query = "SELECT saved_sql.id, report_id, report, - date_run, date_created, last_modified, savedsql, last_run, - report_name, type, notes, - borrowernumber, surname as borrowersurname, firstname as borrowerfirstname, - cache_expiry, public - FROM saved_sql - LEFT JOIN saved_reports ON saved_reports.report_id = saved_sql.id - LEFT OUTER JOIN borrowers USING (borrowernumber)"; if ($filter) { if (my $date = $filter->{date}) { $date = format_date_in_iso($date); @@ -596,6 +627,14 @@ sub get_saved_reports { savedsql LIKE ?"; push @args, $keyword, $keyword, $keyword, $keyword; } + if ($filter->{group}) { + push @cond, "report_group = ?"; + push @args, $filter->{group}; + } + if ($filter->{subgroup}) { + push @cond, "report_subgroup = ?"; + push @args, $filter->{subgroup}; + } } $query .= " WHERE ".join( " AND ", map "($_)", @cond ) if @cond; $query .= " ORDER by date_created"; @@ -610,10 +649,7 @@ sub get_saved_report { my ($id) = @_; my $dbh = C4::Context->dbh(); my $query = " SELECT * FROM saved_sql WHERE id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($id); - my $data = $sth->fetchrow_hashref(); - return ( $data->{'savedsql'}, $data->{'type'}, $data->{'report_name'}, $data->{'notes'}, $data->{'cache_expiry'}, $data->{'public'} ); + return $dbh->selectrow_hashref($query, undef, $id); } =item create_compound($masterID,$subreportID) @@ -623,22 +659,27 @@ This will take 2 reports and create a compound report using both of them =cut sub create_compound { - my ($masterID,$subreportID) = @_; - my $dbh = C4::Context->dbh(); - # get the reports - my ($mastersql,$mastertype) = get_saved_report($masterID); - my ($subsql,$subtype) = get_saved_report($subreportID); - - # now we have to do some checking to see how these two will fit together - # or if they will - my ($mastertables,$subtables); - if ($mastersql =~ / from (.*) where /i){ - $mastertables = $1; - } - if ($subsql =~ / from (.*) where /i){ - $subtables = $1; - } - return ($mastertables,$subtables); + my ( $masterID, $subreportID ) = @_; + my $dbh = C4::Context->dbh(); + + # get the reports + my $master = get_saved_report($masterID); + my $mastersql = $master->{savedsql}; + my $mastertype = $master->{type}; + my $sub = get_saved_report($subreportID); + my $subsql = $master->{savedsql}; + my $subtype = $master->{type}; + + # now we have to do some checking to see how these two will fit together + # or if they will + my ( $mastertables, $subtables ); + if ( $mastersql =~ / from (.*) where /i ) { + $mastertables = $1; + } + if ( $subsql =~ / from (.*) where /i ) { + $subtables = $1; + } + return ( $mastertables, $subtables ); } =item get_column_type($column) @@ -688,43 +729,41 @@ sub get_distinct_values { } sub save_dictionary { - my ($name,$description,$sql,$area) = @_; - my $dbh = C4::Context->dbh(); - my $query = "INSERT INTO reports_dictionary (name,description,saved_sql,area,date_created,date_modified) + my ( $name, $description, $sql, $area ) = @_; + my $dbh = C4::Context->dbh(); + my $query = "INSERT INTO reports_dictionary (name,description,saved_sql,report_area,date_created,date_modified) VALUES (?,?,?,?,now(),now())"; my $sth = $dbh->prepare($query); $sth->execute($name,$description,$sql,$area) || return 0; return 1; } +my $DICTIONARY_BASE_QRY = <dbh(); - my $query = "SELECT * FROM reports_dictionary"; - if ($area){ - $query.= " WHERE area = ?"; - } - elsif ($id){ - $query.= " WHERE id = ?" - } - my $sth = $dbh->prepare($query); - if ($id){ - $sth->execute($id); - } - elsif ($area) { - $sth->execute($area); - } - else { - $sth->execute(); - } - my @loop; - my @reports = ( 'Circulation', 'Catalog', 'Patrons', 'Acquisitions', 'Accounts'); - while (my $data = $sth->fetchrow_hashref()){ - $data->{'areaname'}=$reports[$data->{'area'}-1]; - push @loop,$data; - - } - return (\@loop); + my ( $area, $id ) = @_; + my $dbh = C4::Context->dbh(); + my $query = $DICTIONARY_BASE_QRY; + if ($area) { + $query .= " WHERE report_area = ?"; + } elsif ($id) { + $query .= " WHERE id = ?"; + } + my $sth = $dbh->prepare($query); + if ($id) { + $sth->execute($id); + } elsif ($area) { + $sth->execute($area); + } else { + $sth->execute(); + } + my @loop; + while ( my $data = $sth->fetchrow_hashref() ) { + push @loop, $data; + } + return ( \@loop ); } sub delete_definition { @@ -764,6 +803,72 @@ sub _get_column_defs { close COLUMNS; return \%columns; } + +=item build_authorised_value_list($authorised_value) + +Returns an arrayref - hashref pair. The hashref consists of +various code => name lists depending on the $authorised_value. +The arrayref is the hashref keys, in appropriate order + +=cut + +sub build_authorised_value_list { + my ( $authorised_value ) = @_; + + my $dbh = C4::Context->dbh; + my @authorised_values; + my %authorised_lib; + + # builds list, depending on authorised value... + if ( $authorised_value eq "branches" ) { + my $branches = GetBranchesLoop(); + foreach my $thisbranch (@$branches) { + push @authorised_values, $thisbranch->{value}; + $authorised_lib{ $thisbranch->{value} } = $thisbranch->{branchname}; + } + } elsif ( $authorised_value eq "itemtypes" ) { + my $sth = $dbh->prepare("SELECT itemtype,description FROM itemtypes ORDER BY description"); + $sth->execute; + while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) { + push @authorised_values, $itemtype; + $authorised_lib{$itemtype} = $description; + } + } elsif ( $authorised_value eq "cn_source" ) { + my $class_sources = GetClassSources(); + my $default_source = C4::Context->preference("DefaultClassificationSource"); + foreach my $class_source ( sort keys %$class_sources ) { + next + unless $class_sources->{$class_source}->{'used'} + or ( $class_source eq $default_source ); + push @authorised_values, $class_source; + $authorised_lib{$class_source} = $class_sources->{$class_source}->{'description'}; + } + } elsif ( $authorised_value eq "categorycode" ) { + my $sth = $dbh->prepare("SELECT categorycode, description FROM categories ORDER BY description"); + $sth->execute; + while ( my ( $categorycode, $description ) = $sth->fetchrow_array ) { + push @authorised_values, $categorycode; + $authorised_lib{$categorycode} = $description; + } + + #---- "true" authorised value + } else { + my $authorised_values_sth = $dbh->prepare("SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY lib"); + + $authorised_values_sth->execute($authorised_value); + + while ( my ( $value, $lib ) = $authorised_values_sth->fetchrow_array ) { + push @authorised_values, $value; + $authorised_lib{$value} = $lib; + + # For item location, we show the code and the libelle + $authorised_lib{$value} = $lib; + } + } + + return (\@authorised_values, \%authorised_lib); +} + 1; __END__ diff --git a/admin/authorised_values.pl b/admin/authorised_values.pl index 1545f0e..8c60a0b 100755 --- a/admin/authorised_values.pl +++ b/admin/authorised_values.pl @@ -188,17 +188,18 @@ output_html_with_http_headers $input, $cookie, $template->output; exit 0; sub default_form { - # build categories list - my $sth = $dbh->prepare("select distinct category from authorised_values"); - $sth->execute; - my @category_list; - my %categories; # a hash, to check that some hardcoded categories exist. - while ( my ($category) = $sth->fetchrow_array) { - push(@category_list,$category); - $categories{$category} = 1; - } - # push koha system categories - foreach (qw(Asort1 Asort2 Bsort1 Bsort2 SUGGEST DAMAGED LOST)) { + # build categories list + my $sth = $dbh->prepare("select distinct category from authorised_values"); + $sth->execute; + my @category_list; + my %categories; # a hash, to check that some hardcoded categories exist. + while ( my ($category) = $sth->fetchrow_array ) { + push( @category_list, $category ); + $categories{$category} = 1; + } + + # push koha system categories + foreach (qw(Asort1 Asort2 Bsort1 Bsort2 SUGGEST DAMAGED LOST REPORT_GROUP REPORT_SUBGROUP)) { push @category_list, $_ unless $categories{$_}; } diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 54498c3..7e0ed1a 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -97,7 +97,7 @@ CREATE TABLE `auth_types` ( DROP TABLE IF EXISTS `authorised_values`; CREATE TABLE `authorised_values` ( -- stores values for authorized values categories and values `id` int(11) NOT NULL auto_increment, -- unique key, used to identify the authorized value - `category` varchar(10) NOT NULL default '', -- key used to identify the authorized value category + `category` varchar(16) NOT NULL default '', -- key used to identify the authorized value category `authorised_value` varchar(80) NOT NULL default '', -- code use to identify the authorized value `lib` varchar(80) default NULL, -- authorized value description as printed in the staff client `lib_opac` VARCHAR(80) default NULL, -- authorized value description as printed in the OPAC @@ -1621,8 +1621,9 @@ CREATE TABLE reports_dictionary ( -- definitions (or snippets of SQL) stored for `date_created` datetime default NULL, -- date and time this definition was created `date_modified` datetime default NULL, -- date and time this definition was last modified `saved_sql` text, -- SQL snippet for us in reports - `area` int(11) default NULL, -- Koha module this definition is for (1 = Circulation, 2 = Catalog, 3 = Patrons, 4 = Acquistions, 5 = Accounts) - PRIMARY KEY (`id`) + report_area varchar(6) DEFAULT NULL, -- Koha module this definition is for Circulation, Catalog, Patrons, Acquistions, Accounts) + PRIMARY KEY (id), + KEY dictionary_area_idx (report_area) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- @@ -1718,7 +1719,11 @@ CREATE TABLE saved_sql ( `notes` text, `cache_expiry` int NOT NULL default 300, `public` boolean NOT NULL default FALSE, + report_area varchar(6) default NULL, + report_group varchar(80) default NULL, + report_subgroup varchar(80) default NULL, PRIMARY KEY (`id`), + KEY sql_area_group_idx (report_group, report_subgroup), KEY boridx (`borrowernumber`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index 9b02cb9..46528e5 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -5370,6 +5370,38 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { } + + +$DBversion = "3.09.00.XXX"; +if (C4::Context->preference("Version") < TransformToNum($DBversion)) { + $dbh->do("ALTER TABLE authorised_values MODIFY category varchar(16) NOT NULL DEFAULT '';"); + $dbh->do("INSERT INTO authorised_values (category, authorised_value, lib) VALUES + ('REPORT_GROUP', 'CIRC', 'Circulation'), + ('REPORT_GROUP', 'CAT', 'Catalog'), + ('REPORT_GROUP', 'PAT', 'Patrons'), + ('REPORT_GROUP', 'ACQ', 'Acquisitions'), + ('REPORT_GROUP', 'ACC', 'Accounts');"); + + $dbh->do("ALTER TABLE reports_dictionary ADD report_area varchar(6) DEFAULT NULL;"); + $dbh->do("UPDATE reports_dictionary SET report_area = CASE area + WHEN 1 THEN 'CIRC' + WHEN 2 THEN 'CAT' + WHEN 3 THEN 'PAT' + WHEN 4 THEN 'ACQ' + WHEN 5 THEN 'ACC' + END;"); + $dbh->do("ALTER TABLE reports_dictionary DROP area;"); + $dbh->do("ALTER TABLE reports_dictionary ADD KEY dictionary_area_idx (report_area);"); + + $dbh->do("ALTER TABLE saved_sql ADD report_area varchar(6) DEFAULT NULL;"); + $dbh->do("ALTER TABLE saved_sql ADD report_group varchar(80) DEFAULT NULL;"); + $dbh->do("ALTER TABLE saved_sql ADD report_subgroup varchar(80) DEFAULT NULL;"); + $dbh->do("ALTER TABLE saved_sql ADD KEY sql_area_group_idx (report_group, report_subgroup);"); + + print "Upgrade to $DBversion done saved_sql new fields report_group and report_area; authorised_values.category 16 char \n"; + SetVersion($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/dictionary.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/dictionary.tt index 3f913d4..5248bbd 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/dictionary.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/dictionary.tt @@ -33,7 +33,7 @@
    [% IF ( areas ) %] - Filter by area [% FOREACH area IN areas %] [% IF ( area.selected ) %] @@ -103,7 +103,7 @@
    1. - [% FOREACH area IN areas %] [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt index f6ebbfe..ec0ad82 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt @@ -24,6 +24,25 @@ + [% END %] +
    2. +
    3. + [% END %]
    @@ -579,6 +626,11 @@ canned reports and writing custom SQL reports.

    [% END %] [% IF ( create ) %] +
    Create report from SQL @@ -587,6 +639,27 @@ canned reports and writing custom SQL reports.

    [% IF ( reportname ) %] [% ELSE %][% END %] + [% IF groups_with_subgroups %] +
  • +
  • + [% END %] [% IF (public) %]
  • [% ELSE %] @@ -671,6 +744,11 @@ Sub report: @@ -678,6 +756,27 @@ Sub report: + [% IF groups_with_subgroups %] +
  • +
  • + [% END %] [% IF (public) %]
  • [% ELSE %] @@ -745,12 +844,39 @@ Sub report:

    Filter

      +
    1. + + +
    2. [% INCLUDE 'date-format.inc' %]
      diff --git a/misc/cronjobs/runreport.pl b/misc/cronjobs/runreport.pl index 6a8cce7..690f216 100755 --- a/misc/cronjobs/runreport.pl +++ b/misc/cronjobs/runreport.pl @@ -186,14 +186,26 @@ unless (scalar(@ARGV)) { ($verbose) and print scalar(@ARGV), " argument(s) after options: " . join(" ", @ARGV) . "\n"; -foreach my $report (@ARGV) { - my ($sql, $type) = get_saved_report($report); - unless ($sql) { - carp "ERROR: No saved report $report found"; +foreach my $report_id (@ARGV) { + my $report = get_saved_report($report_id); + unless ($report) { + warn "ERROR: No saved report $report_id found"; next; } + my $sql => $report->{savedsql}; + my $report_name => $report->{report_name}; + my $type => $report->{type}; + $verbose and print "SQL: $sql\n\n"; - # my $results = execute_query($sql, undef, 0, 99999, $format, $report); + if (defined($report_name) and $report_name ne "") + { + $subject = $report_name ; + } + else + { + $subject = 'Koha Saved Report'; + } + # my $results = execute_query($sql, undef, 0, 99999, $format, $report_id); my ($sth) = execute_query($sql); # execute_query(sql, , 0, 20, , ) my $count = scalar($sth->rows); diff --git a/opac/svc/report b/opac/svc/report index 0f9d5fb..8af0b65 100755 --- a/opac/svc/report +++ b/opac/svc/report @@ -32,9 +32,8 @@ my $report = $query->param('id'); my $cache; -my ( $sql, $type, $name, $notes, $cache_expiry, $public ) = - get_saved_report($report); -die "Sorry this report is not public\n" unless $public; +my $report_rec = get_saved_report($report); +die "Sorry this report is not public\n" unless $report_rec->{public}; if (Koha::Cache->is_cache_active) { $cache = Koha::Cache->new( @@ -50,11 +49,11 @@ if (Koha::Cache->is_cache_active) { print $query->header; my $offset = 0; my $limit = C4::Context->preference("SvcMaxReportRows") || 10; -my ( $sth, $errors ) = execute_query( $sql, $offset, $limit ); +my ( $sth, $errors ) = execute_query( $report_rec->{sql}, $offset, $limit ); my $lines = $sth->fetchall_arrayref; my $json_text = to_json($lines); print $json_text; if (Koha::Cache->is_cache_active) { - $cache->set_in_cache( "opac:report:$report", $json_text, $cache_expiry ); + $cache->set_in_cache( "opac:report:$report", $json_text, $report_rec->{cache_expiry} ); } diff --git a/reports/dictionary.pl b/reports/dictionary.pl index 4f94d69..aae96c9 100755 --- a/reports/dictionary.pl +++ b/reports/dictionary.pl @@ -37,11 +37,12 @@ my $input = new CGI; my $referer = $input->referer(); my $phase = $input->param('phase') || 'View Dictionary'; -my $area = $input->param('areas') || ''; -my $no_html = 0; # this will be set if we dont want to print out an html::template -my ( $template, $borrowernumber, $cookie ) = get_template_and_user( - { - template_name => "reports/dictionary.tmpl", +my $definition_name = $input->param('definition_name'); +my $definition_description = $input->param('definition_description'); +my $area = $input->param('area') || ''; +my $no_html = 0; # this will be set if we dont want to print out an html::template +my ( $template, $borrowernumber, $cookie ) = get_template_and_user( + { template_name => "reports/dictionary.tmpl", query => $input, type => "intranet", authnotrequired => 0, @@ -51,78 +52,71 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( ); if ($phase eq 'View Dictionary'){ - # view the dictionary we use to set up abstract variables such as all borrowers over fifty who live in a certain town - my $areas = get_report_areas(); - foreach (@{ $areas }) { - $_->{selected} = 1 if $_->{id} eq $area; # mark active area - } - my $definitions = get_from_dictionary($area); - $template->param( 'areas' => $areas , - 'start_dictionary' => 1, - 'definitions' => $definitions, - ); -} -elsif ($phase eq 'Add New Definition'){ - # display form allowing them to add a new definition - $template->param( 'new_dictionary' => 1, - ); + # view the dictionary we use to set up abstract variables such as all borrowers over fifty who live in a certain town + my $definitions = get_from_dictionary($area); + $template->param( + 'areas'=> areas(), + 'start_dictionary' => 1, + 'definitions' => $definitions, + ); +} elsif ( $phase eq 'Add New Definition' ) { + + # display form allowing them to add a new definition + $template->param( 'new_dictionary' => 1, ); } -elsif ($phase eq 'New Term step 2'){ - # Choosing the area - my $areas = C4::Reports::Guided::get_report_areas(); - my $definition_name=$input->param('definition_name'); - my $definition_description=$input->param('definition_description'); - $template->param( 'step_2' => 1, - 'areas' => $areas, - 'definition_name' => $definition_name, - 'definition_description' => $definition_description, - ); +elsif ( $phase eq 'New Term step 2' ) { + + # Choosing the area + $template->param( + 'step_2' => 1, + 'areas' => areas(), + 'definition_name' => $definition_name, + 'definition_description' => $definition_description, + ); } -elsif ($phase eq 'New Term step 3'){ - # Choosing the columns - my $area = $input->param('areas'); - my $columns = get_columns($area,$input); - my $definition_name=$input->param('definition_name'); - my $definition_description=$input->param('definition_description'); - $template->param( 'step_3' => 1, - 'area' => $area, - 'columns' => $columns, - 'definition_name' => $definition_name, - 'definition_description' => $definition_description, - ); +elsif ( $phase eq 'New Term step 3' ) { + + # Choosing the columns + my $columns = get_columns( $area, $input ); + $template->param( + 'step_3' => 1, + 'area' => $area, + 'columns' => $columns, + 'definition_name' => $definition_name, + 'definition_description' => $definition_description, + ); } -elsif ($phase eq 'New Term step 4'){ - # Choosing the values - my $area=$input->param('area'); - my $definition_name=$input->param('definition_name'); - my $definition_description=$input->param('definition_description'); - my @columns = $input->param('columns'); - my $columnstring = join (',', at columns); - my @column_loop; - foreach my $column (@columns){ - my %tmp_hash; - $tmp_hash{'name'}=$column; - my $type =get_column_type($column); - if ($type eq 'distinct'){ - my $values = get_distinct_values($column); - $tmp_hash{'values'} = $values; - $tmp_hash{'distinct'} = 1; - - } - if ($type eq 'DATE' || $type eq 'DATETIME'){ - $tmp_hash{'date'}=1; - } - if ($type eq 'TEXT' || $type eq 'MEDIUMTEXT'){ - $tmp_hash{'text'}=1; - } -# else { -# warn $type;# -# } - push @column_loop,\%tmp_hash; - } +elsif ( $phase eq 'New Term step 4' ) { + + # Choosing the values + my @columns = $input->param('columns'); + my $columnstring = join( ',', @columns ); + my @column_loop; + foreach my $column (@columns) { + my %tmp_hash; + $tmp_hash{'name'} = $column; + my $type = get_column_type($column); + if ( $type eq 'distinct' ) { + my $values = get_distinct_values($column); + $tmp_hash{'values'} = $values; + $tmp_hash{'distinct'} = 1; + + } + if ( $type eq 'DATE' || $type eq 'DATETIME' ) { + $tmp_hash{'date'} = 1; + } + if ( $type eq 'TEXT' ) { + $tmp_hash{'text'} = 1; + } + + # else { + # warn $type;# + # } + push @column_loop, \%tmp_hash; + } $template->param( 'step_4' => 1, 'area' => $area, @@ -134,83 +128,78 @@ elsif ($phase eq 'New Term step 4'){ ); } -elsif ($phase eq 'New Term step 5'){ - # Confirmation screen - my $areas = C4::Reports::Guided::get_report_areas(); - my $area = $input->param('area'); - my $areaname = $areas->[$area - 1]->{'name'}; - my $columnstring = $input->param('columnstring'); - my $definition_name=$input->param('definition_name'); - my $definition_description=$input->param('definition_description'); - my @criteria = $input->param('criteria_column'); - my $query_criteria; - my @criteria_loop; - foreach my $crit (@criteria) { - my $value = $input->param( $crit . "_value" ); - if ($value) { - my %tmp_hash; - $tmp_hash{'name'}=$crit; - $tmp_hash{'value'} = $value; - push @criteria_loop,\%tmp_hash; - if ($value =~ C4::Dates->regexp(C4::Context->preference('dateformat'))) { - my $date = C4::Dates->new($value); - $value = $date->output("iso"); - } - $query_criteria .= " AND $crit='$value'"; - } - $value = $input->param( $crit . "_start_value" ); - if ($value) { - my %tmp_hash; - $tmp_hash{'name'}="$crit Start"; - $tmp_hash{'value'} = $value; - push @criteria_loop,\%tmp_hash; - if ($value =~ C4::Dates->regexp(C4::Context->preference('dateformat'))) { - my $date = C4::Dates->new($value); - $value = $date->output("iso"); - } - $query_criteria .= " AND $crit >= '$value'"; - } - $value = $input->param( $crit . "_end_value" ); - if ($value) { - my %tmp_hash; - $tmp_hash{'name'}="$crit End"; - $tmp_hash{'value'} = $value; - push @criteria_loop,\%tmp_hash; - if ($value =~ C4::Dates->regexp(C4::Context->preference('dateformat'))) { - my $date = C4::Dates->new($value); - $value = $date->output("iso"); - } - $query_criteria .= " AND $crit <= '$value'"; - } - } - $template->param( 'step_5' => 1, - 'area' => $area, - 'areaname' => $areaname, - 'definition_name' => $definition_name, - 'definition_description' => $definition_description, - 'query' => $query_criteria, - 'columnstring' => $columnstring, - 'criteria_loop' => \@criteria_loop, - ); +elsif ( $phase eq 'New Term step 5' ) { + # Confirmation screen + my $columnstring = $input->param('columnstring'); + my @criteria = $input->param('criteria_column'); + my $query_criteria; + my @criteria_loop; + + foreach my $crit (@criteria) { + my $value = $input->param( $crit . "_value" ); + if ($value) { + my %tmp_hash; + $tmp_hash{'name'} = $crit; + $tmp_hash{'value'} = $value; + push @criteria_loop, \%tmp_hash; + if ( $value =~ C4::Dates->regexp( C4::Context->preference('dateformat') ) ) { + my $date = C4::Dates->new($value); + $value = $date->output("iso"); + } + $query_criteria .= " AND $crit='$value'"; + } + $value = $input->param( $crit . "_start_value" ); + if ($value) { + my %tmp_hash; + $tmp_hash{'name'} = "$crit Start"; + $tmp_hash{'value'} = $value; + push @criteria_loop, \%tmp_hash; + if ( $value =~ C4::Dates->regexp( C4::Context->preference('dateformat') ) ) { + my $date = C4::Dates->new($value); + $value = $date->output("iso"); + } + $query_criteria .= " AND $crit >= '$value'"; + } + $value = $input->param( $crit . "_end_value" ); + if ($value) { + my %tmp_hash; + $tmp_hash{'name'} = "$crit End"; + $tmp_hash{'value'} = $value; + push @criteria_loop, \%tmp_hash; + if ( $value =~ C4::Dates->regexp( C4::Context->preference('dateformat') ) ) { + my $date = C4::Dates->new($value); + $value = $date->output("iso"); + } + $query_criteria .= " AND $crit <= '$value'"; + } + } + my %report_areas = map @$_, get_report_areas(); + $template->param( + 'step_5' => 1, + 'area' => $area, + 'areaname' => $report_areas{$area}, + 'definition_name' => $definition_name, + 'definition_description' => $definition_description, + 'query' => $query_criteria, + 'columnstring' => $columnstring, + 'criteria_loop' => \@criteria_loop, + ); } -elsif ($phase eq 'New Term step 6'){ - # Saving - my $area = $input->param('area'); - my $definition_name=$input->param('definition_name'); - my $definition_description=$input->param('definition_description'); - my $sql=$input->param('sql'); - save_dictionary($definition_name,$definition_description,$sql,$area); - $no_html=1; - print $input->redirect("/cgi-bin/koha/reports/dictionary.pl?phase=View%20Dictionary"); - +elsif ( $phase eq 'New Term step 6' ) { + # Saving + my $area = $input->param('area'); + my $sql = $input->param('sql'); + save_dictionary( $definition_name, $definition_description, $sql, $area ); + $no_html = 1; + print $input->redirect("/cgi-bin/koha/reports/dictionary.pl?phase=View%20Dictionary"); + +} elsif ( $phase eq 'Delete Definition' ) { + $no_html = 1; + my $id = $input->param('id'); + delete_definition($id); + print $input->redirect("/cgi-bin/koha/reports/dictionary.pl?phase=View%20Dictionary"); } -elsif ($phase eq 'Delete Definition'){ - $no_html=1; - my $id = $input->param('id'); - delete_definition($id); - print $input->redirect("/cgi-bin/koha/reports/dictionary.pl?phase=View%20Dictionary"); - } $template->param( 'referer' => $referer ); @@ -218,3 +207,16 @@ $template->param( 'referer' => $referer ); if (!$no_html){ output_html_with_http_headers $input, $cookie, $template->output; } + +sub areas { + my $areas = get_report_areas(); + my @a; + foreach (@$areas) { + push @a, { + id => $_->[0], + name => $_->[1], + selected => ($_->[0] eq $area), + }; + } + return \@a; +} diff --git a/reports/guided_reports.pl b/reports/guided_reports.pl index 1112274..ee0a1de 100755 --- a/reports/guided_reports.pl +++ b/reports/guided_reports.pl @@ -18,14 +18,15 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. use strict; -#use warnings; FIXME - Bug 2505 +use warnings; + use CGI; use Text::CSV; use URI::Escape; use C4::Reports::Guided; use C4::Auth qw/:DEFAULT get_session/; use C4::Output; -use C4::Dates; +use C4::Dates qw/format_date/; use C4::Debug; use C4::Branch; # XXX subfield_is_koha_internal_p @@ -68,7 +69,7 @@ my $session = $cookie ? get_session($cookie->value) : undef; my $filter; if ( $input->param("filter_set") ) { $filter = {}; - $filter->{$_} = $input->param("filter_$_") foreach qw/date author keyword/; + $filter->{$_} = $input->param("filter_$_") foreach qw/date author keyword group subgroup/; $session->param('report_filter', $filter) if $session; $template->param( 'filter_set' => 1 ); } @@ -85,21 +86,27 @@ if ( !$phase ) { elsif ( $phase eq 'Build new' ) { # build a new report $template->param( 'build1' => 1 ); - $template->param( 'areas' => get_report_areas(), 'usecache' => $usecache, 'cache_expiry' => 300, 'public' => '0' ); -} -elsif ( $phase eq 'Use saved' ) { + my $areas = get_report_areas(); + $template->param( + 'areas' => [map { id => $_->[0], name => $_->[1] }, @$areas], + 'usecache' => $usecache, + 'cache_expiry' => 300, + 'public' => '0', + ); +} elsif ( $phase eq 'Use saved' ) { + # use a saved report # get list of reports and display them + my $group = $input->param('group'); + my $subgroup = $input->param('subgroup'); + $filter->{group} = $group; + $filter->{subgroup} = $subgroup; $template->param( 'saved1' => 1, 'savedreports' => get_saved_reports($filter), 'usecache' => $usecache, + 'groups_with_subgroups'=> groups_with_subgroups($group, $subgroup), ); - if ($filter) { - while ( my ($k, $v) = each %$filter ) { - $template->param( "filter_$k" => $v ) if $v; - } - } } elsif ( $phase eq 'Delete Saved') { @@ -113,30 +120,33 @@ elsif ( $phase eq 'Delete Saved') { elsif ( $phase eq 'Show SQL'){ - my $id = $input->param('reports'); - my ($sql,$type,$reportname,$notes) = get_saved_report($id); - $template->param( + my $id = $input->param('reports'); + my $report = get_saved_report($id); + $template->param( 'id' => $id, - 'reportname' => $reportname, - 'notes' => $notes, - 'sql' => $sql, - 'showsql' => 1, + 'reportname' => $report->{report_name}, + 'notes' => $report->{notes}, + 'sql' => $report->{savedsql}, + 'showsql' => 1, ); } elsif ( $phase eq 'Edit SQL'){ my $id = $input->param('reports'); - my ($sql,$type,$reportname,$notes, $cache_expiry, $public) = get_saved_report($id); + my $report = get_saved_report($id); + my $group = $report->{report_group}; + my $subgroup = $report->{report_subgroup}; $template->param( - 'sql' => $sql, - 'reportname' => $reportname, - 'notes' => $notes, + 'sql' => $report->{savedsql}, + 'reportname' => $report->{report_name}, + 'groups_with_subgroups' => groups_with_subgroups($group, $subgroup), + 'notes' => $report->{notes}, 'id' => $id, - 'cache_expiry' => $cache_expiry, - 'public' => $public, + 'cache_expiry' => $report->{cache_expiry}, + 'public' => $report->{public}, 'usecache' => $usecache, - 'editsql' => 1, + 'editsql' => 1, ); } @@ -144,6 +154,8 @@ elsif ( $phase eq 'Update SQL'){ my $id = $input->param('id'); my $sql = $input->param('sql'); my $reportname = $input->param('reportname'); + my $group = $input->param('group'); + my $subgroup = $input->param('subgroup'); my $notes = $input->param('notes'); my $cache_expiry = $input->param('cache_expiry'); my $cache_expiry_units = $input->param('cache_expiry_units'); @@ -177,16 +189,22 @@ elsif ( $phase eq 'Update SQL'){ 'errors' => \@errors, 'sql' => $sql, ); - } - else { - update_sql( $id, $sql, $reportname, $notes, $cache_expiry, $public ); + } else { + update_sql( $id, { + sql => $sql, + name => $reportname, + group => $group, + subgroup => $subgroup, + notes => $notes, + cache_expiry => $cache_expiry, + public => $public, + } ); $template->param( 'save_successful' => 1, 'reportname' => $reportname, 'id' => $id, ); } - } elsif ($phase eq 'retrieve results') { @@ -228,7 +246,7 @@ elsif ( $phase eq 'Report on this Area' ) { # they have choosen a new report and the area to report on $template->param( 'build2' => 1, - 'area' => $input->param('areas'), + 'area' => $input->param('area'), 'types' => get_report_types(), 'cache_expiry' => $cache_expiry, 'public' => $input->param('public'), @@ -275,42 +293,42 @@ elsif ( $phase eq 'Choose these criteria' ) { my $area = $input->param('area'); my $type = $input->param('type'); my $column = $input->param('column'); - my @definitions = $input->param('definition'); - my $definition = join (',', at definitions); + my @definitions = $input->param('definition'); + my $definition = join (',', at definitions); my @criteria = $input->param('criteria_column'); - my $query_criteria; + my $query_criteria; foreach my $crit (@criteria) { my $value = $input->param( $crit . "_value" ); - - # If value is not defined, then it may be range values - if (!defined $value) { - - my $fromvalue = $input->param( "from_" . $crit . "_value" ); - my $tovalue = $input->param( "to_" . $crit . "_value" ); - - # If the range values are dates - if ($fromvalue =~ C4::Dates->regexp('syspref') && $tovalue =~ C4::Dates->regexp('syspref')) { - $fromvalue = C4::Dates->new($fromvalue)->output("iso"); - $tovalue = C4::Dates->new($tovalue)->output("iso"); - } - - if ($fromvalue && $tovalue) { - $query_criteria .= " AND $crit >= '$fromvalue' AND $crit <= '$tovalue'"; - } - - } else { - - # If value is a date - if ($value =~ C4::Dates->regexp('syspref')) { - $value = C4::Dates->new($value)->output("iso"); - } - # don't escape runtime parameters, they'll be at runtime - if ($value =~ /<<.*>>/) { - $query_criteria .= " AND $crit=$value"; + + # If value is not defined, then it may be range values + if (!defined $value) { + + my $fromvalue = $input->param( "from_" . $crit . "_value" ); + my $tovalue = $input->param( "to_" . $crit . "_value" ); + + # If the range values are dates + if ($fromvalue =~ C4::Dates->regexp('syspref') && $tovalue =~ C4::Dates->regexp('syspref')) { + $fromvalue = C4::Dates->new($fromvalue)->output("iso"); + $tovalue = C4::Dates->new($tovalue)->output("iso"); + } + + if ($fromvalue && $tovalue) { + $query_criteria .= " AND $crit >= '$fromvalue' AND $crit <= '$tovalue'"; + } + } else { - $query_criteria .= " AND $crit='$value'"; + + # If value is a date + if ($value =~ C4::Dates->regexp('syspref')) { + $value = C4::Dates->new($value)->output("iso"); + } + # don't escape runtime parameters, they'll be at runtime + if ($value =~ /<<.*>>/) { + $query_criteria .= " AND $crit=$value"; + } else { + $query_criteria .= " AND $crit='$value'"; + } } - } } $template->param( 'build5' => 1, @@ -412,6 +430,7 @@ elsif ( $phase eq 'Build report' ) { build_query( \@columns, $query_criteria, $query_orderby, $area, $totals, $definition ); $template->param( 'showreport' => 1, + 'area' => $area, 'sql' => $sql, 'type' => $type, 'cache_expiry' => $input->param('cache_expiry'), @@ -420,23 +439,29 @@ elsif ( $phase eq 'Build report' ) { } elsif ( $phase eq 'Save' ) { - # Save the report that has just been built + # Save the report that has just been built + my $area = $input->param('area'); my $sql = $input->param('sql'); my $type = $input->param('type'); $template->param( 'save' => 1, + 'area' => $area, 'sql' => $sql, 'type' => $type, 'cache_expiry' => $input->param('cache_expiry'), 'public' => $input->param('public'), + 'groups_with_subgroups' => groups_with_subgroups($area), # in case we have a report group that matches area ); } elsif ( $phase eq 'Save Report' ) { - # save the sql pasted in by a user - my $sql = $input->param('sql'); - my $name = $input->param('reportname'); - my $type = $input->param('types'); + # save the sql pasted in by a user + my $area = $input->param('area'); + my $group = $input->param('group'); + my $subgroup = $input->param('subgroup'); + my $sql = $input->param('sql'); + my $name = $input->param('reportname'); + my $type = $input->param('types'); my $notes = $input->param('notes'); my $cache_expiry = $input->param('cache_expiry'); my $cache_expiry_units = $input->param('cache_expiry_units'); @@ -454,7 +479,7 @@ elsif ( $phase eq 'Save Report' ) { } } # check $cache_expiry isnt too large, Memcached::set requires it to be less than 30 days or it will be treated as if it were an absolute time stamp - if( $cache_expiry >= 2592000 ){ + if( $cache_expiry && $cache_expiry >= 2592000 ){ push @errors, {cache_expiry => $cache_expiry}; } ## FIXME this is AFTER entering a name to save the report under @@ -462,7 +487,7 @@ elsif ( $phase eq 'Save Report' ) { push @errors, {sqlerr => $1}; } elsif ($sql !~ /^(SELECT)/i) { - push @errors, {queryerr => 1}; + push @errors, {queryerr => "No SELECT"}; } if (@errors) { $template->param( @@ -476,157 +501,168 @@ elsif ( $phase eq 'Save Report' ) { ); } else { - my $id = save_report( $borrowernumber, $sql, $name, $type, $notes, $cache_expiry, $public ); - $template->param( - 'save_successful' => 1, - 'reportname' => $name, - 'id' => $id, - ); + save_report( { + borrowernumber => $borrowernumber, + sql => $sql, + name => $name, + area => $area, + group => $group, + subgroup => $subgroup, + type => $type, + notes => $notes, + cache_expiry => $cache_expiry, + public => $public, + } ); + $template->param( 'save_successful' => 1, ); } } elsif ($phase eq 'Run this report'){ # execute a saved report - my $limit = 20; # page size. # TODO: move to DB or syspref? - my $offset = 0; - my $report = $input->param('reports'); + my $limit = 20; # page size. # TODO: move to DB or syspref? + my $offset = 0; + my $report_id = $input->param('reports'); my @sql_params = $input->param('sql_params'); # offset algorithm if ($input->param('page')) { $offset = ($input->param('page') - 1) * $limit; } - my ($sql,$type,$name,$notes) = get_saved_report($report); - unless ($sql) { - push @errors, {no_sql_for_id=>$report}; - } - my @rows = (); - # if we have at least 1 parameter, and it's not filled, then don't execute but ask for parameters - if ($sql =~ /<>/,$sql; - my @tmpl_parameters; - for(my $i=0;$i<($#split/2);$i++) { - my ($text,$authorised_value) = split /\|/,$split[$i*2+1]; - my $input; - if ($authorised_value eq "date") { - $input = 'date'; - } - elsif ($authorised_value) { - my $dbh=C4::Context->dbh; - my @authorised_values; - my %authorised_lib; - # builds list, depending on authorised value... - if ( $authorised_value eq "branches" ) { - my $branches = GetBranchesLoop(); - foreach my $thisbranch (@$branches) { - push @authorised_values, $thisbranch->{value}; - $authorised_lib{$thisbranch->{value}} = $thisbranch->{branchname}; - } + + my ( $sql, $type, $name, $notes ); + if (my $report = get_saved_report($report_id)) { + $sql = $report->{savedsql}; + $name = $report->{report_name}; + $notes = $report->{notes}; + + my @rows = (); + # if we have at least 1 parameter, and it's not filled, then don't execute but ask for parameters + if ($sql =~ /<>/,$sql; + my @tmpl_parameters; + for(my $i=0;$i<($#split/2);$i++) { + my ($text,$authorised_value) = split /\|/,$split[$i*2+1]; + my $input; + if ($authorised_value eq "date") { + $input = 'date'; } - elsif ( $authorised_value eq "itemtypes" ) { - my $sth = $dbh->prepare("SELECT itemtype,description FROM itemtypes ORDER BY description"); - $sth->execute; - while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) { - push @authorised_values, $itemtype; - $authorised_lib{$itemtype} = $description; + elsif ($authorised_value) { + my $dbh=C4::Context->dbh; + my @authorised_values; + my %authorised_lib; + # builds list, depending on authorised value... + if ( $authorised_value eq "branches" ) { + my $branches = GetBranchesLoop(); + foreach my $thisbranch (@$branches) { + push @authorised_values, $thisbranch->{value}; + $authorised_lib{$thisbranch->{value}} = $thisbranch->{branchname}; + } } - } - elsif ( $authorised_value eq "cn_source" ) { - my $class_sources = GetClassSources(); - my $default_source = C4::Context->preference("DefaultClassificationSource"); - foreach my $class_source (sort keys %$class_sources) { - next unless $class_sources->{$class_source}->{'used'} or - ($class_source eq $default_source); - push @authorised_values, $class_source; - $authorised_lib{$class_source} = $class_sources->{$class_source}->{'description'}; + elsif ( $authorised_value eq "itemtypes" ) { + my $sth = $dbh->prepare("SELECT itemtype,description FROM itemtypes ORDER BY description"); + $sth->execute; + while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) { + push @authorised_values, $itemtype; + $authorised_lib{$itemtype} = $description; + } } - } - elsif ( $authorised_value eq "categorycode" ) { - my $sth = $dbh->prepare("SELECT categorycode, description FROM categories ORDER BY description"); - $sth->execute; - while ( my ( $categorycode, $description ) = $sth->fetchrow_array ) { - push @authorised_values, $categorycode; - $authorised_lib{$categorycode} = $description; + elsif ( $authorised_value eq "cn_source" ) { + my $class_sources = GetClassSources(); + my $default_source = C4::Context->preference("DefaultClassificationSource"); + foreach my $class_source (sort keys %$class_sources) { + next unless $class_sources->{$class_source}->{'used'} or + ($class_source eq $default_source); + push @authorised_values, $class_source; + $authorised_lib{$class_source} = $class_sources->{$class_source}->{'description'}; + } } + elsif ( $authorised_value eq "categorycode" ) { + my $sth = $dbh->prepare("SELECT categorycode, description FROM categories ORDER BY description"); + $sth->execute; + while ( my ( $categorycode, $description ) = $sth->fetchrow_array ) { + push @authorised_values, $categorycode; + $authorised_lib{$categorycode} = $description; + } + + #---- "true" authorised value + } + else { + my $authorised_values_sth = $dbh->prepare("SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY lib"); - #---- "true" authorised value - } - else { - my $authorised_values_sth = $dbh->prepare("SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY lib"); - - $authorised_values_sth->execute( $authorised_value); + $authorised_values_sth->execute( $authorised_value); - while ( my ( $value, $lib ) = $authorised_values_sth->fetchrow_array ) { - push @authorised_values, $value; - $authorised_lib{$value} = $lib; - # For item location, we show the code and the libelle - $authorised_lib{$value} = $lib; + while ( my ( $value, $lib ) = $authorised_values_sth->fetchrow_array ) { + push @authorised_values, $value; + $authorised_lib{$value} = $lib; + # For item location, we show the code and the libelle + $authorised_lib{$value} = $lib; + } } - } - $input =CGI::scrolling_list( # FIXME: factor out scrolling_list - -name => "sql_params", - -values => \@authorised_values, + $input =CGI::scrolling_list( # FIXME: factor out scrolling_list + -name => "sql_params", + -values => \@authorised_values, # -default => $value, - -labels => \%authorised_lib, - -override => 1, - -size => 1, - -multiple => 0, - -tabindex => 1, - ); - - } else { - $input = ""; + -labels => \%authorised_lib, + -override => 1, + -size => 1, + -multiple => 0, + -tabindex => 1, + ); + push @tmpl_parameters, {'entry' => $text, 'input' => $input }; + } } - push @tmpl_parameters, {'entry' => $text, 'input' => $input }; - } - $template->param('sql' => $sql, - 'name' => $name, - 'sql_params' => \@tmpl_parameters, - 'enter_params' => 1, - 'reports' => $report, - ); - } else { - # OK, we have parameters, or there are none, we run the report - # if there were parameters, replace before running - # split on ??. Each odd (2,4,6,...) entry should be a parameter to fill - my @split = split /<<|>>/,$sql; - my @tmpl_parameters; - for(my $i=0;$i<$#split/2;$i++) { - my $quoted = C4::Context->dbh->quote($sql_params[$i]); - # if there are special regexp chars, we must \ them - $split[$i*2+1] =~ s/(\||\?|\.|\*|\(|\)|\%)/\\$1/g; - $sql =~ s/<<$split[$i*2+1]>>/$quoted/; - } - my ($sth, $errors) = execute_query($sql, $offset, $limit); - my $total = nb_rows($sql) || 0; - unless ($sth) { - die "execute_query failed to return sth for report $report: $sql"; + $template->param('sql' => $sql, + 'name' => $name, + 'sql_params' => \@tmpl_parameters, + 'enter_params' => 1, + 'reports' => $report, + ); } else { - my $headref = $sth->{NAME} || []; - my @headers = map { +{ cell => $_ } } @$headref; - $template->param(header_row => \@headers); - while (my $row = $sth->fetchrow_arrayref()) { - my @cells = map { +{ cell => $_ } } @$row; - push @rows, { cells => \@cells }; + # OK, we have parameters, or there are none, we run the report + # if there were parameters, replace before running + # split on ??. Each odd (2,4,6,...) entry should be a parameter to fill + my @split = split /<<|>>/,$sql; + my @tmpl_parameters; + for(my $i=0;$i<$#split/2;$i++) { + my $quoted = C4::Context->dbh->quote($sql_params[$i]); + # if there are special regexp chars, we must \ them + $split[$i*2+1] =~ s/(\||\?|\.|\*|\(|\)|\%)/\\$1/g; + $sql =~ s/<<$split[$i*2+1]>>/$quoted/; + } + my ($sth, $errors) = execute_query($sql, $offset, $limit); + my $total = nb_rows($sql) || 0; + unless ($sth) { + die "execute_query failed to return sth for report $report: $sql"; + } else { + my $headref = $sth->{NAME} || []; + my @headers = map { +{ cell => $_ } } @$headref; + $template->param(header_row => \@headers); + while (my $row = $sth->fetchrow_arrayref()) { + my @cells = map { +{ cell => $_ } } @$row; + push @rows, { cells => \@cells }; + } } - } - my $totpages = int($total/$limit) + (($total % $limit) > 0 ? 1 : 0); - my $url = "/cgi-bin/koha/reports/guided_reports.pl?reports=$report&phase=Run%20this%20report"; - if (@sql_params) { - $url = join('&sql_params=', $url, map { URI::Escape::uri_escape($_) } @sql_params); + my $totpages = int($total/$limit) + (($total % $limit) > 0 ? 1 : 0); + my $url = "/cgi-bin/koha/reports/guided_reports.pl?reports=$report&phase=Run%20this%20report"; + if (@sql_params) { + $url = join('&sql_params=', $url, map { URI::Escape::uri_escape($_) } @sql_params); + } + $template->param( + 'results' => \@rows, + 'sql' => $sql, + 'id' => $report, + 'execute' => 1, + 'name' => $name, + 'notes' => $notes, + 'errors' => $errors, + 'pagination_bar' => pagination_bar($url, $totpages, $input->param('page')), + 'unlimited_total' => $total, + ); } - $template->param( - 'results' => \@rows, - 'sql' => $sql, - 'id' => $report, - 'execute' => 1, - 'name' => $name, - 'notes' => $notes, - 'errors' => $errors, - 'pagination_bar' => pagination_bar($url, $totpages, $input->param('page')), - 'unlimited_total' => $total, - ); + } + else { + push @errors, { no_sql_for_id => $report_id }; } } @@ -676,16 +712,26 @@ elsif ($phase eq 'Export'){ ); } -elsif ($phase eq 'Create report from SQL') { - # allow the user to paste in sql - if ($input->param('sql')) { +elsif ( $phase eq 'Create report from SQL' ) { + + my ($group, $subgroup); + # allow the user to paste in sql + if ( $input->param('sql') ) { + $group = $input->param('report_group'); + $subgroup = $input->param('report_subgroup'); $template->param( 'sql' => $input->param('sql'), 'reportname' => $input->param('reportname'), 'notes' => $input->param('notes'), ); } - $template->param('create' => 1, 'public' => '0', 'cache_expiry' => 300, 'usecache' => $usecache); + $template->param( + 'create' => 1, + 'groups_with_subgroups' => groups_with_subgroups($group, $subgroup), + 'public' => '0', + 'cache_expiry' => 300, + 'usecache' => $usecache, + ); } elsif ($phase eq 'Create Compound Report'){ @@ -724,3 +770,29 @@ $template->param( 'referer' => $input->referer(), ); output_html_with_http_headers $input, $cookie, $template->output; + +sub groups_with_subgroups { + my ($group, $subgroup) = @_; + + my $groups_with_subgroups = get_report_groups(); + my @g_sg; + while (my ($g_id, $v) = each %$groups_with_subgroups) { + my @subgroups; + if (my $sg = $v->{subgroups}) { + while (my ($sg_id, $n) = each %$sg) { + push @subgroups, { + id => $sg_id, + name => $n, + selected => ($group && $g_id eq $group && $subgroup && $sg_id eq $subgroup ), + }; + } + } + push @g_sg, { + id => $g_id, + name => $v->{name}, + selected => ($group && $g_id eq $group), + subgroups => \@subgroups, + }; + } + return \@g_sg; +} diff --git a/svc/report b/svc/report index 18e1986..7661d7e 100755 --- a/svc/report +++ b/svc/report @@ -57,15 +57,14 @@ if (Koha::Cache->is_cache_active) { print $query->header; # $public isnt used for intranet -my ( $sql, $type, $name, $notes, $cache_expiry, $public ) = - get_saved_report($report); +my $report_rec = get_saved_report($report); my $offset = 0; my $limit = C4::Context->preference("SvcMaxReportRows") || 10; -my ( $sth, $errors ) = execute_query( $sql, $offset, $limit ); +my ( $sth, $errors ) = execute_query( $report_rec->{sql}, $offset, $limit ); my $lines = $sth->fetchall_arrayref; my $json_text = to_json($lines); print $json_text; if (Koha::Cache->is_cache_active) { - $cache->set_in_cache( "intranet:report:$report", $json_text, $cache_expiry ); + $cache->set_in_cache( "intranet:report:$report", $json_text, $report_rec->{cache_expiry} ); } -- 1.7.9.5 From christophe.croullebois at biblibre.com Thu Jun 21 18:36:25 2012 From: christophe.croullebois at biblibre.com (christophe croullebois) Date: Thu, 21 Jun 2012 18:36:25 +0200 Subject: [Koha-patches] [PATCH 1/1] Bug 6566 Checking if DB's records are properly indexed Message-ID: <1340296586-21851-1-git-send-email-christophe.croullebois@biblibre.com> From: Christophe Croullebois Small script that checks if each bibliorecord in the DB is properly indexed use -h to learn more (MT #6389) --- misc/migration_tools/checkNonIndexedBiblios.pl | 108 ++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100755 misc/migration_tools/checkNonIndexedBiblios.pl diff --git a/misc/migration_tools/checkNonIndexedBiblios.pl b/misc/migration_tools/checkNonIndexedBiblios.pl new file mode 100755 index 0000000..d14a1fb --- /dev/null +++ b/misc/migration_tools/checkNonIndexedBiblios.pl @@ -0,0 +1,108 @@ +#!/usr/bin/perl + +# Copyright 2012 BibLibre +# +# 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 2 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# Small script that checks if each biblio in the DB is properly indexed +# if it is not and if you use -z the not-indexed biblios are inserted in zebraqueue +# To test just ommit the -z option you will have the biblionumber of non-indexed biblios and the total + +use strict; + +BEGIN { + + # find Koha's Perl modules + # test carefully before changing this + use FindBin; + eval { require "$FindBin::Bin/kohalib.pl" }; +} + +# Koha modules used +use MARC::Record; +use C4::Context; +use C4::Search; +use Getopt::Long; + +my ( $help, $confirm, $zebraqueue, $silent,$stealth ); + +GetOptions( + 'c' => \$confirm, + 'h' => \$help, + 'z' => \$zebraqueue, + 's' => \$silent, + 'st' => \$stealth +); + +if ( $help || ( !$confirm ) ) { + print_usage(); + exit 0; +} + +my $dbh = C4::Context->dbh; +my $i = 0; +my $count = 0; + +# flushes output +$| = 1; + +my $sth = $dbh->prepare("SELECT biblionumber FROM biblio"); +my $sth_insert = $dbh->prepare("INSERT INTO zebraqueue (biblio_auth_number,operation,server,done) VALUES (?,'specialUpdate','biblioserver',0)"); + +# We get all biblios +$sth->execute; +my ($nbhits); + +# We check for each biblio +while ( my ($biblionumber) = $sth->fetchrow ) { + (undef,undef,$nbhits) = SimpleSearch("Local-number=$biblionumber"); + print "biblionumber $biblionumber not indexed\n" unless $nbhits || $stealth; +# If -z option we put the biblio in zebraqueue + if ($zebraqueue && !$nbhits){ + $sth_insert->execute($biblionumber); + print "$biblionumber inserted in zebraqueue\n" unless $stealth; + } + $i++; + print "$i done\n" unless $i % 1000 || $silent || $stealth; + $count++ unless $nbhits; +} + +if ($count > 0 && $zebraqueue){ + print "\t$count bibliorecords not indexed and inserted in zebraqueue\n"; +} +else{ + print "\t$count bibliorecords not indexed\n"; +} + +sub print_usage { + print <<_USAGE_; +$0: This script takes all biblios and checks if they are indexed in zebra using biblionumber search. + +parameters: +\th this help screen +\tc confirm (without this parameter, you get the help screen) +\tz inserts a signal in zebraqueue to force indexing of non indexed biblios otherwise you have only the check +\ts silent throws no warnings except for non indexed records. Otherwise throws a warn every 1000 biblios to show progress +\tst stealth do not print warnings for non indexed records and do not warn every 1000 + +Syntax: +\t./batchCheckNonIndexedBiblios.pl -h (or without arguments => shows this screen) +\t./batchCheckNonIndexedBiblios.pl -c (c like confirm => checks all records (may be long) +\t./batchCheckNonIndexedBiblios.pl -z (z like zebraqueue => inserts in zebraqueue. Without => test only, changes nothing in DB just warns) +\t./batchCheckNonIndexedBiblios.pl -s (s like silent => don't throws a warn every 1000 biblios to show progress) +\t./batchCheckNonIndexedBiblios.pl -st (s like stealth => don't throws a warn every 1000 biblios to show progress and no warn for the non indexed biblionumbers, just the total) +_USAGE_ +} \ No newline at end of file -- 1.7.9.5 From tomascohen at gmail.com Thu Jun 21 20:47:20 2012 From: tomascohen at gmail.com (Tomas Cohen Arazi) Date: Thu, 21 Jun 2012 15:47:20 -0300 Subject: [Koha-patches] [PATCH] Bug 8251 - Follow up, use 'day' instead of 'day' for Datetime::truncate Message-ID: <1340304440-18002-1-git-send-email-tomascohen@gmail.com> As noted in comment #4 by Jonathan Druart, this should be fixed in every call to DateTie::truncate function. This patch does exactly that. julian_m tested that truncate( to => 'days' ) didn't actually do anything, so it is understandable that this 'fix' might introduce new bugs as we might have 'fixed' at a higher libs level this issue. 'minutes' is used in truncate function too, so fixing. --- C4/Circulation.pm | 18 +++++++++--------- Koha/Calendar.pm | 6 +++--- Koha/DateUtils.pm | 4 ++-- circ/overdue.pl | 2 +- circ/returns.pl | 2 +- members/moremember.pl | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 96ae0d9..a7e7389 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -701,7 +701,7 @@ sub CanBookBeIssued { } if ($duedate) { my $today = $now->clone(); - $today->truncate( to => 'minutes'); + $today->truncate( to => 'minute'); if (DateTime->compare($duedate,$today) == -1 ) { # duedate cannot be before now $needsconfirmation{INVALID_DATE} = output_pref($duedate); } @@ -738,8 +738,8 @@ sub CanBookBeIssued { day => $d, time_zone => C4::Context->tz, ); - $expiry_dt->truncate( to => 'days'); - my $today = $now->clone()->truncate(to => 'days'); + $expiry_dt->truncate( to => 'day'); + my $today = $now->clone()->truncate(to => 'day'); if (DateTime->compare($today, $expiry_dt) == 1) { $issuingimpossible{EXPIRED} = 1; } @@ -1051,7 +1051,7 @@ sub AddIssue { $datedue = CalcDateDue( $issuedate, $itype, $branch, $borrower ); } - $datedue->truncate( to => 'minutes'); + $datedue->truncate( to => 'minute'); $sth->execute( $borrower->{'borrowernumber'}, # borrowernumber $item->{'itemnumber'}, # itemnumber @@ -2081,10 +2081,10 @@ sub GetItemIssue { my $data = $sth->fetchrow_hashref; return unless $data; $data->{issuedate} = dt_from_string($data->{issuedate}, 'sql'); - $data->{issuedate}->truncate(to => 'minutes'); + $data->{issuedate}->truncate(to => 'minute'); $data->{date_due} = dt_from_string($data->{date_due}, 'sql'); - $data->{date_due}->truncate(to => 'minutes'); - my $dt = DateTime->now( time_zone => C4::Context->tz)->truncate( to => 'minutes'); + $data->{date_due}->truncate(to => 'minute'); + my $dt = DateTime->now( time_zone => C4::Context->tz)->truncate( to => 'minute'); $data->{'overdue'} = DateTime->compare($data->{'date_due'}, $dt ) == -1 ? 1 : 0; return $data; } @@ -2129,7 +2129,7 @@ sub GetItemIssues { my ( $itemnumber, $history ) = @_; my $today = DateTime->now( time_zome => C4::Context->tz); # get today date - $today->truncate( to => 'minutes' ); + $today->truncate( to => 'minute' ); my $sql = "SELECT * FROM issues JOIN borrowers USING (borrowernumber) JOIN items USING (itemnumber) @@ -2151,7 +2151,7 @@ sub GetItemIssues { my $results = $sth->fetchall_arrayref({}); foreach (@$results) { my $date_due = dt_from_string($_->{date_due},'sql'); - $date_due->truncate( to => 'minutes' ); + $date_due->truncate( to => 'minute' ); $_->{overdue} = (DateTime->compare($date_due, $today) == -1) ? 1 : 0; } diff --git a/Koha/Calendar.pm b/Koha/Calendar.pm index dc132cd..f31edf2 100644 --- a/Koha/Calendar.pm +++ b/Koha/Calendar.pm @@ -147,7 +147,7 @@ sub is_holiday { if ( $self->{weekly_closed_days}->[$dow] == 1 ) { return 1; } - $dt->truncate( to => 'days' ); + $dt->truncate( to => 'day' ); my $day = $dt->day; my $month = $dt->month; if ( exists $self->{day_month_closed_days}->{$month}->{$day} ) { @@ -189,8 +189,8 @@ sub days_between { sub hours_between { my ($self, $start_dt, $end_dt) = @_; my $duration = $end_dt->delta_ms($start_dt); - $start_dt->truncate( to => 'days' ); - $end_dt->truncate( to => 'days' ); + $start_dt->truncate( to => 'day' ); + $end_dt->truncate( to => 'day' ); # NB this is a kludge in that it assumes all days are 24 hours # However for hourly loans the logic should be expanded to # take into account open/close times then it would be a duration diff --git a/Koha/DateUtils.pm b/Koha/DateUtils.pm index e2e92bd..a1fd088 100644 --- a/Koha/DateUtils.pm +++ b/Koha/DateUtils.pm @@ -158,7 +158,7 @@ sub format_sqldatetime { my $force_pref = shift; # if testing we want to override Context if ( defined $str && $str =~ m/^\d{4}-\d{2}-\d{2}/ ) { my $dt = dt_from_string( $str, 'sql' ); - $dt->truncate( to => 'minutes' ); + $dt->truncate( to => 'minute' ); return output_pref( $dt, $force_pref ); } return q{}; @@ -178,7 +178,7 @@ sub format_sqlduedatetime { my $force_pref = shift; # if testing we want to override Context if ( defined $str && $str =~ m/^\d{4}-\d{2}-\d{2}/ ) { my $dt = dt_from_string( $str, 'sql' ); - $dt->truncate( to => 'minutes' ); + $dt->truncate( to => 'minute' ); return output_pref_due( $dt, $force_pref ); } return q{}; diff --git a/circ/overdue.pl b/circ/overdue.pl index 56e0941..e44e792 100755 --- a/circ/overdue.pl +++ b/circ/overdue.pl @@ -239,7 +239,7 @@ if ($noreport) { my $today_dt = DateTime->now(time_zone => C4::Context->tz); - $today_dt->truncate(to => 'minutes'); + $today_dt->truncate(to => 'minute'); my $todaysdate = $today_dt->strftime('%Y-%m-%d %H:%M'); $bornamefilter =~s/\*/\%/g; diff --git a/circ/returns.pl b/circ/returns.pl index 38e9887..b9127da 100755 --- a/circ/returns.pl +++ b/circ/returns.pl @@ -250,7 +250,7 @@ if ($barcode) { ); if ($returned) { - my $time_now = DateTime->now( time_zone => C4::Context->tz )->truncate( to => 'minutes'); + my $time_now = DateTime->now( time_zone => C4::Context->tz )->truncate( to => 'minute'); my $duedate = $issueinformation->{date_due}->strftime('%Y-%m-%d %H:%M'); $returneditems{0} = $barcode; $riborrowernumber{0} = $borrower->{'borrowernumber'}; diff --git a/members/moremember.pl b/members/moremember.pl index b4e80f7..e1f8af5 100755 --- a/members/moremember.pl +++ b/members/moremember.pl @@ -251,7 +251,7 @@ if ( @borrowernumbers ) { } my $roaddetails = &GetRoadTypeDetails( $data->{'streettype'} ); my $today = DateTime->now( time_zone => C4::Context->tz); -$today->truncate(to => 'days'); +$today->truncate(to => 'day'); my @borrowers_with_issues; my $overdues_exist = 0; my $totalprice = 0; @@ -494,7 +494,7 @@ sub build_issue_data { $row{red} = 1; } if ($issuedate) { - $issuedate->truncate( to => 'days' ); + $issuedate->truncate( to => 'day' ); if ( DateTime->compare( $issuedate, $today ) == 0 ) { $row{today} = 1; } -- 1.7.9.5 From jcamins at cpbibliography.com Fri Jun 22 04:46:55 2012 From: jcamins at cpbibliography.com (Jared Camins-Esakov) Date: Thu, 21 Jun 2012 22:46:55 -0400 Subject: [Koha-patches] [PATCH] Bug 3462: Links in authorities should be hyperlinks Message-ID: <1340333215-15095-1-git-send-email-jcamins@cpbibliography.com> Make see also links in both the OPAC and authority module search results into hyperlinks and not just textual strings. To test: 1. Do a search for an authority that will bring up a heading with a see also reference in the staff client and the OPAC. 2. Confirm that the see also references listed in the search results are now hyperlinks, which work. --- C4/AuthoritiesMarc.pm | 37 ++++++++++++++++--- .../en/includes/authorities-search-results.inc | 7 +++- .../en/modules/authorities/searchresultlist.tt | 2 +- .../en/includes/authorities-search-results.inc | 7 +++- .../en/modules/opac-authoritiessearchresultlist.tt | 2 +- 5 files changed, 43 insertions(+), 12 deletions(-) diff --git a/C4/AuthoritiesMarc.pm b/C4/AuthoritiesMarc.pm index c92c319..0f91656 100644 --- a/C4/AuthoritiesMarc.pm +++ b/C4/AuthoritiesMarc.pm @@ -948,7 +948,7 @@ sub BuildSummary { $summary{type} = $authref->{authtypetext}; $summary{summary} = $authref->{summary}; } - my $marc21subfields = 'abcdfghjklmnopqrstuvxyz'; + my $marc21subfields = 'abcdfghjklmnopqrstuvxyz68'; my %marc21controlrefs = ( 'a' => 'earlier', 'b' => 'later', 'd' => 'acronym', @@ -1027,11 +1027,26 @@ sub BuildSummary { # see : foreach my $field ($record->field('5..')) { if (($field->subfield('5')) && ($field->subfield('a')) && ($field->subfield('5') eq 'g')) { - push @seealso, { $field->as_string('abcdefgjxyz'), type => 'broader' }; + push @seealso, { + heading => $field->as_string('abcdefgjxyz'), + type => 'broader', + search => $field->as_string('abcdefgjxyz'), + authid => $field->subfield('9') + }; } elsif (($field->subfield('5')) && ($field->as_string) && ($field->subfield('5') eq 'h')){ - push @seealso, { heading => $field->as_string('abcdefgjxyz'), type => 'narrower' }; + push @seealso, { + heading => $field->as_string('abcdefgjxyz'), + type => 'narrower', + search => $field->as_string('abcdefgjxyz'), + authid => $field->subfield('9') + }; } elsif ($field->subfield('a')) { - push @seealso, { heading => $field->as_string('abcdefgxyz'), type => 'seealso' }; + push @seealso, { + heading => $field->as_string('abcdefgxyz'), + type => 'seealso', + search => $field->as_string('abcdefgjxyz'), + authid => $field->subfield('9') + }; } } # // form @@ -1090,9 +1105,19 @@ sub BuildSummary { my $type = 'seealso'; $type = $marc21controlrefs{substr $field->subfield('w'), '0'} if ($field->subfield('w')); if ($type eq 'subfi') { - push @seealso, { heading => $field->as_string($marc21subfields), type => $field->subfield('i') }; + push @seealso, { + heading => $field->as_string($marc21subfields), + type => $field->subfield('i'), + search => $field->as_string($marc21subfields), + authid => $field->subfield('9') + }; } else { - push @seealso, { heading => $field->as_string($marc21subfields), type => $type }; + push @seealso, { + heading => $field->as_string($marc21subfields), + type => $type, + search => $field->as_string($marc21subfields), + authid => $field->subfield('9') + }; } } foreach my $field ($record->field('6..')) { diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/authorities-search-results.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/authorities-search-results.inc index 92314b1..9dc37bd 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/authorities-search-results.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/authorities-search-results.inc @@ -14,7 +14,10 @@ [% END %] [% ELSE %] [% IF ( label ) %][% label %][% END %] - [% heading %] + + [% IF ( linkpath && search ) %][% heading %] + [% ELSE %][% heading %][% END %] + [% UNLESS ( type=='seefrom' || type=='seealso' ) %][% SWITCH type %] [% CASE 'earlier' %](Earlier heading) [% CASE 'later' %](Later heading) @@ -50,7 +53,7 @@ [% IF ( summary.seealso ) %] [% FOREACH seeals IN summary.seealso %]
      - [% PROCESS showreference heading=seeals.heading label="see also:" type=seeals.type %] + [% PROCESS showreference heading=seeals.heading label="see also:" type=seeals.type linkpath=link search=seeals.search %]
      [% END %] [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist.tt index 038959f..362a33a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/searchresultlist.tt @@ -64,7 +64,7 @@ function searchauthority() { [% ELSE %]
    [% END %] - + [% UNLESS ( resul.isEDITORS ) %] [% END %] - + [% UNLESS ( resul.isEDITORS ) %] + [% FOREACH informatio IN information %] + + + + + + + + [% END %] + +
    [% PROCESS authresult summary=resul.summary %][% PROCESS authresult summary=resul.summary link="/cgi-bin/koha/authorities/authorities-home.pl?op=do_search&type=intranet&marclist=any&operator=contains&orderby=HeadingAsc&value=" %] Details diff --git a/koha-tmpl/opac-tmpl/prog/en/includes/authorities-search-results.inc b/koha-tmpl/opac-tmpl/prog/en/includes/authorities-search-results.inc index 92314b1..9dc37bd 100644 --- a/koha-tmpl/opac-tmpl/prog/en/includes/authorities-search-results.inc +++ b/koha-tmpl/opac-tmpl/prog/en/includes/authorities-search-results.inc @@ -14,7 +14,10 @@ [% END %] [% ELSE %] [% IF ( label ) %][% label %][% END %] - [% heading %] + + [% IF ( linkpath && search ) %][% heading %] + [% ELSE %][% heading %][% END %] + [% UNLESS ( type=='seefrom' || type=='seealso' ) %][% SWITCH type %] [% CASE 'earlier' %](Earlier heading) [% CASE 'later' %](Later heading) @@ -50,7 +53,7 @@ [% IF ( summary.seealso ) %] [% FOREACH seeals IN summary.seealso %]
    - [% PROCESS showreference heading=seeals.heading label="see also:" type=seeals.type %] + [% PROCESS showreference heading=seeals.heading label="see also:" type=seeals.type linkpath=link search=seeals.search %]
    [% END %] [% END %] diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt index a27480a..6e0b2fa 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-authoritiessearchresultlist.tt @@ -53,7 +53,7 @@ [% ELSE %]
    [% PROCESS authresult summary=resul.summary %][% PROCESS authresult summary=resul.summary link="/cgi-bin/koha/opac-authorities-home.pl?op=do_search&type=opac&operator=contains&marclist=any&and_ora=and&orderby=HeadingAsc&value=" %] [% authtypetext %] -- 1.7.2.5 From jonathan.druart at biblibre.com Fri Jun 22 16:17:58 2012 From: jonathan.druart at biblibre.com (Jonathan Druart) Date: Fri, 22 Jun 2012 16:17:58 +0200 Subject: [Koha-patches] [PATCH 1/1] Bug 5357: Adds a new page for searching subscriptions Message-ID: <1340374678-22138-1-git-send-email-jonathan.druart@biblibre.com> Test plan: - go on the serial module - click on the 'Advanced search' link (right of subscriptions search in the header) - Search subscriptions (by ISSN, title, EAN, Publisher, Supplier and/or Branch) - Check results are correct --- C4/Serials.pm | 65 +++++++ .../prog/en/includes/serials-search.inc | 60 ++++---- .../prog/en/modules/serials/serials-home.tt | 176 ++++---------------- .../prog/en/modules/serials/serials-search.tt | 172 +++++++++++++++++++ serials/serials-home.pl | 44 ++++-- serials/serials-search.pl | 114 +++++++++++++ 6 files changed, 446 insertions(+), 185 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-search.tt create mode 100755 serials/serials-search.pl diff --git a/C4/Serials.pm b/C4/Serials.pm index 58b6078..9508166 100644 --- a/C4/Serials.pm +++ b/C4/Serials.pm @@ -36,6 +36,7 @@ BEGIN { @EXPORT = qw( &NewSubscription &ModSubscription &DelSubscription &GetSubscriptions &GetSubscription &CountSubscriptionFromBiblionumber &GetSubscriptionsFromBiblionumber + &SearchSubscriptions &GetFullSubscriptionsFromBiblionumber &GetFullSubscription &ModSubscriptionHistory &HasSubscriptionStrictlyExpired &HasSubscriptionExpired &GetExpirationDate &abouttoexpire @@ -630,6 +631,70 @@ sub GetSubscriptions { return @results; } +=head2 SearchSubscriptions + + at results = SearchSubscriptions($args); +$args is a hashref. Its keys can be contained: title, issn, ean, publisher, bookseller and branchcode + +this function gets all subscriptions which have title like $title, ISSN like $issn, EAN like $ean, publisher like $publisher, bookseller like $bookseller AND branchcode eq $branch. + +return: +a table of hashref. Each hash containt the subscription. + +=cut + +sub SearchSubscriptions { + my ( $args ) = @_; + + my $query = qq{ + SELECT subscription.*, subscriptionhistory.*, biblio.*, biblioitems.issn + FROM subscription + LEFT JOIN subscriptionhistory USING(subscriptionid) + LEFT JOIN biblio ON biblio.biblionumber = subscription.biblionumber + LEFT JOIN biblioitems ON biblioitems.biblionumber = subscription.biblionumber + LEFT JOIN aqbooksellers ON subscription.aqbooksellerid = aqbooksellers.id + }; + my @where_strs; + my @where_args; + if( $args->{title} ){ + push @where_strs, "biblio.title LIKE ?"; + push @where_args, "%$args->{title}%"; + } + if( $args->{issn} ){ + push @where_strs, "biblioitems.issn LIKE ?"; + push @where_args, "%$args->{issn}issn%"; + } + if( $args->{ean} ){ + push @where_strs, "biblioitems.ean LIKE ?"; + push @where_args, "%$args->{ean}%"; + } + if( $args->{publisher} ){ + push @where_strs, "biblioitems.publishercode LIKE ?"; + push @where_args, "%$args->{publisher}%"; + } + if( $args->{bookseller} ){ + push @where_strs, "aqbooksellers.name LIKE ?"; + push @where_args, "%$args->bookseller}%"; + } + if( $args->{branch} ){ + push @where_strs, "subscription.branchcode = ?"; + push @where_args, "$args->{branch}"; + } + + if(@where_strs){ + $query .= " WHERE " . join(" AND ", @where_strs); + } + + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare($query); + $sth->execute(@where_args); + my $results = $sth->fetchall_arrayref( {} ); + $sth->finish; + + return @$results; +} + + =head2 GetSerials ($totalissues, at serials) = GetSerials($subscriptionid); diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/serials-search.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/serials-search.inc index dfb908f..beb309c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/serials-search.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/serials-search.inc @@ -1,35 +1,37 @@
    -

    [% LibraryName %]

    -
    diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-home.tt index 1fdf693..973fcc9 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-home.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-home.tt @@ -1,24 +1,6 @@ [% INCLUDE 'doc-head-open.inc' %] Koha › Serials [% biblionumber %] - [% INCLUDE 'doc-head-close.inc' %] - -[% INCLUDE 'datatables-strings.inc' %] - - [% INCLUDE 'header.inc' %] @@ -27,133 +9,39 @@
    - -
    -
    -
    - [% INCLUDE 'serials-toolbar.inc' %] - -[% IF ( information ) %] -Serials updated : - - - - - - - - -[% FOREACH informatio IN information %] - - - - - - - -[% END %] -
    - Serialseq - - Status - - Published date - - Planned date - - Notes -
    - [% informatio.serialseq %] - - [% informatio.status %] - - [% informatio.publisheddate %] - - [% informatio.planneddate %] - - [% informatio.notes %] -
    -[% END %] - [% IF ( done_searched ) %] -

    Serials subscriptions

    - - - - - - - - - [% IF ( routing && CAN_user_serials_routing ) %] - - [% END %] - - - - - - - - - - - [% IF ( routing && CAN_user_serials_routing ) %][% END %] - - - - - - [% FOREACH subscription IN subscriptions %] +
    +
    +
    + [% INCLUDE 'serials-toolbar.inc' %] + [% IF ( information ) %] + Serials updated : +
    ISSNTitle Notes - Library (callnumber) - Routing list  
    + - - - - - [% IF ( routing && CAN_user_serials_routing ) %] - - [% END %] - - + + + + + - [% END %] - -
    - [% IF ( subscription.issn ) %][% subscription.issn %] - [% END %] - [% subscription.title |html %] - [% IF ( subscription.notes ) %][% subscription.notes %][% END %] - [% IF ( subscription.internalnotes ) %]([% subscription.internalnotes %])[% END %] - - [% IF ( subscription.branchname ) %][% subscription.branchname %][% END %] - [% IF ( subscription.callnumber ) %]([% subscription.callnumber %])[% END %] - - [% IF ( subscription.cannotedit ) %] -   - [% ELSE %] - [% IF ( subscription.routingedit ) %] - Edit - [% ELSE %] - New - [% END %] - [% END %] - Issue history - - [% IF ( subscription.cannotedit ) %] -   - [% ELSE %] - [% IF ( CAN_user_serials_receive_serials ) %]Serial receive[% END %] - [% END %] - SerialseqStatusPublished datePlanned dateNotes
    - - [% END %] - -
    -
    - -
    -[% INCLUDE 'serials-menu.inc' %] -
    + +
    [% informatio.serialseq %][% informatio.status %][% informatio.publisheddate %][% informatio.planneddate %][% informatio.notes %]
    + [% END %] + + +
    + [% INCLUDE 'serials-menu.inc' %] +
    [% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-search.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-search.tt new file mode 100644 index 0000000..4f8dfce --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-search.tt @@ -0,0 +1,172 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Serials [% biblionumber %] + +[% INCLUDE 'doc-head-close.inc' %] + +[% INCLUDE 'datatables-strings.inc' %] + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'serials-search.inc' %] + + + +
    +
    +
    +
    + [% INCLUDE 'serials-toolbar.inc' %] + +

    Serials subscriptions

    + +
    +
    +
    + [% IF ( done_searched ) %] + Advanced search +
    +
    +
    + + [% IF ( done_searched ) %] + [% IF ( subscriptions ) %] + + + + + + + + [% IF ( routing && CAN_user_serials_routing ) %] + + [% END %] + + + + + + + + + + + [% IF ( routing && CAN_user_serials_routing ) %][% END %] + + + + + + [% FOREACH subscription IN subscriptions %] + + + + + + [% IF ( routing && CAN_user_serials_routing ) %] + + [% END %] + + + + [% END %] + +
    ISSNTitle Notes + Library (callnumber) + Routing list  
    + [% IF ( subscription.issn ) %][% subscription.issn %] + [% END %] + [% subscription.title |html %] + [% IF ( subscription.notes ) %][% subscription.notes %][% END %] + [% IF ( subscription.internalnotes ) %]([% subscription.internalnotes %])[% END %] + + [% IF ( subscription.branchname ) %][% subscription.branchname %][% END %] + [% IF ( subscription.callnumber ) %]([% subscription.callnumber %])[% END %] + + [% IF ( subscription.cannotedit ) %] +   + [% ELSE %] + [% IF ( subscription.routingedit ) %] + Edit + [% ELSE %] + New + [% END %] + [% END %] + Issue history + + [% IF ( subscription.cannotedit ) %] +   + [% ELSE %] + [% IF ( CAN_user_serials_receive_serials ) %]Serial receive[% END %] + [% END %] +
    + [% ELSE %] + There is no subscription for your search. + [% END %] + [% END %] +
    +
    + +
    + [% INCLUDE 'serials-menu.inc' %] +
    +
    +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/serials/serials-home.pl b/serials/serials-home.pl index 21b76e0..1eaf469 100755 --- a/serials/serials-home.pl +++ b/serials/serials-home.pl @@ -44,18 +44,21 @@ use strict; use warnings; use CGI; use C4::Auth; -use C4::Serials; -use C4::Output; -use C4::Context; use C4::Branch; +use C4::Context; +use C4::Output; +use C4::Serials; -my $query = new CGI; -my $title = $query->param('title_filter'); -my $ISSN = $query->param('ISSN_filter'); -my $EAN = $query->param('EAN_filter'); -my $routing = $query->param('routing') || C4::Context->preference("RoutingSerials"); -my $searched = $query->param('searched'); -my $biblionumber = $query->param('biblionumber'); +my $query = new CGI; +my $title = $query->param('title_filter'); +my $ISSN = $query->param('ISSN_filter'); +my $EAN = $query->param('EAN_filter'); +my $publisher = $query->param('publisher_filter'); +my $supplier = $query->param('supplier_filter'); +my $branch = $query->param('branch_filter'); +my $routing = $query->param('routing') || C4::Context->preference("RoutingSerials"); +my $searched = $query->param('searched'); +my $biblionumber = $query->param('biblionumber'); my @serialseqs = $query->param('serialseq'); my @planneddates = $query->param('planneddate'); @@ -93,8 +96,8 @@ if (@serialseqs){ $template->param('information'=>\@information); } my @subscriptions; -if ($searched) { - @subscriptions = GetSubscriptions( $title, $ISSN, $EAN, $biblionumber ); +if ($searched){ + @subscriptions = SearchSubscriptions( $title, $ISSN, $EAN, $publisher, $supplier, $branch ); } # to toggle between create or edit routing list options @@ -105,10 +108,27 @@ if ($routing) { } } +my $branches = GetBranches(); +my @branches_loop; +foreach (sort keys %$branches){ + my $selected = 0; + $selected = 1 if( $branch eq $_ ); + push @branches_loop, { + branchcode => $_, + branchname => $branches->{$_}->{'branchname'}, + selected => $selected, + }; +} + $template->param( subscriptions => \@subscriptions, title_filter => $title, ISSN_filter => $ISSN, + EAN_filter => $EAN, + publisher_filter => $publisher, + supplier_filter => $supplier, + branch_filter => $branch, + branches_loop => \@branches_loop, done_searched => $searched, routing => $routing, (uc(C4::Context->preference("marcflavour"))) => 1 diff --git a/serials/serials-search.pl b/serials/serials-search.pl new file mode 100755 index 0000000..098c380 --- /dev/null +++ b/serials/serials-search.pl @@ -0,0 +1,114 @@ +#!/usr/bin/perl + +# Copyright 2012 Koha Team +# +# 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 2 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +=head1 NAME + +serials-search.pl + +=head1 DESCRIPTION + +this script is the search page for serials + +=cut + +use Modern::Perl; +use CGI; +use C4::Auth; +use C4::Branch; +use C4::Context; +use C4::Output; +use C4::Serials; + +my $query = new CGI; +my $title = $query->param('title_filter') || ''; +my $ISSN = $query->param('ISSN_filter') || ''; +my $EAN = $query->param('EAN_filter') || ''; +my $publisher = $query->param('publisher_filter') || ''; +my $bookseller = $query->param('bookseller_filter') || ''; +my $branch = $query->param('branch_filter') || ''; +my $routing = $query->param('routing') || C4::Context->preference("RoutingSerials"); +my $searched = $query->param('searched') || 0; + +my @serialseqs = $query->param('serialseq'); +my @planneddates = $query->param('planneddate'); +my @publisheddates = $query->param('publisheddate'); +my @status = $query->param('status'); +my @notes = $query->param('notes'); + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "serials/serials-search.tmpl", + query => $query, + type => "intranet", + authnotrequired => 0, + flagsrequired => { serials => '*' }, + debug => 1, + } +); + +my @subscriptions; +if ($searched){ + @subscriptions = SearchSubscriptions( + { + title =>$title, + isbn => $ISSN, + ean => $EAN, + publisher => $publisher, + bookseller => $bookseller, + branch => $branch + } + ); +} + +# to toggle between create or edit routing list options +if ($routing) { + for my $subscription ( @subscriptions) { + $subscription->{routingedit} = check_routing( $subscription->{subscriptionid} ); + $subscription->{branchname} = GetBranchName ( $subscription->{branchcode} ); + } +} + +my $branches = GetBranches(); +my @branches_loop; +foreach (sort keys %$branches){ + my $selected = 0; + $selected = 1 if( $branch eq $_ ); + push @branches_loop, { + branchcode => $_, + branchname => $branches->{$_}->{'branchname'}, + selected => $selected, + }; +} + +$template->param( + subscriptions => \@subscriptions, + title_filter => $title, + ISSN_filter => $ISSN, + EAN_filter => $EAN, + publisher_filter => $publisher, + bookseller_filter => $bookseller, + branch_filter => $branch, + branches_loop => \@branches_loop, + done_searched => $searched, + routing => $routing, + (uc(C4::Context->preference("marcflavour"))) => 1 +); + +output_html_with_http_headers $query, $cookie, $template->output; -- 1.7.7.3 From oleonard at myacpl.org Fri Jun 22 19:32:16 2012 From: oleonard at myacpl.org (Owen Leonard) Date: Fri, 22 Jun 2012 13:32:16 -0400 Subject: [Koha-patches] [PATCH] Bug 8288 - showmarc.tt should not include full doc-head-close.inc Message-ID: <1340386337-5193-1-git-send-email-oleonard@myacpl.org> showmarc.tt and opac-showmarc.tt are used to load a plain view of a MARC record and thus do not need the full set of page assets loaded with other pages (CSS and JavaScript). Removing the standard doc-head-close include will reduce the load time of these pages. --- .../prog/en/modules/catalogue/showmarc.tt | 2 +- .../opac-tmpl/prog/en/modules/opac-showmarc.tt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/showmarc.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/showmarc.tt index 05467e8..932a50a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/showmarc.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/showmarc.tt @@ -1,6 +1,6 @@ [% INCLUDE 'doc-head-open.inc' %] Koha › Cataloging › MARC import -[% INCLUDE 'doc-head-close.inc' %] +
    diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-showmarc.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-showmarc.tt index 2a30906..3a5a9f8 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-showmarc.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-showmarc.tt @@ -1,4 +1,5 @@ -[% INCLUDE 'doc-head-open.inc' %]MARC view[% INCLUDE 'doc-head-close.inc' %] +[% INCLUDE 'doc-head-open.inc' %]MARC view +
    -- 1.7.9.5 From nengard at bywatersolutions.com Tue Jun 26 07:09:01 2012 From: nengard at bywatersolutions.com (Nicole C. Engard) Date: Tue, 26 Jun 2012 01:09:01 -0400 Subject: [Koha-patches] [PATCH] Bug 8318: Update StatisticsFields preference language Message-ID: <1340687341-4717-1-git-send-email-nengard@bywatersolutions.com> This patch changes around the wording of the StatisticsFields preference to make it clearer where these values will show. --- .../prog/en/modules/admin/preferences/patrons.pref | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref index 030f376..ea4cb46 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref @@ -128,6 +128,7 @@ Patrons: no: Disable - patron phone notifications using Talking Tech i-tiva (overdues, predues and holds notices currently supported). - + - "Show the following fields from the items database table as columns on the statistics tab on the patron record: " - pref: StatisticsFields class: multi - - Define Fields (from the items table) used for statistics members (separate fields with |, for example:"location|itype|ccode"). + - (separate fields with |) -- 1.7.2.3 From nengard at bywatersolutions.com Tue Jun 26 07:24:29 2012 From: nengard at bywatersolutions.com (Nicole C. Engard) Date: Tue, 26 Jun 2012 01:24:29 -0400 Subject: [Koha-patches] [PATCH] Bug 8319: Update headings on Patron Statistics tab Message-ID: <1340688269-4878-1-git-send-email-nengard@bywatersolutions.com> The patron statistics tab had had headings that were too hard to understand for the average library user. This patch changes the language to something less technical. --- .../prog/en/modules/members/statistics.tt | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/statistics.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/statistics.tt index 672cdd6..3ff663c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/statistics.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/statistics.tt @@ -47,10 +47,10 @@ [% FOREACH cn IN column_names %]
    [% cn %]Previous stateIssuesIssues returnedCurrent stateTotal checkouts as of yesterdayToday's checkoutsToday's checkinsTotal checkouts