From 2f5e5c605f0e41c0c0c35564f90f3e5b8e0f135a Mon Sep 17 00:00:00 2001 From: Alex Arnaud Date: Thu, 26 Nov 2015 11:00:22 +0100 Subject: [PATCH] Bug 15261: Verify if checkouts/reserves requests periods overlap... MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... with existing reserves When checking out or placing hold, we should check if an existing reserve whose period overlap exists. A user place an hold from opac whose requested period overlap an existing reserve period => prevent reserve, A librarian place an hold from staff whose requested period overlap an existing reserve period => Warn librarian (Ask for confirmation), A librarian make a checkout from staff whose requested period overlap an existing reserve period => Warn librarian (Ask for confirmation). Test plan: Enable syspref: AllowHoldDateInFuture OPACAllowHoldDateInFuture PreventChechoutOnSameReservePeriod and PreventReservesOnSamePeriod 1 (staff side): Place a hold on title (which has only one items) level with start date and expiration date. Place another hold (also title level) with period overlaping this reserve. Check you are warned about an existing reserve 2 (staff side): Place a hold on title (which has more than one items) level with start date and expiration date. Place another hold (also title level) with period overlaping this reserve. Check you are NOT warned about an existing reserve. Because it remains at least one item not reserved. 3 (staff side): Place a hold on item level with start date and expiration date. Place another hold on item level with period overlaping this reserve. Check you are warned about an existing reserve. 4 (opac side): Do the same than for staff side. Instead of a warn, reserve is prevented. 5: Place a hold on title (which has only one items) level with start date and expiration date. Try to checkout the unique item from this title with period overlaping the reserve period. Check you are warned about an existing reserve 6: Place a hold on title (which has more than one items) level with start date and expiration date. Checkout an item from this title with period overlaping the reserve period. Check you are NOT warned about an existing reserve. 7: Place a hold on item level with start date and expiration date. Checkout this item period overlaping the reserve period. Check you are warned about an existing reserve Rabased on master Rebased on master (2016-06-23) Rebased on master (2017-03-23) Rebased on master (2018-03-15) Signed-off-by: Séverine QUEUNE Signed-off-by: Séverine QUEUNE --- C4/Circulation.pm | 23 + C4/Reserves.pm | 48 + Koha/DateUtils.pm | 44 +- circ/circulation.pl | 4 + ..._preventchechoutonsamereserveperiod_syspref.sql | 1 + ...261-add_preventreservesonsameperiod_syspref.sql | 1 + installer/data/mysql/sysprefs.sql | 4 +- .../en/modules/admin/preferences/circulation.pref | 1428 ++++++++++---------- .../prog/en/modules/circ/circulation.tt | 2 + .../prog/en/modules/reserve/placerequest.tt | 66 + opac/opac-reserve.pl | 9 + reserve/placerequest.pl | 142 +- t/db_dependent/Circulation/CanBookBeIssued.t | 107 ++ t/db_dependent/Reserves/ReserveDate.t | 108 ++ 14 files changed, 1217 insertions(+), 770 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_15261-add_preventchechoutonsamereserveperiod_syspref.sql create mode 100644 installer/data/mysql/atomicupdate/bug_15261-add_preventreservesonsameperiod_syspref.sql create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/reserve/placerequest.tt create mode 100644 t/db_dependent/Circulation/CanBookBeIssued.t create mode 100644 t/db_dependent/Reserves/ReserveDate.t diff --git a/C4/Circulation.pm b/C4/Circulation.pm index d583e53..c10b7ab 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -996,6 +996,7 @@ sub CanBookBeIssued { $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber; $needsconfirmation{'resbranchcode'} = $res->{branchcode}; $needsconfirmation{'reswaitingdate'} = $res->{'waitingdate'}; + $needsconfirmation{resreserveid} = $res->{reserve_id}; } elsif ( $restype eq "Reserved" ) { # The item is on reserve for someone else. @@ -1006,9 +1007,31 @@ sub CanBookBeIssued { $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber; $needsconfirmation{'resbranchcode'} = $patron->branchcode; $needsconfirmation{'resreservedate'} = $res->{reservedate}; + $needsconfirmation{resreserveid} = $res->{reserve_id}; } } } + + my $now = dt_from_string(); + my $preventCheckoutOnSameReservePeriod = + C4::Context->preference("PreventCheckoutOnSameReservePeriod"); + my $reserves_on_same_period = + ReservesOnSamePeriod($item->{biblionumber}, $item->{itemnumber}, $now->ymd, $duedate->ymd); + if ($preventCheckoutOnSameReservePeriod && $reserves_on_same_period) { + my $reserve = $reserves_on_same_period->[0]; + my $patron = Koha::Patrons->find( $reserve->{borrowernumber} ); + my $branchname = Koha::Libraries->find($reserve->{branchcode})->branchname; + + $needsconfirmation{RESERVED} = 1; + $needsconfirmation{resfirstname} = $patron->firstname; + $needsconfirmation{ressurname} = $patron->surname; + $needsconfirmation{rescardnumber} = $patron->cardnumber; + $needsconfirmation{resborrowernumber} = $patron->borrowernumber; + $needsconfirmation{resbranchname} = $branchname; + $needsconfirmation{resreservedate} = $reserve->{reservedate}; + $needsconfirmation{resreserveid} = $reserve->{reserve_id}; + } + } ## CHECK AGE RESTRICTION diff --git a/C4/Reserves.pm b/C4/Reserves.pm index 73b86b6..44169c7 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -134,6 +134,7 @@ BEGIN { &SuspendAll &GetReservesControlBranch + &ReservesOnSamePeriod IsItemOnHoldAndFound @@ -2064,6 +2065,53 @@ sub GetHoldRule { return $sth->fetchrow_hashref(); } +=head2 ReservesOnSamePeriod + + my $reserve = ReservesOnSamePeriod( $biblionumber, $itemnumber, $resdate, $expdate); + + Return the reserve that match the period ($resdate => $expdate), + undef if no reserve match. + +=cut + +sub ReservesOnSamePeriod { + my ($biblionumber, $itemnumber, $resdate, $expdate) = @_; + + unless ($resdate && $expdate) { + return; + } + + my @reserves = Koha::Holds->search({ biblionumber => $biblionumber }); + + $resdate = output_pref({ str => $resdate, dateonly => 1, dateformat => 'iso' }); + $expdate = output_pref({ str => $expdate, dateonly => 1, dateformat => 'iso' }); + + my @reserves_overlaps; + foreach my $reserve ( @reserves ) { + + unless ($reserve->reservedate && $reserve->expirationdate) { + next; + } + + if (date_ranges_overlap($resdate, $expdate, + $reserve->reservedate, + $reserve->expirationdate)) { + + # If reserve is item level and the requested periods overlap. + if ($itemnumber && $reserve->itemnumber == $itemnumber ) { + return [$reserve->unblessed]; + } + push @reserves_overlaps, $reserve->unblessed; + } + } + + if ( @reserves_overlaps >= Koha::Items->search({ biblionumber => $biblionumber })->count() ) { + return \@reserves_overlaps; + } + + return; +} + =head1 AUTHOR Koha Development Team diff --git a/Koha/DateUtils.pm b/Koha/DateUtils.pm index 2b8ee8b..dda1b0d 100644 --- a/Koha/DateUtils.pm +++ b/Koha/DateUtils.pm @@ -24,7 +24,7 @@ use Koha::Exceptions; use base 'Exporter'; our @EXPORT = ( - qw( dt_from_string output_pref format_sqldatetime ) + qw( dt_from_string output_pref format_sqldatetime date_ranges_overlap ) ); =head1 DateUtils @@ -317,4 +317,46 @@ sub format_sqldatetime { return q{}; } +=head2 date_ranges_overlap + + $bool = date_ranges_overlap($start1, $end1, $start2, $end2); + + Tells if first range ($start1 => $end1) overlaps + the second one ($start2 => $end2) + +=cut + +sub date_ranges_overlap { + my ($start1, $end1, $start2, $end2) = @_; + + $start1 = dt_from_string( $start1, 'iso' ); + $end1 = dt_from_string( $end1, 'iso' ); + $start2 = dt_from_string( $start2, 'iso' ); + $end2 = dt_from_string( $end2, 'iso' ); + + if ( + # Start of range 2 is in the range 1. + ( + DateTime->compare($start2, $start1) >= 0 + && DateTime->compare($start2, $end1) <= 0 + ) + || + # End of range 2 is in the range 1. + ( + DateTime->compare($end2, $start1) >= 0 + && DateTime->compare($end2, $end1) <= 0 + ) + || + # Range 2 start before and end after range 1. + ( + DateTime->compare($start2, $start1) < 0 + && DateTime->compare($end2, $end1) > 0 + ) + ) { + return 1; + } + + return; +} + 1; diff --git a/circ/circulation.pl b/circ/circulation.pl index 93ed09c..ffa2e3c 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -419,6 +419,10 @@ if (@$barcodes) { } unless($confirm_required) { my $switch_onsite_checkout = exists $messages->{ONSITE_CHECKOUT_WILL_BE_SWITCHED}; + if ( $cancelreserve eq 'cancel' ) { + CancelReserve({ reserve_id => $query->param('reserveid') }); + } + $cancelreserve = $cancelreserve eq 'revert' ? 'revert' : undef; my $issue = AddIssue( $patron->unblessed, $barcode, $datedue, $cancelreserve, undef, undef, { onsite_checkout => $onsite_checkout, auto_renew => $session->param('auto_renew'), switch_onsite_checkout => $switch_onsite_checkout, } ); $template_params->{issue} = $issue; $session->clear('auto_renew'); diff --git a/installer/data/mysql/atomicupdate/bug_15261-add_preventchechoutonsamereserveperiod_syspref.sql b/installer/data/mysql/atomicupdate/bug_15261-add_preventchechoutonsamereserveperiod_syspref.sql new file mode 100644 index 0000000..d91ae3f --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_15261-add_preventchechoutonsamereserveperiod_syspref.sql @@ -0,0 +1 @@ +INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES ('PreventCheckoutOnSameReservePeriod', '0', 'Prevent to checkout a document if a reserve on same period exists', NULL, 'YesNo'); \ No newline at end of file diff --git a/installer/data/mysql/atomicupdate/bug_15261-add_preventreservesonsameperiod_syspref.sql b/installer/data/mysql/atomicupdate/bug_15261-add_preventreservesonsameperiod_syspref.sql new file mode 100644 index 0000000..6f69486 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_15261-add_preventreservesonsameperiod_syspref.sql @@ -0,0 +1 @@ +INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES ('PreventReservesOnSamePeriod', '0', 'Prevent to hold a document if a reserve on same period exists', NULL, 'YesNo'); \ No newline at end of file diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index 76bb2cc..05f45f5 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -603,5 +603,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('XSLTListsDisplay','default','','Enable XSLT stylesheet control over lists pages display on intranet','Free'), ('XSLTResultsDisplay','default','','Enable XSL stylesheet control over results page display on intranet','Free'), ('z3950AuthorAuthFields','701,702,700',NULL,'Define the MARC biblio fields for Personal Name Authorities to fill biblio.author','free'), -('z3950NormalizeAuthor','0','','If ON, Personal Name Authorities will replace authors in biblio.author','YesNo') +('z3950NormalizeAuthor','0','','If ON, Personal Name Authorities will replace authors in biblio.author','YesNo'), +('PreventCheckoutOnSameReservePeriod','0','','Prevent to checkout a document if a reserve on same period exists','YesNo'), +('PreventReservesOnSamePeriod','0','','Prevent to hold a document if a reserve on same period exists','YesNo') ; 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 178a048..04c086c 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 @@ -1,714 +1,726 @@ Circulation: # FIXME: printcirculationslips is also omitted. It _technically_ could work, but C4::Print is HLT specific and needs a little bit of refactoring. - Interface: - - - - pref: CircSidebar - choices: - yes: Activate - no: Deactivate - - the navigation sidebar on all Circulation pages. - - - - pref: AutoSwitchPatron - choices: - yes: "Enable" - no: "Don't enable" - - the automatic redirection to another patron when a patron barcode is scanned instead of a book. - - This should not be enabled if you have overlapping patron and book barcodes. - - - - pref: CircAutocompl - choices: - yes: Try - no: "Don't try" - - to guess the patron being entered while typing a patron search on the circulation screen. - - Only returns the first 10 results at a time. - - - - pref: itemBarcodeInputFilter - choices: - OFF: "Don't filter" - whitespace: Remove spaces from - cuecat: Convert from CueCat form - T-prefix: Remove the first number from T-prefix style - libsuite8: Convert from Libsuite8 form - EAN13: EAN-13 or zero-padded UPC-A from - - scanned item barcodes. - - - - pref: itemBarcodeFallbackSearch - choices: - yes: "Enable" - no: "Don't enable" - - the automatic use of a keyword catalog search if the phrase entered as a barcode on the checkout page does not turn up any results during an item barcode search. - - - - Sort previous checkouts on the circulation page from - - pref: previousIssuesDefaultSortOrder - choices: - asc: earliest to latest - desc: latest to earliest - - due date. - - - - "Sort today's checkouts on the circulation page from" - - pref: todaysIssuesDefaultSortOrder - type: choice - choices: - asc: earliest to latest - desc: latest to earliest - - due date. - - - - pref: SpecifyDueDate - choices: - yes: Allow - no: "Don't allow" - - staff to specify a due date for a checkout. - - - - pref: SpecifyReturnDate - choices: - yes: Allow - no: "Don't allow" - - staff to specify a return date for a check in. - - - - Set the default start date for the Holds to pull list to - - pref: HoldsToPullStartDate - class: integer - - day(s) ago. Note that the default end date is controlled by preference ConfirmFutureHolds. - - - - pref: AllowAllMessageDeletion - choices: - yes: Allow - no: "Don't allow" - - staff to delete messages added from other libraries. - - - - Show the - - pref: numReturnedItemsToShow - class: integer - - last returned items on the checkin screen. - - - - pref: FineNotifyAtCheckin - choices: - yes: Notify - no: "Don't notify" - - librarians of overdue fines on the items they are checking in. - - - - pref: WaitingNotifyAtCheckin - choices: - yes: Notify - no: "Don't notify" - - librarians of waiting holds for the patron whose items they are checking in. - - - - pref: FilterBeforeOverdueReport - choices: - yes: Require - no: "Don't require" - - staff to choose which checkouts to show before running the overdues report. - - - - pref: DisplayClearScreenButton - choices: - yes: Show - no: "Don't show" - - a button to clear the current patron from the screen on the circulation screen. - - - - pref: RecordLocalUseOnReturn - choices: - yes: Record - no: "Don't record" - - local use when an unissued item is checked in. - - - - When an empty barcode field is submitted in circulation - - pref: CircAutoPrintQuickSlip - choices: - clear: "clear the screen" - qslip: "open a print quick slip window" - slip: "open a print slip window" - - . - - - - Include the stylesheet at - - pref: NoticeCSS - class: url - - on Notices. (This should be a complete URL, starting with http://) - - - - pref: UpdateTotalIssuesOnCirc - choices: - yes: Do - no: "Do not" - - update a bibliographic record's total issues count whenever an item is issued (WARNING! This increases server load significantly; if performance is a concern, use the update_totalissues.pl cron job to update the total issues count). - - - - pref: ExportCircHistory - choices: - yes: Show - no: "Don't show" - - the export patron checkout history options. - - - - The following fields should be excluded from the patron checkout history CSV or iso2709 export - - pref: ExportRemoveFields - - (separate fields with space, e.g. 100a 200b 300c) - - - - pref: AllowOfflineCirculation - choices: - yes: Enable - no: "Do not enable" - - "offline circulation on regular circulation computers. (NOTE: This system preference does not affect the Firefox plugin or the desktop application)" - - - - pref: ShowAllCheckins - choices: - yes: Show - no: "Do not show" - - all items in the "Checked-in items" list, even items that were not checked out. - - - - pref: AllowCheckoutNotes - choices: - yes: Allow - no: "Don't allow" - - patrons to submit notes about checked out items. +Interface: + - + - pref: CircSidebar + choices: + yes: Activate + no: Deactivate + - the navigation sidebar on all Circulation pages. + - + - pref: AutoSwitchPatron + choices: + yes: "Enable" + no: "Don't enable" + - the automatic redirection to another patron when a patron barcode is scanned instead of a book. + - This should not be enabled if you have overlapping patron and book barcodes. + - + - pref: CircAutocompl + choices: + yes: Try + no: "Don't try" + - to guess the patron being entered while typing a patron search on the circulation screen. + - Only returns the first 10 results at a time. + - + - pref: itemBarcodeInputFilter + choices: + OFF: "Don't filter" + whitespace: Remove spaces from + cuecat: Convert from CueCat form + T-prefix: Remove the first number from T-prefix style + libsuite8: Convert from Libsuite8 form + EAN13: EAN-13 or zero-padded UPC-A from + - scanned item barcodes. + - + - pref: itemBarcodeFallbackSearch + choices: + yes: "Enable" + no: "Don't enable" + - the automatic use of a keyword catalog search if the phrase entered as a barcode on the checkout page does not turn up any results during an item barcode search. + - + - Sort previous checkouts on the circulation page from + - pref: previousIssuesDefaultSortOrder + choices: + asc: earliest to latest + desc: latest to earliest + - due date. + - + - "Sort today's checkouts on the circulation page from" + - pref: todaysIssuesDefaultSortOrder + type: choice + choices: + asc: earliest to latest + desc: latest to earliest + - due date. + - + - pref: SpecifyDueDate + choices: + yes: Allow + no: "Don't allow" + - staff to specify a due date for a checkout. + - + - pref: SpecifyReturnDate + choices: + yes: Allow + no: "Don't allow" + - staff to specify a return date for a check in. + - + - Set the default start date for the Holds to pull list to + - pref: HoldsToPullStartDate + class: integer + - day(s) ago. Note that the default end date is controlled by preference ConfirmFutureHolds. + - + - pref: AllowAllMessageDeletion + choices: + yes: Allow + no: "Don't allow" + - staff to delete messages added from other libraries. + - + - Show the + - pref: numReturnedItemsToShow + class: integer + - last returned items on the checkin screen. + - + - pref: FineNotifyAtCheckin + choices: + yes: Notify + no: "Don't notify" + - librarians of overdue fines on the items they are checking in. + - + - pref: WaitingNotifyAtCheckin + choices: + yes: Notify + no: "Don't notify" + - librarians of waiting holds for the patron whose items they are checking in. + - + - pref: FilterBeforeOverdueReport + choices: + yes: Require + no: "Don't require" + - staff to choose which checkouts to show before running the overdues report. + - + - pref: DisplayClearScreenButton + choices: + yes: Show + no: "Don't show" + - a button to clear the current patron from the screen on the circulation screen. + - + - pref: RecordLocalUseOnReturn + choices: + yes: Record + no: "Don't record" + - local use when an unissued item is checked in. + - + - When an empty barcode field is submitted in circulation + - pref: CircAutoPrintQuickSlip + choices: + clear: "clear the screen" + qslip: "open a print quick slip window" + slip: "open a print slip window" + - . + - + - Include the stylesheet at + - pref: NoticeCSS + class: url + - on Notices. (This should be a complete URL, starting with http://) + - + - pref: UpdateTotalIssuesOnCirc + choices: + yes: Do + no: "Do not" + - update a bibliographic record's total issues count whenever an item is issued (WARNING! This increases server load significantly; if performance is a concern, use the update_totalissues.pl cron job to update the total issues count). + - + - pref: ExportCircHistory + choices: + yes: Show + no: "Don't show" + - the export patron checkout history options. + - + - The following fields should be excluded from the patron checkout history CSV or iso2709 export + - pref: ExportRemoveFields + - (separate fields with space, e.g. 100a 200b 300c) + - + - pref: AllowOfflineCirculation + choices: + yes: Enable + no: "Do not enable" + - "offline circulation on regular circulation computers. (NOTE: This system preference does not affect the Firefox plugin or the desktop application)" + - + - pref: ShowAllCheckins + choices: + yes: Show + no: "Do not show" + - all items in the "Checked-in items" list, even items that were not checked out. + - + - pref: AllowCheckoutNotes + choices: + yes: Allow + no: "Don't allow" + - patrons to submit notes about checked out items. - Checkout Policy: - - - - pref: AllowTooManyOverride - choices: - yes: Allow - no: "Don't allow" - - staff to override and check out items when the patron has reached the maximum number of allowed checkouts. - - - - pref: AutoRemoveOverduesRestrictions - choices: - yes: "Do" - no: "Do not" - - allow OVERDUES restrictions triggered by sent notices to be cleared automatically when all overdue items are returned by a patron. - - - - pref: AllowNotForLoanOverride - choices: - yes: Allow - no: "Don't allow" - - staff to override and check out items that are marked as not for loan. - - - - pref: AllowRenewalLimitOverride - choices: - yes: Allow - no: "Don't allow" - - staff to manually override renewal blocks and renew a checkout when it would go over the renewal limit or be premature with respect to the "No renewal before" setting in the circulation policy or has been scheduled for automatic renewal. - - - - pref: AllowItemsOnHoldCheckout - choices: - yes: Allow - no: "Don't allow" - - checkouts of items reserved to someone else. If allowed do not generate RESERVE_WAITING and RESERVED warning. This allows self checkouts for those items. - - - - pref: AllowItemsOnHoldCheckoutSCO - choices: - yes: Allow - no: "Don't allow" - - checkouts of items reserved to someone else in the SCO module. If allowed do not generate RESERVE_WAITING and RESERVED warning. This allows self checkouts for those items. - - - - pref: AllFinesNeedOverride - choices: - yes: Require - no: "Don't require" - - staff to manually override all fines, even fines less than noissuescharge. - - - - pref: AllowFineOverride - choices: - yes: Allow - no: "Don't allow" - - staff to manually override and check out items to patrons who have more than noissuescharge in fines. - - - - pref: InProcessingToShelvingCart - choices: - yes: Move - no: "Don't move" - - items that have the location PROC to the location CART when they are checked in. - - - - pref: ReturnToShelvingCart - choices: - yes: Move - no: "Don't move" - - all items to the location CART when they are checked in. - - - - pref: AutomaticItemReturn - choices: - yes: Do - no: "Don't" - - automatically transfer items to their home library when they are returned. - - - - pref: UseBranchTransferLimits - choices: - yes: Enforce - no: "Don't enforce" - - library transfer limits based on - - pref: BranchTransferLimitsType - choices: - ccode: collection code - itemtype: item type - - . - - - - pref: UseTransportCostMatrix - choices: - yes: Use - no: "Don't use" - - Transport Cost Matrix for calculating optimal holds filling between branches. - - - - Use the checkout and fines rules of - - pref: CircControl - type: choice - choices: - PickupLibrary: the library you are logged in at. - PatronLibrary: the library the patron is from. - ItemHomeLibrary: the library the item is from. - - - - Use the checkout and fines rules of - - pref: HomeOrHoldingBranch - type: choice - choices: - homebranch: the library the item is from. - holdingbranch: the library the item was checked out from. - - - - Allow materials to be returned to - - pref: AllowReturnToBranch - type: choice - choices: - anywhere: to any library. - homebranch: only the library the item is from. - holdingbranch: only the library the item was checked out from. - homeorholdingbranch: either the library the item is from or the library it was checked out from. - - - - For search results in the staff client, display the branch of - - pref: StaffSearchResultsDisplayBranch - type: choice - choices: - homebranch: the library the item is from. - holdingbranch: the library the item is held by. - - - - Calculate the due date using - - pref: useDaysMode - choices: - Days: circulation rules only. - Calendar: the calendar to skip all days the library is closed. - Datedue: the calendar to push the due date to the next open day - - - - Calculate "No renewal before" based on - - pref: NoRenewalBeforePrecision - choices: - date: date. - exact_time: exact time. - - Only relevant for loans calculated in days, hourly loans are not affected. - - - - When renewing checkouts, base the new due date on - - pref: RenewalPeriodBase - choices: - date_due: the old due date of the checkout. - now: the current date. - - - - pref: RenewalSendNotice - choices: - yes: Send - no: "Don't send" - - a renewal notice according to patron checkout alert preferences. - - - - Prevent patrons from making holds on the OPAC if they owe more than - - pref: maxoutstanding - class: currency - - '[% local_currency %] in fines.' - - - - Show a warning on the "Transfers to Receive" screen if the transfer has not been received - - pref: TransfersMaxDaysWarning - class: integer - - days after it was sent. - - - - pref: IssuingInProcess - choices: - yes: "Don't prevent" - no: "Prevent" - - patrons from checking out an item whose rental charge would take them over the limit. - - - - "Restrict patrons with the following target audience values from checking out inappropriate materials:" - - pref: AgeRestrictionMarker - - "E.g. enter target audience keyword(s) split by | (bar) FSK|PEGI|Age| (No white space near |). Be sure to map agerestriction in Koha to MARC mapping (e.g. 521$a). A MARC field value of FSK 12 or PEGI 12 would mean: Borrower must be 12 years old. Leave empty to not apply an age restriction." - - - - pref: AgeRestrictionOverride - choices: - yes: Allow - no: "Don't allow" - - staff to check out an item with age restriction. - - - - Prevent patrons from checking out books if they have more than - - pref: noissuescharge - class: integer - - '[% local_currency %] in fines.' - - - - Prevent a patron from checking out if the patron has guarantees owing in total more than - - pref: NoIssuesChargeGuarantees - class: integer - - '[% local_currency %] in fines.' - - - - pref: RentalsInNoissuesCharge - choices: - yes: Include - no: "Don't include" - - rental charges when summing up charges for noissuescharge. - - - - pref: ManInvInNoissuesCharge - choices: - yes: Include - no: "Don't include" - - MANUAL_INV charges when summing up charges for noissuescharge. - - - - pref: HoldsInNoissuesCharge - choices: - yes: Include - no: "Don't include" - - hold charges when summing up charges for noissuescharge. - - - - pref: ReturnBeforeExpiry - choices: - yes: Require - no: "Don't require" - - "patrons to return books before their accounts expire (by restricting due dates to before the patron's expiration date)." - - - - Send all notices as a BCC to this email address - - pref: NoticeBcc - - - - pref: OverdueNoticeCalendar - choices: - yes: "Use Calendar" - no: "Ignore Calendar" - - when working out the period for overdue notices - - - - Include up to - - pref: PrintNoticesMaxLines - class: integer - - "item lines in a printed overdue notice. 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. Set to 0 to include all overdue items in the notice, no matter how many there are." - - - - pref: OverduesBlockCirc - choices: - block: Block - noblock: "Don't block" - confirmation: Ask for confirmation - - when checking out to a borrower that has overdues outstanding - - - - "When checking out an item with rental fees, " - - pref: RentalFeesCheckoutConfirmation - choices: - yes: ask - no: "do not ask" - - "for confirmation." - - - - By default, set the LOST value of an item to - - pref: DefaultLongOverdueLostValue - class: integer - - when the item has been overdue for more than - - pref: DefaultLongOverdueDays - class: integer - - days. - -
WARNING — These preferences will activate the automatic item loss process. Leave these fields empty if you don't want to activate this feature. - - "
Example: [1] [30] Sets an item to the LOST value 1 when it has been overdue for more than 30 days." - -
(Used when the longoverdue.pl script is called without the --lost parameter) - - - - "Charge a lost item to the borrower's account when the LOST value of the item changes to :" - - pref: DefaultLongOverdueChargeValue - class: integer - -
Leave this field empty if you don't want to charge the user for lost items. - -
(Used when the longoverdue.pl script is called without the --charge parameter) - - - - "When issuing an item that has been marked as lost, " - - pref: IssueLostItem - choices: - confirm: "require confirmation" - alert: "display a message" - nothing : "do nothing" - - . - - - - pref: MarkLostItemsAsReturned - choices: - yes: "Mark" - no: "Do not mark" - - "items as returned when flagged as lost" - - - - pref: AllowMultipleIssuesOnABiblio - choices: - yes: Allow - no: "Don't allow" - - "patrons to check out multiple items from the same record. (NOTE: This will only affect records without a subscription attached.)" - - - - pref: OnSiteCheckouts - choices: - yes: Enable - no: Disable - - the on-site checkouts feature. - - - - pref: OnSiteCheckoutsForce - choices: - yes: Enable - no: Disable - - the on-site for all cases (Even if a user is debarred, etc.). - - - - pref: ConsiderOnSiteCheckoutsAsNormalCheckouts - choices: - yes: Consider - no: "Don't consider" - - on-site checkouts as normal checkouts. - - If enabled, the number of checkouts allowed will be normal checkouts + on-site checkouts. - - If disabled, both values will be checked separately. - - - - pref: SwitchOnSiteCheckouts - choices: - yes: Switch - no: "Don't switch" - - on-site checkouts to normal checkouts when checked out. - - - - When a patron's checked out item is overdue, - - pref: OverduesBlockRenewing - type: choice - choices: - allow: allow renewing. - blockitem: block renewing only for this item. - block: block renewing for all the patron's items. - - - - If patron is restricted, - - pref: RestrictionBlockRenewing - choices: - yes: Block - no: Allow - - renewing of items. - - - - If a patron owes more than the value of OPACFineNoRenewals, - - pref: OPACFineNoRenewalsBlockAutoRenew - choices: - yes: Block - no: Allow - - his/her auto renewals. - Checkin Policy: - - - - pref: BlockReturnOfWithdrawnItems - choices: - yes: Block - no: "Don't block" - - returning of items that have been withdrawn. - - - - pref: BlockReturnOfLostItems - choices: - yes: Block - no: "Don't block" - - returning of items that have been lost. - - - - pref: CalculateFinesOnReturn - choices: - yes: Do - no: "Don't" - - calculate and update overdue charges when an item is returned. - -
NOTE If you are doing hourly loans then you should have this on. - - - - pref: UpdateNotForLoanStatusOnCheckin - type: textarea - class: code - - This is a list of value pairs. When an item is checked in, if the not for loan value on the left matches the items not for loan value - - "it will be updated to the right-hand value. E.g. '-1: 0' will cause an item that was set to 'Ordered' to now be available for loan." - - Each pair of values should be on a separate line. - - - - pref: CumulativeRestrictionPeriods - choices: - yes: Cumulate - no: "Don't cumulate" - - the restriction periods. - Holds Policy: - - - - pref: AllowHoldItemTypeSelection - choices: - yes: Allow - no: "Don't allow" - - hold fulfillment to be limited by itemtype. - - - - pref: AllowRenewalIfOtherItemsAvailable - choices: - yes: Allow - no: "Don't allow" - - a patron to renew an item with unfilled holds if other available items can fill that hold. - - - - pref: AllowHoldPolicyOverride - choices: - yes: Allow - no: "Don't allow" - - staff to override hold policies when placing holds. - - - - pref: AllowHoldsOnDamagedItems - choices: - yes: Allow - no: "Don't allow" - - hold requests to be placed on and filled by damaged items. - - - - pref: AllowHoldDateInFuture - choices: - yes: Allow - no: "Don't allow" - - hold requests to be placed that do not enter the waiting list until a certain future date. - - - - pref: OPACAllowHoldDateInFuture - choices: - yes: Allow - no: "Don't allow" - - "patrons to place holds that don't enter the waiting list until a certain future date. (AllowHoldDateInFuture must also be enabled)." - - - - Confirm future hold requests (starting no later than - - pref: ConfirmFutureHolds - class: integer - - days from now) at checkin time. Note that this number of days will be used too in calculating the default end date for the Holds to pull-report. But it does not interfere with issuing, renewing or transferring books. - - - - Check the - - pref: ReservesControlBranch - choices: - ItemHomeLibrary: "item's home library" - 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" - - - - If using ExpireReservesMaxPickUpDelay, charge a borrower who allows his or her waiting hold to expire a fee of - - pref: ExpireReservesMaxPickUpDelayCharge - class: currency - - - - Satisfy holds using items from the libraries - - pref: StaticHoldsQueueWeight - class: multi - - (as branchcodes, separated by commas; if empty, uses all libraries) - - when they are - - pref: HoldsQueueSkipClosed - choices: - yes: open - no: open or closed - - pref: RandomizeHoldsQueueWeight - choices: - yes: in random order. - no: in that order. - - - - - - pref: canreservefromotherbranches - choices: - yes: Allow - no: "Don't allow (with independent branches)" - - a user from one library to place a hold on an item from another library - - - - pref: OPACAllowUserToChooseBranch - choices: - yes: Allow - no: "Don't allow" - - a user to choose the library to pick up a hold from. - - - - pref: ReservesNeedReturns - choices: - yes: "Don't automatically" - no: Automatically - - mark a hold as found and waiting when a hold is placed on a specific item and that item is already checked in. - - - - Patrons can only have - - pref: maxreserves - class: integer - - holds at once. - - - - pref: emailLibrarianWhenHoldIsPlaced - choices: - yes: Enable - no: "Don't enable" - - "sending an email to the Koha administrator email address whenever a hold request is placed." - - - - pref: DisplayMultiPlaceHold - choices: - yes: Enable - no: "Don't enable" - - "the ability to place holds on multiple biblio from the search results" - - - - pref: TransferWhenCancelAllWaitingHolds - choices: - yes: Transfer - no: "Don't transfer" - - items when cancelling all waiting holds. - - - - pref: AutoResumeSuspendedHolds - choices: - yes: Allow - no: "Don't allow" - - suspended holds to be automatically resumed by a set date. - - - - pref: SuspendHoldsIntranet - choices: - yes: Allow - no: "Don't allow" - - holds to be suspended from the intranet. - - - - pref: SuspendHoldsOpac - choices: - yes: Allow - no: "Don't allow" - - holds to be suspended from the OPAC. - - - - pref: ExpireReservesOnHolidays - choices: - yes: Allow - no: "Don't allow" - - expired holds to be canceled on days the library is closed. - - - - pref: ExcludeHolidaysFromMaxPickUpDelay - choices: - yes: Allow - no: "Don't allow" - - Closed days to be taken into account in reserves max pickup delay. - - - - pref: decreaseLoanHighHolds - choices: - yes: Enable - no: "Don't enable" - - the reduction of loan period to - - pref: decreaseLoanHighHoldsDuration - class: integer - - days for items with more than - - pref: decreaseLoanHighHoldsValue - class: integer - - holds - - pref: decreaseLoanHighHoldsControl - choices: - static: "on the record" - dynamic: "over the number of holdable items on the record" - - . Ignore items with the following statuses when counting items - - pref: decreaseLoanHighHoldsIgnoreStatuses - multiple: - damaged: Damaged - itemlost: Lost - withdrawn: Withdrawn - notforloan: Not for loan - - - - pref: AllowHoldsOnPatronsPossessions - choices: - yes: Allow - no: "Don't allow" - - a patron to place a hold on a record where the patron already has one or more items attached to that record checked out. - - - - pref: LocalHoldsPriority - choices: - yes: Give - no: "Don't give" - - priority for filling holds to patrons whose - - pref: LocalHoldsPriorityPatronControl - choices: - PickupLibrary: "pickup library" - HomeLibrary: "home library" - - matches the item's - - pref: LocalHoldsPriorityItemControl - choices: - homebranch: "home library" - holdingbranch: "holding library" - - - - pref: OPACHoldsIfAvailableAtPickup - choices: - yes: Allow - no: "Don't allow" - - to pickup up holds at libraries where the item is available. - - - - "Patron categories not affected by OPACHoldsIfAvailableAtPickup" - - pref: OPACHoldsIfAvailableAtPickupExceptions - - "(list of patron categories separated with a pipe '|')" +Checkout Policy: + - + - pref: AllowTooManyOverride + choices: + yes: Allow + no: "Don't allow" + - staff to override and check out items when the patron has reached the maximum number of allowed checkouts. + - + - pref: AutoRemoveOverduesRestrictions + choices: + yes: "Do" + no: "Do not" + - allow OVERDUES restrictions triggered by sent notices to be cleared automatically when all overdue items are returned by a patron. + - + - pref: AllowNotForLoanOverride + choices: + yes: Allow + no: "Don't allow" + - staff to override and check out items that are marked as not for loan. + - + - pref: AllowRenewalLimitOverride + choices: + yes: Allow + no: "Don't allow" + - staff to manually override renewal blocks and renew a checkout when it would go over the renewal limit or be premature with respect to the "No renewal before" setting in the circulation policy or has been scheduled for automatic renewal. + - + - pref: AllowItemsOnHoldCheckout + choices: + yes: Allow + no: "Don't allow" + - checkouts of items reserved to someone else. If allowed do not generate RESERVE_WAITING and RESERVED warning. This allows self checkouts for those items. + - + - pref: AllowItemsOnHoldCheckoutSCO + choices: + yes: Allow + no: "Don't allow" + - checkouts of items reserved to someone else in the SCO module. If allowed do not generate RESERVE_WAITING and RESERVED warning. This allows self checkouts for those items. + - + - pref: AllFinesNeedOverride + choices: + yes: Require + no: "Don't require" + - staff to manually override all fines, even fines less than noissuescharge. + - + - pref: AllowFineOverride + choices: + yes: Allow + no: "Don't allow" + - staff to manually override and check out items to patrons who have more than noissuescharge in fines. + - + - pref: InProcessingToShelvingCart + choices: + yes: Move + no: "Don't move" + - items that have the location PROC to the location CART when they are checked in. + - + - pref: ReturnToShelvingCart + choices: + yes: Move + no: "Don't move" + - all items to the location CART when they are checked in. + - + - pref: AutomaticItemReturn + choices: + yes: Do + no: "Don't" + - automatically transfer items to their home library when they are returned. + - + - pref: UseBranchTransferLimits + choices: + yes: Enforce + no: "Don't enforce" + - library transfer limits based on + - pref: BranchTransferLimitsType + choices: + ccode: collection code + itemtype: item type + - . + - + - pref: UseTransportCostMatrix + choices: + yes: Use + no: "Don't use" + - Transport Cost Matrix for calculating optimal holds filling between branches. + - + - Use the checkout and fines rules of + - pref: CircControl + type: choice + choices: + PickupLibrary: the library you are logged in at. + PatronLibrary: the library the patron is from. + ItemHomeLibrary: the library the item is from. + - + - Use the checkout and fines rules of + - pref: HomeOrHoldingBranch + type: choice + choices: + homebranch: the library the item is from. + holdingbranch: the library the item was checked out from. + - + - Allow materials to be returned to + - pref: AllowReturnToBranch + type: choice + choices: + anywhere: to any library. + homebranch: only the library the item is from. + holdingbranch: only the library the item was checked out from. + homeorholdingbranch: either the library the item is from or the library it was checked out from. + - + - For search results in the staff client, display the branch of + - pref: StaffSearchResultsDisplayBranch + type: choice + choices: + homebranch: the library the item is from. + holdingbranch: the library the item is held by. + - + - Calculate the due date using + - pref: useDaysMode + choices: + Days: circulation rules only. + Calendar: the calendar to skip all days the library is closed. + Datedue: the calendar to push the due date to the next open day + - + - Calculate "No renewal before" based on + - pref: NoRenewalBeforePrecision + choices: + date: date. + exact_time: exact time. + - Only relevant for loans calculated in days, hourly loans are not affected. + - + - When renewing checkouts, base the new due date on + - pref: RenewalPeriodBase + choices: + date_due: the old due date of the checkout. + now: the current date. + - + - pref: RenewalSendNotice + choices: + yes: Send + no: "Don't send" + - a renewal notice according to patron checkout alert preferences. + - + - Prevent patrons from making holds on the OPAC if they owe more than + - pref: maxoutstanding + class: currency + - '[% local_currency %] in fines.' + - + - Show a warning on the "Transfers to Receive" screen if the transfer has not been received + - pref: TransfersMaxDaysWarning + class: integer + - days after it was sent. + - + - pref: IssuingInProcess + choices: + yes: "Don't prevent" + no: "Prevent" + - patrons from checking out an item whose rental charge would take them over the limit. + - + - "Restrict patrons with the following target audience values from checking out inappropriate materials:" + - pref: AgeRestrictionMarker + - "E.g. enter target audience keyword(s) split by | (bar) FSK|PEGI|Age| (No white space near |). Be sure to map agerestriction in Koha to MARC mapping (e.g. 521$a). A MARC field value of FSK 12 or PEGI 12 would mean: Borrower must be 12 years old. Leave empty to not apply an age restriction." + - + - pref: AgeRestrictionOverride + choices: + yes: Allow + no: "Don't allow" + - staff to check out an item with age restriction. + - + - Prevent patrons from checking out books if they have more than + - pref: noissuescharge + class: integer + - '[% local_currency %] in fines.' + - + - Prevent a patron from checking out if the patron has guarantees owing in total more than + - pref: NoIssuesChargeGuarantees + class: integer + - '[% local_currency %] in fines.' + - + - pref: RentalsInNoissuesCharge + choices: + yes: Include + no: "Don't include" + - rental charges when summing up charges for noissuescharge. + - + - pref: ManInvInNoissuesCharge + choices: + yes: Include + no: "Don't include" + - MANUAL_INV charges when summing up charges for noissuescharge. + - + - pref: HoldsInNoissuesCharge + choices: + yes: Include + no: "Don't include" + - hold charges when summing up charges for noissuescharge. + - + - pref: ReturnBeforeExpiry + choices: + yes: Require + no: "Don't require" + - "patrons to return books before their accounts expire (by restricting due dates to before the patron's expiration date)." + - + - Send all notices as a BCC to this email address + - pref: NoticeBcc + - + - pref: OverdueNoticeCalendar + choices: + yes: "Use Calendar" + no: "Ignore Calendar" + - when working out the period for overdue notices + - + - Include up to + - pref: PrintNoticesMaxLines + class: integer + - "item lines in a printed overdue notice. 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. Set to 0 to include all overdue items in the notice, no matter how many there are." + - + - pref: OverduesBlockCirc + choices: + block: Block + noblock: "Don't block" + confirmation: Ask for confirmation + - when checking out to a borrower that has overdues outstanding + - + - "When checking out an item with rental fees, " + - pref: RentalFeesCheckoutConfirmation + choices: + yes: ask + no: "do not ask" + - "for confirmation." + - + - By default, set the LOST value of an item to + - pref: DefaultLongOverdueLostValue + class: integer + - when the item has been overdue for more than + - pref: DefaultLongOverdueDays + class: integer + - days. + -
WARNING — These preferences will activate the automatic item loss process. Leave these fields empty if you don't want to activate this feature. + - "
Example: [1] [30] Sets an item to the LOST value 1 when it has been overdue for more than 30 days." + -
(Used when the longoverdue.pl script is called without the --lost parameter) + - + - "Charge a lost item to the borrower's account when the LOST value of the item changes to :" + - pref: DefaultLongOverdueChargeValue + class: integer + -
Leave this field empty if you don't want to charge the user for lost items. + -
(Used when the longoverdue.pl script is called without the --charge parameter) + - + - "When issuing an item that has been marked as lost, " + - pref: IssueLostItem + choices: + confirm: "require confirmation" + alert: "display a message" + nothing : "do nothing" + - . + - + - pref: MarkLostItemsAsReturned + choices: + yes: "Mark" + no: "Do not mark" + - "items as returned when flagged as lost" + - + - pref: AllowMultipleIssuesOnABiblio + choices: + yes: Allow + no: "Don't allow" + - "patrons to check out multiple items from the same record. (NOTE: This will only affect records without a subscription attached.)" + - + - pref: OnSiteCheckouts + choices: + yes: Enable + no: Disable + - the on-site checkouts feature. + - + - pref: OnSiteCheckoutsForce + choices: + yes: Enable + no: Disable + - the on-site for all cases (Even if a user is debarred, etc.). + - + - pref: ConsiderOnSiteCheckoutsAsNormalCheckouts + choices: + yes: Consider + no: "Don't consider" + - on-site checkouts as normal checkouts. + - If enabled, the number of checkouts allowed will be normal checkouts + on-site checkouts. + - If disabled, both values will be checked separately. + - + - pref: SwitchOnSiteCheckouts + choices: + yes: Switch + no: "Don't switch" + - on-site checkouts to normal checkouts when checked out. + - + - When a patron's checked out item is overdue, + - pref: OverduesBlockRenewing + type: choice + choices: + allow: allow renewing. + blockitem: block renewing only for this item. + block: block renewing for all the patron's items. + - + - If patron is restricted, + - pref: RestrictionBlockRenewing + choices: + yes: Block + no: Allow + - renewing of items. + - + - If a patron owes more than the value of OPACFineNoRenewals, + - pref: OPACFineNoRenewalsBlockAutoRenew + choices: + yes: Block + no: Allow + - his/her auto renewals. + - + - pref: PreventCheckoutOnSameReservePeriod + choices: + yes: Do + no: "Don't" + - If yes, checkouts periods can't overlap with a reserve period. +Checkin Policy: + - + - pref: BlockReturnOfWithdrawnItems + choices: + yes: Block + no: "Don't block" + - returning of items that have been withdrawn. + - + - pref: BlockReturnOfLostItems + choices: + yes: Block + no: "Don't block" + - returning of items that have been lost. + - + - pref: CalculateFinesOnReturn + choices: + yes: Do + no: "Don't" + - calculate and update overdue charges when an item is returned. + -
NOTE If you are doing hourly loans then you should have this on. + - + - pref: UpdateNotForLoanStatusOnCheckin + type: textarea + class: code + - This is a list of value pairs. When an item is checked in, if the not for loan value on the left matches the items not for loan value + - "it will be updated to the right-hand value. E.g. '-1: 0' will cause an item that was set to 'Ordered' to now be available for loan." + - Each pair of values should be on a separate line. + - + - pref: CumulativeRestrictionPeriods + choices: + yes: Cumulate + no: "Don't cumulate" + - the restriction periods. +Holds Policy: + - + - pref: AllowHoldItemTypeSelection + choices: + yes: Allow + no: "Don't allow" + - hold fulfillment to be limited by itemtype. + - + - pref: AllowRenewalIfOtherItemsAvailable + choices: + yes: Allow + no: "Don't allow" + - a patron to renew an item with unfilled holds if other available items can fill that hold. + - + - pref: AllowHoldPolicyOverride + choices: + yes: Allow + no: "Don't allow" + - staff to override hold policies when placing holds. + - + - pref: AllowHoldsOnDamagedItems + choices: + yes: Allow + no: "Don't allow" + - hold requests to be placed on and filled by damaged items. + - + - pref: AllowHoldDateInFuture + choices: + yes: Allow + no: "Don't allow" + - hold requests to be placed that do not enter the waiting list until a certain future date. + - + - pref: OPACAllowHoldDateInFuture + choices: + yes: Allow + no: "Don't allow" + - "patrons to place holds that don't enter the waiting list until a certain future date. (AllowHoldDateInFuture must also be enabled)." + - + - Confirm future hold requests (starting no later than + - pref: ConfirmFutureHolds + class: integer + - days from now) at checkin time. Note that this number of days will be used too in calculating the default end date for the Holds to pull-report. But it does not interfere with issuing, renewing or transferring books. + - + - Check the + - pref: ReservesControlBranch + choices: + ItemHomeLibrary: "item's home library" + 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" + - + - If using ExpireReservesMaxPickUpDelay, charge a borrower who allows his or her waiting hold to expire a fee of + - pref: ExpireReservesMaxPickUpDelayCharge + class: currency + - + - Satisfy holds using items from the libraries + - pref: StaticHoldsQueueWeight + class: multi + - (as branchcodes, separated by commas; if empty, uses all libraries) + - when they are + - pref: HoldsQueueSkipClosed + choices: + yes: open + no: open or closed + - pref: RandomizeHoldsQueueWeight + choices: + yes: in random order. + no: in that order. + - + - + - pref: canreservefromotherbranches + choices: + yes: Allow + no: "Don't allow (with independent branches)" + - a user from one library to place a hold on an item from another library + - + - pref: OPACAllowUserToChooseBranch + choices: + yes: Allow + no: "Don't allow" + - a user to choose the library to pick up a hold from. + - + - pref: ReservesNeedReturns + choices: + yes: "Don't automatically" + no: Automatically + - mark a hold as found and waiting when a hold is placed on a specific item and that item is already checked in. + - + - Patrons can only have + - pref: maxreserves + class: integer + - holds at once. + - + - pref: emailLibrarianWhenHoldIsPlaced + choices: + yes: Enable + no: "Don't enable" + - "sending an email to the Koha administrator email address whenever a hold request is placed." + - + - pref: DisplayMultiPlaceHold + choices: + yes: Enable + no: "Don't enable" + - "the ability to place holds on multiple biblio from the search results" + - + - pref: TransferWhenCancelAllWaitingHolds + choices: + yes: Transfer + no: "Don't transfer" + - items when cancelling all waiting holds. + - + - pref: AutoResumeSuspendedHolds + choices: + yes: Allow + no: "Don't allow" + - suspended holds to be automatically resumed by a set date. + - + - pref: SuspendHoldsIntranet + choices: + yes: Allow + no: "Don't allow" + - holds to be suspended from the intranet. + - + - pref: SuspendHoldsOpac + choices: + yes: Allow + no: "Don't allow" + - holds to be suspended from the OPAC. + - + - pref: ExpireReservesOnHolidays + choices: + yes: Allow + no: "Don't allow" + - expired holds to be canceled on days the library is closed. + - + - pref: ExcludeHolidaysFromMaxPickUpDelay + choices: + yes: Allow + no: "Don't allow" + - Closed days to be taken into account in reserves max pickup delay. + - + - pref: decreaseLoanHighHolds + choices: + yes: Enable + no: "Don't enable" + - the reduction of loan period to + - pref: decreaseLoanHighHoldsDuration + class: integer + - days for items with more than + - pref: decreaseLoanHighHoldsValue + class: integer + - holds + - pref: decreaseLoanHighHoldsControl + choices: + static: "on the record" + dynamic: "over the number of holdable items on the record" + - . Ignore items with the following statuses when counting items + - pref: decreaseLoanHighHoldsIgnoreStatuses + multiple: + damaged: Damaged + itemlost: Lost + withdrawn: Withdrawn + notforloan: Not for loan + - + - pref: AllowHoldsOnPatronsPossessions + choices: + yes: Allow + no: "Don't allow" + - a patron to place a hold on a record where the patron already has one or more items attached to that record checked out. + - + - pref: LocalHoldsPriority + choices: + yes: Give + no: "Don't give" + - priority for filling holds to patrons whose + - pref: LocalHoldsPriorityPatronControl + choices: + PickupLibrary: "pickup library" + HomeLibrary: "home library" + - matches the item's + - pref: LocalHoldsPriorityItemControl + choices: + homebranch: "home library" + holdingbranch: "holding library" + - + - pref: OPACHoldsIfAvailableAtPickup + choices: + yes: Allow + no: "Don't allow" + - to pickup up holds at libraries where the item is available. + - + - "Patron categories not affected by OPACHoldsIfAvailableAtPickup" + - pref: OPACHoldsIfAvailableAtPickupExceptions + - "(list of patron categories separated with a pipe '|')" + - + - pref: PreventReservesOnSamePeriod + choices: + yes: Do + no: "Don't" + - If yes, Reserves periods for the same document can't overlap. Interlibrary Loans: - - pref: ILLModule 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 4c66feb..5a13159 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -212,6 +212,7 @@ [% IF ( RESERVED ) %]

+

[% END %] @@ -220,6 +221,7 @@


+

diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/placerequest.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/placerequest.tt new file mode 100644 index 0000000..e2b3409 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/placerequest.tt @@ -0,0 +1,66 @@ +[% INCLUDE 'doc-head-open.inc' %] + Koha › Circulation › Holds › Confirm holds +[% INCLUDE 'doc-head-close.inc' %] + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'circ-search.inc' %] + + + +
+ +
+
+
+ +

Confirm holds

+ +
+

+ Some of the reserves you are trying to do overlaps with existing reserves. + Please confirm you want to proceed. +

+
+ +
+ + [% IF multi_hold %] + + + [% ELSE %] + + [% END %] + + + + + + + [% FOREACH biblionumber IN overlap_reserves.keys %] + [% input_id = "confirm_$biblionumber" %] +
+ + [% IF (overlap_reserves.$biblionumber.checkitem) %] + + [% END %] + + +
+ [% END %] + + +
+ +
+
+ +
+[% INCLUDE 'intranet-bottom.inc' %] diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl index 2be6991..739a5b8 100755 --- a/opac/opac-reserve.pl +++ b/opac/opac-reserve.pl @@ -285,6 +285,15 @@ if ( $query->param('place_reserve') ) { # Inserts a null into the 'itemnumber' field of 'reserves' table. $itemNum = undef; } + + if ($canreserve) { + if (C4::Context->preference("PreventReservesOnSamePeriod") && + ReservesOnSamePeriod($biblioNum, $itemNum, $startdate, $expiration_date)) { + $canreserve = 0; + $failed_holds++; + } + } + my $notes = $query->param('notes_'.$biblioNum)||''; if ( $maxreserves diff --git a/reserve/placerequest.pl b/reserve/placerequest.pl index 3c55656..92b5cee 100755 --- a/reserve/placerequest.pl +++ b/reserve/placerequest.pl @@ -30,48 +30,61 @@ use C4::Output; use C4::Reserves; use C4::Circulation; use C4::Members; -use C4::Auth qw/checkauth/; +use C4::Auth; use Koha::Patrons; my $input = CGI->new(); -checkauth($input, 0, { reserveforothers => 'place_holds' }, 'intranet'); - -my @bibitems = $input->multi_param('biblioitem'); -my @reqbib = $input->multi_param('reqbib'); -my $biblionumber = $input->param('biblionumber'); -my $borrowernumber = $input->param('borrowernumber'); -my $notes = $input->param('notes'); -my $branch = $input->param('pickup'); -my $startdate = $input->param('reserve_date') || ''; -my @rank = $input->multi_param('rank-request'); -my $type = $input->param('type'); -my $title = $input->param('title'); -my $checkitem = $input->param('checkitem'); +my ( $template, $borrowernumber, $cookie, $flags ) = get_template_and_user( + { + template_name => "reserve/placerequest.tt", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => { reserveforothers => 'place_holds' }, + } +); + +my $biblionumber=$input->param('biblionumber'); +my $borrowernumber=$input->param('borrowernumber'); +my $notes=$input->param('notes'); +my $branch=$input->param('pickup'); +my $startdate=$input->param('reserve_date') || ''; +my @rank=$input->param('rank-request'); +my $title=$input->param('title'); +my $checkitem=$input->param('checkitem'); my $expirationdate = $input->param('expiration_date'); my $itemtype = $input->param('itemtype') || undef; - -my $borrower = Koha::Patrons->find( $borrowernumber ); -$borrower = $borrower->unblessed if $borrower; +my $confirm = $input->param('confirm'); +my @confirm_biblionumbers = $input->param('confirm_biblionumbers'); my $multi_hold = $input->param('multi_hold'); my $biblionumbers = $multi_hold ? $input->param('biblionumbers') : ($biblionumber . '/'); my $bad_bibs = $input->param('bad_bibs'); my $holds_to_place_count = $input->param('holds_to_place_count') || 1; +my $borrower = Koha::Patrons->find( $borrowernumber ); +$borrower = $borrower->unblessed if $borrower; +unless ($borrower) { + print $input->header(); + print "Invalid borrower number please try again"; + exit; +} + my %bibinfos = (); my @biblionumbers = split '/', $biblionumbers; foreach my $bibnum (@biblionumbers) { - my %bibinfo = (); + my %bibinfo; $bibinfo{title} = $input->param("title_$bibnum"); + $bibinfo{rank} = $input->param("rank_$bibnum"); $bibinfos{$bibnum} = \%bibinfo; } my $found; -# if we have an item selectionned, and the pickup branch is the same as the holdingbranch -# of the document, we force the value $rank and $found . +# if we have an item selectionned, and the pickup branch is the same as the +# holdingbranch of the document, we force the value $rank and $found . if (defined $checkitem && $checkitem ne ''){ $holds_to_place_count = 1; $rank[0] = '0' unless C4::Context->preference('ReservesNeedReturns'); @@ -82,43 +95,59 @@ if (defined $checkitem && $checkitem ne ''){ } } -if ( $type eq 'str8' && $borrower ) { - - foreach my $biblionumber ( keys %bibinfos ) { - my $count = @bibitems; - @bibitems = sort @bibitems; - my $i2 = 1; - my @realbi; - $realbi[0] = $bibitems[0]; - for ( my $i = 1 ; $i < $count ; $i++ ) { - my $i3 = $i2 - 1; - if ( $realbi[$i3] ne $bibitems[$i] ) { - $realbi[$i2] = $bibitems[$i]; - $i2++; - } - } +my $overlap_reserves = {}; +foreach my $biblionumber (keys %bibinfos) { + next if ($confirm && !grep { $_ eq $biblionumber } @confirm_biblionumbers); - if ( defined $checkitem && $checkitem ne '' ) { - my $item = GetItem($checkitem); - if ( $item->{'biblionumber'} ne $biblionumber ) { - $biblionumber = $item->{'biblionumber'}; - } - } + my ($reserve_title, $reserve_rank); + if ($multi_hold) { + my $bibinfo = $bibinfos{$biblionumber}; + $reserve_rank = $bibinfo->{rank}; + $reserve_title = $bibinfo->{title}; + } else { + $reserve_rank = $rank[0]; + $reserve_title = $title; + } - if ($multi_hold) { - my $bibinfo = $bibinfos{$biblionumber}; - AddReserve($branch,$borrower->{'borrowernumber'},$biblionumber,[$biblionumber], - $bibinfo->{rank},$startdate,$expirationdate,$notes,$bibinfo->{title},$checkitem,$found); - } else { - # place a request on 1st available - for ( my $i = 0 ; $i < $holds_to_place_count ; $i++ ) { - AddReserve( $branch, $borrower->{'borrowernumber'}, - $biblionumber, \@realbi, $rank[0], $startdate, $expirationdate, $notes, $title, - $checkitem, $found, $itemtype ); - } + if (defined $checkitem && $checkitem ne '') { + my $item = GetItem($checkitem); + if ($item->{'biblionumber'} ne $biblionumber) { + $biblionumber = $item->{'biblionumber'}; } } + if (!$confirm && + ReservesOnSamePeriod($biblionumber, $checkitem, $startdate, $expirationdate) && + C4::Context->preference("PreventReservesOnSamePeriod")) { + $overlap_reserves->{$biblionumber} = { + title => $reserve_title , + checkitem => $checkitem, + rank => $reserve_rank + }; + next; + } + + AddReserve($branch, $borrower->{'borrowernumber'}, $biblionumber, undef, + $reserve_rank, $startdate, $expirationdate, $notes, $reserve_title, + $checkitem, $found); +} + +if (scalar keys %$overlap_reserves) { + $template->param( + borrowernumber => $borrowernumber, + biblionumbers => $biblionumbers, + biblionumber => $biblionumber, + overlap_reserves => $overlap_reserves, + reserve_date => $startdate, + expiration_date => $expirationdate, + notes => $notes, + rank_request => \@rank, + pickup => $branch, + multi_hold => $multi_hold, + ); + + output_html_with_http_headers $input, $cookie, $template->output; +} else { if ($multi_hold) { if ($bad_bibs) { $biblionumbers .= $bad_bibs; @@ -128,12 +157,5 @@ if ( $type eq 'str8' && $borrower ) { else { print $input->redirect("request.pl?biblionumber=$biblionumber"); } -} -elsif ( $borrowernumber eq '' ) { - print $input->header(); - print "Invalid borrower number please try again"; - - # Not sure that Dump() does HTML escaping. Use firebug or something to trace - # instead. - #print $input->Dump; + exit; } diff --git a/t/db_dependent/Circulation/CanBookBeIssued.t b/t/db_dependent/Circulation/CanBookBeIssued.t new file mode 100644 index 0000000..487400d --- /dev/null +++ b/t/db_dependent/Circulation/CanBookBeIssued.t @@ -0,0 +1,107 @@ +#!/usr/bin/env perl + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Test::More tests => 1; +use C4::Members; +use C4::Reserves; +use C4::Circulation; +use C4::Branch; +use Koha::DateUtils; + +use t::lib::TestBuilder; + +my $schema = Koha::Database->new->schema; +$schema->storage->txn_begin; + +my $builder = t::lib::TestBuilder->new(); + +subtest 'Tests for CanBookBeIssued with overlap reserves' => sub { + plan tests => 6; + + my $categorycode = $builder->build({ source => 'Category' })->{ categorycode }; + my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode }; + + my $borrower = $builder->build({ + source => 'Borrower', + value => { + branchcode => $branchcode, + categorycode => $categorycode, + } + }); + my $borrowernumber = $borrower->{borrowernumber}; + $borrower = GetMemberDetails($borrowernumber); + + my $biblio = $builder->build({source => 'Biblio'}); + my $biblioitem = $builder->build({ + source => 'Biblioitem', + value => { + biblionumber => $biblio->{biblionumber}, + }, + }); + my $item = $builder->build({ + source => 'Item', + value => { + biblionumber => $biblio->{biblionumber}, + biblioitemnumber => $biblioitem->{biblioitemnumber}, + withdrawn => 0, + itemlost => 0, + notforloan => 0, + }, + }); + + + my $startdate = dt_from_string(); + $startdate->add_duration(DateTime::Duration->new(days => 4)); + my $expdate = $startdate->clone(); + $expdate->add_duration(DateTime::Duration->new(days => 10)); + + my $reserveid = AddReserve($branchcode, $borrowernumber, + $item->{biblionumber}, undef, 1, $startdate->ymd(), $expdate->ymd, + undef, undef, undef, undef); + + my $non_overlap_duedate = dt_from_string(); + $non_overlap_duedate->add_duration(DateTime::Duration->new(days => 2)); + my ($error, $question, $alerts ) = + CanBookBeIssued($borrower, $item->{barcode}, $non_overlap_duedate, 1, 0); + + is_deeply($error, {}, ""); + is_deeply($question, {}, ""); + is_deeply($alerts, {}, ""); + + my $overlap_duedate = dt_from_string(); + $overlap_duedate->add_duration(DateTime::Duration->new(days => 5)); + ($error, $question, $alerts ) = + CanBookBeIssued($borrower, $item->{barcode}, $overlap_duedate, 1, 0); + + is_deeply($error, {}, ""); + my $expected = { + RESERVED => 1, + resfirstname => $borrower->{firstname}, + ressurname => $borrower->{surname}, + rescardnumber => $borrower->{cardnumber}, + resborrowernumber => $borrower->{borrowernumber}, + resbranchname => GetBranchName($branchcode), + resreservedate => $startdate->ymd, + resreserveid => $reserveid, + }; + is_deeply($question, $expected, ""); + is_deeply($alerts, {}, ""); +}; + +$schema->storage->txn_rollback; diff --git a/t/db_dependent/Reserves/ReserveDate.t b/t/db_dependent/Reserves/ReserveDate.t new file mode 100644 index 0000000..4d7f8af --- /dev/null +++ b/t/db_dependent/Reserves/ReserveDate.t @@ -0,0 +1,108 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Test::More tests => 6; +use Test::Warn; + +use MARC::Record; +use DateTime::Duration; + +use C4::Biblio; +use C4::Items; +use C4::Members; +use C4::Circulation; +use Koha::Holds; +use t::lib::TestBuilder; + +use Koha::DateUtils; + + +use_ok('C4::Reserves'); + +my $dbh = C4::Context->dbh; + +# Start transaction +$dbh->{AutoCommit} = 0; +$dbh->{RaiseError} = 1; + +my $builder = t::lib::TestBuilder->new(); +my $categorycode = $builder->build({ source => 'Category' })->{ categorycode }; +my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode }; + +my $borrower = $builder->build({ + source => 'Borrower', + value => { + branchcode => $branchcode, + categorycode => $categorycode, + } +}); + +my $borrower2 = $builder->build({ + source => 'Borrower', + value => { + branchcode => $branchcode, + categorycode => $categorycode, + } +}); + +my $borrowernumber = $borrower->{borrowernumber}; +my $borrowernumber2 = $borrower2->{borrowernumber}; + +# Create a helper biblio +my $biblio = MARC::Record->new(); +my $title = 'Alone in the Dark'; +my $author = 'Karen Rose'; +if( C4::Context->preference('marcflavour') eq 'UNIMARC' ) { + $biblio->append_fields( + MARC::Field->new('600', '', '1', a => $author), + MARC::Field->new('200', '', '', a => $title), + ); +} +else { + $biblio->append_fields( + MARC::Field->new('100', '', '', a => $author), + MARC::Field->new('245', '', '', a => $title), + ); +} +my ($bibnum, $bibitemnum); +($bibnum, $title, $bibitemnum) = AddBiblio($biblio, ''); + +my ($item_bibnum, $item_bibitemnum, $itemnumber) = AddItem({ homebranch => $branchcode, holdingbranch => $branchcode, barcode => '333' } , $bibnum); + +C4::Context->set_preference('AllowHoldDateInFuture', 1); + +AddReserve($branchcode, $borrowernumber, $bibnum, + $bibitemnum, 1, '2015-11-01', '2015-11-20', undef, + undef, undef, undef); + +is(ReservesOnSamePeriod($bibnum, undef, '2015-11-25', '2015-11-30'), undef, "Period doesn't overlaps"); + +ok(ReservesOnSamePeriod($bibnum, undef, '2015-11-02', '2015-11-10'), "Period overlaps"); + +my ($item_bibnum2, $item_bibitemnum2, $itemnumber2) = AddItem({ homebranch => $branchcode, holdingbranch => $branchcode, barcode => '444' } , $bibnum); +is(ReservesOnSamePeriod($bibnum, undef, '2015-11-02', '2015-11-10'), undef, "Period overlaps but there is 2 items"); + +AddReserve($branchcode, $borrowernumber2, $bibnum, + $bibitemnum, 1, '2016-02-01', '2016-02-10', undef, + undef, $itemnumber, undef); +is(ReservesOnSamePeriod($bibnum, $itemnumber, '02/12/2015', '10/12/2015'), undef, "Period on item does not overlap (with metric date format)"); + +my $reserve = ReservesOnSamePeriod($bibnum, $itemnumber, '2016-01-31', '2016-02-05'); +is($reserve->[0]->{itemnumber}, $itemnumber, 'Period on item overlaps'); +$dbh->rollback; -- 2.7.4