Bugzilla – Attachment 32786 Details for
Bug 8367
How long is a hold waiting for pickup at a more granular level
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 8367 - How long is a hold waiting for pickup at a more granular level
Bug-8367---How-long-is-a-hold-waiting-for-pickup-a.patch (text/plain), 42.82 KB, created by
Olli-Antti Kivilahti
on 2014-10-27 11:17:04 UTC
(
hide
)
Description:
Bug 8367 - How long is a hold waiting for pickup at a more granular level
Filename:
MIME Type:
Creator:
Olli-Antti Kivilahti
Created:
2014-10-27 11:17:04 UTC
Size:
42.82 KB
patch
obsolete
>From 6d97cc995d1bfa991d67cc20d026dd56d058d64b Mon Sep 17 00:00:00 2001 >From: Olli-Antti Kivilahti <olli-antti.kivilahti@jns.fi> >Date: Fri, 24 Oct 2014 19:55:48 +0300 >Subject: [PATCH] Bug 8367 - How long is a hold waiting for pickup at a more > granular level > >This patch adds: >- a new column in the issuing rules, including help topics. >- a new column reserves.lastpickupdate (+old_reserves) > It contains the waitingdate + the corresponding "holds pickup wait". > Each time the waitingdate is modified, this value will be modified too. >- a new field issuingrules.holdspickupwait >- a new function C4::Reserves::MoveWaitingdate() to help in testing this feature. > >This patch removes the ReservesMaxPickUpDelay syspref. >- Also removes a code section from C4::Letters::_parseLetter() which worked blatantly > disrespectfully towards Koha Calendar. >- TODO put the <<reserves.lastpickupdate>> as a placeholder in C4::Letters. >- TODO figure out how to rename existing letter placeholders <<expirationdate>> with <<lastpickupdate>> > >The update database script will update the issuingrules table with the >correct value before removing it. > >You can now specify a pickup delay for an hold function of a patron >category and/or a item type and/or a library. > >-TODO Refactoring unit tests is in progress. > >$$$$$$$$$$$$$ >$ TEST PLAN $ >$$$$$$$$$$$$$ > > ****** ****** >*** *** *** TEST: BASIC WORKFLOW * > ****** ****** >1. Check there is no regression with a normal reserve workflow. >2. Add one or more issuingrules. >3. Update the new column 'Holds pickup wait' in your issuing rules. >4. In 4 templates, you can see the 'Last pickup date' for an hold > (circ/circulation.tt, circ/waitingreserves.tt, members/moremember.tt, > opac-user.tt). >5. According to a library and an item type, the lastpickupdate value will be > equal to the waiting date + the "holds pickup wait" defined. > > ** ** ** ** ** ** >*** *** *** TEST: RESPECTING CALENDAR HOLIDAYS * > ** ** ** ** ** ** >1) Note your ReservesMaxPickUpDelay setting. >2) Create and trap a hold >3) View waitingreserves.pl, note the last pickup date, and the pickup > location >4) Cancel this hold >5) Edit the calendar for the given location, and make the pickup date a > single, unrepeated, holiday. Then make the next day a weekly repeating holiday. > Then make the next two days an annual holiday repeatable every year. >6) Repeat step 2 >7) View waitingreserves.pl, the last pickup date for this new hold > should now be increased by four days. > > ** ** ** ** ** ** >*** *** *** TEST: LETTER lastpickupdate PLACEHOLDER AND REGRESSION * > ** ** ** ** ** ** >1. Modify the HOLD-letter, add <<reserves.lastpickupdate>> and <<reserves.waitingdate>> > somewhere. >2. Catch a hold for a borrower. >3. See the members/notices.pl for the message queued and verify that the > lastpickupdate-placeholder is set in your desired datetime format and > that it is not on a holiday. Verify that the waitingdate is today. >--- > C4/Letters.pm | 15 -- > C4/Reserves.pm | 194 +++++++++++++++++--- > Koha/Schema/Result/Reserve.pm | 7 + > admin/smart-rules.pl | 9 +- > circ/waitingreserves.pl | 56 +++--- > installer/data/mysql/kohastructure.sql | 3 + > installer/data/mysql/updatedatabase.pl | 31 ++++ > koha-tmpl/intranet-tmpl/prog/en/js/holds.js | 3 + > .../en/modules/admin/preferences/circulation.pref | 7 +- > .../prog/en/modules/admin/smart-rules.tt | 4 + > .../prog/en/modules/circ/circulation.tt | 1 + > .../prog/en/modules/circ/waitingreserves.tt | 8 +- > .../prog/en/modules/help/admin/smart-rules.tt | 1 + > .../prog/en/modules/help/circ/waitingreserves.tt | 2 +- > .../prog/en/modules/members/moremember.tt | 1 + > .../opac-tmpl/bootstrap/en/modules/opac-user.tt | 2 +- > svc/holds | 7 +- > 17 files changed, 265 insertions(+), 86 deletions(-) > >diff --git a/C4/Letters.pm b/C4/Letters.pm >index 912294e..01207af 100644 >--- a/C4/Letters.pm >+++ b/C4/Letters.pm >@@ -602,21 +602,6 @@ sub _parseletter_sth { > sub _parseletter { > my ( $letter, $table, $values ) = @_; > >- if ( $table eq 'reserves' && $values->{'waitingdate'} ) { >- my @waitingdate = split /-/, $values->{'waitingdate'}; >- >- $values->{'expirationdate'} = ''; >- if( C4::Context->preference('ExpireReservesMaxPickUpDelay') && >- C4::Context->preference('ReservesMaxPickUpDelay') ) { >- my $dt = dt_from_string(); >- $dt->add( days => C4::Context->preference('ReservesMaxPickUpDelay') ); >- $values->{'expirationdate'} = output_pref({ dt => $dt, dateonly => 1 }); >- } >- >- $values->{'waitingdate'} = output_pref({ dt => dt_from_string( $values->{'waitingdate'} ), dateonly => 1 }); >- >- } >- > if ($letter->{content} && $letter->{content} =~ /<<today>>/) { > my $todaysdate = output_pref( DateTime->now() ); > $letter->{content} =~ s/<<today>>/$todaysdate/go; >diff --git a/C4/Reserves.pm b/C4/Reserves.pm >index 7a075a4..3a2952d 100644 >--- a/C4/Reserves.pm >+++ b/C4/Reserves.pm >@@ -175,6 +175,9 @@ sub AddReserve { > $waitingdate = $resdate; > } > >+ my $item = C4::Items::GetItem( $checkitem ); >+ my $lastpickupdate = GetLastPickupDate( undef, $item ); >+ > #eval { > # updates take place here > if ( $fee > 0 ) { >@@ -194,16 +197,16 @@ sub AddReserve { > my $query = qq/ > INSERT INTO reserves > (borrowernumber,biblionumber,reservedate,branchcode,constrainttype, >- priority,reservenotes,itemnumber,found,waitingdate,expirationdate) >+ priority,reservenotes,itemnumber,found,waitingdate,expirationdate,lastpickupdate) > VALUES > (?,?,?,?,?, >- ?,?,?,?,?,?) >+ ?,?,?,?,?,?,?) > /; > my $sth = $dbh->prepare($query); > $sth->execute( > $borrowernumber, $biblionumber, $resdate, $branch, > $const, $priority, $notes, $checkitem, >- $found, $waitingdate, $expdate >+ $found, $waitingdate, $expdate, $lastpickupdate > ); > > # Send e-mail to librarian if syspref is active >@@ -806,10 +809,10 @@ sub GetReservesToBranch { > > sub GetReservesForBranch { > my ($frombranch) = @_; >- my $dbh = C4::Context->dbh; > >- my $query = " >- SELECT reserve_id,borrowernumber,reservedate,itemnumber,waitingdate >+ my $dbh = C4::Context->dbh; >+ my $query = " >+ SELECT reserve_id, borrowernumber, reservedate, itemnumber, waitingdate, lastpickupdate > FROM reserves > WHERE priority='0' > AND found='W' >@@ -874,6 +877,93 @@ sub GetReserveStatus { > return ''; # empty string here will remove need for checking undef, or less log lines > } > >+=head2 GetLastPickupDate >+ >+ my $lastpickupdate = GetLastPickupDate($reserve, $item); >+ my $lastpickupdate = GetLastPickupDate($reserve, $item, $borrower); >+ my $lastpickupdate = GetLastPickupDate(undef, $item); >+ >+Gets the last pickup date from the issuingrules for the given reserves-row and sets the >+$reserve->{lastpickupdate}.-value. >+If the reserves-row is not passed, function tries to figure it out from the item-row. >+ >+Calculating the last pickup date respects Calendar holidays and skips to the next open day. >+ >+@PARAM1 koha.reserves-row >+@PARAM2 koha.items-row, If the reserve is not given, an item must be given to be >+ able to find a reservation >+@PARAM3 koha.borrowers-row, OPTIONAL >+RETURNS DateTime, depicting the last pickup date. >+=cut >+ >+sub GetLastPickupDate { >+ my ($reserve, $item, $borrower) = @_; >+ >+ ##Verify parameters >+ if ( not defined $reserve and not defined $item ) { >+ warn "C4::Reserves::GetMaxPickupDate(), is called without a reserve and a item"; >+ return; >+ } >+ if ( defined $reserve and not defined $item ) { >+ $item = C4::Items::GetItem( $reserve->{itemnumber} ); >+ } >+ unless ( defined $reserve ) { >+ my $reserve = GetReservesFromItemnumber( $item->{itemnumber} ); >+ } >+ >+ my $date = $reserve->{waitingdate}; >+ unless ( $date ) { #It is possible that a reserve is just caught and it doesn't have a waitingdate yet. >+ $date = DateTime->now( time_zone => C4::Context->tz() ); #So default to NOW() >+ } >+ else { >+ $date = (ref $reserve->{waitingdate} eq 'DateTime') ? $reserve->{waitingdate} : dt_from_string($reserve->{waitingdate}); >+ } >+ $borrower = C4::Members::GetMember( 'borrowernumber' => $reserve->{borrowernumber} ) unless $borrower; >+ >+ ##Get churning the LastPickupDate >+ my $controlbranch = GetReservesControlBranch( $item, $borrower ); >+ >+ my $issuingrule = C4::Circulation::GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $controlbranch ); >+ >+ my $holdspickupwait = 0; >+ if ( defined($issuingrule) >+ and defined $issuingrule->{holdspickupwait} ) { >+ $holdspickupwait = $issuingrule->{holdspickupwait} >+ } >+ $date->add( days => $holdspickupwait ); >+ >+ my $calendar = Koha::Calendar->new( branchcode => $reserve->{'branchcode'} ); >+ my $is_holiday = $calendar->is_holiday( $date ); >+ >+ while ( $is_holiday ) { >+ $date->add( days => 1 ); >+ $is_holiday = $calendar->is_holiday( $date ); >+ } >+ >+ $reserve->{lastpickupdate} = $date->ymd(); >+ return $date; >+} >+=head2 GetReservesControlBranch >+ >+ $branchcode = &GetReservesControlBranch($borrower, $item) >+ >+Returns the branchcode to consider to check hold rules against >+ >+=cut >+ >+sub GetReservesControlBranch { >+ my ( $borrower, $item ) = @_; >+ my $controlbranch = C4::Context->preference('ReservesControlBranch'); >+ my $hbr = C4::Context->preference('HomeOrHoldingBranch') || "homebranch"; >+ my $branchcode = "*"; >+ if ( $controlbranch eq "ItemHomeLibrary" ) { >+ $branchcode = $item->{$hbr}; >+ } elsif ( $controlbranch eq "PatronLibrary" ) { >+ $branchcode = $borrower->{branchcode}; >+ } >+ return $branchcode; >+} >+ > =head2 CheckReserves > > ($status, $reserve, $all_reserves) = &CheckReserves($itemnumber); >@@ -1018,15 +1108,14 @@ sub CancelExpiredReserves { > > # Cancel reserves that have been waiting too long > if ( C4::Context->preference("ExpireReservesMaxPickUpDelay") ) { >- my $max_pickup_delay = C4::Context->preference("ReservesMaxPickUpDelay"); > my $charge = C4::Context->preference("ExpireReservesMaxPickUpDelayCharge"); > my $cancel_on_holidays = C4::Context->preference('ExpireReservesOnHolidays'); > > my $today = dt_from_string(); > >- my $query = "SELECT * FROM reserves WHERE TO_DAYS( NOW() ) - TO_DAYS( waitingdate ) > ? AND found = 'W' AND priority = 0"; >+ my $query = "SELECT * FROM reserves WHERE NOW() > lastpickupdate AND found = 'W' AND priority = 0"; > $sth = $dbh->prepare( $query ); >- $sth->execute( $max_pickup_delay ); >+ $sth->execute(); > > while ( my $res = $sth->fetchrow_hashref ) { > my $do_cancel = 1; >@@ -1284,9 +1373,28 @@ sub ModReserveStatus { > my ($itemnumber, $newstatus) = @_; > my $dbh = C4::Context->dbh; > >- my $query = "UPDATE reserves SET found = ?, waitingdate = NOW() WHERE itemnumber = ? AND found IS NULL AND priority = 0"; >+ my $now = dt_from_string; >+ my $reserve = $dbh->selectrow_hashref(q{ >+ SELECT * >+ FROM reserves >+ WHERE itemnumber = ? >+ AND found IS NULL >+ AND priority = 0 >+ }, {}, $itemnumber); >+ return unless $reserve; >+ >+ my $lastpickupdate = GetLastPickupDate( $reserve ); >+ my $query = q{ >+ UPDATE reserves >+ SET found = ?, >+ waitingdate = ?, >+ maxpickupdate = ? >+ WHERE itemnumber = ? >+ AND found IS NULL >+ AND priority = 0 >+ }; > my $sth_set = $dbh->prepare($query); >- $sth_set->execute( $newstatus, $itemnumber ); >+ $sth_set->execute( $newstatus, $now, $lastpickupdate, $itemnumber ); > > if ( C4::Context->preference("ReturnToShelvingCart") && $newstatus ) { > CartToShelf( $itemnumber ); >@@ -1331,29 +1439,34 @@ sub ModReserveAffect { > # If we affect a reserve that has to be transfered, don't set to Waiting > my $query; > if ($transferToDo) { >- $query = " >- UPDATE reserves >- SET priority = 0, >- itemnumber = ?, >- found = 'T' >- WHERE borrowernumber = ? >- AND biblionumber = ? >- "; >+ $query = " >+ UPDATE reserves >+ SET priority = 0, >+ itemnumber = ?, >+ found = 'T' >+ WHERE borrowernumber = ? >+ AND biblionumber = ? >+ "; >+ $sth = $dbh->prepare($query); >+ $sth->execute( $itemnumber, $borrowernumber,$biblionumber); > } > else { >- # affect the reserve to Waiting as well. >+ # affect the reserve to Waiting as well. >+ my $item = C4::Items::GetItem( $itemnumber ); >+ my $lastpickupdate = GetLastPickupDate( $request, $item ); > $query = " > UPDATE reserves > SET priority = 0, > found = 'W', > waitingdate = NOW(), >+ lastpickupdate = ?, > itemnumber = ? > WHERE borrowernumber = ? > AND biblionumber = ? > "; >+ $sth = $dbh->prepare($query); >+ $sth->execute( $lastpickupdate, $itemnumber, $borrowernumber,$biblionumber); > } >- $sth = $dbh->prepare($query); >- $sth->execute( $itemnumber, $borrowernumber,$biblionumber); > _koha_notify_reserve( $itemnumber, $borrowernumber, $biblionumber ) if ( !$transferToDo && !$already_on_shelf ); > _FixPriority( { biblionumber => $biblionumber } ); > if ( C4::Context->preference("ReturnToShelvingCart") ) { >@@ -1429,6 +1542,7 @@ sub GetReserveInfo { > reserves.biblionumber, > reserves.branchcode, > reserves.waitingdate, >+ reserves.lastpickupdate, > notificationdate, > reminderdate, > priority, >@@ -1840,6 +1954,7 @@ sub _Findgroupreserve { > reserves.borrowernumber AS borrowernumber, > reserves.reservedate AS reservedate, > reserves.branchcode AS branchcode, >+ reserves.lastpickupdate AS maxpickupdate, > reserves.cancellationdate AS cancellationdate, > reserves.found AS found, > reserves.reservenotes AS reservenotes, >@@ -1872,6 +1987,7 @@ sub _Findgroupreserve { > reserves.borrowernumber AS borrowernumber, > reserves.reservedate AS reservedate, > reserves.branchcode AS branchcode, >+ reserves.lastpickupdate AS maxpickupdate, > reserves.cancellationdate AS cancellationdate, > reserves.found AS found, > reserves.reservenotes AS reservenotes, >@@ -1904,6 +2020,7 @@ sub _Findgroupreserve { > reserves.reservedate AS reservedate, > reserves.waitingdate AS waitingdate, > reserves.branchcode AS branchcode, >+ reserves.lastpickupdate AS maxpickupdate, > reserves.cancellationdate AS cancellationdate, > reserves.found AS found, > reserves.reservenotes AS reservenotes, >@@ -2117,6 +2234,36 @@ sub MoveReserve { > } > } > >+=head MoveWaitingdate >+ >+ #Move waitingdate two months and fifteen days forward. >+ my $dateDuration = DateTime::Duration->new( months => 2, days => 15 ); >+ $reserve = MoveWaitingdate( $reserve, $dateDuration); >+ >+ #Move waitingdate one year and eleven days backwards. >+ my $dateDuration = DateTime::Duration->new( years => -1, days => -11 ); >+ $reserve = MoveWaitingdate( $reserve, $dateDuration); >+ >+Moves the waitingdate and updates the lastpickupdate to match. >+Is intended to be used from automated tests, because under normal library >+operations there should be NO REASON to move the waitingdate. >+ >+@PARAM1 koha.reserves-row, with waitingdate set. >+@PARAM2 DateTime::Duration, with the desired offset. >+RETURNS koha.reserve-row, with keys waitingdate and lastpickupdate updated. >+=cut >+sub MoveWaitingdate { >+ my ($reserve, $dateDuration) = @_; >+ >+ my $dt = dt_from_string( $reserve->{waitingdate} ); >+ $dt->add_duration( $dateDuration ); >+ $reserve->{waitingdate} = $dateDuration->ymd(); >+ >+ GetLastPickupDate( $reserve ); #Update the $reserve->{lastpickupdate} >+ >+ return $reserve; >+} >+ > =head2 MergeHolds > > MergeHolds($dbh,$to_biblio, $from_biblio); >@@ -2213,7 +2360,8 @@ sub RevertWaitingStatus { > SET > priority = 1, > found = NULL, >- waitingdate = NULL >+ waitingdate = NULL, >+ lastpickupdate = NULL, > WHERE > reserve_id = ? > "; >diff --git a/Koha/Schema/Result/Reserve.pm b/Koha/Schema/Result/Reserve.pm >index 16f951b..894febe 100644 >--- a/Koha/Schema/Result/Reserve.pm >+++ b/Koha/Schema/Result/Reserve.pm >@@ -139,6 +139,11 @@ __PACKAGE__->table("reserves"); > datetime_undef_if_invalid: 1 > is_nullable: 1 > >+=head2 lastpickupdate >+ date_type: 'date' >+ datetime_undef_if_invalid: 1 >+ is_nullable: 1 >+ > =cut > > __PACKAGE__->add_columns( >@@ -199,6 +204,8 @@ __PACKAGE__->add_columns( > datetime_undef_if_invalid => 1, > is_nullable => 1, > }, >+ "lastpickupdate", >+ { data_type => "date", datetime_undef_if_invalid => 1, is_nullable => 1 }, > ); > > =head1 PRIMARY KEY >diff --git a/admin/smart-rules.pl b/admin/smart-rules.pl >index eb3e875..a0d8dc0 100755 >--- a/admin/smart-rules.pl >+++ b/admin/smart-rules.pl >@@ -101,8 +101,8 @@ elsif ($op eq 'delete-branch-item') { > # save the values entered > elsif ($op eq 'add') { > my $sth_search = $dbh->prepare('SELECT COUNT(*) AS total FROM issuingrules WHERE branchcode=? AND categorycode=? AND itemtype=?'); >- my $sth_insert = $dbh->prepare('INSERT INTO issuingrules (branchcode, categorycode, itemtype, maxissueqty, renewalsallowed, renewalperiod, norenewalbefore, auto_renew, reservesallowed, issuelength, lengthunit, hardduedate, hardduedatecompare, fine, finedays, maxsuspensiondays, firstremind, chargeperiod,rentaldiscount, overduefinescap) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'); >- my $sth_update=$dbh->prepare("UPDATE issuingrules SET fine=?, finedays=?, maxsuspensiondays=?, firstremind=?, chargeperiod=?, maxissueqty=?, renewalsallowed=?, renewalperiod=?, norenewalbefore=?, auto_renew=?, reservesallowed=?, issuelength=?, lengthunit = ?, hardduedate=?, hardduedatecompare=?, rentaldiscount=?, overduefinescap=? WHERE branchcode=? AND categorycode=? AND itemtype=?"); >+ my $sth_insert = $dbh->prepare('INSERT INTO issuingrules (branchcode, categorycode, itemtype, maxissueqty, renewalsallowed, renewalperiod, norenewalbefore, auto_renew, reservesallowed, holdspickupwait, issuelength, lengthunit, hardduedate, hardduedatecompare, fine, finedays, maxsuspensiondays, firstremind, chargeperiod,rentaldiscount, overduefinescap) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'); >+ my $sth_update=$dbh->prepare("UPDATE issuingrules SET fine=?, finedays=?, maxsuspensiondays=?, firstremind=?, chargeperiod=?, maxissueqty=?, renewalsallowed=?, renewalperiod=?, norenewalbefore=?, auto_renew=?, reservesallowed=?, holdspickupwait=?, issuelength=?, lengthunit = ?, hardduedate=?, hardduedatecompare=?, rentaldiscount=?, overduefinescap=? WHERE branchcode=? AND categorycode=? AND itemtype=?"); > > my $br = $branch; # branch > my $bor = $input->param('categorycode'); # borrower category >@@ -120,6 +120,7 @@ elsif ($op eq 'add') { > $norenewalbefore = undef if $norenewalbefore eq '0' or $norenewalbefore =~ /^\s*$/; > my $auto_renew = $input->param('auto_renew') eq 'yes' ? 1 : 0; > my $reservesallowed = $input->param('reservesallowed'); >+ my $holdspickupwait = $input->param('holdspickupwait'); > $maxissueqty =~ s/\s//g; > $maxissueqty = undef if $maxissueqty !~ /^\d+/; > my $issuelength = $input->param('issuelength'); >@@ -134,9 +135,9 @@ elsif ($op eq 'add') { > $sth_search->execute($br,$bor,$cat); > my $res = $sth_search->fetchrow_hashref(); > if ($res->{total}) { >- $sth_update->execute($fine, $finedays, $maxsuspensiondays, $firstremind, $chargeperiod, $maxissueqty, $renewalsallowed, $renewalperiod, $norenewalbefore, $auto_renew, $reservesallowed, $issuelength,$lengthunit, $hardduedate,$hardduedatecompare,$rentaldiscount,$overduefinescap, $br,$bor,$cat); >+ $sth_update->execute($fine, $finedays, $maxsuspensiondays, $firstremind, $chargeperiod, $maxissueqty, $renewalsallowed, $renewalperiod, $norenewalbefore, $auto_renew, $reservesallowed, $holdspickupwait, $issuelength,$lengthunit, $hardduedate,$hardduedatecompare,$rentaldiscount,$overduefinescap, $br,$bor,$cat); > } else { >- $sth_insert->execute($br,$bor,$cat,$maxissueqty,$renewalsallowed, $renewalperiod, $norenewalbefore, $auto_renew, $reservesallowed,$issuelength,$lengthunit,$hardduedate,$hardduedatecompare,$fine,$finedays, $maxsuspensiondays, $firstremind,$chargeperiod,$rentaldiscount,$overduefinescap); >+ $sth_insert->execute($br,$bor,$cat, $maxissueqty, $renewalsallowed, $renewalperiod, $norenewalbefore, $auto_renew, $reservesallowed, $holdspickupwait, $issuelength, $lengthunit, $hardduedate, $hardduedatecompare, $fine, $finedays, $maxsuspensiondays, $firstremind, $chargeperiod, $rentaldiscount, $overduefinescap); > } > } > elsif ($op eq "set-branch-defaults") { >diff --git a/circ/waitingreserves.pl b/circ/waitingreserves.pl >index 07190a1..0a6d3b6 100755 >--- a/circ/waitingreserves.pl >+++ b/circ/waitingreserves.pl >@@ -27,17 +27,14 @@ use C4::Branch; # GetBranchName > use C4::Auth; > use C4::Dates qw/format_date/; > use C4::Circulation; >+use C4::Reserves; > use C4::Members; > use C4::Biblio; > use C4::Items; > >-use Date::Calc qw( >- Today >- Add_Delta_Days >- Date_to_Days >-); > use C4::Reserves; > use C4::Koha; >+use Koha::DateUtils; > > my $input = new CGI; > >@@ -86,31 +83,44 @@ my ($reservcount, $overcount); > my @getreserves = $all_branches ? GetReservesForBranch() : GetReservesForBranch($default); > # get reserves for the branch we are logged into, or for all branches > >-my $today = Date_to_Days(&Today); >+my $today = dt_from_string; > foreach my $num (@getreserves) { > next unless ($num->{'waitingdate'} && $num->{'waitingdate'} ne '0000-00-00'); > > my $itemnumber = $num->{'itemnumber'}; > my $gettitle = GetBiblioFromItemNumber( $itemnumber ); >- my $borrowernum = $num->{'borrowernumber'}; >+ my $borrowernumber = $num->{'borrowernumber'}; > my $holdingbranch = $gettitle->{'holdingbranch'}; > my $homebranch = $gettitle->{'homebranch'}; > > my %getreserv = ( > itemnumber => $itemnumber, >- borrowernum => $borrowernum, >+ borrowernum => $borrowernumber, > ); > > # fix up item type for display > $gettitle->{'itemtype'} = C4::Context->preference('item-level_itypes') ? $gettitle->{'itype'} : $gettitle->{'itemtype'}; > my $getborrower = GetMember(borrowernumber => $num->{'borrowernumber'}); > my $itemtypeinfo = getitemtypeinfo( $gettitle->{'itemtype'} ); # using the fixed up itype/itemtype >- $getreserv{'waitingdate'} = $num->{'waitingdate'}; >- my ( $waiting_year, $waiting_month, $waiting_day ) = split (/-/, $num->{'waitingdate'}); >- ( $waiting_year, $waiting_month, $waiting_day ) = >- Add_Delta_Days( $waiting_year, $waiting_month, $waiting_day, >- C4::Context->preference('ReservesMaxPickUpDelay')); >- my $calcDate = Date_to_Days( $waiting_year, $waiting_month, $waiting_day ); >+ >+ if ( $num->{waitingdate} ) { >+ my $lastpickupdate = dt_from_string($num->{lastpickupdate}); >+ $getreserv{waitingdate} = $num->{waitingdate}; >+ $getreserv{lastpickupdate} = $num->{lastpickupdate}; >+ if ( DateTime->compare( $today, $lastpickupdate ) == 1 ) { >+ if ($cancelall) { >+ my $res = cancel( $itemnumber, $borrowernumber, $holdingbranch, $homebranch, !$transfer_when_cancel_all ); >+ push @cancel_result, $res if $res; >+ next; >+ } else { >+ push @overloop, \%getreserv; >+ $overcount++; >+ } >+ }else{ >+ push @reservloop, \%getreserv; >+ $reservcount++; >+ } >+ } > > $getreserv{'itemtype'} = $itemtypeinfo->{'description'}; > $getreserv{'title'} = $gettitle->{'title'}; >@@ -129,26 +139,11 @@ foreach my $num (@getreserves) { > $getreserv{'borrowerfirstname'} = $getborrower->{'firstname'}; > $getreserv{'borrowerphone'} = $getborrower->{'phone'}; > >- my $borEmail = GetFirstValidEmailAddress( $borrowernum ); >+ my $borEmail = GetFirstValidEmailAddress( $borrowernumber ); > > if ( $borEmail ) { > $getreserv{'borrowermail'} = $borEmail; > } >- >- if ($today > $calcDate) { >- if ($cancelall) { >- my $res = cancel( $itemnumber, $borrowernum, $holdingbranch, $homebranch, !$transfer_when_cancel_all ); >- push @cancel_result, $res if $res; >- next; >- } else { >- push @overloop, \%getreserv; >- $overcount++; >- } >- }else{ >- push @reservloop, \%getreserv; >- $reservcount++; >- } >- > } > > $template->param(cancel_result => \@cancel_result) if @cancel_result; >@@ -158,7 +153,6 @@ $template->param( > overloop => \@overloop, > overcount => $overcount, > show_date => format_date(C4::Dates->today('iso')), >- ReservesMaxPickUpDelay => C4::Context->preference('ReservesMaxPickUpDelay') > ); > > if ($cancelall) { >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index e33c168..2f0c24b 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -1163,6 +1163,7 @@ CREATE TABLE `issuingrules` ( -- circulation and fine rules > `norenewalbefore` int(4) default NULL, -- no renewal allowed until X days or hours before due date. In the unit set in issuingrules.lengthunit > `auto_renew` BOOLEAN default FALSE, -- automatic renewal > `reservesallowed` smallint(6) NOT NULL default "0", -- how many holds are allowed >+ `holdspickupwait` int(11) default NULL, -- How many open library days a hold can wait in the pickup shelf until it becomes problematic > `branchcode` varchar(10) NOT NULL default '', -- the branch this rule is for (branches.branchcode) > overduefinescap decimal(28,6) default NULL, -- the maximum amount of an overdue fine > PRIMARY KEY (`branchcode`,`categorycode`,`itemtype`), >@@ -1634,6 +1635,7 @@ CREATE TABLE `old_reserves` ( -- this table holds all holds/reserves that have b > `lowestPriority` tinyint(1) NOT NULL, -- has this hold been pinned to the lowest priority in the holds queue (1 for yes, 0 for no) > `suspend` BOOLEAN NOT NULL DEFAULT 0, -- in this hold suspended (1 for yes, 0 for no) > `suspend_until` DATETIME NULL DEFAULT NULL, -- the date this hold is suspended until (NULL for infinitely) >+ `lastpickupdate` date NULL DEFAULT NULL, -- the last day this hold is available for pickup, until it becomes problematic > PRIMARY KEY (`reserve_id`), > KEY `old_reserves_borrowernumber` (`borrowernumber`), > KEY `old_reserves_biblionumber` (`biblionumber`), >@@ -1836,6 +1838,7 @@ CREATE TABLE `reserves` ( -- information related to holds/reserves in Koha > `lowestPriority` tinyint(1) NOT NULL, > `suspend` BOOLEAN NOT NULL DEFAULT 0, > `suspend_until` DATETIME NULL DEFAULT NULL, >+ `lastpickupdate` date NULL DEFAULT NULL, -- the last day this hold is available for pickup, until it becomes problematic > PRIMARY KEY (`reserve_id`), > KEY priorityfoundidx (priority,found), > KEY `borrowernumber` (`borrowernumber`), >diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl >index e34d214..d916de7 100755 >--- a/installer/data/mysql/updatedatabase.pl >+++ b/installer/data/mysql/updatedatabase.pl >@@ -8838,6 +8838,37 @@ if ( CheckVersion($DBversion) ) { > SetVersion($DBversion); > } > >+$DBversion = "3.17.00.XXX"; >+if ( CheckVersion($DBversion) ) { >+ my $maxpickupdelay = C4::Context->preference('ReservesMaxPickUpDelay') || 0; #MaxPickupDelay >+ #$dbh->do(q{ >+ # DELETE FROM systempreferences WHERE variable='ReservesMaxPickUpDelay'; >+ # //DELETE FROM systempreferences WHERE variable='ExpireReservesMaxPickUpDelay'; #This syspref is not needed and would be better suited to be calculated from the holdspickupwait >+ # //ExpireReservesMaxPickUpDelayCharge #This could be added as a column to the issuing rules. >+ #}); >+ $dbh->do(qq{ >+ ALTER TABLE issuingrules ADD COLUMN holdspickupwait INT(11) NULL default NULL AFTER reservesallowed; >+ }); >+ my $sth = $dbh->prepare(q{ >+ UPDATE issuingrules SET holdspickupwait = ? >+ }); >+ $sth->execute( $maxpickupdelay ); >+ $dbh->do(q{ >+ ALTER TABLE reserves ADD COLUMN lastpickupdate DATE NULL default NULL AFTER suspend_until; >+ }); >+ #$sth = $dbh->prepare(q{ #THIS NOT WORKY WORKY BECAUSE OF HOLIDAYS >+ # UPDATE reserves SET lastpickupdate = ADDDATE(waitingdate, INTERVAL ? DAY); >+ #}); >+ #$sth->execute( $maxpickupdelay ); >+ #TODO Make a function to migrate this value from. >+ $dbh->do(q{ >+ ALTER TABLE old_reserves ADD COLUMN lastpickupdate DATE NULL default NULL AFTER suspend_until; >+ }); >+ print "Upgrade to $DBversion done (8367: Add colum issuingrules.holdspickupwait and reserves.lastpickupdate. Delete the ReservesMaxPickUpDelay syspref)\n"; >+ SetVersion($DBversion); >+} >+ >+ > =head1 FUNCTIONS > > =head2 TableExists($table) >diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/holds.js b/koha-tmpl/intranet-tmpl/prog/en/js/holds.js >index 73807ea..1d325c0 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/js/holds.js >+++ b/koha-tmpl/intranet-tmpl/prog/en/js/holds.js >@@ -11,6 +11,9 @@ $(document).ready(function() { > "mDataProp": "reservedate_formatted" > }, > { >+ "mDataProp": "lastpickupdate_formatted" >+ }, >+ { > "mDataProp": function ( oObj ) { > title = "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" > + oObj.biblionumber >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 2190004..5150455 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 >@@ -427,16 +427,11 @@ Circulation: > PatronLibrary: "patron's home library" > - to see if the patron can place a hold on the item. > - >- - Mark a hold as problematic if it has been waiting for more than >- - pref: ReservesMaxPickUpDelay >- class: integer >- - days. >- - > - pref: ExpireReservesMaxPickUpDelay > choices: > yes: Allow > no: "Don't allow" >- - "holds to expire automatically if they have not been picked by within the time period specified in ReservesMaxPickUpDelay" >+ - "holds to expire automatically if they have not been picked by within the time period specified in hold pickup delay defined in the issuing rules" > - > - If using ExpireReservesMaxPickUpDelay, charge a borrower who allows his or her waiting hold to expire a fee of > - pref: ExpireReservesMaxPickUpDelayCharge >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt >index 8bc5809..a7fa8e0 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt >@@ -117,6 +117,7 @@ $(document).ready(function() { > <li>default (all libraries), all patron types, same item type</li> > <li>default (all libraries), all patron types, all item types</li> > </ul> >+ <p>To get more information about how these settings affect Koha, hover your cursor over a column header.</p> > <p>To modify a rule, create a new one with the same patron type and item type.</p> > </div> > <div> >@@ -153,6 +154,7 @@ for="tobranch"><strong>Clone these rules to:</strong></label> <input type="hidde > <th>Max. suspension duration (day)</th> > <th>Renewals allowed (count)</th> > <th>Renewal period</th> >+ <th>Holds wait for pickup (day)</th> > <th>No renewal before</th> > <th>Automatic renewal</th> > <th>Holds allowed (count)</th> >@@ -209,6 +211,7 @@ for="tobranch"><strong>Clone these rules to:</strong></label> <input type="hidde > <td>[% rule.maxsuspensiondays %]</td> > <td>[% rule.renewalsallowed %]</td> > <td>[% rule.renewalperiod %]</td> >+ <td>[% rule.holdspickupwait %]</td> > <td>[% rule.norenewalbefore %]</td> > <td> > [% IF ( rule.auto_renew ) %] >@@ -267,6 +270,7 @@ for="tobranch"><strong>Clone these rules to:</strong></label> <input type="hidde > <td><input type="text" name="maxsuspensiondays" id="maxsuspensiondays" size="3" /> </td> > <td><input type="text" name="renewalsallowed" id="renewalsallowed" size="2" /></td> > <td><input type="text" name="renewalperiod" id="renewalperiod" size="3" /></td> >+ <td><input type="text" name="holdspickupwait" id="holdspickupwait" size="2" /></td> > <td><input type="text" name="norenewalbefore" id="norenewalbefore" size="3" /></td> > <td> > <select name="auto_renew" id="auto_renew"> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >index 3708e0e..6e732ba 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >@@ -776,6 +776,7 @@ No patron matched <span class="ex">[% message %]</span> > <thead> > <tr> > <th>Hold date</th> >+ <th>Last pickup date</th> > <th>Title</th> > <th>Call number</th> > <th>Barcode</th> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/waitingreserves.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/waitingreserves.tt >index 7ba913a..8b4b3e7 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/waitingreserves.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/waitingreserves.tt >@@ -77,7 +77,7 @@ > [% IF ( reserveloop ) %] > <table id="holdst"> > <thead><tr> >- <th class="title-string">Available since</th> >+ <th class="title-string">Available since-until</th> > <th class="anti-the">Title</th> > <th>Patron</th> > <th>Location</th> >@@ -87,7 +87,7 @@ > </tr></thead> > <tbody>[% FOREACH reserveloo IN reserveloop %] > <tr> >- <td><span title="[% reserveloo.waitingdate %]">[% reserveloo.waitingdate | $KohaDates %]</span></td> >+ <td><span title="[% reserveloo.waitingdate %]">[% reserveloo.waitingdate | $KohaDates %] - [% reserveloo.lastpickupdate | $KohaDates %]</span></td> > <td>[% INCLUDE 'biblio-default-view.inc' biblionumber = reserveloo.biblionumber %] > [% reserveloo.title |html %] [% reserveloo.subtitle |html %] > </a> >@@ -137,7 +137,7 @@ > <br/> > <table id="holdso"> > <thead><tr> >- <th class="title-string">Available since</th> >+ <th class="title-string">Available since-until</th> > <th class="anti-the">Title</th> > <th>Patron</th> > <th>Location</th> >@@ -147,7 +147,7 @@ > </tr></thead> > <tbody>[% FOREACH overloo IN overloop %] > <tr> >- <td><p><span title="[% overloo.waitingdate %]">[% overloo.waitingdate | $KohaDates %]</span></p></td> >+ <td><p><span title="[% overloo.waitingdate %]">[% overloo.waitingdate | $KohaDates %] - [% overloo.lastpickupdate | $KohaDates %]</span></p></td> > <td>[% INCLUDE 'biblio-default-view.inc' biblionumber = overloo.biblionumber %][% overloo.title |html %] [% overloo.subtitle |html %] > </a> > [% UNLESS ( item_level_itypes ) %][% IF ( overloo.itemtype ) %] (<b>[% overloo.itemtype %]</b>)[% END %][% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/admin/smart-rules.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/help/admin/smart-rules.tt >index 8efcdc6..f099d1a 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/help/admin/smart-rules.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/help/admin/smart-rules.tt >@@ -57,6 +57,7 @@ > </li> > <li>Next decide if the patron can renew this item type and if so, enter how many times they can renew it in the 'Renewals Allowed' box</li> > <li>If you're allowing renewals you can control how long the renewal loan period will be (in the units you have chosen) in the 'Renewal period' box</li> >+ <li><i>Holds wait for pickup (day)</i> - After a hold is caught and put waiting for pickup, the hold will wait for this many days until it becomes problematic. Set it to 0 or less to disable the expiration of waiting holds. This value respects the Calendar holidays, skipping the last pickup date to the next available open library day.</li> > <li>If you're allowing renewals you can control how soon before the due date patrons can renew their materials with the 'No renewals before' box. > <ul><li>Items can be renewed at any time if this value is left blank. Otherwise items can only be renewed if the item is before the number in units (days/hours) entered in this box.</li></ul></li> > <li>If the patron can place holds on this item type, enter the total numbers of items (of this type) that can be put on hold in the 'Holds Allowed' field</li> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/circ/waitingreserves.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/help/circ/waitingreserves.tt >index b174a96..c49fd2f 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/help/circ/waitingreserves.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/help/circ/waitingreserves.tt >@@ -4,7 +4,7 @@ > > <p>This report will show all of the holds that are waiting for patrons to pick them up.</p> > >-<p>Items that have been on the hold shelf longer than you normally allow (based on the ReservesMaxPickUpDelay preference value) will appear on the 'Holds Over' tab, they will not automatically be cancelled unless you have set the cron job to do that for you, but you can cancel all holds using the button at the top of the list.</p> >+<p>Items that have been on the hold shelf longer than you normally allow (based on the holds pickup delay defined in the issuing rules) will appear on the 'Holds Over' tab, they will not automatically be cancelled.</p> > > <p><strong>See the full documentation for Holds Awaiting Pickup in the <a href="http://manual.koha-community.org/[% helpVersion %]/en/circreports.html#holdspickup">manual</a> (online).</strong></p> > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt >index 24408ca..37e300c 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt >@@ -522,6 +522,7 @@ function validate1(date) { > <thead> > <tr> > <th>Hold date</th> >+ <th>Last pickup date</th> > <th>Title</th> > <th>Call number</th> > <th>Barcode</th> >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt >index f4cbddb..90e87b0 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt >@@ -560,7 +560,7 @@ > [% IF ( RESERVE.wait ) %] > [% IF ( RESERVE.atdestination ) %] > [% IF ( RESERVE.found ) %] >- Item waiting at <b> [% RESERVE.wbrname %]</b>[% IF ( RESERVE.waitingdate ) %] since [% RESERVE.waitingdate | $KohaDates %][% END %] >+ Item waiting at <b> [% RESERVE.wbrname %]</b>[% IF ( RESERVE.waitingdate ) %] since [% RESERVE.waitingdate | $KohaDates %] until [% RESERVE.lastpickupdate | $KohaDates %][% END %] > <input type="hidden" name="pickup" value="[% RESERVE.wbrcd %]" /> > [% ELSE %] > Item waiting to be pulled from <b> [% RESERVE.wbrname %]</b> >diff --git a/svc/holds b/svc/holds >index 3ff704f..d135299 100755 >--- a/svc/holds >+++ b/svc/holds >@@ -47,7 +47,7 @@ my $branch = C4::Context->userenv->{'branch'}; > my $schema = Koha::Database->new()->schema(); > > my @sort_columns = >- qw/reservedate title itemcallnumber barcode expirationdate priority/; >+ qw/reservedate lastpickupdate title itemcallnumber barcode expirationdate priority/; > > my $borrowernumber = $input->param('borrowernumber'); > my $offset = $input->param('iDisplayStart'); >@@ -81,6 +81,7 @@ while ( my $h = $holds_rs->next() ) { > author => $h->biblio()->author(), > reserve_id => $h->reserve_id(), > reservedate => $h->reservedate(), >+ lastpickupdate => $h->lastpickupdate(), > expirationdate => $h->expirationdate(), > suspend => $h->suspend(), > suspend_until => $h->suspend_until(), >@@ -97,6 +98,10 @@ while ( my $h = $holds_rs->next() ) { > { dt => dt_from_string( $h->reservedate() ), dateonly => 1 } > ) > : q{}, >+ lastpickupdate_formatted => $h->lastpickupdate() ? output_pref( >+ { dt => dt_from_string( $h->lastpickupdate() ), dateonly => 1 } >+ ) >+ : q{}, > suspend_until_formatted => $h->suspend_until() ? output_pref( > { dt => dt_from_string( $h->suspend_until() ), dateonly => 1 } > ) >-- >1.7.9.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 8367
:
12130
|
13139
|
13602
|
13603
|
13604
|
13624
|
15334
|
15335
|
15369
|
15498
|
15613
|
15658
|
15659
|
19093
|
19094
|
19095
|
19096
|
19104
|
19105
|
19107
|
19108
|
19116
|
19180
|
19181
|
19182
|
19360
|
19361
|
19362
|
20300
|
20301
|
20302
|
20303
|
20304
|
32786
|
32826
|
32884
|
32885
|
32916
|
32930
|
42706
|
42754
|
79790
|
79791
|
79798
|
79799
|
79800
|
79853
|
79854
|
79855
|
79859
|
92412
|
92413
|
92414
|
92415
|
92416
|
92417
|
92418
|
92419
|
92420
|
92421
|
92422
|
92423
|
92424
|
92425
|
92426
|
92427
|
92428
|
92958
|
92959
|
92960
|
92961
|
103425
|
113211
|
117284
|
118017
|
118021
|
124568
|
125087
|
131299
|
131300
|
131301
|
131302
|
131646
|
131647
|
131718
|
131719
|
131720
|
131722
|
131723
|
131724
|
133089
|
133090
|
133091
|
133092
|
133093
|
133094
|
142897
|
142898
|
142899
|
142900
|
142901
|
142902
|
142903
|
144097
|
144098
|
144099
|
144100
|
144101
|
144102
|
144103
|
144146
|
145644
|
145657
|
147798
|
147799
|
147800
|
147801
|
147802
|
147803
|
147804
|
147805
|
147806
|
147807
|
148536
|
148537
|
148538
|
148539
|
148540
|
148541
|
148542
|
148543
|
148544
|
148545
|
150437
|
150438
|
150439
|
153235
|
153237
|
153238
|
153239
|
153240
|
153241
|
153242
|
153243
|
153244
|
153245
|
153246
|
157138
|
157139
|
157140
|
157141
|
157142
|
157143
|
157144
|
157145
|
157146
|
157147
|
157148
|
157149
|
157150
|
157298
|
157343
|
157344
|
157345
|
157346
|
157347
|
157348
|
157349
|
157350
|
157351
|
157352
|
157354
|
157355
|
157356
|
157697
|
157698
|
157699
|
157700
|
157701
|
157702
|
157703
|
157704
|
157705
|
157706
|
157707
|
157708
|
157709
|
157715
|
158023
|
158024
|
158025
|
158026
|
158027
|
158028
|
158029
|
158030
|
158031
|
158032
|
158033
|
158034
|
158035
|
158254
|
158255