From srdjan at catalyst.net.nz Fri Nov 1 05:25:48 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 1 Nov 2013 17:25:48 +1300 Subject: [Koha-patches] [PATCH] bug_11156: binmode STDOUT, ':utf8' Message-ID: <1383279948-2644-1-git-send-email-srdjan@catalyst.net.nz> This is a noop. To test: * Run misc/cronjobs/check-url.pl If you *really* want to test, place some non-ascii bogus urls in 856 and observe absence of "wide character" warning --- misc/cronjobs/check-url.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/cronjobs/check-url.pl b/misc/cronjobs/check-url.pl index 589a4c5..61162b8 100755 --- a/misc/cronjobs/check-url.pl +++ b/misc/cronjobs/check-url.pl @@ -222,6 +222,8 @@ EOS # BEGIN +binmode STDOUT, ':utf8'; + usage() if $help; if ( $html && !$host_pro ) { -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Nov 1 08:25:52 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 1 Nov 2013 20:25:52 +1300 Subject: [Koha-patches] [PATCH] bug_11182: get rid of some warnings Message-ID: <1383290752-22397-1-git-send-email-srdjan@catalyst.net.nz> To testi - circulation: * For a child patron, check that "Upgrade to adult" link on the "More" drop-down is clickable * Set sys pref FineNotifyAtCheckin to yes (Notify), and check in an overdue item that attracts fine. Fine amount should be displayed. --- circ/circulation.pl | 6 +++--- circ/returns.pl | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/circ/circulation.pl b/circ/circulation.pl index 9769731..3f287ed 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -482,7 +482,7 @@ sub build_issue_data { ($it->{'charge'}, $it->{'itemtype_charge'}) = GetIssuingCharges( $it->{'itemnumber'}, $it->{'borrowernumber'} ); - $it->{'charge'} = sprintf("%.2f", $it->{'charge'}); + $it->{'charge'} = sprintf("%.2f", $it->{'charge'}) if defined $it->{'charge'}; my ($can_renew, $can_renew_error) = CanBookBeRenewed( $it->{'borrowernumber'},$it->{'itemnumber'} ); @@ -650,7 +650,7 @@ $amountold =~ s/^.*\$//; # remove upto the $, if any my ( $total, $accts, $numaccts) = GetMemberAccountRecords( $borrowernumber ); -if ( $borrower->{'category_type'} eq 'C') { +if ( $borrower->{'category_type'} && $borrower->{'category_type'} eq 'C') { my ( $catcodes, $labels ) = GetborCatFromCatType( 'A', 'WHERE category_type = ?' ); my $cnt = scalar(@$catcodes); $template->param( 'CATCODE_MULTI' => 1) if $cnt > 1; @@ -748,7 +748,7 @@ $template->param( inprocess => $inprocess, memberofinstution => $member_of_institution, CGIorganisations => $CGIorganisations, - is_child => ($borrower->{'category_type'} eq 'C'), + is_child => ($borrower->{'category_type'} && $borrower->{'category_type'} eq 'C'), circview => 1, soundon => C4::Context->preference("SoundOn"), fast_cataloging => $fast_cataloging, diff --git a/circ/returns.pl b/circ/returns.pl index 93f36f2..1ab23ba 100755 --- a/circ/returns.pl +++ b/circ/returns.pl @@ -75,7 +75,8 @@ my ( $template, $librarian, $cookie ) = get_template_and_user( my $branches = GetBranches(); my $printers = GetPrinters(); -my $printer = C4::Context->userenv ? C4::Context->userenv->{'branchprinter'} : ""; +my $printer = C4::Context->userenv ? C4::Context->userenv->{'branchprinter'} : undef; +$printer ||= ""; my $overduecharges = (C4::Context->preference('finesMode') && C4::Context->preference('finesMode') ne 'off'); my $userenv_branch = C4::Context->userenv->{'branch'} || ''; @@ -266,7 +267,7 @@ if ($barcode) { if ( C4::Context->preference("FineNotifyAtCheckin") ) { my ( $od, $issue, $fines ) = GetMemberIssuesAndFines( $borrower->{'borrowernumber'} ); - if ($fines > 0) { + if ($fines && $fines > 0) { $template->param( fines => sprintf("%.2f",$fines) ); $template->param( fineborrowernumber => $borrower->{'borrowernumber'} ); } -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Nov 1 09:10:09 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 1 Nov 2013 21:10:09 +1300 Subject: [Koha-patches] [PATCH] bug_11183: get rid of some warninngs Message-ID: <1383293409-27366-1-git-send-email-srdjan@catalyst.net.nz> To test in OPAC: * Set EnableOpacSearchHistory to yes (Keep). Do an advanced search with limits. Complete search with limits should show. * Have an item with Collection Code. Check that the Collection Code shows. --- opac/opac-detail.pl | 2 +- opac/opac-search.pl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl index 41de4fd..3ee292c 100755 --- a/opac/opac-detail.pl +++ b/opac/opac-detail.pl @@ -573,7 +573,7 @@ for my $itm (@items) { # get collection code description, too my $ccode = $itm->{'ccode'}; - $itm->{'ccode'} = $collections->{$ccode} if ( defined($collections) && exists( $collections->{$ccode} ) ); + $itm->{'ccode'} = $collections->{$ccode} if $ccode && $collections; my $copynumber = $itm->{'copynumber'}; $itm->{'copynumber'} = $copynumbers->{$copynumber} if ( defined($copynumbers) && defined($copynumber) && exists( $copynumbers->{$copynumber} ) ); if ( defined $itm->{'location'} ) { diff --git a/opac/opac-search.pl b/opac/opac-search.pl index 2854da6..8604d0f 100755 --- a/opac/opac-search.pl +++ b/opac/opac-search.pl @@ -623,7 +623,7 @@ for (my $i=0;$i<@servers;$i++) { my $query_cgi_history = $cgi->url(-query=>1); $query_cgi_history =~ s/^$path_info\?//; $query_cgi_history =~ s/;/&/g; - my $query_desc_history = "$query_desc, $limit_desc"; + my $query_desc_history = join ", ", grep { defined $_ } $query_desc, $limit_desc; if (!$borrowernumber || $borrowernumber eq '') { # To a cookie (the user is not logged in) -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Nov 1 09:27:40 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 1 Nov 2013 21:27:40 +1300 Subject: [Koha-patches] [PATCH] bug_11184: correct attribute cloning for the maint screen Message-ID: <1383294460-29369-1-git-send-email-srdjan@catalyst.net.nz> To test - Patron details entry page: * Have ExtendedPatronAttributes enabled. Check that "Additional attributes and identifiers" section behaves. --- members/memberentry.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/members/memberentry.pl b/members/memberentry.pl index 4b410a7..13ba805 100755 --- a/members/memberentry.pl +++ b/members/memberentry.pl @@ -798,7 +798,7 @@ sub patron_attributes_form { }; if (exists $attr_hash{$attr_type->code()}) { foreach my $attr (@{ $attr_hash{$attr_type->code()} }) { - my $newentry = { map { $_ => $entry->{$_} } %$entry }; + my $newentry = { %$entry }; $newentry->{value} = $attr->{value}; $newentry->{password} = $attr->{password}; $newentry->{use_dropdown} = 0; -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Nov 1 09:44:01 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 1 Nov 2013 21:44:01 +1300 Subject: [Koha-patches] [PATCH] bug_11077: get rid of some warnings Message-ID: <1383295441-31219-1-git-send-email-srdjan@catalyst.net.nz> --- C4/Auth.pm | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/C4/Auth.pm b/C4/Auth.pm index 8b0bebe..584f298 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -650,6 +650,7 @@ sub checkauth { # This parameter is the name of the CAS server we want to authenticate against, # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml my $casparam = $query->param('cas'); + my $q_userid = $query->param('userid'); if ( $userid = $ENV{'REMOTE_USER'} ) { # Using Basic Authentication, no cookies required @@ -669,9 +670,11 @@ sub checkauth { my $session = get_session($sessionID); C4::Context->_new_userenv($sessionID); my ($ip, $lasttime, $sessiontype); + my $s_userid; if ($session){ + $s_userid = $session->param('id'); C4::Context::set_userenv( - $session->param('number'), $session->param('id'), + $session->param('number'), $s_userid, $session->param('cardnumber'), $session->param('firstname'), $session->param('surname'), $session->param('branch'), $session->param('branchname'), $session->param('flags'), @@ -684,14 +687,14 @@ sub checkauth { $debug and printf STDERR "AUTH_SESSION: (%s)\t%s %s - %s\n", map {$session->param($_)} qw(cardnumber firstname surname branch) ; $ip = $session->param('ip'); $lasttime = $session->param('lasttime'); - $userid = $session->param('id'); + $userid = $s_userid; $sessiontype = $session->param('sessiontype') || ''; } - if ( ( ($query->param('koha_login_context')) && ($query->param('userid') ne $session->param('id')) ) + if ( ( $query->param('koha_login_context') && ($q_userid && $s_userid && $q_userid ne $s_userid) ) || ( $cas && $query->param('ticket') ) ) { #if a user enters an id ne to the id in the current session, we need to log them in... #first we need to clear the anonymous session... - $debug and warn "query id = " . $query->param('userid') . " but session id = " . $session->param('id'); + $debug and warn "query id = $q_userid but session id = $s_userid"; $session->flush; $session->delete(); C4::Context->_unset_userenv($sessionID); @@ -711,7 +714,7 @@ sub checkauth { logout_cas($query); } } - elsif ( $lasttime < time() - $timeout ) { + elsif ( $lasttime && ($lasttime < time() - $timeout) ) { # timed logout $info{'timed_out'} = 1; $session->delete() if $session; @@ -759,7 +762,7 @@ sub checkauth { -value => $session->id, -HttpOnly => 1 ); - $userid = $query->param('userid'); + $userid = $q_userid; if ( ( $cas && $query->param('ticket') ) || $userid || ( my $pki_field = C4::Context->preference('AllowPKIAuth') ) ne -- 1.8.1.2 From mathieu.saby at univ-rennes2.fr Sun Nov 3 12:50:08 2013 From: mathieu.saby at univ-rennes2.fr (Mathieu Saby) Date: Sun, 03 Nov 2013 12:50:08 +0100 Subject: [Koha-patches] [PATCH] Bug 11189 : Rename Print label in UNIMARC advanced search Message-ID: <52763870.4070605@univ-rennes2.fr> "Print" label for search on 106 field is not correct in UNIMARC advanced search : - 106 field can be used for non printed ressources (manuscript...) - "Print" is ambiguous for translation tool, as it can be understood as a verb or a noun. The official label for 106 field is "Type of form". The offical label for 106$a subfield is "Medium designator". I think "Physical presentation" is the best way to describe the content of 106$a in a user understandable label. Test plan : Check the "Print" label is replaced with "Physical presentation" in OPAC and Staff Advanced Search --- .../prog/en/includes/subtypes_unimarc.inc | 2 +- .../prog/en/includes/subtypes_unimarc.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/subtypes_unimarc.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/subtypes_unimarc.inc index 10f9cba..bae4ed5 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/subtypes_unimarc.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/subtypes_unimarc.inc @@ -18,7 +18,7 @@

- +

- + + [% lateorder.orderdate %] @@ -138,30 +138,30 @@ $(document).ready(function() { [% END %] - [% lateorder.supplier %] - ([% lateorder.supplierid %]) + [% lateorder.supplier_name %] + ([% lateorder.supplier_id %]) [% lateorder.title |html %] [% IF ( lateorder.author ) %]
Author: [% lateorder.author %][% END %] - [% IF ( lateorder.publisher ) %] -
Published by: [% lateorder.publisher %] + [% IF ( lateorder.publishercode ) %] +
Published by: [% lateorder.publishercode %] [% IF ( lateorder.publicationyear ) %] in [% lateorder.publicationyear %] [% END %] [% END %] - [% lateorder.unitpricesupplier %]x[% lateorder.quantity %] = - [% lateorder.subtotal %] -

[% lateorder.budget %]

+ [% lateorder.rrp %]x[% lateorder.quantity %] = + [% lateorder.rrp_subtotal_to_receive %] +

[% lateorder.budget_name %]

-

- [% lateorder.basketno %] +

+ [% lateorder.basket_id %]

-

[% lateorder.branch %]

+

[% lateorder.borrower_branchcode %]

[% lateorder.claims_count %] [% lateorder.claimed_date %] -- 1.7.9.5 -- Mathieu Saby Service d'Informatique Documentaire Service Commun de la Documentation Universit? Rennes 2 T?l?phone : 02 99 14 12 65 Courriel : mathieu.saby at univ-rennes2.fr From srdjan at catalyst.net.nz Fri Nov 8 04:16:11 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 8 Nov 2013 16:16:11 +1300 Subject: [Koha-patches] [PATCH] bug_11213: Changed XSLTParse4Display() interface Message-ID: <1383880571-17326-1-git-send-email-srdjan@catalyst.net.nz> The list of biblio items is passed on now, instead of GetItemsInfo() being called. This is because the callers already have the list ready, so the GetItemsInfo() call is being duplicated unnecessarily. Search::searchResults() builds items list from XML, and that one is passed instead. * XSLT::XSLTParse4Display() - supply the items list as input param - removed hidden items list param - hidden should not be in the items list - changed buildKohaItemsNamespace() accordingly * Items - removed GetItemsLocationInfo() - added sort_by input param to GetItemsInfo() - VirtualShelves::Page::shelfpage() - replaced GetItemsLocationInfo() call with GetItemsInfo() call, passing order_by "cn_sort" * catalogue/detail.pl, opac/opac-detail.pl, shelfpage() - added items list to the XSLTParse4Display() call * Search::searchResults() - include all available info when building items lists - added combined items list (available, on loan, other) to the XSLTParse4Display() call To test: This change is a noop, so following screens need to be checked against any changes: * Intranet: - catalogue/search.pl (results) - catalogue/detail.pl - virtualshelves/shelves.pl * Opac - opac-search.pl (results, hidelostitems syspref on and off) - opac-detail.pl - opac-shelves.pl The display should stay the same before and after patch. The speed should increase though. --- C4/Items.pm | 88 ++++++++++------------------------------------- C4/Search.pm | 45 ++++++++++-------------- C4/VirtualShelves/Page.pm | 8 ++--- C4/XSLT.pm | 23 +++++++------ catalogue/detail.pl | 12 +++---- opac/opac-detail.pl | 10 +++--- 6 files changed, 66 insertions(+), 120 deletions(-) diff --git a/C4/Items.pm b/C4/Items.pm index 073d6f7..776affb 100644 --- a/C4/Items.pm +++ b/C4/Items.pm @@ -65,7 +65,6 @@ BEGIN { GetItemInfosOf GetItemsByBiblioitemnumber GetItemsInfo - GetItemsLocationInfo GetHostItemsInfo GetItemnumbersForBiblio get_itemnumbers_of @@ -1185,10 +1184,14 @@ sub GetItemsByBiblioitemnumber { =head2 GetItemsInfo - @results = GetItemsInfo($biblionumber); + @results = GetItemsInfo($biblionumber, $order_by); Returns information about items with the given biblionumber. +The list is ordered by home branch name and some complex criteria +within it (see the code), unless $order_by is specified. +Currently only "cn_sort" is supported. + C returns a list of references-to-hash. Each element contains a number of keys. Most of them are attributes from the C, C, C, and C tables in the @@ -1226,7 +1229,8 @@ If this is set, it is set to C. =cut sub GetItemsInfo { - my ( $biblionumber ) = @_; + my ( $biblionumber, $order_by ) = @_; + my $dbh = C4::Context->dbh; # note biblioitems.* must be avoided to prevent large marc and marcxml fields from killing performance. my $query = " @@ -1256,7 +1260,18 @@ sub GetItemsInfo { LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber LEFT JOIN itemtypes ON itemtypes.itemtype = " . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype'); - $query .= " WHERE items.biblionumber = ? ORDER BY home.branchname, items.enumchron, LPAD( items.copynumber, 8, '0' ), items.dateaccessioned DESC" ; + $query .= " WHERE items.biblionumber = ? ORDER BY "; + my $order_by_cause = "home.branchname, items.enumchron, LPAD( items.copynumber, 8, '0' ), items.dateaccessioned DESC" ; + if ($order_by) { + if ($order_by eq 'cn_sort') { + $order_by_cause = "cn_sort ASC"; + } + else { + warn qq{Unsupported order by "$order_by"}; + } + } + $query .= $order_by_cause; + my $sth = $dbh->prepare($query); $sth->execute($biblionumber); my $i = 0; @@ -1343,71 +1358,6 @@ sub GetItemsInfo { } } -=head2 GetItemsLocationInfo - - my @itemlocinfo = GetItemsLocationInfo($biblionumber); - -Returns the branch names, shelving location and itemcallnumber for each item attached to the biblio in question - -C returns a list of references-to-hash. Data returned: - -=over 2 - -=item C<$data-E{homebranch}> - -Branch Name of the item's homebranch - -=item C<$data-E{holdingbranch}> - -Branch Name of the item's holdingbranch - -=item C<$data-E{location}> - -Item's shelving location code - -=item C<$data-E{location_intranet}> - -The intranet description for the Shelving Location as set in authorised_values 'LOC' - -=item C<$data-E{location_opac}> - -The OPAC description for the Shelving Location as set in authorised_values 'LOC'. Falls back to intranet description if no OPAC -description is set. - -=item C<$data-E{itemcallnumber}> - -Item's itemcallnumber - -=item C<$data-E{cn_sort}> - -Item's call number normalized for sorting - -=back - -=cut - -sub GetItemsLocationInfo { - my $biblionumber = shift; - my @results; - - my $dbh = C4::Context->dbh; - my $query = "SELECT a.branchname as homebranch, b.branchname as holdingbranch, - location, itemcallnumber, cn_sort - FROM items, branches as a, branches as b - WHERE homebranch = a.branchcode AND holdingbranch = b.branchcode - AND biblionumber = ? - ORDER BY cn_sort ASC"; - my $sth = $dbh->prepare($query); - $sth->execute($biblionumber); - - while ( my $data = $sth->fetchrow_hashref ) { - $data->{location_intranet} = GetKohaAuthorisedValueLib('LOC', $data->{location}); - $data->{location_opac}= GetKohaAuthorisedValueLib('LOC', $data->{location}, 1); - push @results, $data; - } - return @results; -} - =head2 GetHostItemsInfo $hostiteminfo = GetHostItemsInfo($hostfield); diff --git a/C4/Search.pm b/C4/Search.pm index bec1f89..4b13ad9 100644 --- a/C4/Search.pm +++ b/C4/Search.pm @@ -1827,7 +1827,6 @@ sub searchResults { my $items_count = scalar(@fields); my $maxitems_pref = C4::Context->preference('maxItemsinSearchResults'); my $maxitems = $maxitems_pref ? $maxitems_pref - 1 : 1; - my @hiddenitems; # hidden itemnumbers based on OpacHiddenItems syspref # loop through every item foreach my $field (@fields) { @@ -1849,7 +1848,6 @@ sub searchResults { # hidden based on OpacHiddenItems syspref my @hi = C4::Items::GetHiddenItemnumbers($item); if (scalar @hi) { - push @hiddenitems, @hi; $hideatopac_count++; next; } @@ -1866,19 +1864,17 @@ sub searchResults { $item->{'branchname'} = $branches{$item->{$otherbranch}}; } - my $prefix = $item->{$hbranch} . '--' . $item->{location} . $item->{itype} . $item->{itemcallnumber}; + my $prefix = $item->{$hbranch} . '--' . $item->{location} . $item->{itype} . $item->{itemcallnumber}; # For each grouping of items (onloan, available, unavailable), we build a key to store relevant info about that item my $userenv = C4::Context->userenv; if ( $item->{onloan} && !(C4::Members::GetHideLostItemsPreference($userenv->{'number'}) && $item->{itemlost}) ) { $onloan_count++; - my $key = $prefix . $item->{onloan} . $item->{barcode}; - $onloan_items->{$key}->{due_date} = format_date($item->{onloan}); - $onloan_items->{$key}->{count}++ if $item->{$hbranch}; - $onloan_items->{$key}->{branchname} = $item->{branchname}; - $onloan_items->{$key}->{location} = $shelflocations->{ $item->{location} }; - $onloan_items->{$key}->{itemcallnumber} = $item->{itemcallnumber}; - $onloan_items->{$key}->{description} = $item->{description}; - $onloan_items->{$key}->{imageurl} = getitemtypeimagelocation( $search_context, $itemtypes{ $item->{itype} }->{imageurl} ); + my $key = $prefix . $item->{onloan} . $item->{barcode}; + $onloan_items->{$key} = { %$item }; + $onloan_items->{$key}->{due_date} = format_date($item->{onloan}); + $onloan_items->{$key}->{count}++ if $item->{$hbranch}; + $onloan_items->{$key}->{location} = $shelflocations->{ $item->{location} }; + $onloan_items->{$key}->{imageurl} = getitemtypeimagelocation( $search_context, $itemtypes{ $item->{itype} }->{imageurl} ); # if something's checked out and lost, mark it as 'long overdue' if ( $item->{itemlost} ) { $onloan_items->{$prefix}->{longoverdue}++; @@ -1955,27 +1951,24 @@ sub searchResults { $other_count++; my $key = $prefix . $item->{status}; - foreach (qw(withdrawn itemlost damaged branchname itemcallnumber)) { - $other_items->{$key}->{$_} = $item->{$_}; - } + $other_items->{$key} = { %$item }; $other_items->{$key}->{intransit} = ( $transfertwhen ne '' ) ? 1 : 0; $other_items->{$key}->{onhold} = ($reservestatus) ? 1 : 0; - $other_items->{$key}->{notforloan} = GetAuthorisedValueDesc('','',$item->{notforloan},'','',$notforloan_authorised_value) if $notforloan_authorised_value and $item->{notforloan}; - $other_items->{$key}->{count}++ if $item->{$hbranch}; - $other_items->{$key}->{location} = $shelflocations->{ $item->{location} }; - $other_items->{$key}->{description} = $item->{description}; - $other_items->{$key}->{imageurl} = getitemtypeimagelocation( $search_context, $itemtypes{ $item->{itype} }->{imageurl} ); + $other_items->{$key}->{notforloan} = GetAuthorisedValueDesc('','',$item->{notforloan},'','',$notforloan_authorised_value) + if $notforloan_authorised_value and $item->{notforloan}; + $other_items->{$key}->{count}++ + if $item->{$hbranch}; + $other_items->{$key}->{location} = $shelflocations->{ $item->{location} }; + $other_items->{$key}->{imageurl} = getitemtypeimagelocation( $search_context, $itemtypes{ $item->{itype} }->{imageurl} ); } # item is available else { $can_place_holds = 1; $available_count++; - $available_items->{$prefix}->{count}++ if $item->{$hbranch}; - foreach (qw(branchname itemcallnumber description)) { - $available_items->{$prefix}->{$_} = $item->{$_}; - } - $available_items->{$prefix}->{location} = $shelflocations->{ $item->{location} }; - $available_items->{$prefix}->{imageurl} = getitemtypeimagelocation( $search_context, $itemtypes{ $item->{itype} }->{imageurl} ); + $available_items->{$prefix} = { %$item }; + $available_items->{$prefix}->{count}++ if $item->{$hbranch}; + $available_items->{$prefix}->{location} = $shelflocations->{ $item->{location} }; + $available_items->{$prefix}->{imageurl} = getitemtypeimagelocation( $search_context, $itemtypes{ $item->{itype} }->{imageurl} ); } } } # notforloan, item level and biblioitem level @@ -2005,7 +1998,7 @@ sub searchResults { warn $marcrecord->as_formatted if $DEBUG; my $interface = $search_context eq 'opac' ? 'OPAC' : ''; if (!$scan && C4::Context->preference($interface . "XSLTResultsDisplay")) { - $oldbiblio->{XSLTResultsRecord} = XSLTParse4Display($oldbiblio->{biblionumber}, $marcrecord, $interface."XSLTResultsDisplay", 1, \@hiddenitems); + $oldbiblio->{XSLTResultsRecord} = XSLTParse4Display($oldbiblio->{biblionumber}, $marcrecord, $interface."XSLTResultsDisplay", [@available_items_loop, @onloan_items_loop, @other_items_loop], 1); # the last parameter tells Koha to clean up the problematic ampersand entities that Zebra outputs } diff --git a/C4/VirtualShelves/Page.pm b/C4/VirtualShelves/Page.pm index 259e12d..823248f 100644 --- a/C4/VirtualShelves/Page.pm +++ b/C4/VirtualShelves/Page.pm @@ -261,11 +261,13 @@ sub shelfpage { ( $items, $totitems ) = GetShelfContents( $shelfnumber, $shelflimit, $shelfoffset, $sortfield, $direction ); for my $this_item (@$items) { my $biblionumber = $this_item->{'biblionumber'}; + # Getting items infos for location display + my @items_infos = &GetItemsInfo( $this_item->{'biblionumber'}, "cn_sort" ); my $record = GetMarcBiblio($biblionumber); if (C4::Context->preference("OPACXSLTResultsDisplay") && $type eq 'opac') { - $this_item->{XSLTBloc} = XSLTParse4Display($biblionumber, $record, "OPACXSLTResultsDisplay"); + $this_item->{XSLTBloc} = XSLTParse4Display($biblionumber, $record, "OPACXSLTResultsDisplay", \@items_infos); } elsif (C4::Context->preference("XSLTResultsDisplay") && $type eq 'intranet') { - $this_item->{XSLTBloc} = XSLTParse4Display($biblionumber, $record, "XSLTResultsDisplay"); + $this_item->{XSLTBloc} = XSLTParse4Display($biblionumber, $record, "XSLTResultsDisplay", \@items_infos); } # the virtualshelfcontents table does not store these columns nor are they retrieved from the items @@ -281,8 +283,6 @@ sub shelfpage { $this_item->{'normalized_oclc'} = GetNormalizedOCLCNumber($record,$marcflavour); $this_item->{'normalized_isbn'} = GetNormalizedISBN(undef,$record,$marcflavour); if(!defined($this_item->{'size'})) { $this_item->{'size'} = "" }; #TT has problems with size - # Getting items infos for location display - my @items_infos = &GetItemsLocationInfo( $this_item->{'biblionumber'}); $this_item->{'itemsissued'} = CountItemsIssued( $this_item->{'biblionumber'} ); $this_item->{'ITEM_RESULTS'} = \@items_infos; if ( grep {$_ eq $biblionumber} @cart_list) { diff --git a/C4/XSLT.pm b/C4/XSLT.pm index d85b048..0fde9dc 100644 --- a/C4/XSLT.pm +++ b/C4/XSLT.pm @@ -156,8 +156,17 @@ sub _get_best_default_xslt_filename { return $xslfilename; } +=head2 XSLTParse4Display( $biblionumber, $orig_record, $xslsyspref, $items, $fixamps ) + + $items => an array of items rerords, as returned from eg. GetItemsInfo + +Returns XSLT block + +=cut + sub XSLTParse4Display { - my ( $biblionumber, $orig_record, $xslsyspref, $fixamps, $hidden_items ) = @_; + my ( $biblionumber, $orig_record, $xslsyspref, $items, $fixamps ) = @_; + my $xslfilename = C4::Context->preference($xslsyspref); if ( $xslfilename =~ /^\s*"?default"?\s*$/i ) { my $htdocs; @@ -196,7 +205,7 @@ sub XSLTParse4Display { # grab the XML, run it through our stylesheet, push it out to the browser my $record = transformMARCXML4XSLT($biblionumber, $orig_record); #return $record->as_formatted(); - my $itemsxml = buildKohaItemsNamespace($biblionumber, $hidden_items); + my $itemsxml = $items ? buildKohaItemsNamespace($biblionumber, $items) : ""; my $xmlrecord = $record->as_xml(C4::Context->preference('marcflavour')); my $sysxml = "\n"; foreach my $syspref ( qw/ hidelostitems OPACURLOpenInNewWindow @@ -243,13 +252,7 @@ sub XSLTParse4Display { } sub buildKohaItemsNamespace { - my ($biblionumber, $hidden_items) = @_; - - my @items = C4::Items::GetItemsInfo($biblionumber); - if ($hidden_items && @$hidden_items) { - my %hi = map {$_ => 1} @$hidden_items; - @items = grep { !$hi{$_->{itemnumber}} } @items; - } + my ($biblionumber, $items) = @_; my $shelflocations = GetKohaAuthorisedValues('items.location',GetFrameworkCode($biblionumber), 'opac'); my $ccodes = GetKohaAuthorisedValues('items.ccode',GetFrameworkCode($biblionumber), 'opac'); @@ -259,7 +262,7 @@ sub buildKohaItemsNamespace { my $location = ""; my $ccode = ""; my $xml = ''; - for my $item (@items) { + for my $item (@$items) { my $status; my ( $transfertwhen, $transfertfrom, $transfertto ) = C4::Circulation::GetTransfers($item->{itemnumber}); diff --git a/catalogue/detail.pl b/catalogue/detail.pl index 955dbf5..f644461 100755 --- a/catalogue/detail.pl +++ b/catalogue/detail.pl @@ -85,12 +85,6 @@ my $fw = GetFrameworkCode($biblionumber); my $showallitems = $query->param('showallitems'); my $marcflavour = C4::Context->preference("marcflavour"); -# XSLT processing of some stuff -if (C4::Context->preference("XSLTDetailsDisplay") ) { - $template->param('XSLTDetailsDisplay' =>'1', - 'XSLTBloc' => XSLTParse4Display($biblionumber, $record, "XSLTDetailsDisplay") ); -} - $template->param( 'SpineLabelShowPrintOnBibDetails' => C4::Context->preference("SpineLabelShowPrintOnBibDetails") ); $template->param( ocoins => GetCOinSBiblio($record) ); @@ -138,6 +132,12 @@ if (@hostitems){ push (@items, at hostitems); } +# XSLT processing of some stuff +if (C4::Context->preference("XSLTDetailsDisplay") ) { + $template->param('XSLTDetailsDisplay' =>'1', + 'XSLTBloc' => XSLTParse4Display($biblionumber, $record, "XSLTDetailsDisplay", \@all_items) ); +} + my $dat = &GetBiblioData($biblionumber); #coping with subscriptions diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl index 41de4fd..0b25866 100755 --- a/opac/opac-detail.pl +++ b/opac/opac-detail.pl @@ -107,11 +107,6 @@ SetUTF8Flag($record); my $marcflavour = C4::Context->preference("marcflavour"); my $ean = GetNormalizedEAN( $record, $marcflavour ); -# XSLT processing of some stuff -if (C4::Context->preference("OPACXSLTDetailsDisplay") ) { - $template->param( 'XSLTBloc' => XSLTParse4Display($biblionumber, $record, "OPACXSLTDetailsDisplay" ) ); -} - my $OpacBrowseResults = C4::Context->preference("OpacBrowseResults"); $template->{VARS}->{'OpacBrowseResults'} = $OpacBrowseResults; @@ -449,6 +444,11 @@ if ($hideitems) { @items = @all_items; } +# XSLT processing of some stuff +if (C4::Context->preference("OPACXSLTDetailsDisplay") ) { + $template->param( 'XSLTBloc' => XSLTParse4Display($biblionumber, $record, "OPACXSLTDetailsDisplay", \@items) ); +} + my $branches = GetBranches(); my $branch = ''; if (C4::Context->userenv){ -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Nov 8 08:49:21 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 8 Nov 2013 20:49:21 +1300 Subject: [Koha-patches] [PATCH] bug_11077: get rid of some warnings Message-ID: <1383896961-14663-1-git-send-email-srdjan@catalyst.net.nz> --- C4/Auth.pm | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/C4/Auth.pm b/C4/Auth.pm index c6475bb..9d0b623 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -650,6 +650,7 @@ sub checkauth { # This parameter is the name of the CAS server we want to authenticate against, # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml my $casparam = $query->param('cas'); + my $q_userid = $query->param('userid'); if ( $userid = $ENV{'REMOTE_USER'} ) { # Using Basic Authentication, no cookies required @@ -669,9 +670,11 @@ sub checkauth { my $session = get_session($sessionID); C4::Context->_new_userenv($sessionID); my ($ip, $lasttime, $sessiontype); + my $s_userid; if ($session){ + $s_userid = $session->param('id'); C4::Context::set_userenv( - $session->param('number'), $session->param('id'), + $session->param('number'), $s_userid, $session->param('cardnumber'), $session->param('firstname'), $session->param('surname'), $session->param('branch'), $session->param('branchname'), $session->param('flags'), @@ -684,14 +687,14 @@ sub checkauth { $debug and printf STDERR "AUTH_SESSION: (%s)\t%s %s - %s\n", map {$session->param($_)} qw(cardnumber firstname surname branch) ; $ip = $session->param('ip'); $lasttime = $session->param('lasttime'); - $userid = $session->param('id'); + $userid = $s_userid; $sessiontype = $session->param('sessiontype') || ''; } - if ( ( ($query->param('koha_login_context')) && ($query->param('userid') ne ($session->param('id') // '')) ) + if ( ( $query->param('koha_login_context') && ($q_userid && $s_userid && $q_userid ne $s_userid) ) || ( $cas && $query->param('ticket') ) ) { #if a user enters an id ne to the id in the current session, we need to log them in... #first we need to clear the anonymous session... - $debug and warn "query id = " . $query->param('userid') . " but session id = " . $session->param('id'); + $debug and warn "query id = $q_userid but session id = $s_userid"; $session->flush; $session->delete(); C4::Context->_unset_userenv($sessionID); @@ -711,7 +714,7 @@ sub checkauth { logout_cas($query); } } - elsif ( $lasttime < time() - $timeout ) { + elsif ( $lasttime && ($lasttime < time() - $timeout) ) { # timed logout $info{'timed_out'} = 1; $session->delete() if $session; @@ -759,7 +762,7 @@ sub checkauth { -value => $session->id, -HttpOnly => 1 ); - $userid = $query->param('userid'); + $userid = $q_userid; my $pki_field = C4::Context->preference('AllowPKIAuth') // 'None'; if ( ( $cas && $query->param('ticket') ) || $userid -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Nov 8 08:55:29 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 8 Nov 2013 20:55:29 +1300 Subject: [Koha-patches] [PATCH] Bug 11077 - Correct silent warnings in C4/Auth.pm Message-ID: <1383897329-15490-1-git-send-email-srdjan@catalyst.net.nz> From: Mark Tompsett This patch corrects a noisy ne condition. $userid = $retuserid if ( $retuserid ne ''); became $userid = $retuserid if ( $retuserid ); It also integrates Srdjan Jankovic's patch with Petter Goksoyrsen's patch, while correcting the problems found. --- C4/Auth.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/C4/Auth.pm b/C4/Auth.pm index 9d0b623..1e038a2 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -714,7 +714,7 @@ sub checkauth { logout_cas($query); } } - elsif ( $lasttime && ($lasttime < time() - $timeout) ) { + elsif ( !$lasttime || ($lasttime < time() - $timeout) ) { # timed logout $info{'timed_out'} = 1; $session->delete() if $session; @@ -838,7 +838,7 @@ sub checkauth { my $retuserid; ( $return, $cardnumber, $retuserid ) = checkpw( $dbh, $userid, $password, $query ); - $userid = $retuserid if ( $retuserid ne '' ); + $userid = $retuserid if ( $retuserid ); } if ($return) { #_session_log(sprintf "%20s from %16s logged in at %30s.\n", $userid,$ENV{'REMOTE_ADDR'},(strftime '%c', localtime)); -- 1.8.1.2 From christophe.croullebois at biblibre.com Fri Nov 8 12:25:03 2013 From: christophe.croullebois at biblibre.com (Christophe Croullebois) Date: Fri, 8 Nov 2013 12:25:03 +0100 Subject: [Koha-patches] [PATCH 1/1] Bug 9865: SIP msg encoding configurable via SIPconfig.xml Message-ID: <1383909903-12726-1-git-send-email-christophe.croullebois@biblibre.com> The accounts->login tag in SIPconfig.xml can now accept a new parameter, "encoding". It will be mostly used to encore to utf8. For this, simply add the parameter: encoding="utf8" note: this patch was made by Adrien Saurat I have simply rebased it --- C4/SIP/Sip.pm | 6 ++++-- C4/SIP/Sip/MsgType.pm | 34 +++++++++++++++++----------------- etc/SIPconfig.xml | 4 ++-- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/C4/SIP/Sip.pm b/C4/SIP/Sip.pm index f407634..b6f1916 100644 --- a/C4/SIP/Sip.pm +++ b/C4/SIP/Sip.pm @@ -7,7 +7,7 @@ package Sip; use strict; use warnings; use Exporter; - +use Encode; use Sys::Syslog qw(syslog); use POSIX qw(strftime); use Socket qw(:crlf); @@ -209,11 +209,13 @@ sub read_SIP_packet { # sub write_msg { - my ($self, $msg, $file, $terminator) = @_; + my ($self, $msg, $file, $terminator, $encoding) = @_; $terminator ||= q{}; $terminator = ( $terminator eq 'CR' ) ? $CR : $CRLF; + $msg = encode($encoding, $msg) if ( $encoding ); + my $cksum; # $msg = encode_utf8($msg); diff --git a/C4/SIP/Sip/MsgType.pm b/C4/SIP/Sip/MsgType.pm index 17185e0..fceb16b 100644 --- a/C4/SIP/Sip/MsgType.pm +++ b/C4/SIP/Sip/MsgType.pm @@ -490,7 +490,7 @@ sub handle_patron_status { $ils->check_inst_id($fields->{(FID_INST_ID)}, "handle_patron_status"); $patron = $ils->find_patron($fields->{(FID_PATRON_ID)}); $resp = build_patron_status($patron, $lang, $fields, $server ); - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return (PATRON_STATUS_REQ); } @@ -608,7 +608,7 @@ sub handle_checkout { } } - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(CHECKOUT); } @@ -696,7 +696,7 @@ sub handle_checkin { $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg); $resp .= maybe_add(FID_PRINT_LINE, $status->print_line); - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(CHECKIN); } @@ -740,7 +740,7 @@ sub handle_block_patron { } $resp = build_patron_status( $patron, $patron->language, $fields, $server ); - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(BLOCK_PATRON); } @@ -782,7 +782,7 @@ sub handle_request_acs_resend { if (!$last_response) { # We haven't sent anything yet, so respond with a # REQUEST_SC_RESEND msg (p. 16) - $self->write_msg(REQUEST_SC_RESEND,undef,$server->{account}->{terminator}); + $self->write_msg(REQUEST_SC_RESEND,undef,$server->{account}->{terminator},$server->{account}->{encoding}); } elsif ((length($last_response) < 9) || substr($last_response, -9, 2) ne 'AY') { # When resending a message, we aren't supposed to include @@ -794,7 +794,7 @@ sub handle_request_acs_resend { # Cut out the sequence number and checksum, since the old # checksum is wrong for the resent message. my $rebuilt = substr($last_response, 0, -9); - $self->write_msg($rebuilt,undef,$server->{account}->{terminator}); + $self->write_msg($rebuilt,undef,$server->{account}->{terminator},$server->{account}->{encoding}); } return REQUEST_ACS_RESEND; @@ -870,7 +870,7 @@ sub handle_login { } else { $status = login_core($server,$uid,$pwd); } - $self->write_msg(LOGIN_RESP . $status,undef,$server->{account}->{terminator}); + $self->write_msg(LOGIN_RESP . $status,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return $status ? LOGIN : ''; } @@ -1019,7 +1019,7 @@ sub handle_patron_info { } } - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(PATRON_INFO); } @@ -1046,7 +1046,7 @@ sub handle_end_patron_session { $resp .= maybe_add(FID_SCREEN_MSG, $screen_msg); $resp .= maybe_add(FID_PRINT_LINE, $print_line); - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(END_PATRON_SESSION); } @@ -1080,7 +1080,7 @@ sub handle_fee_paid { $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg); $resp .= maybe_add(FID_PRINT_LINE, $status->print_line); - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(FEE_PAID); } @@ -1147,7 +1147,7 @@ sub handle_item_information { $resp .= maybe_add(FID_PRINT_LINE, $item->print_line); } - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(ITEM_INFORMATION); } @@ -1196,7 +1196,7 @@ sub handle_item_status_update { $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg); $resp .= maybe_add(FID_PRINT_LINE, $status->print_line); - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(ITEM_STATUS_UPDATE); } @@ -1247,7 +1247,7 @@ sub handle_patron_enable { $resp .= add_field(FID_INST_ID, $ils->institution); - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(PATRON_ENABLE); } @@ -1313,7 +1313,7 @@ sub handle_hold { $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg); $resp .= maybe_add(FID_PRINT_LINE, $status->print_line); - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(HOLD); } @@ -1402,7 +1402,7 @@ sub handle_renew { $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg); $resp .= maybe_add(FID_PRINT_LINE, $status->print_line); - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(RENEW); } @@ -1452,7 +1452,7 @@ sub handle_renew_all { $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg); $resp .= maybe_add(FID_PRINT_LINE, $status->print_line); - $self->write_msg($resp,undef,$server->{account}->{terminator}); + $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return(RENEW_ALL); } @@ -1562,7 +1562,7 @@ sub send_acs_status { # Do we want to tell the terminal its location? - $self->write_msg($msg,undef,$server->{account}->{terminator}); + $self->write_msg($msg,undef,$server->{account}->{terminator},$server->{account}->{encoding}); return 1; } diff --git a/etc/SIPconfig.xml b/etc/SIPconfig.xml index bd464e2..6da9c01 100644 --- a/etc/SIPconfig.xml +++ b/etc/SIPconfig.xml @@ -36,8 +36,8 @@ - - + + Although AllowOnShelfHolds does, under certain cirmcumstances restrict items from having holds placed on them there are certain conditions that cause OPAC to still display an available Hold when it shouldn't. Eg. It there are two items, one is on the self and one is Checked Out. This patch adds a new SystemPreference 'PreventOPACHoldsAnyAvailableItem' which will enforce the restriction of placing a hold when any item is on the shelf. --- C4/Reserves.pm | 66 ++++++++++++++++++++ installer/data/mysql/sysprefs.sql | 1 + installer/data/mysql/updatedatabase.pl | 6 ++ .../en/modules/admin/preferences/circulation.pref | 7 +++ .../prog/en/includes/opac-detail-sidebar.inc | 12 ++-- .../opac-tmpl/prog/en/modules/opac-results.tt | 10 +-- opac/opac-detail.pl | 9 ++- opac/opac-search.pl | 9 ++- 8 files changed, 109 insertions(+), 11 deletions(-) diff --git a/C4/Reserves.pm b/C4/Reserves.pm index d1bca25..46bc6e0 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -133,6 +133,7 @@ BEGIN { &SuspendAll &GetReservesControlBranch + &PreventOPACHoldsAnyAvailableItem ); @EXPORT_OK = qw( MergeHolds ); } @@ -2214,6 +2215,71 @@ sub GetReservesControlBranch { return $branchcode; } + +=head2 PreventOPACHoldsAnyAvailableItem +Checks if an item is available to have a hold placed on it from the OPAC only. +Specifically relates to items currently on the shelf (without a datedue). +If 'AllowOnShelfHolds' syspref is allowed then this will always return false i.e +PreventOPACHoldsAnyAvailableItem will not prevent OPAC holds. + +Is controlled by the 'PreventOPACHoldsAnyAvailableItem' system preference. + +The system preference has 2 states: + +* off: Not in effect. Allowing of hold will be determined elsewhere in the system. +* on: Each bibnumber will be checked for attached items. Each item is checked for +its availability. The only status that prevents a hold is when an item is on the +shelf and available. All other status should be ignored. + +Returns true when any item attached to the bib is on the shelf and available + +=cut + +sub PreventOPACHoldsAnyAvailableItem { + my $biblionumber = shift; + + if ( C4::Context->preference('AllowOnShelfHolds') or not C4::Context->preference('PreventOPACHoldsAnyAvailableItem') ) { + return 0; # we shouldn't be in here + } + + my @items = GetItemsInfo( $biblionumber ); + my $prevent_hold = 0; + my $dbh = C4::Context->dbh; + my $notforloan_query; + if (C4::Context->preference('item-level_itypes')) { + $notforloan_query = "SELECT itemtypes.notforloan + FROM items + JOIN itemtypes ON (itemtypes.itemtype = items.itype) + WHERE itemnumber = ?"; + } else { + $notforloan_query = "SELECT itemtypes.notforloan + FROM items + JOIN biblioitems USING (biblioitemnumber) + JOIN itemtypes USING (itemtype) + WHERE itemnumber = ?"; + } + my $sth = $dbh->prepare($notforloan_query); + foreach my $item (@items) { + $sth->execute( $item->{itemnumber} ); + my $notforloan_itemtype = 0; + if (my ($notforloan) = $sth->fetchrow_array) { + $notforloan_itemtype = 1 if $notforloan; + } + + if ( not $item->{datedue} ) { + if ($item->{itemlost} + or ( $item->{notforloan} > 0 ) + or ( $item->{damaged} and not C4::Context->preference('AllowHoldsOnDamagedItems') ) + or $item->{wthdrawn} + or $notforloan_itemtype) { + next; + } + else {$prevent_hold++} + } + } + return $prevent_hold; +} + =head1 AUTHOR Koha Development Team diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index 72eead2..0fda5d5 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -301,6 +301,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('Persona','0','','Use Mozilla Persona for login','YesNo'), ('PrefillItem','0','','When a new item is added, should it be prefilled with last created item values?','YesNo'), ('previousIssuesDefaultSortOrder','asc','asc|desc','Specify the sort order of Previous Issues on the circulation page','Choice'), +('PreventOPACHoldsAnyAvailableItem,'0',NULL,'Define how OPAC users can place holds on items that are checked in (on the self),'Choice'), ('printcirculationslips','1','','If ON, enable printing circulation receipts','YesNo'), ('PrintNoticesMaxLines','0','','If greater than 0, sets the maximum number of lines an overdue notice will print. If the number of items is greater than this number, the notice will end with a warning asking the borrower to check their online account for a full list of overdue items.','Integer'), ('QueryAutoTruncate','1',NULL,'If ON, query truncation is enabled by default','YesNo'), diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index 6162bc5..3ed8a5f 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -7743,6 +7743,12 @@ if(CheckVersion($DBversion)) { SetVersion($DBversion); } +$DBversion = "3.13.00.XXX"; + if ( CheckVersion($DBversion) ) { + $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('PreventOPACHoldsAnyAvailableItem', '0', 'Define how OPAC users can place holds on items that are checked in (on the self)', NULL ,'Choice')"); + print "Upgrade to $DBversion done (Bug 6837: Enchances AllowOnShelfHolds SystemPref, give more granular control over OPAC holds )\n"; + SetVersion($DBversion); + } =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref index 9ae9c44..2827f93 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -370,6 +370,13 @@ Circulation: no: "Don't allow" - hold requests to be placed on items that are not checked out. - + - pref: PreventOPACHoldsAnyAvailableItem + type: choice + choices: + yes: Prevent + no: Do not explicitly prevent + - holds to be placed when ANY item is on the shelf. (Preference is ignored if AllowOnShelfHolds is ON) + - - pref: AllowHoldDateInFuture choices: yes: Allow diff --git a/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc b/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc index 0f16f3a..4a6a573 100644 --- a/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc +++ b/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc @@ -2,12 +2,14 @@ [% UNLESS ( norequests ) %] [% IF ( opacuserlogin ) %] [% IF ( RequestOnOpac ) %] - [% IF ( AllowOnShelfHolds ) %] -
  • Place hold
  • - [% ELSE %] - [% IF ( ItemsIssued ) %] + [% UNLESS (PreventOPACHoldsAnyAvailableItem) %] + [% IF ( AllowOnShelfHolds ) %]
  • Place hold
  • - [% END %] + [% ELSE %] + [% IF ( ItemsIssued ) %] +
  • Place hold
  • + [% END %] + [% END %] [% END %] [% END %] [% END %] 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 9235b2b..3b0d3db 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt @@ -667,11 +667,13 @@ $(document).ready(function(){ [% IF ( RequestOnOpac ) %] [% UNLESS ( SEARCH_RESULT.norequests ) %] [% IF ( opacuserlogin ) %] - [% IF ( AllowOnShelfHolds ) %] - Place hold - [% ELSE %] - [% IF ( SEARCH_RESULT.itemsissued ) %] + [% UNLESS SEARCH_RESULT.prevent_holds %] + [% IF ( AllowOnShelfHolds ) %] Place hold + [% ELSE %] + [% IF ( SEARCH_RESULT.itemsissued ) %] + Place hold + [% END %] [% END %] [% END %] [% END %] diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl index 41de4fd..8829400 100755 --- a/opac/opac-detail.pl +++ b/opac/opac-detail.pl @@ -401,9 +401,16 @@ if ($session->param('busc')) { } +# Check if we can place a hold on this bib where there is an item out but others available +my $prevent_holds = 0; +if ( C4::Context->preference('PreventOPACHoldsAnyAvailableItem') && not C4::Context->preference('AllowOnShelfHolds') ) { + $prevent_holds = PreventOPACHoldsAnyAvailableItem( $biblionumber ); + print "HOLDS: $prevent_holds
    "; +} +$template->param( 'PreventOPACHoldsAnyAvailableItem' => $prevent_holds ); $template->param( 'AllowOnShelfHolds' => C4::Context->preference('AllowOnShelfHolds') ); -$template->param( 'ItemsIssued' => CountItemsIssued( $biblionumber ) ); +$template->param( 'ItemsIssued' => CountItemsIssued( $biblionumber ) ) if not $prevent_holds; diff --git a/opac/opac-search.pl b/opac/opac-search.pl index 2854da6..1fffbdb 100755 --- a/opac/opac-search.pl +++ b/opac/opac-search.pl @@ -52,7 +52,7 @@ use C4::Branch; # GetBranches use C4::SocialData; use C4::Ratings; use C4::External::OverDrive; - +use C4::Reserves; use POSIX qw(ceil floor strftime); use URI::Escape; use JSON qw/decode_json encode_json/; @@ -675,6 +675,13 @@ for (my $i=0;$i<@servers;$i++) { my $j = 0; foreach (@newresults) { my $bibnum = ($_->{biblionumber})?$_->{biblionumber}:0; + my $prevent_holds = 0; + if ( C4::Context->preference('PreventOPACHoldsAnyAvailableItem') && not C4::Context->preference('AllowOnShelfHolds') ) { + $prevent_holds = PreventOPACHoldsAnyAvailableItem($bibnum) if $bibnum; + } + if ( $prevent_holds ) { + $_->{prevent_holds} =1; + } $pasarParams .= $bibnum . ','; $j++; last if ($j == $results_per_page); -- 1.7.10.4 From mathieu.saby at univ-rennes2.fr Sat Nov 9 14:53:50 2013 From: mathieu.saby at univ-rennes2.fr (Mathieu Saby) Date: Sat, 09 Nov 2013 14:53:50 +0100 Subject: [Koha-patches] [PATCH] Bug 11224 : Add UT to subs of C4::Acquisition returning order(s) Message-ID: <527E3E6E.1060804@univ-rennes2.fr> C4::Acquisition need more UT, and more robust ones. This patch adds UT to - GetOrder - GetOrders - GetCancelledOrders - GetLateOrders It refactors UT for SearchOrders New UT use 2 new subs, used for check the list of fields returns by a sub. _check_fields_of_order _check_fields_of_orders These 2 subs could later be used by other UT _check_fields_of_order has its own UT (tests n??14,15,16). They should maybe be commented after this patch is QAed. to test : prove t/db_dependent/Acquisition.t -v --- C4/Acquisition.pm | 1 + t/db_dependent/Acquisition.t | 597 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 516 insertions(+), 82 deletions(-) diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm index aabc0ed..c75d298 100644 --- a/C4/Acquisition.pm +++ b/C4/Acquisition.pm @@ -1034,6 +1034,7 @@ biblio, and biblioitems tables in the Koha database. sub GetOrders { my ( $basketno, $orderby ) = @_; + return () unless $basketno; my $dbh = C4::Context->dbh; my $query =" SELECT biblio.*,biblioitems.*, diff --git a/t/db_dependent/Acquisition.t b/t/db_dependent/Acquisition.t index 8b737ba..f311fe6 100755 --- a/t/db_dependent/Acquisition.t +++ b/t/db_dependent/Acquisition.t @@ -8,7 +8,7 @@ use POSIX qw(strftime); use C4::Bookseller qw( GetBookSellerFromId ); -use Test::More tests => 60; +use Test::More tests => 64; BEGIN { use_ok('C4::Acquisition'); @@ -18,10 +18,66 @@ BEGIN { use_ok('C4::Bookseller'); } +# Sub used for testing C4::Acquisition subs returning order(s) : GetOrdersByStatus,GetOrders, GetDeletedOrders, GetOrder etc. +# (\@test_missing_fields,\@test_extra_fields,\@test_different_fields,$test_nbr_fields) = _check_fields_of_order ($exp_fields, $original_order_content, $order_to_check); +# params : +# $exp_fields : arrayref whose elements are the keys we expect to find +# $original_order_content : hashref whose 2 keys str and num contains hashrefs containing content fields of the order created with NewOrder +# $order_to_check : hashref whose keys/values are the content of an order returned by the C4::Acquisition sub we are testing +# returns : +# \@test_missing_fields : arrayref void if ok ; otherwise contains the list of fields missing in $order_to_check +# \@test_extra_fields : arrayref void if ok ; otherwise contains the list of fields unexpected in $order_to_check +# \@test_different_fields : arrayref void if ok ; otherwise contains the list of fields which value is not the same in between $order_to_check and +# $test_nbr_fields : contains the number of fields of $order_to_check + +sub _check_fields_of_order { + my ($exp_fields, $original_order_content, $order_to_check) = @_; + my @test_missing_fields = (); + my @test_extra_fields = (); + my @test_different_fields = (); + my $test_nbr_fields = scalar (keys %$order_to_check); + foreach my $field ( @$exp_fields ) { + push @test_missing_fields, $field unless exists( $order_to_check->{ $field }); + } + foreach my $field ( keys %$order_to_check) { + push @test_extra_fields, $field unless grep (/^$field$/, @$exp_fields); + } + foreach my $field ( keys %{$original_order_content->{str}}) { + push @test_different_fields, $field unless (! exists $order_to_check->{ $field }) or ($original_order_content->{str}->{$field} eq $order_to_check->{ $field }); + } + foreach my $field ( keys %{$original_order_content->{num}}) { + push @test_different_fields, $field unless (! exists $order_to_check->{ $field }) or ($original_order_content->{num}->{$field} == $order_to_check->{ $field }); + } + return ( \@test_missing_fields,\@test_extra_fields,\@test_different_fields,$test_nbr_fields); +} + +# Sub used for testing C4::Acquisition subs returning several orders +# (\@test_missing_fields,\@test_extra_fields,\@test_different_fields,\@test_nbr_fields) = _check_fields_of_orders ($exp_fields, $original_orders_content, $orders_to_check) +sub _check_fields_of_orders { + my ($exp_fields, $original_orders_content, $orders_to_check) = @_; + my @test_missing_fields = (); + my @test_extra_fields = (); + my @test_different_fields = (); + my @test_nbr_fields = (); + foreach my $order_to_check (@$orders_to_check ) { + my $original_order_content = (grep {$_->{str}->{ordernumber} eq $order_to_check-> {ordernumber}} @$original_orders_content)[0]; + my ($t_missing_fields,$t_extra_fields,$t_different_fields,$t_nbr_fields) = _check_fields_of_order ($exp_fields,$original_order_content,$order_to_check); + push @test_missing_fields, @$t_missing_fields; + push @test_extra_fields, @$t_extra_fields; + push @test_different_fields, @$t_different_fields; + push @test_nbr_fields, $t_nbr_fields; + } + @test_missing_fields = keys %{{map {$_ => 1} @test_missing_fields}}; + @test_extra_fields = keys %{{map {$_ => 1} @test_extra_fields}}; + @test_different_fields = keys %{{map {$_ => 1} @test_different_fields}}; + return (\@test_missing_fields,\@test_extra_fields,\@test_different_fields,\@test_nbr_fields); +} + my $dbh = C4::Context->dbh; $dbh->{AutoCommit} = 0; $dbh->{RaiseError} = 1; +# Creating some orders my $booksellerid = C4::Bookseller::AddBookseller( { name => "my vendor", @@ -48,89 +104,481 @@ my $budgetid = C4::Budgets::AddBudget( ); my $budget = C4::Budgets::GetBudget( $budgetid ); -my ($ordernumber1, $ordernumber2, $ordernumber3); +my @ordernumbers; my ($biblionumber1, $biblioitemnumber1) = AddBiblio(MARC::Record->new, ''); my ($biblionumber2, $biblioitemnumber2) = AddBiblio(MARC::Record->new, ''); -( undef, $ordernumber1 ) = C4::Acquisition::NewOrder( - { +my ($biblionumber3, $biblioitemnumber3) = AddBiblio(MARC::Record->new, ''); +my ($biblionumber4, $biblioitemnumber4) = AddBiblio(MARC::Record->new, ''); + + +# +# Test NewOrder +# + +my ($mandatoryparams, $return_error,$basketnum); + +# returns undef and croaks if basketno, quantity, biblionumber or budget_id is missing +eval {($basketnum, $ordernumbers[0] ) = C4::Acquisition::NewOrder()}; +$return_error = $@; +ok ((!(defined $basketnum || defined $ordernumbers[0])) && (defined $return_error),"NewOrder with no params returns undef and croaks"); + +$mandatoryparams = { + basketno => $basketno, + quantity => 24, + biblionumber => $biblionumber1, + budget_id => $budget->{budget_id}, + }; +my @mandatoryparams_keys = keys %$mandatoryparams; +foreach my $mandatoryparams_key (@mandatoryparams_keys) { + my %test_missing_mandatoryparams = %$mandatoryparams; + delete $test_missing_mandatoryparams {$mandatoryparams_key}; + eval {($basketnum, $ordernumbers[0] ) = C4::Acquisition::NewOrder(\%test_missing_mandatoryparams)}; + $return_error = $@; + my $expected_error = "Mandatory parameter $mandatoryparams_key missing"; + ok ((!(defined $basketnum || defined $ordernumbers[0])) && ( index ($return_error, $expected_error) >=0 ),"NewOrder with no $mandatoryparams_key returns undef and croaks with expected error message"); +} + +# FIXME to do : test the other features of NewOrder + +# Prepare 5 orders, and make distinction beween fields to be tested with eq and with == +# Ex : a price of 50.1 will be stored internally as 5.100000 + +my @order_content = ( + {str => { basketno => $basketno, - quantity => 24, biblionumber => $biblionumber1, budget_id => $budget->{budget_id}, - } -); - -( undef, $ordernumber2 ) = C4::Acquisition::NewOrder( - { + uncertainprice=>0, + notes=>"some notes", + }, + num => { + quantity => 24, + listprice=>50.121111, + ecost => 38.15, + rrp => 40.15, + discount =>5.1111, + gstrate=>0.0515 + }}, + {str => { basketno => $basketno, - quantity => 42, biblionumber => $biblionumber2, - budget_id => $budget->{budget_id}, - } -); - -( undef, $ordernumber3 ) = C4::Acquisition::NewOrder( - { + budget_id => $budget->{budget_id} + }, + num => { + quantity => 42 + }}, + {str => { basketno => $basketno, - quantity => 4, biblionumber => $biblionumber2, budget_id => $budget->{budget_id}, - ecost => 42, + uncertainprice=>0, + notes=>"ordernotes" + }, + num =>{ + quantity => 4, + ecost => 42.1, + rrp => 42.1, + listprice=>10.1, + ecost => 38.1, + rrp => 11.0, + discount =>5.1, + gstrate=>0.1 + }}, + {str =>{ + basketno => $basketno, + biblionumber => $biblionumber3, + budget_id => $budget->{budget_id}, + notes=>"ordernotes" + }, + num => { + quantity => 4, + ecost => 40, rrp => 42, - } + listprice=>10, + ecost => 38.15, + rrp => 11.00, + discount =>0, + uncertainprice=>0, + gstrate=>0 + }}, + {str =>{ + basketno => $basketno, + biblionumber => $biblionumber4, + budget_id => $budget->{budget_id}, + notes=>"ordernotes" + }, + num => { + quantity => 1, + ecost => 10, + rrp => 10, + listprice=>10, + ecost => 10, + rrp => 10, + discount =>0, + uncertainprice=>0, + gstrate=>0 + }} + ); + +# Create 4 orders in database +for (0..4) { + my %ocontent ; + @ocontent { keys %{$order_content[$_]->{num}} } = values %{$order_content[$_]->{num}}; + @ocontent { keys %{$order_content[$_]->{str}} } = values %{$order_content[$_]->{str}}; + ( undef, $ordernumbers[$_] ) = C4::Acquisition::NewOrder(\%ocontent); + $order_content[$_]->{str}->{ordernumber} = $ordernumbers[$_]; +} + + +# Test UT sub _check_fields_of_order + +my ($test_missing_fields,$test_extra_fields,$test_different_fields,$test_nbr_fields) = _check_fields_of_order ([qw /a b c d e/], {str=>{a=>"bla",b=>"105"},num=>{c=>15.12}}, {a=>"blabla",f=>"f",b=>"105",c=>15.1200,g=>''}); +ok ((($test_nbr_fields == 5) and (join (" ",sort @$test_missing_fields) eq 'd e') and (join (" ",sort @$test_extra_fields) eq 'f g') and (join(" ",@$test_different_fields) eq 'a')), "_check_fields_of_order can check an order (test 1)"); +($test_missing_fields,$test_extra_fields,$test_different_fields,$test_nbr_fields) = _check_fields_of_order ([qw /a b c /], {str=>{a=>"bla",b=>"105"},num=>{c=>15.00}}, {a=>"bla",b=>"105",c=>15}); +ok ((($test_nbr_fields == 3) and (scalar @$test_missing_fields == 0) and (scalar @$test_extra_fields == 0) and (scalar @$test_different_fields == 0)) , "_check_fields_of_order can check an order (test 2)"); +($test_missing_fields,$test_extra_fields,$test_different_fields,$test_nbr_fields) = _check_fields_of_order ([qw /a b c d e/], {str=>{a=>"bla",b=>"105"},num=>{c=>15.12}}, {a=>"blabla",b=>"105",c=>15,d=>"error"}); +ok ((($test_nbr_fields == 4) and (join (" ",sort @$test_missing_fields) eq 'e') and (scalar @$test_extra_fields == 0) and (join(" ",@$test_different_fields) eq 'a c')) , "_check_fields_of_order can check an order (test 3)"); + + +# +# test GetOrder +# + +my @expectedfields = qw( + ordernumber + biblionumber + entrydate + quantity + currency + listprice + totalamount + datereceived + invoiceid + freight + unitprice + quantityreceived + cancelledby + datecancellationprinted + notes + supplierreference + purchaseordernumber + basketno + timestamp + rrp + ecost + unitpricesupplier + unitpricelib + gstrate + discount + budget_id + budgetgroup_id + budgetdate + sort1 + sort2 + sort1_authcat + sort2_authcat + uncertainprice + claims_count + claimed_date + subscriptionid + parent_ordernumber + orderstatus + title + author + basketname + branchcode + publicationyear + copyrightdate + editionstatement + isbn + ean + seriestitle + publishercode + publisher + budget + supplier + supplierid + estimateddeliverydate + orderdate + quantity_to_receive + subtotal + latesince + ); +($test_missing_fields,$test_extra_fields,$test_different_fields,$test_nbr_fields) = _check_fields_of_order (\@expectedfields , $order_content[0], GetOrder($ordernumbers[0])); +is($test_nbr_fields,scalar @expectedfields , "GetOrder gets an order with the right number of fields" ); +is(join (" ",@$test_missing_fields),'', "GetOrder gets an order with no missing fields" ); +is(join (" ",@$test_extra_fields),'', "GetOrder gets an order with no unexpected fields" ); +is(join (" ",@$test_different_fields),'', "GetOrder gets an order with the right content in every fields" ); + +# +# Test GetOrders +# + +my @base_expectedfields = qw( + ordernumber + ecost + uncertainprice + marc + cancelledby + url + isbn + copyrightdate + serial + cn_suffix + cn_item + marcxml + freight + cn_class + title + pages + budget_encumb + budget_name + number + itemtype + totalissues + author + budget_permission + parent_ordernumber + size + claims_count + currency + seriestitle + timestamp + editionstatement + budget_parent_id + publishercode + unitprice + collectionvolume + budget_amount + budget_owner_id + datecreated + claimed_date + subscriptionid + editionresponsibility + sort2 + notes + volumedate + budget_id + illus + ean + biblioitemnumber + datereceived + orderstatus + supplierreference + agerestriction + budget_branchcode + gstrate + listprice + budget_code + budgetdate + basketno + discount + abstract + collectionissn + publicationyear + collectiontitle + invoiceid + budgetgroup_id + place + issn + quantityreceived + entrydate + cn_source + sort1_authcat + budget_notes + biblionumber + unititle + sort2_authcat + budget_expend + rrp + cn_sort + totalamount + lccn + sort1 + volume + purchaseordernumber + quantity + budget_period_id + frameworkcode + volumedesc + datecancellationprinted + ); + at expectedfields = (@base_expectedfields, ('transferred_from_timestamp','transferred_from')); +is(GetOrders(),undef,"GetOrders with no params returns undef"); +DelOrder ($order_content[3]->{str}->{biblionumber},$ordernumbers[3]); +my @get_orders = GetOrders($basketno); +($test_missing_fields,$test_extra_fields,$test_different_fields,$test_nbr_fields) = _check_fields_of_orders (\@expectedfields , \@order_content, \@get_orders); +is($$test_nbr_fields [0],scalar @expectedfields , "GetOrders gets orders with the right number of fields" ); +is(join (" ",@$test_missing_fields),'', "GetOrders gets orders with no missing fields" ); +is(join (" ",@$test_extra_fields),'', "GetOrders gets orders with no unexpected fields" ); +is(join (" ",@$test_different_fields),'', "GetOrders gets orders with the right content in every fields" ); +ok(((scalar @get_orders == 4) and !grep ($_->{ordernumber} eq $ordernumbers[3], @get_orders)),"GetOrders only gets non-cancelled orders" ); + +# +# Test GetCancelledOrders +# + + at expectedfields = (@base_expectedfields, ('transferred_to_timestamp','transferred_to')); +is(GetCancelledOrders(),undef,"GetCancelledOrders with no params returns undef"); + at get_orders = GetCancelledOrders($basketno); +($test_missing_fields,$test_extra_fields,$test_different_fields,$test_nbr_fields) = _check_fields_of_orders (\@expectedfields , \@order_content, \@get_orders); +is($$test_nbr_fields [0],scalar @expectedfields , "GetCancelledOrders gets orders with the right number of fields" ); +is(join (" ",@$test_missing_fields),'', "GetCancelledOrders gets orders with no missing fields" ); +is(join (" ",@$test_extra_fields),'', "GetCancelledOrders gets orders with no unexpected fields" ); +is(join (" ",@$test_different_fields),'', "GetCancelledOrders gets orders with the right content in every fields" ); +ok(((scalar @get_orders == 1) and grep ($_->{ordernumber} eq $ordernumbers[3], @get_orders)),"GetCancelledOrders only gets cancelled orders" ); + +# +# Test SearchOrders +# + + at expectedfields = qw ( + firstname + biblioitemnumber + ecost + uncertainprice + creationdate + datereceived + orderstatus + supplierreference + cancelledby + isbn + copyrightdate + gstrate + serial + listprice + budgetdate + basketno + discount + surname + freight + abstract + title + closedate + basketname + budgetgroup_id + invoiceid + author + parent_ordernumber + claims_count + entrydate + currency + quantityreceived + seriestitle + sort1_authcat + timestamp + biblionumber + unititle + sort2_authcat + rrp + unitprice + totalamount + sort1 + ordernumber + datecreated + purchaseordernumber + quantity + claimed_date + subscriptionid + frameworkcode + sort2 + notes + datecancellationprinted + budget_id ); -my $orders = SearchOrders({ +my $invoiceid = AddInvoice( + invoicenumber => 'invoice', booksellerid => $booksellerid, + unknown => "unknown" +); + +my ($datereceived, $new_ordernumber) = ModReceiveOrder( + $biblionumber4, + $ordernumbers[4], + 1, + undef, + 10, + 10, + $invoiceid, + 10, + $order_content[4]->{str}->{budget_id} + ); + +my $search_orders = SearchOrders({ + booksellerid => $booksellerid, + basketno => $basketno +}); +isa_ok( $search_orders, 'ARRAY' ); +($test_missing_fields,$test_extra_fields,$test_different_fields,$test_nbr_fields) = _check_fields_of_orders (\@expectedfields , \@order_content, $search_orders ); +is($$test_nbr_fields [0],scalar @expectedfields , "SearchOrders gets orders with the right number of fields" ); +is(join (" ",@$test_missing_fields),'', "SearchOrders gets orders with no missing fields" ); +is(join (" ",@$test_extra_fields),'', "SearchOrders gets orders with no unexpected fields" ); +is(join (" ",@$test_different_fields),'', "SearchOrders gets orders with the right content in every fields" ); +ok(((scalar @$search_orders == 4) and !grep ($_->{ordernumber} eq $ordernumbers[3], @$search_orders)),"SearchOrders only gets non-cancelled orders" ); + +$search_orders = SearchOrders({ + booksellerid => $booksellerid, + basketno => $basketno, pending => 1 }); -isa_ok( $orders, 'ARRAY' ); -is(scalar(@$orders), 3, 'retrieved 3 pending orders'); +ok(((scalar @$search_orders == 3) and !grep ((($_->{ordernumber} eq $ordernumbers[3]) or ($_->{ordernumber} eq $ordernumbers[4])), @$search_orders)),"SearchOrders with pending params gets only pending orders" ); -ok( GetBudgetByOrderNumber($ordernumber1)->{'budget_id'} eq $budgetid, "GetBudgetByOrderNumber returns expected budget" ); +# +# Test GetBudgetByOrderNumber +# -C4::Acquisition::CloseBasket( $basketno ); +ok( GetBudgetByOrderNumber($ordernumbers[0])->{'budget_id'} eq $budgetid, "GetBudgetByOrderNumber returns expected budget" ); + + +# +# Test GetLateOrders +# + + at expectedfields = qw ( + orderdate + author + budget + supplierid + claims_count + supplier + publisher + ordernumber + quantity + basketno + claimed_date + branch + estimateddeliverydate + title + publicationyear + unitpricelib + unitpricesupplier + subtotal + latesince +); my @lateorders = GetLateOrders(0); +is(scalar grep ($_->{basketno} eq $basketno, @lateorders),0, "GetLateOrders does not get orders from opened baskets" ); +C4::Acquisition::CloseBasket( $basketno ); + at lateorders = GetLateOrders(0); +isnt(scalar grep ($_->{basketno} eq $basketno, @lateorders),0, "GetLateOrders gets orders from closed baskets" ); +ok(!grep ($_->{ordernumber} eq $ordernumbers[3], @lateorders),"GetLateOrders does not gets cancelled orders" ); +ok(!grep ($_->{ordernumber} eq $ordernumbers[4], @lateorders),"GetLateOrders does not gets reveived orders" ); +($test_missing_fields,$test_extra_fields,$test_different_fields,$test_nbr_fields) = _check_fields_of_orders (\@expectedfields , \@order_content, \@lateorders ); +is($$test_nbr_fields [0],scalar @expectedfields , "GetLateOrders gets orders with the right number of fields" ); +is(join (" ",@$test_missing_fields),'', "GetLateOrders gets orders with no missing fields" ); +is(join (" ",@$test_extra_fields),'', "GetLateOrders gets orders with no unexpected fields" ); +is(join (" ",@$test_different_fields),'', "GetLateOrders gets orders with the right content in every fields" ); + +# +# Test AddClaim +# + my $order = $lateorders[0]; AddClaim( $order->{ordernumber} ); my $neworder = GetOrder( $order->{ordernumber} ); is( $neworder->{claimed_date}, strftime( "%Y-%m-%d", localtime(time) ), "AddClaim : Check claimed_date" ); -my @expectedfields = qw( basketno - biblionumber - invoiceid - budgetdate - cancelledby - closedate - creationdate - currency - datecancellationprinted - datereceived - ecost - entrydate - firstname - freight - gstrate - listprice - notes - ordernumber - purchaseordernumber - quantity - quantityreceived - rrp - sort1 - sort2 - subscriptionid - supplierreference - surname - timestamp - title - totalamount - unitprice ); -my $firstorder = $orders->[0]; -for my $field ( @expectedfields ) { - ok( exists( $firstorder->{ $field } ), "This order has a $field field" ); -} +my $firstorder = $search_orders->[0]; # fake receiving the order ModOrder({ @@ -138,25 +586,10 @@ ModOrder({ biblionumber => $firstorder->{biblionumber}, quantityreceived => $firstorder->{quantity}, }); -my $pendingorders = SearchOrders({ - booksellerid => $booksellerid, - pending => 1 -}); -is(scalar(@$pendingorders), 2, 'retrieved 2 pending orders after receiving on one (bug 10723)'); -my $allorders = SearchOrders({ - booksellerid => $booksellerid, -}); -is(scalar(@$allorders), 3, 'retrieved all 3 orders even after after receiving on one (bug 10723)'); -my $invoiceid = AddInvoice( - invoicenumber => 'invoice', - booksellerid => $booksellerid, - unknown => "unknown" -); - -my ($datereceived, $new_ordernumber) = ModReceiveOrder( +($datereceived, $new_ordernumber) = ModReceiveOrder( $biblionumber2, - $ordernumber2, + $ordernumbers[1], 2, undef, 12, @@ -164,7 +597,7 @@ my ($datereceived, $new_ordernumber) = ModReceiveOrder( $invoiceid, 42, ); -my $order2 = GetOrder( $ordernumber2 ); +my $order2 = GetOrder( $ordernumbers[1] ); is($order2->{'quantityreceived'}, 0, 'Splitting up order did not receive any on original order'); is($order2->{'quantity'}, 40, '40 items on original order'); is($order2->{'budget_id'}, $budgetid, 'Budget on original order is unchanged'); @@ -183,7 +616,7 @@ my $budgetid2 = C4::Budgets::AddBudget( ($datereceived, $new_ordernumber) = ModReceiveOrder( $biblionumber2, - $ordernumber3, + $ordernumbers[2], 2, undef, 12, @@ -193,7 +626,7 @@ my $budgetid2 = C4::Budgets::AddBudget( $budgetid2 ); -my $order3 = GetOrder( $ordernumber3 ); +my $order3 = GetOrder( $ordernumbers[2] ); is($order3->{'quantityreceived'}, 0, 'Splitting up order did not receive any on original order'); is($order3->{'quantity'}, 2, '2 items on original order'); is($order3->{'budget_id'}, $budgetid, 'Budget on original order is unchanged'); @@ -205,7 +638,7 @@ is($neworder->{'budget_id'}, $budgetid2, 'Budget on new order is changed'); ($datereceived, $new_ordernumber) = ModReceiveOrder( $biblionumber2, - $ordernumber3, + $ordernumbers[2], 2, undef, 12, @@ -215,7 +648,7 @@ is($neworder->{'budget_id'}, $budgetid2, 'Budget on new order is changed'); $budgetid2 ); -$order3 = GetOrder( $ordernumber3 ); +$order3 = GetOrder( $ordernumbers[2] ); is($order3->{'quantityreceived'}, 2, 'Order not split up'); is($order3->{'quantity'}, 2, '2 items on order'); is($order3->{'budget_id'}, $budgetid2, 'Budget has changed'); -- 1.7.9.5 -- Mathieu Saby Service d'Informatique Documentaire Service Commun de Documentation Universit? Rennes 2 T?l?phone : 02 99 14 12 65 Courriel : mathieu.saby at univ-rennes2.fr From mathieu.saby at univ-rennes2.fr Sun Nov 10 16:38:27 2013 From: mathieu.saby at univ-rennes2.fr (Mathieu Saby) Date: Sun, 10 Nov 2013 16:38:27 +0100 Subject: [Koha-patches] [PATCH] Bug 11230 - Refactor C4::Stats::UpdateStats and add UT Message-ID: <527FA873.90508@univ-rennes2.fr> This patch - refactors C4::Stats::UpdateStats (it now takes a hashref as unique parameter, instead of a list of parameters) - add UT for it - change the calls made to this sub in C4::Accounts and C4::Circulation Additionnaly it also - adds POD to C4::Stats::TotalPaid - adds some comments to C4::Stats::TotalPaid (I think I found some errors in it) To test : 1. run "prove t/db_dependant/Stats.t -v" 2. make some circulation operations (checkout, checkin, renew, localuse) check the operations are rightly recorded in Statistics table (with a SQL query like "SELECT * FROM statistics WHERE datetime LIKE "2013-11-15%", if you run your test on the 15th november) 3. make some fine payments operations (writeoff, payment) check the operations are rightly recorded in Statistics table (with a SQL query like "SELECT * FROM statistics WHERE datetime LIKE "2013-11-15%", if you run your test on the 15th november) Note that there is probably an issue to fix in Accounts.pm : the user is saved instead of the branch. But this is not the purpose of this patch, so I kept the previous behavior for the moment. --- C4/Accounts.pm | 44 ++++++++++++---- C4/Circulation.pm | 48 ++++++++++++----- C4/Stats.pm | 121 ++++++++++++++++++++++++++++++++++--------- t/db_dependent/Stats.t | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 297 insertions(+), 49 deletions(-) create mode 100644 t/db_dependent/Stats.t diff --git a/C4/Accounts.pm b/C4/Accounts.pm index c34b330..c8e2e05 100644 --- a/C4/Accounts.pm +++ b/C4/Accounts.pm @@ -149,7 +149,13 @@ sub recordpayment { ); $usth->execute( $borrowernumber, $nextaccntno, 0 - $data, 0 - $amountleft, $manager_id ); - UpdateStats( $branch, 'payment', $data, '', '', '', $borrowernumber, $nextaccntno ); + UpdateStats({ + branch => $branch, + type =>'payment', + amount => $data, + borrowernumber => $borrowernumber, + accountno => $nextaccntno } + ); if ( C4::Context->preference("FinesLog") ) { $accdata->{'amountoutstanding_new'} = $newamtos; @@ -260,12 +266,13 @@ sub makepayment { })); } - - # FIXME - The second argument to &UpdateStats is supposed to be the - # branch code. - # UpdateStats is now being passed $accountno too. MTJ - UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber, - $accountno ); + UpdateStats({ + branch => $user, + type => 'payment', + amount => $amount, + borrowernumber => $borrowernumber, + accountno => $accountno} + ); #check to see what accounttype if ( $data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L' ) { @@ -659,7 +666,13 @@ sub recordpayment_selectaccts { '(borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding,manager_id,note) ' . q|VALUES (?,?,now(),?,'Payment,thanks','Pay',?,?,?)|; $dbh->do($sql,{},$borrowernumber, $nextaccntno, 0 - $amount, 0 - $amountleft, $manager_id, $note ); - UpdateStats( $branch, 'payment', $amount, '', '', '', $borrowernumber, $nextaccntno ); + UpdateStats({ + branch => $branch, + type => 'payment', + amount => $amount, + borrowernumber => $borrowernumber, + accountno => $nextaccntno} + ); if ( C4::Context->preference("FinesLog") ) { logaction("FINES", 'CREATE',$borrowernumber,Dumper({ @@ -720,7 +733,13 @@ sub makepartialpayment { $dbh->do( $insert, undef, $borrowernumber, $nextaccntno, $amount, "Payment, thanks - $user", 'Pay', $data->{'itemnumber'}, $manager_id, $payment_note); - UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber, $accountno ); + UpdateStats({ + branch => $user, + type => 'payment', + amount => $amount, + borrowernumber => $borrowernumber, + accountno => $accountno} + ); if ( C4::Context->preference("FinesLog") ) { logaction("FINES", 'CREATE',$borrowernumber,Dumper({ @@ -804,7 +823,12 @@ sub WriteOffFee { })); } - UpdateStats( $branch, 'writeoff', $amount, q{}, q{}, q{}, $borrowernumber ); + UpdateStats({ + branch => $branch, + type => 'writeoff', + amount => $amount, + borrowernumber => $borrowernumber} + ); } diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 0a22b76..3b0a8d6 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -739,7 +739,14 @@ sub CanBookBeIssued { # if ( $borrower->{'category_type'} eq 'X' && ( $item->{barcode} )) { # stats only borrower -- add entry to statistics table, and return issuingimpossible{STATS} = 1 . - &UpdateStats(C4::Context->userenv->{'branch'},'localuse','','',$item->{'itemnumber'},$item->{'itemtype'},$borrower->{'borrowernumber'}, undef, $item->{'ccode'}); + &UpdateStats({ + branch => C4::Context->userenv->{'branch'}, + type => 'localuse', + itemnumber => $item->{'itemnumber'}, + itemtype => $item->{'itemtype'}, + borrowernumber => $borrower->{'borrowernumber'}, + ccode => $item->{'ccode'}} + ); ModDateLastSeen( $item->{'itemnumber'} ); return( { STATS => 1 }, {}); } @@ -1301,11 +1308,15 @@ sub AddIssue { } # Record the fact that this book was issued. - &UpdateStats( - C4::Context->userenv->{'branch'}, - 'issue', $charge, - ($sipmode ? "SIP-$sipmode" : ''), $item->{'itemnumber'}, - $item->{'itype'}, $borrower->{'borrowernumber'}, undef, $item->{'ccode'} + &UpdateStats({ + branch => C4::Context->userenv->{'branch'}, + type => 'issue', + amount => $charge, + other => ($sipmode ? "SIP-$sipmode" : ''), + itemnumber => $item->{'itemnumber'}, + itemtype => $item->{'itype'}, + borrowernumber => $borrower->{'borrowernumber'}, + ccode => $item->{'ccode'}} ); # Send a checkout slip. @@ -1720,7 +1731,7 @@ sub AddReturn { my $biblio; my $doreturn = 1; my $validTransfert = 0; - my $stat_type = 'return'; + my $stat_type = 'return'; # get information on item my $itemnumber = GetItemnumberFromBarcode( $barcode ); @@ -1892,13 +1903,15 @@ sub AddReturn { $messages->{'ResFound'} = $resrec; } - # update stats? # Record the fact that this book was returned. - UpdateStats( - $branch, $stat_type, '0', '', - $item->{'itemnumber'}, - $biblio->{'itemtype'}, - $borrowernumber, undef, $item->{'ccode'} + # FIXME itemtype should record item level type, not bibliolevel type + UpdateStats({ + branch => $branch, + type => $stat_type, + itemnumber => $item->{'itemnumber'}, + itemtype => $biblio->{'itemtype'}, + borrowernumber => $borrowernumber, + ccode => $item->{'ccode'}} ); # Send a check-in slip. # NOTE: borrower may be undef. probably shouldn't try to send messages then. @@ -2630,7 +2643,14 @@ sub AddRenewal { } # Log the renewal - UpdateStats( $branch, 'renew', $charge, '', $itemnumber, $item->{itype}, $borrowernumber, undef, $item->{'ccode'}); + UpdateStats({branch => $branch, + type => 'renew', + amount => $charge, + itemnumber => $itemnumber, + itemtype => $item->{itype}, + borrowernumber => $borrowernumber, + ccode => $item->{'ccode'}} + ); return $datedue; } diff --git a/C4/Stats.pm b/C4/Stats.pm index e1cbd42..2ec5269 100644 --- a/C4/Stats.pm +++ b/C4/Stats.pm @@ -21,6 +21,7 @@ package C4::Stats; use strict; use warnings; require Exporter; +use Carp; use C4::Context; use C4::Debug; use vars qw($VERSION @ISA @EXPORT); @@ -48,60 +49,128 @@ C4::Stats - Update Koha statistics (log) =head1 DESCRIPTION -The C<&UpdateStats> function adds an entry to the statistics table in -the Koha database, which acts as an activity log. +The functions of this module deals with statistics table of Koha database. =head1 FUNCTIONS -=over 2 +=head2 UpdateStats -=item UpdateStats + &UpdateStats($params); - &UpdateStats($branch, $type, $value, $other, $itemnumber, - $itemtype, $borrowernumber); +Adds an entry to the statistics table in the Koha database, which acts as an activity log. -Adds a line to the statistics table of the Koha database. In effect, -it logs an event. +C<$params> is an hashref whose expected keys are: + branch : the branch where the transaction occurred + type : the type of transaction (renew, issue, localuse, return, writeoff, payment + itemnumber : the itemnumber of the item + borrowernumber : the borrowernumber of the patron + amount : the amount of the transaction + other : sipmode + itemtype : the type of the item + accountno : the count + ccode : the collection code of the item -C<$branch>, C<$type>, C<$value>, C<$other>, C<$itemnumber>, -C<$itemtype>, and C<$borrowernumber> correspond to the fields of the -statistics table in the Koha database. +type key is mandatory. +For types used in C4::Circulation (renew,issue,localuse,return), the following other keys are mandatory: +branch, borrowernumber, itemnumber, ccode, itemtype +For types used in C4::Accounts (writeoff, payment), the following other keys are mandatory: +branch, borrowernumber, itemnumber, ccode, itemtype +If an optional key is not provided, the value '' is used for this key. + +Returns undef if no C<$param> is given =cut -#' sub UpdateStats { + my ($params) = @_; +# make some controls + return () if ! defined $params; +# change these arrays if new types of transaction or new parameters are allowed + my @allowed_keys = qw (type branch amount other itemnumber itemtype borrowernumber accountno ccode); + my @allowed_circulation_types = qw (renew issue localuse return); + my @allowed_accounts_types = qw (writeoff payment); + my @circulation_mandatory_keys = qw (type branch borrowernumber itemnumber ccode itemtype); + my @accounts_mandatory_keys = qw (type branch borrowernumber amount); + + my @mandatory_keys = (); + if (! exists $params->{type} or ! defined $params->{type}) { + croak ("UpdateStats does not received type param"); + } + if (grep ($_ eq $params->{type}, @allowed_circulation_types )) { + @mandatory_keys = @circulation_mandatory_keys; + } elsif (grep ($_ eq $params->{type}, @allowed_accounts_types )) { + @mandatory_keys = @accounts_mandatory_keys; + } else { + croak ("UpdateStats received forbidden type param: ".$params->{type}); + } + my @missing_params = (); + for my $mykey (@mandatory_keys ) { + push @missing_params, $mykey if !grep (/^$mykey/, keys $params); + } + if (scalar @missing_params > 0 ) { + croak ("UpdateStats does not received mandatory param(s): ".join (", ", at missing_params )); + } + my @invalid_params = (); + for my $myparam (keys $params ) { + push @invalid_params, $myparam unless grep (/^$myparam$/, @allowed_keys); + } + if (scalar @invalid_params > 0 ) { + croak ("UpdateStats received invalid param(s): ".join (", ", at invalid_params )); + } +# get the parameters + my $branch = $params->{branch}; + my $type = $params->{type}; + my $borrowernumber = exists $params->{borrowernumber} ? $params->{borrowernumber} :''; + my $itemnumber = exists $params->{itemnumber} ? $params->{itemnumber} :''; + my $amount = exists $params->{amount} ? $params->{amount} :''; + my $other = exists $params->{other} ? $params->{other} :''; + my $itemtype = exists $params->{itemtype} ? $params->{itemtype} :''; + my $accountno = exists $params->{accountno} ? $params->{accountno} :''; + my $ccode = exists $params->{ccode} ? $params->{ccode} :''; - #module to insert stats data into stats table - my ( - $branch, $type, - $amount, $other, $itemnum, - $itemtype, $borrowernumber, $accountno, $ccode - ) - = @_; my $dbh = C4::Context->dbh; my $sth = $dbh->prepare( "INSERT INTO statistics - (datetime, branch, type, value, - other, itemnumber, itemtype, borrowernumber, proccode, ccode) + (datetime, + branch, type, value, + other, itemnumber, itemtype, + borrowernumber, proccode, ccode) VALUES (now(),?,?,?,?,?,?,?,?,?)" ); $sth->execute( - $branch, $type, $amount, - $other, $itemnum, $itemtype, $borrowernumber, - $accountno, $ccode + $branch, $type, $amount, + $other, $itemnumber, $itemtype, + $borrowernumber, $accountno, $ccode ); } -# Otherwise, it'd need a POD. +=head2 TotalPaid + + @total = &TotalPaid ( $time, [$time2], [$spreadsheet ]); + +Returns an array containing the payments and writeoffs made between two dates +C<$time> and C<$time2>, or on a specific one, or from C<$time> onwards. + +C<$time> param is mandatory. +If C<$time> eq 'today', returns are limited to the current day +If C<$time2> eq '', results are returned from C<$time> onwards. +If C<$time2> is undef, returns are limited to C<$time> +C<$spreadsheet> param is optional and controls the sorting of the results. + +Returns undef if no param is given + +=cut + sub TotalPaid { my ( $time, $time2, $spreadsheet ) = @_; + return () unless (defined $time); $time2 = $time unless $time2; my $dbh = C4::Context->dbh; my $query = "SELECT * FROM statistics LEFT JOIN borrowers ON statistics.borrowernumber= borrowers.borrowernumber WHERE (statistics.type='payment' OR statistics.type='writeoff') "; if ( $time eq 'today' ) { +# FIXME wrong condition. Now() will not get all the payments of the day but of a specific timestamp $query .= " AND datetime = now()"; } else { $query .= " AND datetime > '$time'"; # FIXME: use placeholders @@ -109,6 +178,8 @@ sub TotalPaid { if ( $time2 ne '' ) { $query .= " AND datetime < '$time2'"; # FIXME: use placeholders } +# FIXME if $time2 is undef, query will be "AND datetime > $time AND AND datetime < $time" +# Operators should probably be <= and >= if ($spreadsheet) { $query .= " ORDER BY branch, type"; } diff --git a/t/db_dependent/Stats.t b/t/db_dependent/Stats.t new file mode 100644 index 0000000..5ad9608 --- /dev/null +++ b/t/db_dependent/Stats.t @@ -0,0 +1,133 @@ +#!/usr/bin/perl + +use Modern::Perl; +use C4::Stats; + +use Test::More tests => 17; + +BEGIN { + use_ok('C4::Stats'); +} +can_ok( + 'C4::Stats', + qw(UpdateStats + TotalPaid + ) +); + +#Start transaction +my $dbh = C4::Context->dbh; +$dbh->{RaiseError} = 1; +$dbh->{AutoCommit} = 0; + +# +# Test UpdateStats +# + +is (UpdateStats () ,undef, "UpdateStats returns undef if no params"); + +my $params = { + branch => "BRA", + itemnumber => 31, + borrowernumber => 5, + amount =>5.1, + other => "bla", + itemtype => "BK", + accountno => 51, + ccode => "CODE", +}; +my $return_error; + +# returns undef and croaks if type is not allowed +$params -> {type} = "bla"; +eval {UpdateStats($params)}; +$return_error = $@; +isnt ($return_error,'',"UpdateStats returns undef and croaks if type is not allowed"); + +delete $params->{type}; +# returns undef and croaks if type is missing +eval {UpdateStats($params)}; +$return_error = $@; +isnt ($return_error,'',"UpdateStats returns undef and croaks if no type given"); + +$params -> {type} = undef; +# returns undef and croaks if type is undef +eval {UpdateStats($params)}; +$return_error = $@; +isnt ($return_error,'',"UpdateStats returns undef and croaks if type is undef"); + +# returns undef and croaks if mandatory params are missing +my @allowed_circulation_types = qw (renew issue localuse return); +my @allowed_accounts_types = qw (writeoff payment); +my @circulation_mandatory_keys = qw (branch borrowernumber itemnumber ccode itemtype); #don't check type here +my @accounts_mandatory_keys = qw (branch borrowernumber amount); #don't check type here + +my @missing_errors = (); +foreach my $key (@circulation_mandatory_keys) { + my $value = $params->{$key}; + delete $params->{$key}; + foreach my $type (@allowed_circulation_types) { + $params->{type} = $type; + eval {UpdateStats($params)}; + $return_error = $@; + push @missing_errors, "key:$key for type:$type" unless $return_error; + } + $params->{$key} = $value; +} +foreach my $key (@accounts_mandatory_keys) { + my $value = $params->{$key}; + delete $params->{$key}; + foreach my $type (@allowed_accounts_types) { + $params->{type} = $type; + eval {UpdateStats($params)}; + $return_error = $@; + push @missing_errors, "key:$key for type:$type" unless $return_error; + } + $params->{$key} = $value; + +} +is (join (", ", @missing_errors),'',"UpdateStats returns undef and croaks if mandatory params are missing"); + +# returns undef and croaks if forbidden params are given +$params -> {type} = "return"; +$params -> {newparam} = "true"; +eval {UpdateStats($params)}; +$return_error = $@; +isnt ($return_error,'',"UpdateStats returns undef and croaks if a forbidden param is given"); +delete $params->{newparam}; + +# save the params in the right database fields +$dbh->do(q|DELETE FROM statistics|); +$params = { + branch => "BRA", + itemnumber => 31, + borrowernumber => 5, + amount =>5.1, + other => "bla", + itemtype => "BK", + accountno => 51, + ccode => "CODE", + type => "return" +}; +UpdateStats ($params); +my $sth = $dbh->prepare("SELECT * FROM statistics"); +$sth->execute(); +my $line = ${ $sth->fetchall_arrayref( {} ) }[0]; +is ($params-> {branch}, $line->{branch}, "UpdateStats save branch param in branch field of statistics table"); +is ($params-> {type}, $line->{type}, "UpdateStats save type param in type field of statistics table"); +is ($params-> {borrowernumber}, $line->{borrowernumber}, "UpdateStats save borrowernumber param in borrowernumber field of statistics table"); +cmp_ok($params-> {amount},'==', $line->{value}, "UpdateStats save amount param in value field of statistics table"); +is ($params-> {other}, $line->{other}, "UpdateStats save other param in other field of statistics table"); +is ($params-> {itemtype}, $line->{itemtype}, "UpdateStats save itemtype param in itemtype field of statistics table"); +is ($params-> {accountno}, $line->{proccode}, "UpdateStats save accountno param in proccode field of statistics table"); +is ($params-> {ccode}, $line->{ccode}, "UpdateStats save ccode param in ccode field of statistics table"); + +# +# Test TotalPaid +# + +is (TotalPaid (),undef,"TotalPaid returns undef if no params are given"); +# More tests to write! + +#End transaction +$dbh->rollback; -- 1.7.9.5 -- Mathieu Saby Service d'Informatique Documentaire Service Commun de Documentation Universit? Rennes 2 T?l?phone : 02 99 14 12 65 Courriel : mathieu.saby at univ-rennes2.fr From srdjan at catalyst.net.nz Mon Nov 11 02:37:42 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Mon, 11 Nov 2013 14:37:42 +1300 Subject: [Koha-patches] [PATCH] bug_11183: get rid of some warninngs Message-ID: <1384133862-32024-1-git-send-email-srdjan@catalyst.net.nz> To test in OPAC: * Set EnableOpacSearchHistory to yes (Keep). Do an advanced search with limits. Complete search with limits should show. * Have an item with Collection Code. Check that the Collection Code shows. --- opac/opac-detail.pl | 2 +- opac/opac-search.pl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl index 41de4fd..045491e 100755 --- a/opac/opac-detail.pl +++ b/opac/opac-detail.pl @@ -573,7 +573,7 @@ for my $itm (@items) { # get collection code description, too my $ccode = $itm->{'ccode'}; - $itm->{'ccode'} = $collections->{$ccode} if ( defined($collections) && exists( $collections->{$ccode} ) ); + $itm->{'ccode'} = $collections->{$ccode} if $ccode && $collections && exists( $collections->{$ccode} ); my $copynumber = $itm->{'copynumber'}; $itm->{'copynumber'} = $copynumbers->{$copynumber} if ( defined($copynumbers) && defined($copynumber) && exists( $copynumbers->{$copynumber} ) ); if ( defined $itm->{'location'} ) { diff --git a/opac/opac-search.pl b/opac/opac-search.pl index 2854da6..8604d0f 100755 --- a/opac/opac-search.pl +++ b/opac/opac-search.pl @@ -623,7 +623,7 @@ for (my $i=0;$i<@servers;$i++) { my $query_cgi_history = $cgi->url(-query=>1); $query_cgi_history =~ s/^$path_info\?//; $query_cgi_history =~ s/;/&/g; - my $query_desc_history = "$query_desc, $limit_desc"; + my $query_desc_history = join ", ", grep { defined $_ } $query_desc, $limit_desc; if (!$borrowernumber || $borrowernumber eq '') { # To a cookie (the user is not logged in) -- 1.8.1.2 From srdjan at catalyst.net.nz Mon Nov 11 03:50:25 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Mon, 11 Nov 2013 15:50:25 +1300 Subject: [Koha-patches] [PATCH] bug_11183: get rid of some warninngs Message-ID: <1384138225-11937-1-git-send-email-srdjan@catalyst.net.nz> To test in OPAC: * Set EnableOpacSearchHistory to yes (Keep). Do an advanced search with limits. Complete search with limits should show. * Have an item with Collection Code. Check that the Collection Code shows. --- opac/opac-detail.pl | 2 +- opac/opac-search.pl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl index 41de4fd..77de12f 100755 --- a/opac/opac-detail.pl +++ b/opac/opac-detail.pl @@ -573,7 +573,7 @@ for my $itm (@items) { # get collection code description, too my $ccode = $itm->{'ccode'}; - $itm->{'ccode'} = $collections->{$ccode} if ( defined($collections) && exists( $collections->{$ccode} ) ); + $itm->{'ccode'} = $collections->{$ccode} if defined($ccode) && $collections && exists( $collections->{$ccode} ); my $copynumber = $itm->{'copynumber'}; $itm->{'copynumber'} = $copynumbers->{$copynumber} if ( defined($copynumbers) && defined($copynumber) && exists( $copynumbers->{$copynumber} ) ); if ( defined $itm->{'location'} ) { diff --git a/opac/opac-search.pl b/opac/opac-search.pl index 2854da6..8604d0f 100755 --- a/opac/opac-search.pl +++ b/opac/opac-search.pl @@ -623,7 +623,7 @@ for (my $i=0;$i<@servers;$i++) { my $query_cgi_history = $cgi->url(-query=>1); $query_cgi_history =~ s/^$path_info\?//; $query_cgi_history =~ s/;/&/g; - my $query_desc_history = "$query_desc, $limit_desc"; + my $query_desc_history = join ", ", grep { defined $_ } $query_desc, $limit_desc; if (!$borrowernumber || $borrowernumber eq '') { # To a cookie (the user is not logged in) -- 1.8.1.2 From mathieu.saby at univ-rennes2.fr Mon Nov 11 22:31:20 2013 From: mathieu.saby at univ-rennes2.fr (Mathieu Saby) Date: Mon, 11 Nov 2013 22:31:20 +0100 Subject: [Koha-patches] [PATCH] Bug 10928 - Make orders note visible when receiving an order Message-ID: <52814CA8.6020901@univ-rennes2.fr> Content-Type: text/plain; charset="utf-8" notes field is used in biblio table as well as in aqorders table, so results are messed up. The SQL query in C4:Acquisitions:SearchOrders must be changed. This is also the case for timestamp field. This patch change C4:Acquisitions:SearchOrders: - biblio.* is replaced with all fields of biblio table - except for notes, returned as biblionotes and tilmestamp as bibliotimestamp Further improvements could be made later (as suppressing useless biblio.fields from the query). To test : create an order with an order note receive this order, and check the order note is visible in the textarea dedicated to that purpose --- C4/Acquisition.pm | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm index aabc0ed..bb604e7 100644 --- a/C4/Acquisition.pm +++ b/C4/Acquisition.pm @@ -1650,7 +1650,8 @@ C<$pending> Finds pending orders. Ignores completed and cancelled orders. C<@results> is an array of references-to-hash with the keys are fields -from aqorders, biblio, biblioitems and aqbasket tables. +from aqorders, biblio, biblioitems and aqbasket tables, except for +biblio.notes returned as biblionotes and biblio.timestamp returned as bibliotimestamp. =cut @@ -1672,7 +1673,17 @@ sub SearchOrders { SELECT aqbasket.basketno, borrowers.surname, borrowers.firstname, - biblio.*, + biblio.frameworkcode, + biblio.author, + biblio.title, + biblio.unititle, + biblio.serial, + biblio.seriestitle, + biblio.copyrightdate, + biblio.datecreated, + biblio.abstract, + biblio.notes as biblionotes, + biblio.timestamp as bibliotimestamp, biblioitems.isbn, biblioitems.biblioitemnumber, aqbasket.closedate, -- 1.7.9.5 -- Mathieu Saby Service d'Informatique Documentaire Service Commun de Documentation Universit? Rennes 2 T?l?phone : 02 99 14 12 65 Courriel : mathieu.saby at univ-rennes2.fr From srdjan at catalyst.net.nz Tue Nov 12 01:23:38 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Tue, 12 Nov 2013 13:23:38 +1300 Subject: [Koha-patches] [PATCH] [SIGNED-OFF] Bug 11183 - Warnings in opac Message-ID: <1384215818-17411-1-git-send-email-srdjan@catalyst.net.nz> From: Mark Tompsett This may affect staff as well. During testing of Srdjan Jankovic's patch, the following error message was triggered: opac-search.pl: Use of uninitialized value $code_wanted in string eq at /usr/share/perl5/MARC/Field.pm line 314. This was traced to a bad call on subfields in C4::Search. By adding an if check around the call, this warning is no longer triggered. Signed-off-by: Srdjan --- C4/Search.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/C4/Search.pm b/C4/Search.pm index bec1f89..32f7c36 100644 --- a/C4/Search.pm +++ b/C4/Search.pm @@ -1835,7 +1835,9 @@ sub searchResults { # populate the items hash foreach my $code ( keys %subfieldstosearch ) { - $item->{$code} = $field->subfield( $subfieldstosearch{$code} ); + if ( defined( $subfieldstosearch{$code} ) ) { + $item->{$code} = $field->subfield( $subfieldstosearch{$code} ); + } } $item->{description} = $itemtypes{ $item->{itype} }{description}; -- 1.8.1.2 From srdjan at catalyst.net.nz Tue Nov 12 08:01:31 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Tue, 12 Nov 2013 20:01:31 +1300 Subject: [Koha-patches] [PATCH] bug_11182: get rid of some warnings Message-ID: <1384239691-26688-1-git-send-email-srdjan@catalyst.net.nz> To test - circulation: * For a child patron, check that "Upgrade to adult" link on the "More" drop-down is clickable * Set sys pref FineNotifyAtCheckin to yes (Notify), and check in an overdue item that attracts fine. Fine amount should be displayed. --- circ/circulation.pl | 2 +- circ/returns.pl | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/circ/circulation.pl b/circ/circulation.pl index 9769731..8f7068a 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -482,7 +482,7 @@ sub build_issue_data { ($it->{'charge'}, $it->{'itemtype_charge'}) = GetIssuingCharges( $it->{'itemnumber'}, $it->{'borrowernumber'} ); - $it->{'charge'} = sprintf("%.2f", $it->{'charge'}); + $it->{'charge'} = sprintf("%.2f", $it->{'charge'}) if defined $it->{'charge'}; my ($can_renew, $can_renew_error) = CanBookBeRenewed( $it->{'borrowernumber'},$it->{'itemnumber'} ); diff --git a/circ/returns.pl b/circ/returns.pl index 93f36f2..fb1ca40 100755 --- a/circ/returns.pl +++ b/circ/returns.pl @@ -49,7 +49,8 @@ use Koha::Calendar; my $query = new CGI; -if (!C4::Context->userenv){ +my $userenv = C4::Context->userenv; +if (!$userenv){ my $sessionID = $query->cookie("CGISESSID"); my $session = get_session($sessionID); if ($session->param('branch') eq 'NO_LIBRARY_SET'){ @@ -74,11 +75,10 @@ my ( $template, $librarian, $cookie ) = get_template_and_user( #Global vars my $branches = GetBranches(); my $printers = GetPrinters(); +my $userenv_branch = $userenv->{'branch'} // ''; +my $printer = $userenv->{'branchprinter'} // ''; -my $printer = C4::Context->userenv ? C4::Context->userenv->{'branchprinter'} : ""; my $overduecharges = (C4::Context->preference('finesMode') && C4::Context->preference('finesMode') ne 'off'); - -my $userenv_branch = C4::Context->userenv->{'branch'} || ''; # # Some code to handle the error if there is no branch or printer setting..... # @@ -266,7 +266,7 @@ if ($barcode) { if ( C4::Context->preference("FineNotifyAtCheckin") ) { my ( $od, $issue, $fines ) = GetMemberIssuesAndFines( $borrower->{'borrowernumber'} ); - if ($fines > 0) { + if ($fines && $fines > 0) { $template->param( fines => sprintf("%.2f",$fines) ); $template->param( fineborrowernumber => $borrower->{'borrowernumber'} ); } -- 1.8.1.2 From srdjan at catalyst.net.nz Tue Nov 12 08:15:52 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Tue, 12 Nov 2013 20:15:52 +1300 Subject: [Koha-patches] [PATCH] bug_11182: get rid of some warnings Message-ID: <1384240552-28643-1-git-send-email-srdjan@catalyst.net.nz> To test - circulation: * For a child patron, check that "Upgrade to adult" link on the "More" drop-down is clickable * Set sys pref FineNotifyAtCheckin to yes (Notify), and check in an overdue item that attracts fine. Fine amount should be displayed. --- circ/circulation.pl | 2 +- circ/returns.pl | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/circ/circulation.pl b/circ/circulation.pl index 9769731..8f7068a 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -482,7 +482,7 @@ sub build_issue_data { ($it->{'charge'}, $it->{'itemtype_charge'}) = GetIssuingCharges( $it->{'itemnumber'}, $it->{'borrowernumber'} ); - $it->{'charge'} = sprintf("%.2f", $it->{'charge'}); + $it->{'charge'} = sprintf("%.2f", $it->{'charge'}) if defined $it->{'charge'}; my ($can_renew, $can_renew_error) = CanBookBeRenewed( $it->{'borrowernumber'},$it->{'itemnumber'} ); diff --git a/circ/returns.pl b/circ/returns.pl index 93f36f2..9abe985 100755 --- a/circ/returns.pl +++ b/circ/returns.pl @@ -49,7 +49,8 @@ use Koha::Calendar; my $query = new CGI; -if (!C4::Context->userenv){ +my $userenv = C4::Context->userenv; +if (!$userenv){ my $sessionID = $query->cookie("CGISESSID"); my $session = get_session($sessionID); if ($session->param('branch') eq 'NO_LIBRARY_SET'){ @@ -74,11 +75,10 @@ my ( $template, $librarian, $cookie ) = get_template_and_user( #Global vars my $branches = GetBranches(); my $printers = GetPrinters(); +my $userenv_branch = $userenv->{'branch'} // ''; +my $printer = $userenv->{'branchprinter'} // ''; -my $printer = C4::Context->userenv ? C4::Context->userenv->{'branchprinter'} : ""; my $overduecharges = (C4::Context->preference('finesMode') && C4::Context->preference('finesMode') ne 'off'); - -my $userenv_branch = C4::Context->userenv->{'branch'} || ''; # # Some code to handle the error if there is no branch or printer setting..... # @@ -266,7 +266,7 @@ if ($barcode) { if ( C4::Context->preference("FineNotifyAtCheckin") ) { my ( $od, $issue, $fines ) = GetMemberIssuesAndFines( $borrower->{'borrowernumber'} ); - if ($fines > 0) { + if ($fines && $fines > 0) { $template->param( fines => sprintf("%.2f",$fines) ); $template->param( fineborrowernumber => $borrower->{'borrowernumber'} ); } @@ -536,11 +536,18 @@ foreach ( sort { $a <=> $b } keys %returneditems ) { } push @riloop, \%ri; } +my ($genbrname, $genprname); +if (my $b = $branches->{$userenv_branch}) { + $genbrname = $b->{'branchname'}; +} +if (my $p = $printers->{$printer}) { + $genprname = $p->{'printername'}; +} $template->param( riloop => \@riloop, - genbrname => $branches->{$userenv_branch}->{'branchname'}, - genprname => $printers->{$printer}->{'printername'}, - branchname => $branches->{$userenv_branch}->{'branchname'}, + genbrname => $genbrname, + genprname => $genprname, + branchname => $genbrname, printer => $printer, errmsgloop => \@errmsgloop, exemptfine => $exemptfine, -- 1.8.1.2 From srdjan at catalyst.net.nz Tue Nov 12 08:59:12 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Tue, 12 Nov 2013 20:59:12 +1300 Subject: [Koha-patches] [PATCH] bug_11183: Supress undef warning in opac-MARCdetail.pl Message-ID: <1384243152-1367-1-git-send-email-srdjan@catalyst.net.nz> To test: * Go to /cgi-bin/koha/opac-MARCdetail.pl?biblionumber= and confirm that pre and post patch page looks the same. An apology: I tried to find a syspref combination that displays opac-MARCdetail.pl links in OPAC search results, and failed. If anyone knows, the secret combination, please disclose. I resorted to entering the url by hand. --- opac/opac-MARCdetail.pl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/opac/opac-MARCdetail.pl b/opac/opac-MARCdetail.pl index d6be0a6..aa72a3e 100755 --- a/opac/opac-MARCdetail.pl +++ b/opac/opac-MARCdetail.pl @@ -176,8 +176,9 @@ for ( my $tabloop = 0 ; $tabloop <= 9 ; $tabloop++ ) { next if ( ($sf_def->{tab}||0) != $tabloop ); next if ( ($sf_def->{hidden}||0) > 0 ); my %subfield_data; - $subfield_data{marc_lib} = ($sf_def->{lib} eq $previous) ? '--' : $sf_def->{lib}; - $previous = $sf_def->{lib}; + my $lib = $sf_def->{lib} // ''; + $subfield_data{marc_lib} = ($lib eq $previous) ? '--' : $sf_def->{lib}; + $previous = $lib; $subfield_data{link} = $sf_def->{link}; $subf[$i][1] =~ s/\n//g; if ( $sf_def->{isurl} ) { -- 1.8.1.2 From srdjan at catalyst.net.nz Tue Nov 12 09:07:27 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Tue, 12 Nov 2013 21:07:27 +1300 Subject: [Koha-patches] [PATCH] bug_11183: Supress undef warning in opac-MARCdetail.pl Message-ID: <1384243647-2711-1-git-send-email-srdjan@catalyst.net.nz> To test: * Go to /cgi-bin/koha/opac-MARCdetail.pl?biblionumber= and confirm that pre and post patch page looks the same. An apology: I tried to find a syspref combination that displays opac-MARCdetail.pl links in OPAC search results, and failed. If anyone knows, the secret combination, please disclose. I resorted to entering the url by hand. --- opac/opac-MARCdetail.pl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/opac/opac-MARCdetail.pl b/opac/opac-MARCdetail.pl index d6be0a6..bb19998 100755 --- a/opac/opac-MARCdetail.pl +++ b/opac/opac-MARCdetail.pl @@ -176,8 +176,9 @@ for ( my $tabloop = 0 ; $tabloop <= 9 ; $tabloop++ ) { next if ( ($sf_def->{tab}||0) != $tabloop ); next if ( ($sf_def->{hidden}||0) > 0 ); my %subfield_data; - $subfield_data{marc_lib} = ($sf_def->{lib} eq $previous) ? '--' : $sf_def->{lib}; - $previous = $sf_def->{lib}; + my $lib = $sf_def->{lib} // ''; + $subfield_data{marc_lib} = ($lib eq $previous) ? '--' : $sf_def->{lib}; + $previous = $lib; $subfield_data{link} = $sf_def->{link}; $subf[$i][1] =~ s/\n//g; if ( $sf_def->{isurl} ) { @@ -211,12 +212,13 @@ for ( my $tabloop = 0 ; $tabloop <= 9 ; $tabloop++ ) { $tag_data{tag} = $tagslib->{ $fields[$x_i]->tag() }->{lib}; } else { + my $tag = $fields[$x_i]->tag(); $tag_data{tag} = - $fields[$x_i]->tag() + $tag . ' ' . C4::Koha::display_marc_indicators($fields[$x_i]) . ' - ' - . $tagslib->{ $fields[$x_i]->tag() }->{lib}; + . ($tagslib->{ $tag }->{lib} // ''); } } my @tmp = @subfields_data; -- 1.8.1.2 From srdjan at catalyst.net.nz Thu Nov 14 07:19:47 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Thu, 14 Nov 2013 19:19:47 +1300 Subject: [Koha-patches] [PATCH] bug_11247: Removed unused params from TransformHtmlToXml() Message-ID: <1384409987-32299-1-git-send-email-srdjan@catalyst.net.nz> $indicator and $ind_tag should not be TransformHtmlToXml() params. TransformHtmlToXml() is only used for items: - $indicator is always empty - $ind_tag was not even used in the function To test: Check that integrity of following functions is preserved: * Acquisition - ordering and receiving, needs setting AcqCreateItem to placing and receiving an order * Cataloging - create/modify an item * Batcih modify in Tools * Serials receiving --- C4/Biblio.pm | 31 +++++-------------------------- acqui/addorder.pl | 7 +------ acqui/addorderiso2709.pl | 6 +----- acqui/finishreceive.pl | 7 +------ cataloguing/additem.pl | 26 ++------------------------ serials/serials-edit.pl | 6 ------ tools/batchMod.pl | 21 +-------------------- 7 files changed, 11 insertions(+), 93 deletions(-) diff --git a/C4/Biblio.pm b/C4/Biblio.pm index add0f74..9428f47 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -2203,8 +2203,7 @@ sub PrepHostMarcField { =head2 TransformHtmlToXml - $xml = TransformHtmlToXml( $tags, $subfields, $values, $indicator, - $ind_tag, $auth_type ) + $xml = TransformHtmlToXml( $tags, $subfields, $values, $indicator, $auth_type ) $auth_type contains : @@ -2221,7 +2220,7 @@ $auth_type contains : =cut sub TransformHtmlToXml { - my ( $tags, $subfields, $values, $indicator, $ind_tag, $auth_type ) = @_; + my ( $tags, $subfields, $values, $auth_type ) = @_; my $xml = MARC::File::XML::header('UTF-8'); $xml .= "\n"; $auth_type = C4::Context->preference('marcflavour') unless $auth_type; @@ -2260,21 +2259,11 @@ sub TransformHtmlToXml { # } if ( ( @$tags[$i] ne $prevtag ) ) { $j++ unless ( @$tags[$i] eq "" ); - my $indicator1 = eval { substr( @$indicator[$j], 0, 1 ) }; - my $indicator2 = eval { substr( @$indicator[$j], 1, 1 ) }; - my $ind1 = _default_ind_to_space($indicator1); - my $ind2; - if ( @$indicator[$j] ) { - $ind2 = _default_ind_to_space($indicator2); - } else { - warn "Indicator in @$tags[$i] is empty"; - $ind2 = " "; - } if ( !$first ) { $xml .= "\n"; if ( ( @$tags[$i] && @$tags[$i] > 10 ) && ( @$values[$i] ne "" ) ) { - $xml .= "\n"; + $xml .= "\n"; $xml .= "@$values[$i]\n"; $first = 0; } else { @@ -2293,27 +2282,17 @@ sub TransformHtmlToXml { $xml .= "@$values[$i]\n"; $first = 1; } else { - $xml .= "\n"; + $xml .= "\n"; $xml .= "@$values[$i]\n"; $first = 0; } } } } else { # @$tags[$i] eq $prevtag - my $indicator1 = eval { substr( @$indicator[$j], 0, 1 ) }; - my $indicator2 = eval { substr( @$indicator[$j], 1, 1 ) }; - my $ind1 = _default_ind_to_space($indicator1); - my $ind2; - if ( @$indicator[$j] ) { - $ind2 = _default_ind_to_space($indicator2); - } else { - warn "Indicator in @$tags[$i] is empty"; - $ind2 = " "; - } if ( @$values[$i] eq "" ) { } else { if ($first) { - $xml .= "\n"; + $xml .= "\n"; $first = 0; } $xml .= "@$values[$i]\n"; diff --git a/acqui/addorder.pl b/acqui/addorder.pl index 1b05f07..ecbe68c 100755 --- a/acqui/addorder.pl +++ b/acqui/addorder.pl @@ -286,8 +286,6 @@ if ( $orderinfo->{quantity} ne '0' ) { my @field_values = $input->param('field_value'); my @serials = $input->param('serial'); my @itemid = $input->param('itemid'); - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); #Rebuilding ALL the data for items into a hash # parting them on $itemid. @@ -301,16 +299,13 @@ if ( $orderinfo->{quantity} ne '0' ) { push @{$itemhash{$itemid[$i]}->{'tags'}},$tags[$i]; push @{$itemhash{$itemid[$i]}->{'subfields'}},$subfields[$i]; push @{$itemhash{$itemid[$i]}->{'field_values'}},$field_values[$i]; - push @{$itemhash{$itemid[$i]}->{'ind_tag'}},$ind_tag[$i]; - push @{$itemhash{$itemid[$i]}->{'indicator'}},$indicator[$i]; } foreach my $item (keys %itemhash){ + use Data::Dumper; die Dumper($itemhash{$item}); my $xml = TransformHtmlToXml( $itemhash{$item}->{'tags'}, $itemhash{$item}->{'subfields'}, $itemhash{$item}->{'field_values'}, - $itemhash{$item}->{'ind_tag'}, - $itemhash{$item}->{'indicator'}, 'ITEM'); my $record=MARC::Record::new_from_xml($xml, 'UTF-8'); my ($biblionumber,$bibitemnum,$itemnumber) = AddItemFromMarc($record,$$orderinfo{biblionumber}); diff --git a/acqui/addorderiso2709.pl b/acqui/addorderiso2709.pl index abfb870..e615c4f 100755 --- a/acqui/addorderiso2709.pl +++ b/acqui/addorderiso2709.pl @@ -244,15 +244,11 @@ if ($op eq ""){ my @subfields = $input->param('subfield'); my @field_values = $input->param('field_value'); my @serials = $input->param('serial'); - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); my $item; push @{ $item->{tags} }, $tags[0]; push @{ $item->{subfields} }, $subfields[0]; push @{ $item->{field_values} }, $field_values[0]; - push @{ $item->{ind_tag} }, $ind_tag[0]; - push @{ $item->{indicator} }, $indicator[0]; - my $xml = TransformHtmlToXml( \@tags, \@subfields, \@field_values, \@ind_tag, \@indicator ); + my $xml = TransformHtmlToXml( \@tags, \@subfields, \@field_values ); my $record = MARC::Record::new_from_xml( $xml, 'UTF-8' ); for (my $qtyloop=1;$qtyloop <=$quantity;$qtyloop++) { my ( $biblionumber, $bibitemnum, $itemnumber ) = AddItemFromMarc( $record, $biblionumber ); diff --git a/acqui/finishreceive.pl b/acqui/finishreceive.pl index 900733d..7c28afd 100755 --- a/acqui/finishreceive.pl +++ b/acqui/finishreceive.pl @@ -123,8 +123,6 @@ if ($quantityrec > $origquantityrec ) { my @field_values = $input->param('field_value'); my @serials = $input->param('serial'); my @itemid = $input->param('itemid'); - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); #Rebuilding ALL the data for items into a hash # parting them on $itemid. my %itemhash; @@ -137,15 +135,12 @@ if ($quantityrec > $origquantityrec ) { push @{$itemhash{$itemid[$i]}->{'tags'}},$tags[$i]; push @{$itemhash{$itemid[$i]}->{'subfields'}},$subfields[$i]; push @{$itemhash{$itemid[$i]}->{'field_values'}},$field_values[$i]; - push @{$itemhash{$itemid[$i]}->{'ind_tag'}},$ind_tag[$i]; - push @{$itemhash{$itemid[$i]}->{'indicator'}},$indicator[$i]; } foreach my $item (keys %itemhash){ my $xml = TransformHtmlToXml( $itemhash{$item}->{'tags'}, $itemhash{$item}->{'subfields'}, $itemhash{$item}->{'field_values'}, - $itemhash{$item}->{'ind_tag'}, - $itemhash{$item}->{'indicator'},'ITEM'); + 'ITEM'); my $record=MARC::Record::new_from_xml($xml, 'UTF-8'); my (undef,$bibitemnum,$itemnumber) = AddItemFromMarc($record,$biblionumber); NewOrderItem($itemnumber, $new_ordernumber); diff --git a/cataloguing/additem.pl b/cataloguing/additem.pl index a819019..ed1ea9b 100755 --- a/cataloguing/additem.pl +++ b/cataloguing/additem.pl @@ -43,22 +43,6 @@ use URI::Escape; our $dbh = C4::Context->dbh; -sub find_value { - my ($tagfield,$insubfield,$record) = @_; - my $result; - my $indicator; - foreach my $field ($record->field($tagfield)) { - my @subfields = $field->subfields(); - foreach my $subfield (@subfields) { - if (@$subfield[0] eq $insubfield) { - $result .= @$subfield[1]; - $indicator = $field->indicator(1).$field->indicator(2); - } - } - } - return($indicator,$result); -} - sub get_item_from_barcode { my ($barcode)=@_; my $dbh=C4::Context->dbh; @@ -377,10 +361,7 @@ if ($op eq "additem") { my @tags = $input->param('tag'); my @subfields = $input->param('subfield'); my @values = $input->param('field_value'); - # build indicator hash. - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); - my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag, 'ITEM'); + my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values, 'ITEM'); my $record = MARC::Record::new_from_xml($xml, 'UTF-8'); # type of add @@ -585,11 +566,8 @@ if ($op eq "additem") { my @tags = $input->param('tag'); my @subfields = $input->param('subfield'); my @values = $input->param('field_value'); - # build indicator hash. - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); # my $itemnumber = $input->param('itemnumber'); - my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag,'ITEM'); + my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,'ITEM'); my $itemtosave=MARC::Record::new_from_xml($xml, 'UTF-8'); # MARC::Record builded => now, record in DB # warn "R: ".$record->as_formatted; diff --git a/serials/serials-edit.pl b/serials/serials-edit.pl index 8fb2e60..a3adef7 100755 --- a/serials/serials-edit.pl +++ b/serials/serials-edit.pl @@ -251,8 +251,6 @@ if ( $op and $op eq 'serialchangestatus' ) { my @serials = $query->param('serial'); my @bibnums = $query->param('bibnum'); my @itemid = $query->param('itemid'); - my @ind_tag = $query->param('ind_tag'); - my @indicator = $query->param('indicator'); #Rebuilding ALL the data for items into a hash # parting them on $itemid. @@ -277,8 +275,6 @@ if ( $op and $op eq 'serialchangestatus' ) { push @{ $itemhash{ $itemid[$i] }->{'subfields'} }, $subfields[$i]; push @{ $itemhash{ $itemid[$i] }->{'field_values'} }, $field_values[$i]; - push @{ $itemhash{ $itemid[$i] }->{'ind_tag'} }, $ind_tag[$i]; - push @{ $itemhash{ $itemid[$i] }->{'indicator'} }, $indicator[$i]; } foreach my $item ( keys %itemhash ) { @@ -298,8 +294,6 @@ if ( $op and $op eq 'serialchangestatus' ) { $itemhash{$item}->{'tags'}, $itemhash{$item}->{'subfields'}, $itemhash{$item}->{'field_values'}, - $itemhash{$item}->{'indicator'}, - $itemhash{$item}->{'ind_tag'} ); # warn $xml; diff --git a/tools/batchMod.pl b/tools/batchMod.pl index 69762b1..349730c 100755 --- a/tools/batchMod.pl +++ b/tools/batchMod.pl @@ -98,9 +98,6 @@ if ($op eq "action") { my @subfields = $input->param('subfield'); my @values = $input->param('field_value'); my @disabled = $input->param('disable_input'); - # build indicator hash. - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); # Is there something to modify ? # TODO : We shall use this var to warn the user in case no modification was done to the items @@ -140,7 +137,7 @@ if ($op eq "action") { #initializing values for updates my ( $itemtagfield, $itemtagsubfield) = &GetMarcFromKohaField("items.itemnumber", ""); if ($values_to_modify){ - my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag, 'ITEM'); + my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values, 'ITEM'); utf8::encode($xml); $marcitem = MARC::Record::new_from_xml($xml, 'UTF-8'); } @@ -595,22 +592,6 @@ sub UpdateMarcWith { return $modified; } -sub find_value { - my ($tagfield,$insubfield,$record) = @_; - my $result; - my $indicator; - foreach my $field ($record->field($tagfield)) { - my @subfields = $field->subfields(); - foreach my $subfield (@subfields) { - if (@$subfield[0] eq $insubfield) { - $result .= @$subfield[1]; - $indicator = $field->indicator(1).$field->indicator(2); - } - } - } - return($indicator,$result); -} - # ---------------------------- # Background functions -- 1.8.1.2 From srdjan at catalyst.net.nz Thu Nov 14 07:23:51 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Thu, 14 Nov 2013 19:23:51 +1300 Subject: [Koha-patches] [PATCH] bug_11247: Removed unused params from TransformHtmlToXml() Message-ID: <1384410231-646-1-git-send-email-srdjan@catalyst.net.nz> $indicator and $ind_tag should not be TransformHtmlToXml() params. TransformHtmlToXml() is only used for items: - $indicator is always empty - $ind_tag was not even used in the function To test: Check that integrity of following functions is preserved: * Acquisition - ordering and receiving, needs setting AcqCreateItem to placing and receiving an order * Cataloging - create/modify an item * Batcih modify in Tools * Serials receiving --- C4/Biblio.pm | 31 +++++-------------------------- acqui/addorder.pl | 7 +------ acqui/addorderiso2709.pl | 6 +----- acqui/finishreceive.pl | 7 +------ cataloguing/additem.pl | 26 ++------------------------ serials/serials-edit.pl | 6 ------ tools/batchMod.pl | 21 +-------------------- 7 files changed, 11 insertions(+), 93 deletions(-) diff --git a/C4/Biblio.pm b/C4/Biblio.pm index add0f74..12a6415 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -2203,8 +2203,7 @@ sub PrepHostMarcField { =head2 TransformHtmlToXml - $xml = TransformHtmlToXml( $tags, $subfields, $values, $indicator, - $ind_tag, $auth_type ) + $xml = TransformHtmlToXml( $tags, $subfields, $values, $auth_type ) $auth_type contains : @@ -2221,7 +2220,7 @@ $auth_type contains : =cut sub TransformHtmlToXml { - my ( $tags, $subfields, $values, $indicator, $ind_tag, $auth_type ) = @_; + my ( $tags, $subfields, $values, $auth_type ) = @_; my $xml = MARC::File::XML::header('UTF-8'); $xml .= "\n"; $auth_type = C4::Context->preference('marcflavour') unless $auth_type; @@ -2260,21 +2259,11 @@ sub TransformHtmlToXml { # } if ( ( @$tags[$i] ne $prevtag ) ) { $j++ unless ( @$tags[$i] eq "" ); - my $indicator1 = eval { substr( @$indicator[$j], 0, 1 ) }; - my $indicator2 = eval { substr( @$indicator[$j], 1, 1 ) }; - my $ind1 = _default_ind_to_space($indicator1); - my $ind2; - if ( @$indicator[$j] ) { - $ind2 = _default_ind_to_space($indicator2); - } else { - warn "Indicator in @$tags[$i] is empty"; - $ind2 = " "; - } if ( !$first ) { $xml .= "\n"; if ( ( @$tags[$i] && @$tags[$i] > 10 ) && ( @$values[$i] ne "" ) ) { - $xml .= "\n"; + $xml .= "\n"; $xml .= "@$values[$i]\n"; $first = 0; } else { @@ -2293,27 +2282,17 @@ sub TransformHtmlToXml { $xml .= "@$values[$i]\n"; $first = 1; } else { - $xml .= "\n"; + $xml .= "\n"; $xml .= "@$values[$i]\n"; $first = 0; } } } } else { # @$tags[$i] eq $prevtag - my $indicator1 = eval { substr( @$indicator[$j], 0, 1 ) }; - my $indicator2 = eval { substr( @$indicator[$j], 1, 1 ) }; - my $ind1 = _default_ind_to_space($indicator1); - my $ind2; - if ( @$indicator[$j] ) { - $ind2 = _default_ind_to_space($indicator2); - } else { - warn "Indicator in @$tags[$i] is empty"; - $ind2 = " "; - } if ( @$values[$i] eq "" ) { } else { if ($first) { - $xml .= "\n"; + $xml .= "\n"; $first = 0; } $xml .= "@$values[$i]\n"; diff --git a/acqui/addorder.pl b/acqui/addorder.pl index 1b05f07..ecbe68c 100755 --- a/acqui/addorder.pl +++ b/acqui/addorder.pl @@ -286,8 +286,6 @@ if ( $orderinfo->{quantity} ne '0' ) { my @field_values = $input->param('field_value'); my @serials = $input->param('serial'); my @itemid = $input->param('itemid'); - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); #Rebuilding ALL the data for items into a hash # parting them on $itemid. @@ -301,16 +299,13 @@ if ( $orderinfo->{quantity} ne '0' ) { push @{$itemhash{$itemid[$i]}->{'tags'}},$tags[$i]; push @{$itemhash{$itemid[$i]}->{'subfields'}},$subfields[$i]; push @{$itemhash{$itemid[$i]}->{'field_values'}},$field_values[$i]; - push @{$itemhash{$itemid[$i]}->{'ind_tag'}},$ind_tag[$i]; - push @{$itemhash{$itemid[$i]}->{'indicator'}},$indicator[$i]; } foreach my $item (keys %itemhash){ + use Data::Dumper; die Dumper($itemhash{$item}); my $xml = TransformHtmlToXml( $itemhash{$item}->{'tags'}, $itemhash{$item}->{'subfields'}, $itemhash{$item}->{'field_values'}, - $itemhash{$item}->{'ind_tag'}, - $itemhash{$item}->{'indicator'}, 'ITEM'); my $record=MARC::Record::new_from_xml($xml, 'UTF-8'); my ($biblionumber,$bibitemnum,$itemnumber) = AddItemFromMarc($record,$$orderinfo{biblionumber}); diff --git a/acqui/addorderiso2709.pl b/acqui/addorderiso2709.pl index abfb870..e615c4f 100755 --- a/acqui/addorderiso2709.pl +++ b/acqui/addorderiso2709.pl @@ -244,15 +244,11 @@ if ($op eq ""){ my @subfields = $input->param('subfield'); my @field_values = $input->param('field_value'); my @serials = $input->param('serial'); - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); my $item; push @{ $item->{tags} }, $tags[0]; push @{ $item->{subfields} }, $subfields[0]; push @{ $item->{field_values} }, $field_values[0]; - push @{ $item->{ind_tag} }, $ind_tag[0]; - push @{ $item->{indicator} }, $indicator[0]; - my $xml = TransformHtmlToXml( \@tags, \@subfields, \@field_values, \@ind_tag, \@indicator ); + my $xml = TransformHtmlToXml( \@tags, \@subfields, \@field_values ); my $record = MARC::Record::new_from_xml( $xml, 'UTF-8' ); for (my $qtyloop=1;$qtyloop <=$quantity;$qtyloop++) { my ( $biblionumber, $bibitemnum, $itemnumber ) = AddItemFromMarc( $record, $biblionumber ); diff --git a/acqui/finishreceive.pl b/acqui/finishreceive.pl index 900733d..7c28afd 100755 --- a/acqui/finishreceive.pl +++ b/acqui/finishreceive.pl @@ -123,8 +123,6 @@ if ($quantityrec > $origquantityrec ) { my @field_values = $input->param('field_value'); my @serials = $input->param('serial'); my @itemid = $input->param('itemid'); - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); #Rebuilding ALL the data for items into a hash # parting them on $itemid. my %itemhash; @@ -137,15 +135,12 @@ if ($quantityrec > $origquantityrec ) { push @{$itemhash{$itemid[$i]}->{'tags'}},$tags[$i]; push @{$itemhash{$itemid[$i]}->{'subfields'}},$subfields[$i]; push @{$itemhash{$itemid[$i]}->{'field_values'}},$field_values[$i]; - push @{$itemhash{$itemid[$i]}->{'ind_tag'}},$ind_tag[$i]; - push @{$itemhash{$itemid[$i]}->{'indicator'}},$indicator[$i]; } foreach my $item (keys %itemhash){ my $xml = TransformHtmlToXml( $itemhash{$item}->{'tags'}, $itemhash{$item}->{'subfields'}, $itemhash{$item}->{'field_values'}, - $itemhash{$item}->{'ind_tag'}, - $itemhash{$item}->{'indicator'},'ITEM'); + 'ITEM'); my $record=MARC::Record::new_from_xml($xml, 'UTF-8'); my (undef,$bibitemnum,$itemnumber) = AddItemFromMarc($record,$biblionumber); NewOrderItem($itemnumber, $new_ordernumber); diff --git a/cataloguing/additem.pl b/cataloguing/additem.pl index a819019..ed1ea9b 100755 --- a/cataloguing/additem.pl +++ b/cataloguing/additem.pl @@ -43,22 +43,6 @@ use URI::Escape; our $dbh = C4::Context->dbh; -sub find_value { - my ($tagfield,$insubfield,$record) = @_; - my $result; - my $indicator; - foreach my $field ($record->field($tagfield)) { - my @subfields = $field->subfields(); - foreach my $subfield (@subfields) { - if (@$subfield[0] eq $insubfield) { - $result .= @$subfield[1]; - $indicator = $field->indicator(1).$field->indicator(2); - } - } - } - return($indicator,$result); -} - sub get_item_from_barcode { my ($barcode)=@_; my $dbh=C4::Context->dbh; @@ -377,10 +361,7 @@ if ($op eq "additem") { my @tags = $input->param('tag'); my @subfields = $input->param('subfield'); my @values = $input->param('field_value'); - # build indicator hash. - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); - my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag, 'ITEM'); + my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values, 'ITEM'); my $record = MARC::Record::new_from_xml($xml, 'UTF-8'); # type of add @@ -585,11 +566,8 @@ if ($op eq "additem") { my @tags = $input->param('tag'); my @subfields = $input->param('subfield'); my @values = $input->param('field_value'); - # build indicator hash. - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); # my $itemnumber = $input->param('itemnumber'); - my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag,'ITEM'); + my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,'ITEM'); my $itemtosave=MARC::Record::new_from_xml($xml, 'UTF-8'); # MARC::Record builded => now, record in DB # warn "R: ".$record->as_formatted; diff --git a/serials/serials-edit.pl b/serials/serials-edit.pl index 8fb2e60..a3adef7 100755 --- a/serials/serials-edit.pl +++ b/serials/serials-edit.pl @@ -251,8 +251,6 @@ if ( $op and $op eq 'serialchangestatus' ) { my @serials = $query->param('serial'); my @bibnums = $query->param('bibnum'); my @itemid = $query->param('itemid'); - my @ind_tag = $query->param('ind_tag'); - my @indicator = $query->param('indicator'); #Rebuilding ALL the data for items into a hash # parting them on $itemid. @@ -277,8 +275,6 @@ if ( $op and $op eq 'serialchangestatus' ) { push @{ $itemhash{ $itemid[$i] }->{'subfields'} }, $subfields[$i]; push @{ $itemhash{ $itemid[$i] }->{'field_values'} }, $field_values[$i]; - push @{ $itemhash{ $itemid[$i] }->{'ind_tag'} }, $ind_tag[$i]; - push @{ $itemhash{ $itemid[$i] }->{'indicator'} }, $indicator[$i]; } foreach my $item ( keys %itemhash ) { @@ -298,8 +294,6 @@ if ( $op and $op eq 'serialchangestatus' ) { $itemhash{$item}->{'tags'}, $itemhash{$item}->{'subfields'}, $itemhash{$item}->{'field_values'}, - $itemhash{$item}->{'indicator'}, - $itemhash{$item}->{'ind_tag'} ); # warn $xml; diff --git a/tools/batchMod.pl b/tools/batchMod.pl index 69762b1..349730c 100755 --- a/tools/batchMod.pl +++ b/tools/batchMod.pl @@ -98,9 +98,6 @@ if ($op eq "action") { my @subfields = $input->param('subfield'); my @values = $input->param('field_value'); my @disabled = $input->param('disable_input'); - # build indicator hash. - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); # Is there something to modify ? # TODO : We shall use this var to warn the user in case no modification was done to the items @@ -140,7 +137,7 @@ if ($op eq "action") { #initializing values for updates my ( $itemtagfield, $itemtagsubfield) = &GetMarcFromKohaField("items.itemnumber", ""); if ($values_to_modify){ - my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag, 'ITEM'); + my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values, 'ITEM'); utf8::encode($xml); $marcitem = MARC::Record::new_from_xml($xml, 'UTF-8'); } @@ -595,22 +592,6 @@ sub UpdateMarcWith { return $modified; } -sub find_value { - my ($tagfield,$insubfield,$record) = @_; - my $result; - my $indicator; - foreach my $field ($record->field($tagfield)) { - my @subfields = $field->subfields(); - foreach my $subfield (@subfields) { - if (@$subfield[0] eq $insubfield) { - $result .= @$subfield[1]; - $indicator = $field->indicator(1).$field->indicator(2); - } - } - } - return($indicator,$result); -} - # ---------------------------- # Background functions -- 1.8.1.2 From dpavlin at rot13.org Thu Nov 14 13:15:43 2013 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Thu, 14 Nov 2013 12:15:43 -0000 Subject: [Koha-patches] [PATCH] Bug 10451 - Firefox prints only first page of table with shrink to fit option Message-ID: <1371049404-27406-1-git-send-email-dpavlin@rot13.org> According to Firefox bug tracker, versions up to 21 doesn't print tables correctly when using shrink to fit option. See: https://bugzilla.mozilla.org/show_bug.cgi?id=684622 However, even with v21 or newer, we still need to add css to print media which instruct it not to break table tag to print all pages of table. This has a side-effect that table starts always on next page, wasting some space on first printed page. --- koha-tmpl/intranet-tmpl/prog/en/css/print.css | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/print.css b/koha-tmpl/intranet-tmpl/prog/en/css/print.css index 239059c..203ca55 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/print.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/print.css @@ -95,6 +95,8 @@ table { margin : 3px 0px 5px 0px; padding : 0px; width : 99%; + /* tries to fix firefox 21+ shrink-to-fit */ + page-break-inside: avoid; } table.list { -- 1.7.2.5 From dpavlin at rot13.org Thu Nov 14 13:19:54 2013 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Thu, 14 Nov 2013 12:19:54 -0000 Subject: [Koha-patches] [PATCH] Bug 10670 - koha-common fails to start zebra without log permissions Message-ID: <1375357508-25901-1-git-send-email-dpavlin@rot13.org> If koha-common is started when zebra log files are owned by root it will fail to start without any useful message (since zebra can't write errors in log files because it lacks permissions to do so). This patch creates empty log files and ensure they have correct permissions. I can't pin-point why log files gets owned root, but I suspect it has something to do with zebra crashing and logrotate, but this is just theory. We have seen this behaviour since koha 3.1 every few months, and every time it happends we have root owned logs and crashed zebra so this patch will at least help sites which have some kind of automatic koha-common start if it's not running. --- debian/scripts/koha-start-zebra | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/debian/scripts/koha-start-zebra b/debian/scripts/koha-start-zebra index 222b0ef..f63ab42 100755 --- a/debian/scripts/koha-start-zebra +++ b/debian/scripts/koha-start-zebra @@ -77,6 +77,13 @@ start_zebra_instance() if is_enabled $instancename; then echo "Starting Zebra server for $instancename" + touch "/var/log/koha/$instancename/zebra-error.log" \ + "/var/log/koha/$instancename/zebra.log" \ + "/var/log/koha/$instancename/zebra-output.log" + chown "$instancename-koha:$instancename-koha" \ + "/var/log/koha/$instancename/zebra-error.log" \ + "/var/log/koha/$instancename/zebra.log" \ + "/var/log/koha/$instancename/zebra-output.log" daemon \ --name="$instancename-koha-zebra" \ --errlog="/var/log/koha/$instancename/zebra-error.log" \ -- 1.7.2.5 From dpavlin at rot13.org Thu Nov 14 13:22:57 2013 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Thu, 14 Nov 2013 12:22:57 -0000 Subject: [Koha-patches] [PATCH] Bug 10451 - Firefox prints only first page of table with shrink to fit option Message-ID: <1371214927-7772-1-git-send-email-dpavlin@rot13.org> According to Firefox bug tracker, versions up to 21 doesn't print tables correctly when using shrink to fit option. See: https://bugzilla.mozilla.org/show_bug.cgi?id=684622 However, even with v21 or newer, we still need to add css to print media which instruct it not to break table tag to print all pages of table. This has a side-effect that table starts always on next page, wasting some space on first printed page (but only in Firefox since CSS selector is specific to it). --- koha-tmpl/intranet-tmpl/prog/en/css/print.css | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/print.css b/koha-tmpl/intranet-tmpl/prog/en/css/print.css index 239059c..ffd9630 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/print.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/print.css @@ -97,6 +97,13 @@ table { width : 99%; } + at -moz-document url-prefix() { + table { + /* tries to fix firefox 21+ shrink-to-fit */ + page-break-inside: avoid; + } +} + table.list { background-color : #FFFFFF; border : 0; -- 1.7.2.5 From dpavlin at rot13.org Thu Nov 14 13:23:50 2013 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Thu, 14 Nov 2013 12:23:50 -0000 Subject: [Koha-patches] [PATCH 2/2] Bug 8378 - show all items columns and new items.fine In-Reply-To: <1363700621-22744-1-git-send-email-dpavlin@rot13.org> References: <1363700621-22744-1-git-send-email-dpavlin@rot13.org> Message-ID: <1363700621-22744-2-git-send-email-dpavlin@rot13.org> This allows users to select any columns from items and adds new items.fine field introduced by previous patch to user interface. --- tools/letter.pl | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/tools/letter.pl b/tools/letter.pl index a462aba..68c6701 100755 --- a/tools/letter.pl +++ b/tools/letter.pl @@ -195,8 +195,9 @@ sub add_form { } else { push @{$field_selection}, add_fields('biblio','biblioitems'), - {value => q{}, text => '---ITEMS---' }, + add_fields('items'), {value => 'items.content', text => 'items.content'}, + {value => 'items.fine', text => 'items.fine'}, add_fields('borrowers'); if ($module eq 'circulation') { push @{$field_selection}, add_fields('opac_news'); -- 1.7.2.5 From dpavlin at rot13.org Fri Nov 8 15:51:03 2013 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Fri, 8 Nov 2013 15:51:03 +0100 Subject: [Koha-patches] [PATCH] Bug 11216 - Patron modification creates indefinite manual restriction Message-ID: <1383922263-19262-1-git-send-email-dpavlin@rot13.org> Editing partron data results in unintended adding of indefinite manual restriction to it. Reason for it is hidden field add_debarment which is wrongly initialized to 1 instead of 0. Also JavaScript code seems to want to toggle checkbox, and sice this field is hidden correct approach would be to change it's value to 1. Test scenario: 1. edit patron data 2. verify that debarrment is wrongly added 3. remove debarrment 3. apply this patch 4. edit patron again 5. verify that debarrment wasn't added 6. intentionally add debarrment and verify that it's saved 7. add debarment, enter something in comment but press cancel and verify that debarment isn't added --- .../prog/en/modules/members/memberentrygen.tt | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt index b158556..4aa88cf 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt @@ -59,7 +59,7 @@ }); $("#cancel_manual_restriction").on("click",function(e){ $('#debarred_expiration').val(''); - $('#add_debarment').prop('checked', false); + $('#add_debarment').val(0); $('#debarred_comment').val(''); mrlink.show(); mrform.hide(); @@ -1221,11 +1221,11 @@ [% END %]

    Add manual restriction

    - + Add manual restriction
      -
    1. -
    2. +
    3. +
    4. Clear date
    -- 1.7.2.5 From dpavlin at rot13.org Thu Nov 14 13:40:27 2013 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Thu, 14 Nov 2013 12:40:27 -0000 Subject: [Koha-patches] [PATCH 1/2] Bug 8378 - in overdues changed to <> Message-ID: <1363700621-22744-1-git-send-email-dpavlin@rot13.org> This patch reintroduces fines in overdue_notices.pl with minimal changes to exsiting code. It DOES changes template syntax, it used to be USD but currency was not recalculated and used only to select format, so now we are using active system currency because values are in it anyway. Example notify template: "<>" by <>, <>, Barcode: <> Fine: <> If your active currency doesn't have valid ISO code this code will fallback to sprintf with two decimal digits, and you can insert currency symbol in template itself (currency field is not editable through web interface, so this fallback might be useful for existing installations). Test scenario: 1. configure fine amount under "Circulation and fines rules" for patron category and item type 2. checkout item with correct type to partron in correct category with due date set to yesterday 3. verify that overdue notice uses new <> tag 4. run ./misc/cronjobs/fines.pl to calculate fines 5. run ./misc/cronjobs/overdue_notices.pl -n and verify that fine amount is included --- misc/cronjobs/overdue_notices.pl | 14 +++++--------- 1 files changed, 5 insertions(+), 9 deletions(-) diff --git a/misc/cronjobs/overdue_notices.pl b/misc/cronjobs/overdue_notices.pl index ba58e95..aad5ec0 100755 --- a/misc/cronjobs/overdue_notices.pl +++ b/misc/cronjobs/overdue_notices.pl @@ -40,6 +40,7 @@ use C4::Dates qw/format_date/; use C4::Debug; use C4::Letters; use C4::Overdues qw(GetFine); +use C4::Budgets qw(GetCurrency); =head1 NAME @@ -707,13 +708,7 @@ sub parse_letter { $tables{'branches'} = $p; } - my $currency_format; - if ( defined $params->{'letter'}->{'content'} - and $params->{'letter'}->{'content'} =~ m/(.*)<\/fine>/o ) - { # process any fine tags... - $currency_format = $1; - $params->{'letter'}->{'content'} =~ s/.*<\/fine>/<>/o; - } + my $currency_format = GetCurrency()->{currency}; my @item_tables; if ( my $i = $params->{'items'} ) { @@ -725,8 +720,9 @@ sub parse_letter { $item_format = $1; } - $item->{'fine'} = currency_format($currency_format, "$fine", FMT_SYMBOL) - if $currency_format; + $item->{'fine'} = currency_format($currency_format, "$fine", FMT_SYMBOL); + # if active currency isn't correct ISO code fallback to sprintf + $item->{'fine'} = sprintf('%.2f', $fine) unless $item->{'fine'}; push @item_tables, { 'biblio' => $item->{'biblionumber'}, -- 1.7.2.5 From dpavlin at rot13.org Fri Nov 8 14:58:34 2013 From: dpavlin at rot13.org (Dobrica Pavlinusic) Date: Fri, 8 Nov 2013 14:58:34 +0100 Subject: [Koha-patches] [PATCH] Bug 11216 - Patron modification creates indefinite manual restriction Message-ID: <1383919114-11287-1-git-send-email-dpavlin@rot13.org> Editing partron data results in unintended adding of indefinite manual restriction to it. Reason for it is hidden field add_debarment which is wrongly initialized to 1 instead of 0. Also JavaScript code seems to want to toggle checkbox, and sice this field is hidden correct approach would be to change it's value to 1. Test scenario: 1. edit patron data 2. verify that debarrment is wrongly added 3. remove debarrment 3. apply this patch 4. edit patron again 5. verify that debarrment wasn't added 6. intentionally add debarrment and verify that it's saved --- .../prog/en/modules/members/memberentrygen.tt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt index b158556..15ed9d7 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt @@ -1221,11 +1221,11 @@ [% END %]

    Add manual restriction

    - + Add manual restriction
      -
    1. -
    2. +
    3. +
    4. Clear date
    -- 1.7.2.5 From srdjan at catalyst.net.nz Fri Nov 15 00:27:19 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 15 Nov 2013 12:27:19 +1300 Subject: [Koha-patches] [PATCH] bug_11247: Removed unused params from TransformHtmlToXml() Message-ID: <1384471639-10084-1-git-send-email-srdjan@catalyst.net.nz> $indicator and $ind_tag should not be TransformHtmlToXml() params. TransformHtmlToXml() is only used for items: - $indicator is always empty - $ind_tag was not even used in the function To test: Check that integrity of following functions is preserved: * Acquisition - ordering and receiving, needs setting AcqCreateItem to placing and receiving an order * Cataloging - create/modify an item * Batcih modify in Tools * Serials receiving --- C4/Biblio.pm | 31 +++++-------------------------- acqui/addorder.pl | 6 ------ acqui/addorderiso2709.pl | 6 +----- acqui/finishreceive.pl | 7 +------ cataloguing/additem.pl | 26 ++------------------------ serials/serials-edit.pl | 6 ------ tools/batchMod.pl | 21 +-------------------- 7 files changed, 10 insertions(+), 93 deletions(-) diff --git a/C4/Biblio.pm b/C4/Biblio.pm index add0f74..12a6415 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -2203,8 +2203,7 @@ sub PrepHostMarcField { =head2 TransformHtmlToXml - $xml = TransformHtmlToXml( $tags, $subfields, $values, $indicator, - $ind_tag, $auth_type ) + $xml = TransformHtmlToXml( $tags, $subfields, $values, $auth_type ) $auth_type contains : @@ -2221,7 +2220,7 @@ $auth_type contains : =cut sub TransformHtmlToXml { - my ( $tags, $subfields, $values, $indicator, $ind_tag, $auth_type ) = @_; + my ( $tags, $subfields, $values, $auth_type ) = @_; my $xml = MARC::File::XML::header('UTF-8'); $xml .= "\n"; $auth_type = C4::Context->preference('marcflavour') unless $auth_type; @@ -2260,21 +2259,11 @@ sub TransformHtmlToXml { # } if ( ( @$tags[$i] ne $prevtag ) ) { $j++ unless ( @$tags[$i] eq "" ); - my $indicator1 = eval { substr( @$indicator[$j], 0, 1 ) }; - my $indicator2 = eval { substr( @$indicator[$j], 1, 1 ) }; - my $ind1 = _default_ind_to_space($indicator1); - my $ind2; - if ( @$indicator[$j] ) { - $ind2 = _default_ind_to_space($indicator2); - } else { - warn "Indicator in @$tags[$i] is empty"; - $ind2 = " "; - } if ( !$first ) { $xml .= "\n"; if ( ( @$tags[$i] && @$tags[$i] > 10 ) && ( @$values[$i] ne "" ) ) { - $xml .= "\n"; + $xml .= "\n"; $xml .= "@$values[$i]\n"; $first = 0; } else { @@ -2293,27 +2282,17 @@ sub TransformHtmlToXml { $xml .= "@$values[$i]\n"; $first = 1; } else { - $xml .= "\n"; + $xml .= "\n"; $xml .= "@$values[$i]\n"; $first = 0; } } } } else { # @$tags[$i] eq $prevtag - my $indicator1 = eval { substr( @$indicator[$j], 0, 1 ) }; - my $indicator2 = eval { substr( @$indicator[$j], 1, 1 ) }; - my $ind1 = _default_ind_to_space($indicator1); - my $ind2; - if ( @$indicator[$j] ) { - $ind2 = _default_ind_to_space($indicator2); - } else { - warn "Indicator in @$tags[$i] is empty"; - $ind2 = " "; - } if ( @$values[$i] eq "" ) { } else { if ($first) { - $xml .= "\n"; + $xml .= "\n"; $first = 0; } $xml .= "@$values[$i]\n"; diff --git a/acqui/addorder.pl b/acqui/addorder.pl index 1b05f07..73b4f96 100755 --- a/acqui/addorder.pl +++ b/acqui/addorder.pl @@ -286,8 +286,6 @@ if ( $orderinfo->{quantity} ne '0' ) { my @field_values = $input->param('field_value'); my @serials = $input->param('serial'); my @itemid = $input->param('itemid'); - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); #Rebuilding ALL the data for items into a hash # parting them on $itemid. @@ -301,16 +299,12 @@ if ( $orderinfo->{quantity} ne '0' ) { push @{$itemhash{$itemid[$i]}->{'tags'}},$tags[$i]; push @{$itemhash{$itemid[$i]}->{'subfields'}},$subfields[$i]; push @{$itemhash{$itemid[$i]}->{'field_values'}},$field_values[$i]; - push @{$itemhash{$itemid[$i]}->{'ind_tag'}},$ind_tag[$i]; - push @{$itemhash{$itemid[$i]}->{'indicator'}},$indicator[$i]; } foreach my $item (keys %itemhash){ my $xml = TransformHtmlToXml( $itemhash{$item}->{'tags'}, $itemhash{$item}->{'subfields'}, $itemhash{$item}->{'field_values'}, - $itemhash{$item}->{'ind_tag'}, - $itemhash{$item}->{'indicator'}, 'ITEM'); my $record=MARC::Record::new_from_xml($xml, 'UTF-8'); my ($biblionumber,$bibitemnum,$itemnumber) = AddItemFromMarc($record,$$orderinfo{biblionumber}); diff --git a/acqui/addorderiso2709.pl b/acqui/addorderiso2709.pl index abfb870..e615c4f 100755 --- a/acqui/addorderiso2709.pl +++ b/acqui/addorderiso2709.pl @@ -244,15 +244,11 @@ if ($op eq ""){ my @subfields = $input->param('subfield'); my @field_values = $input->param('field_value'); my @serials = $input->param('serial'); - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); my $item; push @{ $item->{tags} }, $tags[0]; push @{ $item->{subfields} }, $subfields[0]; push @{ $item->{field_values} }, $field_values[0]; - push @{ $item->{ind_tag} }, $ind_tag[0]; - push @{ $item->{indicator} }, $indicator[0]; - my $xml = TransformHtmlToXml( \@tags, \@subfields, \@field_values, \@ind_tag, \@indicator ); + my $xml = TransformHtmlToXml( \@tags, \@subfields, \@field_values ); my $record = MARC::Record::new_from_xml( $xml, 'UTF-8' ); for (my $qtyloop=1;$qtyloop <=$quantity;$qtyloop++) { my ( $biblionumber, $bibitemnum, $itemnumber ) = AddItemFromMarc( $record, $biblionumber ); diff --git a/acqui/finishreceive.pl b/acqui/finishreceive.pl index 900733d..7c28afd 100755 --- a/acqui/finishreceive.pl +++ b/acqui/finishreceive.pl @@ -123,8 +123,6 @@ if ($quantityrec > $origquantityrec ) { my @field_values = $input->param('field_value'); my @serials = $input->param('serial'); my @itemid = $input->param('itemid'); - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); #Rebuilding ALL the data for items into a hash # parting them on $itemid. my %itemhash; @@ -137,15 +135,12 @@ if ($quantityrec > $origquantityrec ) { push @{$itemhash{$itemid[$i]}->{'tags'}},$tags[$i]; push @{$itemhash{$itemid[$i]}->{'subfields'}},$subfields[$i]; push @{$itemhash{$itemid[$i]}->{'field_values'}},$field_values[$i]; - push @{$itemhash{$itemid[$i]}->{'ind_tag'}},$ind_tag[$i]; - push @{$itemhash{$itemid[$i]}->{'indicator'}},$indicator[$i]; } foreach my $item (keys %itemhash){ my $xml = TransformHtmlToXml( $itemhash{$item}->{'tags'}, $itemhash{$item}->{'subfields'}, $itemhash{$item}->{'field_values'}, - $itemhash{$item}->{'ind_tag'}, - $itemhash{$item}->{'indicator'},'ITEM'); + 'ITEM'); my $record=MARC::Record::new_from_xml($xml, 'UTF-8'); my (undef,$bibitemnum,$itemnumber) = AddItemFromMarc($record,$biblionumber); NewOrderItem($itemnumber, $new_ordernumber); diff --git a/cataloguing/additem.pl b/cataloguing/additem.pl index a819019..ed1ea9b 100755 --- a/cataloguing/additem.pl +++ b/cataloguing/additem.pl @@ -43,22 +43,6 @@ use URI::Escape; our $dbh = C4::Context->dbh; -sub find_value { - my ($tagfield,$insubfield,$record) = @_; - my $result; - my $indicator; - foreach my $field ($record->field($tagfield)) { - my @subfields = $field->subfields(); - foreach my $subfield (@subfields) { - if (@$subfield[0] eq $insubfield) { - $result .= @$subfield[1]; - $indicator = $field->indicator(1).$field->indicator(2); - } - } - } - return($indicator,$result); -} - sub get_item_from_barcode { my ($barcode)=@_; my $dbh=C4::Context->dbh; @@ -377,10 +361,7 @@ if ($op eq "additem") { my @tags = $input->param('tag'); my @subfields = $input->param('subfield'); my @values = $input->param('field_value'); - # build indicator hash. - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); - my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag, 'ITEM'); + my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values, 'ITEM'); my $record = MARC::Record::new_from_xml($xml, 'UTF-8'); # type of add @@ -585,11 +566,8 @@ if ($op eq "additem") { my @tags = $input->param('tag'); my @subfields = $input->param('subfield'); my @values = $input->param('field_value'); - # build indicator hash. - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); # my $itemnumber = $input->param('itemnumber'); - my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag,'ITEM'); + my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,'ITEM'); my $itemtosave=MARC::Record::new_from_xml($xml, 'UTF-8'); # MARC::Record builded => now, record in DB # warn "R: ".$record->as_formatted; diff --git a/serials/serials-edit.pl b/serials/serials-edit.pl index 8fb2e60..a3adef7 100755 --- a/serials/serials-edit.pl +++ b/serials/serials-edit.pl @@ -251,8 +251,6 @@ if ( $op and $op eq 'serialchangestatus' ) { my @serials = $query->param('serial'); my @bibnums = $query->param('bibnum'); my @itemid = $query->param('itemid'); - my @ind_tag = $query->param('ind_tag'); - my @indicator = $query->param('indicator'); #Rebuilding ALL the data for items into a hash # parting them on $itemid. @@ -277,8 +275,6 @@ if ( $op and $op eq 'serialchangestatus' ) { push @{ $itemhash{ $itemid[$i] }->{'subfields'} }, $subfields[$i]; push @{ $itemhash{ $itemid[$i] }->{'field_values'} }, $field_values[$i]; - push @{ $itemhash{ $itemid[$i] }->{'ind_tag'} }, $ind_tag[$i]; - push @{ $itemhash{ $itemid[$i] }->{'indicator'} }, $indicator[$i]; } foreach my $item ( keys %itemhash ) { @@ -298,8 +294,6 @@ if ( $op and $op eq 'serialchangestatus' ) { $itemhash{$item}->{'tags'}, $itemhash{$item}->{'subfields'}, $itemhash{$item}->{'field_values'}, - $itemhash{$item}->{'indicator'}, - $itemhash{$item}->{'ind_tag'} ); # warn $xml; diff --git a/tools/batchMod.pl b/tools/batchMod.pl index 69762b1..349730c 100755 --- a/tools/batchMod.pl +++ b/tools/batchMod.pl @@ -98,9 +98,6 @@ if ($op eq "action") { my @subfields = $input->param('subfield'); my @values = $input->param('field_value'); my @disabled = $input->param('disable_input'); - # build indicator hash. - my @ind_tag = $input->param('ind_tag'); - my @indicator = $input->param('indicator'); # Is there something to modify ? # TODO : We shall use this var to warn the user in case no modification was done to the items @@ -140,7 +137,7 @@ if ($op eq "action") { #initializing values for updates my ( $itemtagfield, $itemtagsubfield) = &GetMarcFromKohaField("items.itemnumber", ""); if ($values_to_modify){ - my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag, 'ITEM'); + my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values, 'ITEM'); utf8::encode($xml); $marcitem = MARC::Record::new_from_xml($xml, 'UTF-8'); } @@ -595,22 +592,6 @@ sub UpdateMarcWith { return $modified; } -sub find_value { - my ($tagfield,$insubfield,$record) = @_; - my $result; - my $indicator; - foreach my $field ($record->field($tagfield)) { - my @subfields = $field->subfields(); - foreach my $subfield (@subfields) { - if (@$subfield[0] eq $insubfield) { - $result .= @$subfield[1]; - $indicator = $field->indicator(1).$field->indicator(2); - } - } - } - return($indicator,$result); -} - # ---------------------------- # Background functions -- 1.8.1.2 From dpk at randomnotes.org Sun Nov 17 21:07:23 2013 From: dpk at randomnotes.org (Doug Kingston) Date: Sun, 17 Nov 2013 12:07:23 -0800 Subject: [Koha-patches] [PATCH 6/6] Bug 11078 Add locking to rebuild_zebra QA Patch 4 Message-ID: <1384718843-7367-1-git-send-email-dpk@randomnotes.org> Address coding style issues from koha-qa.pl --- misc/migration_tools/rebuild_zebra.pl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/misc/migration_tools/rebuild_zebra.pl b/misc/migration_tools/rebuild_zebra.pl index 8b77686..74976c1 100755 --- a/misc/migration_tools/rebuild_zebra.pl +++ b/misc/migration_tools/rebuild_zebra.pl @@ -146,7 +146,7 @@ my ($biblioitemnumbertagfield,$biblioitemnumbertagsubfield) = &GetMarcFromKohaFi my $lockdir = C4::Context->config("lockdir"); $lockdir = "/var/lock" if $lockdir == ""; $lockdir .= ("/koha_rebuild_zebra_" . C4::Context->config("database")); -mkpath($lockdir, 0, 0755) unless (-d $lockdir); +mkpath($lockdir, 0, oct(755)) unless (-d $lockdir); my $lockfile = $lockdir . "/lock"; if ( $verbose_logging ) { @@ -173,14 +173,14 @@ my $tester = XML::LibXML->new(); # record being overwritten by a rebuild if the update is applied after the export # by the rebuild and before the rebuild finishes (more likely to effect large # catalogs). -open(LockFH, ">$lockfile") or die "$lockfile: $!"; +open my $LockFH, q{>}, $lockfile or die "$lockfile: $!"; if ($daemon_mode) { while (1) { # For incremental updates, skip the update if the updates are locked - if (flock(LockFH, LOCK_EX|LOCK_NB)) { - do_one_pass() if ( zebraqueue_not_empty() ); - flock(LockFH, LOCK_UN); - } + if (flock(LockFH, LOCK_EX|LOCK_NB)) { + do_one_pass() if ( zebraqueue_not_empty() ); + flock(LockFH, LOCK_UN); + } sleep $daemon_sleep; } } else { -- 1.7.9.5 From dpk at randomnotes.org Sun Nov 17 22:02:10 2013 From: dpk at randomnotes.org (Doug Kingston) Date: Sun, 17 Nov 2013 13:02:10 -0800 Subject: [Koha-patches] [PATCH 2/2] ENH Bug 6435 Add daemon mode QA Patch 1 Message-ID: <1384722130-7873-1-git-send-email-dpk@randomnotes.org> Based on feedback, make daemon mode imply -z, -a, -b and abort on startup if flags incompatible with an incremental update daemon are used. Update documentation to match. --- misc/migration_tools/rebuild_zebra.pl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/misc/migration_tools/rebuild_zebra.pl b/misc/migration_tools/rebuild_zebra.pl index 6489fc5..7f17fcb 100755 --- a/misc/migration_tools/rebuild_zebra.pl +++ b/misc/migration_tools/rebuild_zebra.pl @@ -115,6 +115,19 @@ if ($noshadow) { $noshadow = ' -n '; } +if ($daemon) { + # incompatible flags handled above: help, reset, and do_not_clear_zebraqueue + if ($skip_export or $keep_export or $skip_index or + $where or $length or $offset) { + my $msg = "Cannot specify -s, -k, -I, -where, -length, or -offset with -daemon.\n"; + $msg .= "Please do '$0 --help' to see usage.\n"; + die $msg; + } + $authorities = 1; + $biblios = 1; + $process_zebraqueue = 1; +} + # -v is for verbose, which seems backwards here because of how logging is set # on the CLI of zebraidx. It works this way. The default is to not log much if ($verbose_logging >= 2) { @@ -207,6 +220,8 @@ sub do_one_pass { } # Check the zebra update queue and return true if there are records to process +# This routine will handle each of -ab, -a, or -b, but in practice we force +# -ab when in daemon mode. sub zebraqueue_not_empty { my $where_str; @@ -736,6 +751,11 @@ Parameters: the zebra search index with low system overhead. Use -sleep to control the checking interval. + Daemon mode implies -z, -a, -b. The program will + refuse to start if options are present that do not + make sense while running as an incremental update + daemon (e.g. -r or -offset). + -sleep 10 Seconds to sleep between checks of the zebraqueue table in daemon mode. The default is 5 seconds. -- 1.7.9.5 From dpk at randomnotes.org Sun Nov 17 22:12:49 2013 From: dpk at randomnotes.org (Doug Kingston) Date: Sun, 17 Nov 2013 13:12:49 -0800 Subject: [Koha-patches] [PATCH 2/2] ENH Bug 6435 Add daemon mode QA Patch 1a Message-ID: <1384722769-8011-1-git-send-email-dpk@randomnotes.org> Based on feedback, make daemon mode imply -z -a -b and abort on startup if flags incompatible with an incremental update daemon are used. Update documentation to match. --- misc/migration_tools/rebuild_zebra.pl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/misc/migration_tools/rebuild_zebra.pl b/misc/migration_tools/rebuild_zebra.pl index 6489fc5..1da497c 100755 --- a/misc/migration_tools/rebuild_zebra.pl +++ b/misc/migration_tools/rebuild_zebra.pl @@ -115,6 +115,19 @@ if ($noshadow) { $noshadow = ' -n '; } +if ($daemon_mode) { + # incompatible flags handled above: help, reset, and do_not_clear_zebraqueue + if ($skip_export or $keep_export or $skip_index or + $where or $length or $offset) { + my $msg = "Cannot specify -s, -k, -I, -where, -length, or -offset with -daemon.\n"; + $msg .= "Please do '$0 --help' to see usage.\n"; + die $msg; + } + $authorities = 1; + $biblios = 1; + $process_zebraqueue = 1; +} + # -v is for verbose, which seems backwards here because of how logging is set # on the CLI of zebraidx. It works this way. The default is to not log much if ($verbose_logging >= 2) { @@ -207,6 +220,8 @@ sub do_one_pass { } # Check the zebra update queue and return true if there are records to process +# This routine will handle each of -ab, -a, or -b, but in practice we force +# -ab when in daemon mode. sub zebraqueue_not_empty { my $where_str; @@ -736,6 +751,11 @@ Parameters: the zebra search index with low system overhead. Use -sleep to control the checking interval. + Daemon mode implies -z, -a, -b. The program will + refuse to start if options are present that do not + make sense while running as an incremental update + daemon (e.g. -r or -offset). + -sleep 10 Seconds to sleep between checks of the zebraqueue table in daemon mode. The default is 5 seconds. -- 1.7.9.5 From dpk at randomnotes.org Mon Nov 18 06:34:19 2013 From: dpk at randomnotes.org (Doug Kingston) Date: Sun, 17 Nov 2013 21:34:19 -0800 Subject: [Koha-patches] [PATCH 7/7] Bug 11078 Add locking to rebuild_zebra QA Patch 5 Message-ID: <1384752859-23407-1-git-send-email-dpk@randomnotes.org> Address concern on the initialization of $lockdir. If lockdir is undef, then it will default to /var/lock. If lockdir is specified in the config, it is expected to be a valid directory. mkpath() will fail if its not a valid path. --- misc/migration_tools/rebuild_zebra.pl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/misc/migration_tools/rebuild_zebra.pl b/misc/migration_tools/rebuild_zebra.pl index 74976c1..702377c 100755 --- a/misc/migration_tools/rebuild_zebra.pl +++ b/misc/migration_tools/rebuild_zebra.pl @@ -143,8 +143,7 @@ my ($biblioitemnumbertagfield,$biblioitemnumbertagsubfield) = &GetMarcFromKohaFi # We need to create our own lock directory which incorporates the database instance # we are indexing to facilitate multiple instances on the same machine. -my $lockdir = C4::Context->config("lockdir"); -$lockdir = "/var/lock" if $lockdir == ""; +my $lockdir = C4::Context->config("lockdir") // "/var/lock"; $lockdir .= ("/koha_rebuild_zebra_" . C4::Context->config("database")); mkpath($lockdir, 0, oct(755)) unless (-d $lockdir); my $lockfile = $lockdir . "/lock"; @@ -177,17 +176,17 @@ open my $LockFH, q{>}, $lockfile or die "$lockfile: $!"; if ($daemon_mode) { while (1) { # For incremental updates, skip the update if the updates are locked - if (flock(LockFH, LOCK_EX|LOCK_NB)) { + if (flock($LockFH, LOCK_EX|LOCK_NB)) { do_one_pass() if ( zebraqueue_not_empty() ); - flock(LockFH, LOCK_UN); + flock($LockFH, LOCK_UN); } sleep $daemon_sleep; } } else { # all one-off invocations, wait for the lock to free - flock(LockFH, LOCK_EX); + flock($LockFH, LOCK_EX); do_one_pass(); - flock(LockFH, LOCK_UN); + flock($LockFH, LOCK_UN); } -- 1.7.9.5 From barry at oslo.ie Mon Nov 18 17:39:02 2013 From: barry at oslo.ie (Barry Cannon) Date: Mon, 18 Nov 2013 16:39:02 +0000 Subject: [Koha-patches] [PATCH] Bug 6837 - When AllowOnShelfHolds is OFF then holds on records with available items should not be possible Message-ID: <1384792742-10980-1-git-send-email-barry@oslo.ie> This patch corrects this bug. Allows holds when systempref is set to "Allow", disallows when set to "Don't Allow". --- koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc | 4 ---- koha-tmpl/opac-tmpl/prog/en/modules/opac-results-grouped.tt | 4 ---- koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt | 4 ---- 3 files changed, 12 deletions(-) diff --git a/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc b/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc index 0f16f3a..634fb95 100644 --- a/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc +++ b/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc @@ -4,10 +4,6 @@ [% IF ( RequestOnOpac ) %] [% IF ( AllowOnShelfHolds ) %]
  • Place hold
  • - [% ELSE %] - [% IF ( ItemsIssued ) %] -
  • Place hold
  • - [% END %] [% END %] [% END %] [% END %] diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results-grouped.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results-grouped.tt index 2010cee..83d4a61 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results-grouped.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results-grouped.tt @@ -275,10 +275,6 @@ function highlightOn() { [% IF ( opacuserlogin ) %] [% IF ( AllowOnShelfHolds ) %] Place hold - [% ELSE %] - [% IF ( GROUP_RESULT.itemsissued ) %] - Place hold - [% END %] [% END %] [% END %] [% END %] 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 9235b2b..5598ca1 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt @@ -669,10 +669,6 @@ $(document).ready(function(){ [% IF ( opacuserlogin ) %] [% IF ( AllowOnShelfHolds ) %] Place hold - [% ELSE %] - [% IF ( SEARCH_RESULT.itemsissued ) %] - Place hold - [% END %] [% END %] [% END %] [% END %] -- 1.7.10.4 From barry at oslo.ie Tue Nov 26 17:15:11 2013 From: barry at oslo.ie (Barry Cannon) Date: Tue, 26 Nov 2013 16:15:11 +0000 Subject: [Koha-patches] [PATCH] Bug 6837 - When AllowOnShelfHolds is OFF then holds on records with available items should not be possible Message-ID: <1385482511-12040-1-git-send-email-barry@oslo.ie> The original "AllowOnShelfHolds" SysPref had two options: "Allow" and "Don't Allow". When the preference was set to "Don't Allow" the system would still allow a hold to be placed on a bib if at least one of it's items was not on the shelf. This violated the SystemPreference. When this patch is implemented, and the "AllowShelfHolds" SysPref is set to "Don't Allow" the system will not provide a "Place Hold" option to the OPAC user if ANY item is on the shelf (in ANY location). Setting the SysPref to "Allow" will allow holds to be placed on the bib if there is an attached item on the shelf. I will look to address the issues of allowing holds for items in remote branches in a later patch. --- C4/Reserves.pm | 61 +++++++++++++++++++- .../prog/en/includes/opac-detail-sidebar.inc | 10 ++-- .../prog/en/modules/opac-results-grouped.tt | 14 +++-- .../opac-tmpl/prog/en/modules/opac-results.tt | 10 ++-- opac/opac-detail.pl | 7 ++- opac/opac-reserve.pl | 18 ++++-- opac/opac-search.pl | 12 +++- 7 files changed, 109 insertions(+), 23 deletions(-) diff --git a/C4/Reserves.pm b/C4/Reserves.pm index d1bca25..2e616b0 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -133,6 +133,7 @@ BEGIN { &SuspendAll &GetReservesControlBranch + &PreventHoldsAnyAvailableItem ); @EXPORT_OK = qw( MergeHolds ); } @@ -788,7 +789,6 @@ If several reserves exist, the reserve with the lower priority is given. ## the sub is only used once in the codebase. sub GetReserveStatus { my ($itemnumber, $biblionumber) = @_; - my $dbh = C4::Context->dbh; my ($sth, $found, $priority); @@ -2214,6 +2214,65 @@ sub GetReservesControlBranch { return $branchcode; } +=head2 PreventHoldsAnyAvailableItem +Checks if an item is available to have a hold placed on it. +Specifically relates to items currently on the shelf (without a datedue). + +Returns true when any item attached to the bib is on the shelf and available + +=cut + +sub PreventHoldsAnyAvailableItem { + my $biblionumber = shift; + my @items = GetItemsInfo( $biblionumber ); + my $prevent_hold = 0; + my $not_out = 0; + my $checked_out = 0; + my $dbh = C4::Context->dbh; + my $notforloan_query; + if (C4::Context->preference('item-level_itypes')) { + $notforloan_query = "SELECT itemtypes.notforloan + FROM items + JOIN itemtypes ON (itemtypes.itemtype = items.itype) + WHERE itemnumber = ?"; + } else { + $notforloan_query = "SELECT itemtypes.notforloan + FROM items + JOIN biblioitems USING (biblioitemnumber) + JOIN itemtypes USING (itemtype) + WHERE itemnumber = ?"; + } + my $sth = $dbh->prepare($notforloan_query); + + foreach my $item (@items) { + $sth->execute( $item->{itemnumber} ); + my $notforloan_itemtype = 0; + if (my ($notforloan) = $sth->fetchrow_array) { + $notforloan_itemtype = 1 if $notforloan; + } + + if ( not $item->{datedue} ) { + my $reserve_status = GetReserveStatus( $item->{itemnumber} ); + if ($item->{itemlost} + or ( $item->{notforloan} > 0 ) + or ( $item->{damaged} and not C4::Context->preference('AllowHoldsOnDamagedItems') ) + or $item->{wthdrawn} + or $notforloan_itemtype + or $reserve_status eq "Waiting" + or $reserve_status eq "Reserved") + { + next; + } + else {$prevent_hold++} + + } + + } + + return $prevent_hold; + +} + =head1 AUTHOR Koha Development Team diff --git a/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc b/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc index 0f16f3a..68db1dd 100644 --- a/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc +++ b/koha-tmpl/opac-tmpl/prog/en/includes/opac-detail-sidebar.inc @@ -2,11 +2,13 @@ [% UNLESS ( norequests ) %] [% IF ( opacuserlogin ) %] [% IF ( RequestOnOpac ) %] - [% IF ( AllowOnShelfHolds ) %] -
  • Place hold
  • - [% ELSE %] - [% IF ( ItemsIssued ) %] + [% UNLESS ( PreventHoldsAnyAvailableItem ) %] + [% IF ( AllowOnShelfHolds ) %]
  • Place hold
  • + [% ELSE %] + [% IF ( ItemsIssued ) %] +
  • Place hold
  • + [% END %] [% END %] [% END %] [% END %] diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results-grouped.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results-grouped.tt index 2010cee..970d6f8 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results-grouped.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results-grouped.tt @@ -273,13 +273,15 @@ function highlightOn() { [% IF ( RequestOnOpac ) %] [% UNLESS ( GROUP_RESULT.norequests ) %] [% IF ( opacuserlogin ) %] - [% IF ( AllowOnShelfHolds ) %] - Place hold - [% ELSE %] - [% IF ( GROUP_RESULT.itemsissued ) %] - Place hold + [% UNLESS SEARCH_RESULT.prevent_holds %] + [% IF ( AllowOnShelfHolds ) %] + Place hold + [% ELSE %] + [% IF ( GROUP_RESULT.itemsissued ) %] + Place hold + [% END %] [% END %] - [% END %] + [% END %] [% END %] [% END %] [% END %] 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 9235b2b..ac9607a 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt @@ -667,11 +667,13 @@ $(document).ready(function(){ [% IF ( RequestOnOpac ) %] [% UNLESS ( SEARCH_RESULT.norequests ) %] [% IF ( opacuserlogin ) %] - [% IF ( AllowOnShelfHolds ) %] - Place hold - [% ELSE %] - [% IF ( SEARCH_RESULT.itemsissued ) %] + [% UNLESS SEARCH_RESULT.prevent_holds %] + [% IF ( AllowOnShelfHolds ) %] Place hold + [% ELSE %] + [% IF ( SEARCH_RESULT.itemsissued ) %] + Place hold + [% END %] [% END %] [% END %] [% END %] diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl index 41de4fd..030c5c0 100755 --- a/opac/opac-detail.pl +++ b/opac/opac-detail.pl @@ -401,12 +401,17 @@ if ($session->param('busc')) { } +my $prevent_holds = 0; +if ( not C4::Context->preference('AllowOnShelfHolds') ) { + $prevent_holds = PreventHoldsAnyAvailableItem( $biblionumber ); +} + +$template->param( 'PreventHoldsAnyAvailableItem' => $prevent_holds ); $template->param( 'AllowOnShelfHolds' => C4::Context->preference('AllowOnShelfHolds') ); $template->param( 'ItemsIssued' => CountItemsIssued( $biblionumber ) ); - $template->param('OPACShowCheckoutName' => C4::Context->preference("OPACShowCheckoutName") ); $template->param('OPACShowBarcode' => C4::Context->preference("OPACShowBarcode") ); diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl index 97d136a..f4759c4 100755 --- a/opac/opac-reserve.pl +++ b/opac/opac-reserve.pl @@ -352,9 +352,12 @@ my $itemdata_enumchron = 0; my $anyholdable = 0; my $itemLevelTypes = C4::Context->preference('item-level_itypes'); $template->param('item_level_itypes' => $itemLevelTypes); - +my $prevent_holds = 0; foreach my $biblioNum (@biblionumbers) { - + if ( not C4::Context->preference('AllowOnShelfHolds') ) { + $prevent_holds = PreventHoldsAnyAvailableItem($biblioNum) + } + my $record = GetMarcBiblio($biblioNum); # Init the bib item with the choices for branch pickup my %biblioLoopIter = ( branchloop => $branchloop ); @@ -500,11 +503,14 @@ foreach my $biblioNum (@biblionumbers) { $policy_holdallowed = 0; } - if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum) and ($itemLoopIter->{already_reserved} ne 1)) { - $itemLoopIter->{available} = 1; - $numCopiesAvailable++; + unless ($prevent_holds > 0 ) { + if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum) and ($itemLoopIter->{already_reserved} ne 1)) { + $itemLoopIter->{available} = 1; + $numCopiesAvailable++; + } } + # FIXME: move this to a pm my $dbh = C4::Context->dbh; my $sth2 = $dbh->prepare("SELECT * FROM reserves WHERE borrowernumber=? AND itemnumber=? AND found='W'"); @@ -544,7 +550,7 @@ foreach my $biblioNum (@biblionumbers) { push @$biblioLoop, \%biblioLoopIter; } -if ( $numBibsAvailable == 0 || $anyholdable == 0) { +if ( $numBibsAvailable == 0 || $anyholdable == 0 || $prevent_holds > 0 ) { $template->param( none_available => 1 ); } diff --git a/opac/opac-search.pl b/opac/opac-search.pl index 2854da6..4e8f80e 100755 --- a/opac/opac-search.pl +++ b/opac/opac-search.pl @@ -52,7 +52,7 @@ use C4::Branch; # GetBranches use C4::SocialData; use C4::Ratings; use C4::External::OverDrive; - +use C4::Reserves; use POSIX qw(ceil floor strftime); use URI::Escape; use JSON qw/decode_json encode_json/; @@ -675,9 +675,19 @@ for (my $i=0;$i<@servers;$i++) { my $j = 0; foreach (@newresults) { my $bibnum = ($_->{biblionumber})?$_->{biblionumber}:0; + # Check if holds are allowed + my $prevent_holds = 0; + if ( not C4::Context->preference('AllowOnShelfHolds') ) { + $prevent_holds = PreventHoldsAnyAvailableItem($bibnum) if $bibnum; + } + if ( $prevent_holds ) { + $_->{prevent_holds} =1; + } + $pasarParams .= $bibnum . ','; $j++; last if ($j == $results_per_page); + } chop $pasarParams if ($pasarParams =~ /,$/); $pasarParams .= '&total=' . int($total) if ($pasarParams !~ /total=(?:[0-9]+)?/); -- 1.7.10.4 From dpk at randomnotes.org Fri Nov 29 08:20:22 2013 From: dpk at randomnotes.org (Doug Kingston) Date: Thu, 28 Nov 2013 23:20:22 -0800 Subject: [Koha-patches] [PATCH] Bug 11078 Add locking to rebuild_zebra.pl Message-ID: <1385709622-9876-1-git-send-email-dpk@randomnotes.org> This patch adds locking to rebuild_zebra.pl to ensure that simultaneous changes are prevented (as one is likely to overwrite the other). Incremental updates in daemon mode will skipped if the lock is busy and they will be picked up on the next pass. Non-daemon mode invocations will wait for the lock to clear and then proceed. Supporting changes made to Makefile.PL and templates for the new locking directory (paralleling the other zebra lock directories). We stash the zebra_lockdir in koha-conf.xml so rebuild_zebra.pl can find it. --- Makefile.PL | 5 ++++- debian/templates/koha-conf-site.xml.in | 1 + etc/koha-conf.xml | 1 + misc/bin/koha-zebra-ctl.sh | 1 + misc/migration_tools/rebuild_zebra.pl | 26 +++++++++++++++++++++++++- skel/var/lock/koha/zebradb/rebuild/README | 1 + 6 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 skel/var/lock/koha/zebradb/rebuild/README diff --git a/Makefile.PL b/Makefile.PL index 66f9a0f..7d5eb4a 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -186,7 +186,9 @@ Directory for Zebra configuration files. =item ZEBRA_LOCK_DIR -Directory for Zebra's lock files. +Directory for Zebra's lock files. This includes subdirs for authorities, +biblios, and the zebra rebuild function. Any activity to reindex +zebra from koha should interlock here with rebuild_zebra.pl. =item ZEBRA_DATA_DIR @@ -318,6 +320,7 @@ my $target_map = { './skel/var/lib/koha/zebradb/biblios/register' => { target => 'ZEBRA_DATA_DIR', trimdir => 6 }, './skel/var/lib/koha/zebradb/biblios/shadow' => { target => 'ZEBRA_DATA_DIR', trimdir => 6 }, './skel/var/lib/koha/zebradb/biblios/tmp' => { target => 'ZEBRA_DATA_DIR', trimdir => 6 }, + './skel/var/lock/koha/zebradb/rebuild' => { target => 'ZEBRA_LOCK_DIR', trimdir => 6 }, './skel/var/lib/koha/plugins' => { target => 'PLUGINS_DIR', trimdir => 6 }, './sms' => 'INTRANET_CGI_DIR', './suggestion' => 'INTRANET_CGI_DIR', diff --git a/debian/templates/koha-conf-site.xml.in b/debian/templates/koha-conf-site.xml.in index 9bf090b..371b1d2 100644 --- a/debian/templates/koha-conf-site.xml.in +++ b/debian/templates/koha-conf-site.xml.in @@ -280,6 +280,7 @@ __MEMCACHED_NAMESPACE__ __BIBLIOS_INDEXING_MODE__ __AUTHORITIES_INDEXING_MODE__ + /var/lock/koha/__KOHASITE__ /etc/koha/searchengine/queryparser.yaml diff --git a/etc/koha-conf.xml b/etc/koha-conf.xml index d42f041..3bdbdf9 100644 --- a/etc/koha-conf.xml +++ b/etc/koha-conf.xml @@ -296,6 +296,7 @@ __PAZPAR2_TOGGLE_XML_POST__ 0 __BIB_INDEX_MODE__ __AUTH_INDEX_MODE__ + __ZEBRA_LOCK_DIR__ __KOHA_CONF_DIR__/searchengine/queryparser.yaml diff --git a/misc/bin/koha-zebra-ctl.sh b/misc/bin/koha-zebra-ctl.sh index 397eb19..82b9162 100755 --- a/misc/bin/koha-zebra-ctl.sh +++ b/misc/bin/koha-zebra-ctl.sh @@ -65,6 +65,7 @@ case "$1" in mkdir -p $LOCKDIR mkdir -p $LOCKDIR/biblios mkdir -p $LOCKDIR/authorities + mkdir -p $LOCKDIR/rebuild if [[ $EUID -eq 0 ]]; then chown -R $USER:$GROUP $LOCKDIR fi diff --git a/misc/migration_tools/rebuild_zebra.pl b/misc/migration_tools/rebuild_zebra.pl index 7e0c83a..1e9b300 100755 --- a/misc/migration_tools/rebuild_zebra.pl +++ b/misc/migration_tools/rebuild_zebra.pl @@ -5,6 +5,7 @@ use strict; use C4::Context; use Getopt::Long; +use Fcntl qw(:flock); use File::Temp qw/ tempdir /; use File::Path; use C4::Biblio; @@ -153,12 +154,21 @@ my $dbh = C4::Context->dbh; my ($biblionumbertagfield,$biblionumbertagsubfield) = &GetMarcFromKohaField("biblio.biblionumber",""); my ($biblioitemnumbertagfield,$biblioitemnumbertagsubfield) = &GetMarcFromKohaField("biblioitems.biblioitemnumber",""); +# Protect again simultaneous update of the zebra index by using a lock file. +# Create our own lock directory if its missing. This shouild be created +# by koha-zebra-ctl.sh. + +my $lockdir = C4::Context->config("zebra_lockdir") // "/var/lock"; +mkpath($lockdir, 0, oct(755)) unless (-d $lockdir); +my $lockfile = $lockdir . "/rebuild..LCK"; + if ( $verbose_logging ) { print "Zebra configuration information\n"; print "================================\n"; print "Zebra biblio directory = $biblioserverdir\n"; print "Zebra authorities directory = $authorityserverdir\n"; print "Koha directory = $kohadir\n"; + print "Lockfile = $lockfile\n"; print "BIBLIONUMBER in : $biblionumbertagfield\$$biblionumbertagsubfield\n"; print "BIBLIOITEMNUMBER in : $biblioitemnumbertagfield\$$biblioitemnumbertagsubfield\n"; print "================================\n"; @@ -170,13 +180,27 @@ if ($do_munge) { my $tester = XML::LibXML->new(); +# The main work is done here by calling do_one_pass(). We have added locking +# avoid race conditions between Full rebuilds and incremental updates either from +# daemon mode or periodic invocation from cron. The race can lead to an updated +# record being overwritten by a rebuild if the update is applied after the export +# by the rebuild and before the rebuild finishes (more likely to effect large +# catalogs). +open my $LockFH, q{>}, $lockfile or die "$lockfile: $!"; if ($daemon_mode) { while (1) { - do_one_pass() if ( zebraqueue_not_empty() ); + # For incremental updates, skip the update if the updates are locked + if (flock($LockFH, LOCK_EX|LOCK_NB)) { + do_one_pass() if ( zebraqueue_not_empty() ); + flock($LockFH, LOCK_UN); + } sleep $daemon_sleep; } } else { + # all one-off invocations, wait for the lock to free + flock($LockFH, LOCK_EX); do_one_pass(); + flock($LockFH, LOCK_UN); } diff --git a/skel/var/lock/koha/zebradb/rebuild/README b/skel/var/lock/koha/zebradb/rebuild/README new file mode 100644 index 0000000..98b4c5b --- /dev/null +++ b/skel/var/lock/koha/zebradb/rebuild/README @@ -0,0 +1 @@ +Zebra rebuild lock dir -- 1.7.9.5 From dpk at randomnotes.org Fri Nov 29 09:07:26 2013 From: dpk at randomnotes.org (Doug Kingston) Date: Fri, 29 Nov 2013 00:07:26 -0800 Subject: [Koha-patches] [PATCH 2/2] Bug 11078 Add locking to rebuild_zebra.pl (path fix) Message-ID: <1385712446-10738-1-git-send-email-dpk@randomnotes.org> Add missing reference to subdirectory for rebuild_zebra locks under zebra lock diretory. This is already handled correctly in the docs, template and makefiles. The code in fact works either way, but docs and reality should match. --- misc/migration_tools/rebuild_zebra.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/misc/migration_tools/rebuild_zebra.pl b/misc/migration_tools/rebuild_zebra.pl index 1e9b300..6e713ff 100755 --- a/misc/migration_tools/rebuild_zebra.pl +++ b/misc/migration_tools/rebuild_zebra.pl @@ -159,6 +159,7 @@ my ($biblioitemnumbertagfield,$biblioitemnumbertagsubfield) = &GetMarcFromKohaFi # by koha-zebra-ctl.sh. my $lockdir = C4::Context->config("zebra_lockdir") // "/var/lock"; +$lockdir .= "/rebuild"; mkpath($lockdir, 0, oct(755)) unless (-d $lockdir); my $lockfile = $lockdir . "/rebuild..LCK"; -- 1.7.9.5