From 6b2b62eb5723258eb34b210120c3423f74da2877 Mon Sep 17 00:00:00 2001 From: Matthias Meusburger Date: Sat, 26 Mar 2011 04:41:55 -0400 Subject: [PATCH] Bug 5952: Shows member relatives in issues lists Duplicate of '[PATCH] MT3747: Shows member relatives in issueslists' : Subject was wrong MT3747, Follow-up: Adds siblings issues MT3747, Follow-up: Shows member relatives in issues lists - Now displays patron's and relatives' issues apart MT3747, Follow-up: Shows member relatives in issues lists - Removes renewal in circulation.pl - Adds links to moremember.pl MT3747, Follow-up: Shows member relatives in issues lists - Remove unuseful warn MT3747, Follow-up: Shows member relatives in issues lists - Removes renewal in moremember.pl MT3747, Follow-up: Shows member relatives in issues lists - Adds sorting for circulation.pl Signed-off-by: Nicole C. Engard Signed-off-by: Chris Cormack --- C4/Members.pm | 64 +++++++- circ/circulation.pl | 40 ++++- .../en/includes/checkouts-table-footer.inc | 2 +- .../prog/en/modules/circ/circulation.tmpl | 100 ++++++++++++- .../prog/en/modules/members/moremember.tmpl | 86 +++++++++-- members/moremember.pl | 140 ++++++++++-------- 6 files changed, 350 insertions(+), 82 deletions(-) diff --git a/C4/Members.pm b/C4/Members.pm index 9fdb357664..bf73e0e906 100644 --- a/C4/Members.pm +++ b/C4/Members.pm @@ -45,6 +45,7 @@ BEGIN { &Search &SearchMember &GetMemberDetails + &GetMemberRelatives &GetMember &GetGuarantees @@ -582,6 +583,46 @@ sub GetMember { return; } +=head2 GetMemberRelatives + + @borrowernumbers = GetMemberRelatives($borrowernumber); + + C returns a borrowersnumber's list of guarantor/guarantees of the member given in parameter + +=cut +sub GetMemberRelatives { + my $borrowernumber = shift; + my $dbh = C4::Context->dbh; + my @glist; + + # Getting guarantor + my $query = "SELECT guarantorid FROM borrowers WHERE borrowernumber=?"; + my $sth = $dbh->prepare($query); + $sth->execute($borrowernumber); + my $data = $sth->fetchrow_arrayref(); + push @glist, $data->[0] if $data->[0]; + my $guarantor = $data->[0] if $data->[0]; + + # Getting guarantees + $query = "SELECT borrowernumber FROM borrowers WHERE guarantorid=?"; + $sth = $dbh->prepare($query); + $sth->execute($borrowernumber); + while ($data = $sth->fetchrow_arrayref()) { + push @glist, $data->[0]; + } + + # Getting sibling guarantees + if ($guarantor) { + $query = "SELECT borrowernumber FROM borrowers WHERE guarantorid=?"; + $sth = $dbh->prepare($query); + $sth->execute($guarantor); + while ($data = $sth->fetchrow_arrayref()) { + push @glist, $data->[0] if ($data->[0] != $borrowernumber); + } + } + + return @glist; +} =head2 IsMemberBlocked @@ -963,7 +1004,7 @@ sub UpdateGuarantees { } =head2 GetPendingIssues - my $issues = &GetPendingIssues($borrowernumber); + my $issues = &GetPendingIssues(@borrowernumber); Looks up what the patron with the given borrowernumber has borrowed. @@ -976,14 +1017,22 @@ The keys include C fields except marc and marcxml. #' sub GetPendingIssues { - my ($borrowernumber) = @_; + my (@borrowernumbers) = @_; + + # Borrowers part of the query + my $bquery = ''; + for (my $i = 0; $i < @borrowernumbers; $i++) { + $bquery .= " borrowernumber = ?"; + $bquery .= " OR" if ($i < (scalar(@borrowernumbers) - 1)); + } + # must avoid biblioitems.* to prevent large marc and marcxml fields from killing performance # FIXME: namespace collision: each table has "timestamp" fields. Which one is "timestamp" ? # FIXME: circ/ciculation.pl tries to sort by timestamp! # FIXME: C4::Print::printslip tries to sort by timestamp! # FIXME: namespace collision: other collisions possible. # FIXME: most of this data isn't really being used by callers. - my $sth = C4::Context->dbh->prepare( + my $query = "SELECT issues.*, items.*, biblio.*, @@ -1000,16 +1049,19 @@ sub GetPendingIssues { biblioitems.url, issues.timestamp AS timestamp, issues.renewals AS renewals, + issues.borrowernumber AS borrowernumber, items.renewals AS totalrenewals FROM issues LEFT JOIN items ON items.itemnumber = issues.itemnumber LEFT JOIN biblio ON items.biblionumber = biblio.biblionumber LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber WHERE - borrowernumber=? + $bquery ORDER BY issues.issuedate" - ); - $sth->execute($borrowernumber); + ; + + my $sth = C4::Context->dbh->prepare($query); + $sth->execute(@borrowernumbers); my $data = $sth->fetchall_arrayref({}); my $today = C4::Dates->new->output('iso'); foreach (@$data) { diff --git a/circ/circulation.pl b/circ/circulation.pl index e521e19f2a..524219355e 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -42,6 +42,7 @@ use Date::Calc qw( Add_Delta_Days Date_to_Days ); +use List::MoreUtils qw/uniq/; # @@ -403,15 +404,24 @@ my $todaysissues = ''; my $previssues = ''; my @todaysissues; my @previousissues; +my @relissues; +my @relprevissues; +my $displayrelissues; my $totalprice = 0; -if ($borrower) { -# get each issue of the borrower & separate them in todayissues & previous issues - my ($issueslist) = GetPendingIssues($borrower->{'borrowernumber'}); +sub build_issue_data { + my $issueslist = shift; + my $relatives = shift; + # split in 2 arrays for today & previous foreach my $it ( @$issueslist ) { my $itemtypeinfo = getitemtypeinfo( (C4::Context->preference('item-level_itypes')) ? $it->{'itype'} : $it->{'itemtype'} ); + + # Getting borrower details + my $memberdetails = GetMemberDetails($it->{'borrowernumber'}); + $it->{'borrowername'} = $memberdetails->{'firstname'} . " " . $memberdetails->{'surname'}; + # set itemtype per item-level_itype syspref - FIXME this is an ugly hack $it->{'itemtype'} = ( C4::Context->preference( 'item-level_itypes' ) ) ? $it->{'itype'} : $it->{'itemtype'}; @@ -439,11 +449,28 @@ if ($borrower) { $it->{'renew_failed'} = $renew_failed{$it->{'itemnumber'}}; if ( $todaysdate eq $it->{'issuedate'} or $todaysdate eq $it->{'lastreneweddate'} ) { - push @todaysissues, $it; + (!$relatives) ? push @todaysissues, $it : push @relissues, $it; } else { - push @previousissues, $it; + (!$relatives) ? push @previousissues, $it : push @relprevissues, $it; } } +} + +if ($borrower) { + + # Getting borrower relatives + my @relborrowernumbers = GetMemberRelatives($borrower->{'borrowernumber'}); + #push @borrowernumbers, $borrower->{'borrowernumber'}; + + # get each issue of the borrower & separate them in todayissues & previous issues + my ($issueslist) = GetPendingIssues($borrower->{'borrowernumber'}); + my ($relissueslist) = GetPendingIssues(@relborrowernumbers); + + build_issue_data($issueslist, 0); + build_issue_data($relissueslist, 1); + + $displayrelissues = scalar($relissueslist); + if ( C4::Context->preference( "todaysIssuesDefaultSortOrder" ) eq 'asc' ) { @todaysissues = sort { $a->{'timestamp'} cmp $b->{'timestamp'} } @todaysissues; } @@ -641,6 +668,9 @@ $template->param( totaldue => sprintf('%.2f', $total), todayissues => \@todaysissues, previssues => \@previousissues, + relissues => \@relissues, + relprevissues => \@relprevissues, + displayrelissues => $displayrelissues, inprocess => $inprocess, memberofinstution => $member_of_institution, CGIorganisations => $CGIorganisations, diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc index df1acbf977..87d245e7f0 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc @@ -1,6 +1,6 @@ - Totals: + Totals: diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tmpl index 4d509c3dd3..b7e02d33bd 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tmpl @@ -24,9 +24,19 @@ if($.cookie("holdfor") != ){ $.cookie("ho dateFormat: 'uk', headers: { 1: { sorter: 'articles' },5: { sorter: false },6:{sorter:false},7:{sorter:false},8:{sorter:false}} }); + $("#relissuest").tablesorter({ + dateFormat: 'uk', + headers: { 1: { sorter: 'articles' },5: { sorter: false },6:{sorter:false},7:{sorter:false},8:{sorter:false}} + }); + + //FIXME: Sorting does not work when there are previous checkouts only + // (It works fine when there are only checkouts of the day, or both previous and today checkouts) $("#issuest").bind("sortEnd",function() { $("#previous").parents("tr").remove(); // 'previous checkouts' header chokes table sorter }); + $("#relissuest").bind("sortEnd",function() { + $("#relprevious").parents("tr").remove(); // 'previous checkouts' header chokes table sorter + }); $("#holdst").tablesorter({ dateFormat: 'uk', sortList: [[0,0]], @@ -62,6 +72,25 @@ var allcheckboxes = $(".checkboxed"); $(allcheckboxes).unCheckCheckboxes(":input[name*=barcodes]"); return false; }); + $("#relrenew_all").click(function(){ + $(allcheckboxes).checkCheckboxes(":input[name*=items]"); + $(allcheckboxes).unCheckCheckboxes(":input[name*=barcodes]"); + }); + $("#relCheckAllitems").click(function(){ + $(allcheckboxes).checkCheckboxes(":input[name*=items]"); + $(allcheckboxes).unCheckCheckboxes(":input[name*=barcodes]"); return false; + }); + $("#relCheckNoitems").click(function(){ + $(allcheckboxes).unCheckCheckboxes(":input[name*=items]"); return false; + }); + $("#relCheckAllreturns").click(function(){ + $(allcheckboxes).checkCheckboxes(":input[name*=barcodes]"); + $(allcheckboxes).unCheckCheckboxes(":input[name*=items]"); return false; + }); + $("#relCheckNoreturns").click(function(){ + $(allcheckboxes).unCheckCheckboxes(":input[name*=barcodes]"); return false; + }); + $( '#override_limit' ).click( function () { @@ -659,6 +688,7 @@ No patron matched &type=intra">, by - &itemnumber=#item"> " alt="" /> + @@ -726,6 +756,7 @@ No patron matched + @@ -787,10 +818,77 @@ No patron matched -

Patron has nothing checked out.

+ + + +

Relatives issues

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Due dateTitleItem TypeBranchChecked out onChargeBorrowerMaterial
+ &type=intra">, by - &itemnumber=#item"> " alt="" /> + ()">
Previous checkouts
+ + &type=intra">, by - &itemnumber=#item"> + + + ()">
+ + + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tmpl index 2cdc13a019..d3e71ed12d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tmpl @@ -17,7 +17,11 @@ $(document).ready(function() { $.tablesorter.defaults.widgets = ['zebra']; $("#issuest").tablesorter({ dateFormat: 'uk', - headers: { 1: { sorter: 'articles' },5: { sorter: false },6:{sorter:false},7:{sorter:false},8:{sorter:false}} + headers: { 1: { sorter: 'articles' }} + }); + $("#relissuest").tablesorter({ + dateFormat: 'uk', + headers: { 1: { sorter: 'articles' }} }); $("#holdst").tablesorter({ dateFormat: 'uk', @@ -42,6 +46,13 @@ $(document).ready(function() { $("#CheckAllreturns").click(function(){ $(".checkboxed").checkCheckboxes(":input[name*=barcodes]"); $(".checkboxed").unCheckCheckboxes(":input[name*=items]"); return false; }); $("#CheckNoreturns" ).click(function(){ $(".checkboxed").unCheckCheckboxes(":input[name*=barcodes]"); return false; }); + $("#relrenew_all" ).click(function(){ $(".checkboxed").checkCheckboxes(":input[name*=items]" ); $(".checkboxed").unCheckCheckboxes(":input[name*=barcodes]"); }); + $("#relCheckAllitems" ).click(function(){ $(".checkboxed").checkCheckboxes(":input[name*=items]" ); $(".checkboxed").unCheckCheckboxes(":input[name*=barcodes]"); return false; }); + $("#relCheckNoitems" ).click(function(){ $(".checkboxed").unCheckCheckboxes(":input[name*=items]"); return false; }); + $("#relCheckAllreturns").click(function(){ $(".checkboxed").checkCheckboxes(":input[name*=barcodes]"); $(".checkboxed").unCheckCheckboxes(":input[name*=items]"); return false; }); + $("#relCheckNoreturns" ).click(function(){ $(".checkboxed").unCheckCheckboxes(":input[name*=barcodes]"); return false; }); + + $( '#override_limit' ).click( function () { @@ -398,11 +409,11 @@ function validate1(date) { -
-
" /> " /> +
+ @@ -410,7 +421,7 @@ function validate1(date) { - + @@ -494,7 +505,58 @@ function validate1(date) { -

Patron has nothing checked out.

+

Patron has nothing checked out.

+ + + +

Relatives issues

+
Title Item Type Checked out onCall noCall no Charge Price Renew

select all | none

+ + + + + + + + + + + + + + + + + + + + + + + + class="od"> + + + + + + + + + + + + + + + + + + + + +
Due dateTitleCollectionStock numberBarcodeItem TypeChecked out onBorrowerCall noChargePrice
">, by ; , &itemnumber=#item"> " alt="" />">
+
@@ -543,12 +605,14 @@ function validate1(date) { -
- - -

Patron has nothing on hold.

- -
+ +
+ + +
+

Patron has nothing checked out.

+
+ diff --git a/members/moremember.pl b/members/moremember.pl index bb593c4586..9dcfa3ad21 100755 --- a/members/moremember.pl +++ b/members/moremember.pl @@ -51,6 +51,7 @@ use C4::Reserves; use C4::Branch; # GetBranchName use C4::Form::MessagingPreferences; use C4::NewsChannels; #get slip news +use List::MoreUtils qw/uniq/; #use Smart::Comments; #use Data::Dumper; @@ -239,73 +240,94 @@ if ( C4::Context->preference('OPACPrivacy') ) { # current issues # -my $issue = GetPendingIssues($borrowernumber); +my @borrowernumbers = GetMemberRelatives($borrowernumber); +my $issue = GetPendingIssues($borrowernumber); +my $relissue = GetPendingIssues(@borrowernumbers); my $issuecount = scalar(@$issue); +my $relissuecount = scalar(@$relissue); my $roaddetails = &GetRoadTypeDetails( $data->{'streettype'} ); my $today = POSIX::strftime("%Y-%m-%d", localtime); # iso format my @issuedata; +my @borrowers_with_issues; my $overdues_exist = 0; my $totalprice = 0; -for ( my $i = 0 ; $i < $issuecount ; $i++ ) { - my $datedue = $issue->[$i]{'date_due'}; - my $issuedate = $issue->[$i]{'issuedate'}; - $issue->[$i]{'date_due'} = C4::Dates->new($issue->[$i]{'date_due'}, 'iso')->output('syspref'); - $issue->[$i]{'issuedate'} = C4::Dates->new($issue->[$i]{'issuedate'},'iso')->output('syspref'); - my $biblionumber = $issue->[$i]{'biblionumber'}; - my %row = %{ $issue->[$i] }; - $totalprice += $issue->[$i]{'replacementprice'}; - $row{'replacementprice'} = $issue->[$i]{'replacementprice'}; - # item lost, damaged loops - if ($row{'itemlost'}) { - my $fw = GetFrameworkCode($issue->[$i]{'biblionumber'}); - my $category = GetAuthValCode('items.itemlost',$fw); - my $lostdbh = C4::Context->dbh; - my $sth = $lostdbh->prepare("select lib from authorised_values where category=? and authorised_value =? "); - $sth->execute($category, $row{'itemlost'}); - my $loststat = $sth->fetchrow; - if ($loststat) { - $row{'itemlost'} = $loststat; + +my @issuedata = build_issue_data($issue, $issuecount); +my @relissuedata = build_issue_data($relissue, $relissuecount); + +sub build_issue_data { + my $issue = shift; + my $issuecount = shift; + + my $localissue; + + for ( my $i = 0 ; $i < $issuecount ; $i++ ) { + # Getting borrower details + my $memberdetails = GetMemberDetails($issue->[$i]{'borrowernumber'}); + $issue->[$i]{'borrowername'} = $memberdetails->{'firstname'} . " " . $memberdetails->{'surname'}; + + my $datedue = $issue->[$i]{'date_due'}; + my $issuedate = $issue->[$i]{'issuedate'}; + $issue->[$i]{'date_due'} = C4::Dates->new($issue->[$i]{'date_due'}, 'iso')->output('syspref'); + $issue->[$i]{'issuedate'} = C4::Dates->new($issue->[$i]{'issuedate'},'iso')->output('syspref'); + my $biblionumber = $issue->[$i]{'biblionumber'}; + my %row = %{ $issue->[$i] }; + $totalprice += $issue->[$i]{'replacementprice'}; + $row{'replacementprice'} = $issue->[$i]{'replacementprice'}; + # item lost, damaged loops + if ($row{'itemlost'}) { + my $fw = GetFrameworkCode($issue->[$i]{'biblionumber'}); + my $category = GetAuthValCode('items.itemlost',$fw); + my $lostdbh = C4::Context->dbh; + my $sth = $lostdbh->prepare("select lib from authorised_values where category=? and authorised_value =? "); + $sth->execute($category, $row{'itemlost'}); + my $loststat = $sth->fetchrow; + if ($loststat) { + $row{'itemlost'} = $loststat; + } } - } - if ($row{'damaged'}) { - my $fw = GetFrameworkCode($issue->[$i]{'biblionumber'}); - my $category = GetAuthValCode('items.damaged',$fw); - my $damageddbh = C4::Context->dbh; - my $sth = $damageddbh->prepare("select lib from authorised_values where category=? and authorised_value =? "); - $sth->execute($category, $row{'damaged'}); - my $damagedstat = $sth->fetchrow; - if ($damagedstat) { - $row{'itemdamaged'} = $damagedstat; + if ($row{'damaged'}) { + my $fw = GetFrameworkCode($issue->[$i]{'biblionumber'}); + my $category = GetAuthValCode('items.damaged',$fw); + my $damageddbh = C4::Context->dbh; + my $sth = $damageddbh->prepare("select lib from authorised_values where category=? and authorised_value =? "); + $sth->execute($category, $row{'damaged'}); + my $damagedstat = $sth->fetchrow; + if ($damagedstat) { + $row{'itemdamaged'} = $damagedstat; + } } + # end lost, damaged + if ( $datedue lt $today ) { + $overdues_exist = 1; + $row{'red'} = 1; + } + if ( $issuedate eq $today ) { + $row{'today'} = 1; + } + + #find the charge for an item + my ( $charge, $itemtype ) = + GetIssuingCharges( $issue->[$i]{'itemnumber'}, $borrowernumber ); + + my $itemtypeinfo = getitemtypeinfo($itemtype); + $row{'itemtype_description'} = $itemtypeinfo->{description}; + $row{'itemtype_image'} = $itemtypeinfo->{imageurl}; + + $row{'charge'} = sprintf( "%.2f", $charge ); + + my ( $renewokay,$renewerror ) = CanBookBeRenewed( $borrowernumber, $issue->[$i]{'itemnumber'}, $override_limit ); + $row{'norenew'} = !$renewokay; + $row{'can_confirm'} = ( !$renewokay && $renewerror ne 'on_reserve' ); + $row{"norenew_reason_$renewerror"} = 1 if $renewerror; + $row{'renew_failed'} = $renew_failed{ $issue->[$i]{'itemnumber'} }; + $row{'return_failed'} = $return_failed{$issue->[$i]{'barcode'}}; + push( @$localissue, \%row ); } - # end lost, damaged - if ( $datedue lt $today ) { - $overdues_exist = 1; - $row{'red'} = 1; - } - if ( $issuedate eq $today ) { - $row{'today'} = 1; - } - - #find the charge for an item - my ( $charge, $itemtype ) = - GetIssuingCharges( $issue->[$i]{'itemnumber'}, $borrowernumber ); - - my $itemtypeinfo = getitemtypeinfo($itemtype); - $row{'itemtype_description'} = $itemtypeinfo->{description}; - $row{'itemtype_image'} = $itemtypeinfo->{imageurl}; - - $row{'charge'} = sprintf( "%.2f", $charge ); - - my ( $renewokay,$renewerror ) = CanBookBeRenewed( $borrowernumber, $issue->[$i]{'itemnumber'}, $override_limit ); - $row{'norenew'} = !$renewokay; - $row{'can_confirm'} = ( !$renewokay && $renewerror ne 'on_reserve' ); - $row{"norenew_reason_$renewerror"} = 1 if $renewerror; - $row{'renew_failed'} = $renew_failed{ $issue->[$i]{'itemnumber'} }; - $row{'return_failed'} = $return_failed{$issue->[$i]{'barcode'}}; - push( @issuedata, \%row ); + return $localissue; } + ### ############################################################################### # BUILD HTML # show all reserves of this borrower, and the position of the reservation .... @@ -437,8 +459,10 @@ $template->param( totalprice => sprintf("%.2f", $totalprice), totaldue => sprintf("%.2f", $total), totaldue_raw => $total, - issueloop => \@issuedata, - issuecount => $issuecount, + issueloop => @issuedata, + relissueloop => @relissuedata, + issuecount => $issuecount, + relissuecount => $relissuecount, overdues_exist => $overdues_exist, error => $error, $error => 1, -- 2.39.5