View | Details | Raw Unified | Return to bug 4045
Collapse All | Expand All

(-)a/installer/data/mysql/updatedatabase.pl (+7 lines)
Lines 8551-8556 if (CheckVersion($DBversion)) { Link Here
8551
    SetVersion($DBversion);
8551
    SetVersion($DBversion);
8552
}
8552
}
8553
8553
8554
$DBversion = "3.15.00.XXX";
8555
if ( CheckVersion($DBversion) ) {
8556
    $dbh->do("INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES ('maxreserves',50,'System-wide maximum number of holds a patron can place','','Integer')");
8557
    print "Upgrade to $DBversion done (Re-add system preference maxreserves)\n";
8558
    SetVersion($DBversion);
8559
}
8560
8554
=head1 FUNCTIONS
8561
=head1 FUNCTIONS
8555
8562
8556
=head2 TableExists($table)
8563
=head2 TableExists($table)
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt (+13 lines)
Lines 105-110 Link Here
105
                            </div>
105
                            </div>
106
                        [% END %]
106
                        [% END %]
107
107
108
                        [% IF ( new_reserves_allowed ) %]
109
                            <div id="new_reserves_allowed" class="alert">
110
                                <strong>Sorry,</strong> you can only place [% new_reserves_allowed %] more holds. Please uncheck the checkboxes for the items you wish to not place holds on.
111
                            </div>
112
                        [% END %]
113
108
                        <form action="/cgi-bin/koha/opac-reserve.pl" method="post" id="hold-request-form">
114
                        <form action="/cgi-bin/koha/opac-reserve.pl" method="post" id="hold-request-form">
109
                            <input type="hidden" name="place_reserve" value="1"/>
115
                            <input type="hidden" name="place_reserve" value="1"/>
110
                            <!-- These values are set dynamically by js -->
116
                            <!-- These values are set dynamically by js -->
Lines 563-568 Link Here
563
            var biblionumbers = "";
569
            var biblionumbers = "";
564
            var selections = "";
570
            var selections = "";
565
571
572
            [% IF new_reserves_allowed %]
573
                if ($(".confirmjs:checked").size() > [% new_reserves_allowed %] ) {
574
                    alert(_("You cannot place this many new holds. Please reduce the number of selected holds to %s holds").format([% new_reserves_allowed %]));
575
                    return false;
576
                }
577
            [% END %]
578
566
            if ($(".confirmjs:checked").size() == 0) {
579
            if ($(".confirmjs:checked").size() == 0) {
567
                alert(MSG_NO_RECORD_SELECTED);
580
                alert(MSG_NO_RECORD_SELECTED);
568
                return false;
581
                return false;
(-)a/koha-tmpl/opac-tmpl/bootstrap/js/global.js (-1 / +13 lines)
Lines 1-3 Link Here
1
// http://stackoverflow.com/questions/1038746/equivalent-of-string-format-in-jquery/5341855#5341855
2
String.prototype.format = function() { return formatstr(this, arguments) }
3
function formatstr(str, col) {
4
    col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1);
5
    var idx = 0;
6
    return str.replace(/%%|%s|%(\d+)\$s/g, function (m, n) {
7
        if (m == "%%") { return "%"; }
8
        if (m == "%s") { return col[idx++]; }
9
        return col[n];
10
    });
11
};
12
1
function confirmDelete(message) {
13
function confirmDelete(message) {
2
    return (confirm(message) ? true : false);
14
    return (confirm(message) ? true : false);
3
}
15
}
Lines 22-25 function prefixOf (s, tok) { Link Here
22
function suffixOf (s, tok) {
34
function suffixOf (s, tok) {
23
    var index = s.indexOf(tok);
35
    var index = s.indexOf(tok);
24
    return s.substring(index + 1);
36
    return s.substring(index + 1);
25
}
37
}
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt (+15 lines)
Lines 7-16 Link Here
7
<script type="text/javascript">
7
<script type="text/javascript">
8
// <![CDATA[
8
// <![CDATA[
9
 var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection.");
9
 var MSG_NO_ITEM_SELECTED = _("Expecting a specific item selection.");
10
10
 var ForceHoldNotesReasons=new Array(
11
 var ForceHoldNotesReasons=new Array(
11
    _("This title consists of multiple volumes/parts. Please indicate which part you need. Clicking on specific item information may be helpful."),
12
    _("This title consists of multiple volumes/parts. Please indicate which part you need. Clicking on specific item information may be helpful."),
12
    "*** Add a new reason above this line ***" ); // NOTE: Do not renumber reasons; this will affect use of existing ones.
13
    "*** Add a new reason above this line ***" ); // NOTE: Do not renumber reasons; this will affect use of existing ones.
13
14
15
 var MSG_MAX_HOLDS_EXCEEDED = _("You cannot place this many more holds, please reduce the amount of holds requested to [% new_reserves_allowed %] or less.");
16
14
 function prefixOf (s, tok) {
17
 function prefixOf (s, tok) {
15
     var index = s.indexOf(tok);
18
     var index = s.indexOf(tok);
16
     return s.substring(0, index);
19
     return s.substring(0, index);
Lines 176-181 function select_first_available(id){ Link Here
176
            return false;
179
            return false;
177
        }
180
        }
178
181
182
   [% IF ( new_reserves_allowed ) %]
183
        if ($(".confirmjs:checked").size() > [% new_reserves_allowed %]) {
184
            alert(MSG_MAX_HOLDS_EXCEEDED);
185
            return false;
186
        }
187
    [% END %]
188
179
        // Find the items with the 'Hold' box checked
189
        // Find the items with the 'Hold' box checked
180
        var badBib = null;
190
        var badBib = null;
181
        $(".confirmjs:checked").each(function() {
191
        $(".confirmjs:checked").each(function() {
Lines 248-253 function select_first_available(id){ Link Here
248
    [% INCLUDE 'masthead.inc' %]
258
    [% INCLUDE 'masthead.inc' %]
249
	  <div id="yui-g">
259
	  <div id="yui-g">
250
        <div id="holds" class="container">
260
        <div id="holds" class="container">
261
            [% IF ( new_reserves_allowed ) %]
262
              <div id="new_reserves_allowed" class="dialog alert">
263
                <p><strong>Sorry</strong>, you cannot place holds on all these items. You can only place [% new_reserves_allowed %] more hold(s). Please choose the items you wish to be held.</p>
264
              </div>
265
            [% END %]
251
        [% IF ( message ) %]
266
        [% IF ( message ) %]
252
            [% IF ( GNA ) %]
267
            [% IF ( GNA ) %]
253
              <div id="gna" class="dialog alert">
268
              <div id="gna" class="dialog alert">
(-)a/opac/opac-reserve.pl (-14 / +24 lines)
Lines 38-44 use Koha::DateUtils; Link Here
38
use Date::Calc qw/Today Date_to_Days/;
38
use Date::Calc qw/Today Date_to_Days/;
39
# use Data::Dumper;
39
# use Data::Dumper;
40
40
41
my $MAXIMUM_NUMBER_OF_RESERVES = C4::Context->preference("maxreserves");
41
my $maxreserves = C4::Context->preference("maxreserves");
42
42
43
my $query = new CGI;
43
my $query = new CGI;
44
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
44
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
Lines 114-119 if (($#biblionumbers < 0) && (! $query->param('place_reserve'))) { Link Here
114
    &get_out($query, $cookie, $template->output);
114
    &get_out($query, $cookie, $template->output);
115
}
115
}
116
116
117
117
# pass the pickup branch along....
118
# pass the pickup branch along....
118
my $branch = $query->param('branch') || $borr->{'branchcode'} || C4::Context->userenv->{branch} || '' ;
119
my $branch = $query->param('branch') || $borr->{'branchcode'} || C4::Context->userenv->{branch} || '' ;
119
($branches->{$branch}) or $branch = "";     # Confirm branch is real
120
($branches->{$branch}) or $branch = "";     # Confirm branch is real
Lines 183-189 foreach my $biblioNumber (@biblionumbers) { Link Here
183
#
184
#
184
if ( $query->param('place_reserve') ) {
185
if ( $query->param('place_reserve') ) {
185
    my $reserve_cnt = 0;
186
    my $reserve_cnt = 0;
186
    if ($MAXIMUM_NUMBER_OF_RESERVES) {
187
    if ($maxreserves) {
187
        $reserve_cnt = GetReservesFromBorrowernumber( $borrowernumber );
188
        $reserve_cnt = GetReservesFromBorrowernumber( $borrowernumber );
188
    }
189
    }
189
190
Lines 267-274 if ( $query->param('place_reserve') ) { Link Here
267
        }
268
        }
268
        my $notes = $query->param('notes_'.$biblioNum)||'';
269
        my $notes = $query->param('notes_'.$biblioNum)||'';
269
270
270
        if (   $MAXIMUM_NUMBER_OF_RESERVES
271
        if (   $maxreserves
271
            && $reserve_cnt >= $MAXIMUM_NUMBER_OF_RESERVES )
272
            && $reserve_cnt >= $maxreserves )
272
        {
273
        {
273
            $canreserve = 0;
274
            $canreserve = 0;
274
        }
275
        }
Lines 308-339 if ( $borr->{'amountoutstanding'} && ($borr->{'amountoutstanding'} > $maxoutstan Link Here
308
if ( $borr->{gonenoaddress} && ($borr->{gonenoaddress} == 1) ) {
309
if ( $borr->{gonenoaddress} && ($borr->{gonenoaddress} == 1) ) {
309
    $noreserves = 1;
310
    $noreserves = 1;
310
    $template->param(
311
    $template->param(
311
                     message => 1,
312
        message => 1,
312
                     GNA     => 1
313
        GNA     => 1
313
                    );
314
    );
314
}
315
}
315
if ( $borr->{lost} && ($borr->{lost} == 1) ) {
316
if ( $borr->{lost} && ($borr->{lost} == 1) ) {
316
    $noreserves = 1;
317
    $noreserves = 1;
317
    $template->param(
318
    $template->param(
318
                     message => 1,
319
        message => 1,
319
                     lost    => 1
320
        lost    => 1
320
                    );
321
    );
321
}
322
}
322
if ( $borr->{'debarred'} ) {
323
if ( $borr->{'debarred'} ) {
323
    $noreserves = 1;
324
    $noreserves = 1;
324
    $template->param(
325
    $template->param(
325
                     message  => 1,
326
        message  => 1,
326
                     debarred => 1
327
        debarred => 1
327
                    );
328
    );
328
}
329
}
329
330
330
my @reserves = GetReservesFromBorrowernumber( $borrowernumber );
331
my @reserves = GetReservesFromBorrowernumber( $borrowernumber );
332
my $reserves_count = scalar(@reserves);
331
$template->param( RESERVES => \@reserves );
333
$template->param( RESERVES => \@reserves );
332
if ( $MAXIMUM_NUMBER_OF_RESERVES && (scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RESERVES) ) {
334
if ( $maxreserves && ( $reserves_count >= $maxreserves ) ) {
333
    $template->param( message => 1 );
335
    $template->param( message => 1 );
334
    $noreserves = 1;
336
    $noreserves = 1;
335
    $template->param( too_many_reserves => scalar(@reserves));
337
    $template->param( too_many_reserves => scalar(@reserves));
336
}
338
}
339
340
unless ( $noreserves ) {
341
    my $requested_reserves_count = scalar( @biblionumbers );
342
    if ( $maxreserves && ( $reserves_count + $requested_reserves_count > $maxreserves ) ) {
343
        $template->param( new_reserves_allowed => $maxreserves - $reserves_count );
344
    }
345
}
346
337
foreach my $res (@reserves) {
347
foreach my $res (@reserves) {
338
    foreach my $biblionumber (@biblionumbers) {
348
    foreach my $biblionumber (@biblionumbers) {
339
        if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) {
349
        if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) {
(-)a/reserve/request.pl (-6 / +9 lines)
Lines 78-83 $findborrower =~ s|,| |g; Link Here
78
my $borrowernumber_hold = $input->param('borrowernumber') || '';
78
my $borrowernumber_hold = $input->param('borrowernumber') || '';
79
my $messageborrower;
79
my $messageborrower;
80
my $maxreserves;
80
my $maxreserves;
81
my $warnings;
82
my $messages;
81
83
82
my $date = C4::Dates->today('iso');
84
my $date = C4::Dates->today('iso');
83
my $action = $input->param('action');
85
my $action = $input->param('action');
Lines 122-134 if ($borrowernumber_hold && !$action) { Link Here
122
    my @getreservloop;
124
    my @getreservloop;
123
    my $count_reserv = 0;
125
    my $count_reserv = 0;
124
126
125
#   we check the reserves of the borrower, and if he can reserv a document
127
    # we check the reserves of the borrower, and if he can reserv a document
126
# FIXME At this time we have a simple count of reservs, but, later, we could improve the infos "title" ...
128
    # FIXME At this time we have a simple count of reservs, but, later, we could improve the infos "title" ...
127
129
128
    my $number_reserves =
130
    my $number_reserves =
129
      GetReserveCount( $borrowerinfo->{'borrowernumber'} );
131
      GetReserveCount( $borrowerinfo->{'borrowernumber'} );
130
132
131
    if ( C4::Context->preference('maxreserves') && ($number_reserves >= C4::Context->preference('maxreserves')) ) {
133
    if ( C4::Context->preference('maxreserves') && ($number_reserves >= C4::Context->preference('maxreserves')) ) {
134
        $warnings = 1;
132
        $maxreserves = 1;
135
        $maxreserves = 1;
133
    }
136
    }
134
137
Lines 136-142 if ($borrowernumber_hold && !$action) { Link Here
136
    my $expiry_date = $borrowerinfo->{dateexpiry};
139
    my $expiry_date = $borrowerinfo->{dateexpiry};
137
    my $expiry = 0; # flag set if patron account has expired
140
    my $expiry = 0; # flag set if patron account has expired
138
    if ($expiry_date and $expiry_date ne '0000-00-00' and
141
    if ($expiry_date and $expiry_date ne '0000-00-00' and
139
            Date_to_Days(split /-/,$date) > Date_to_Days(split /-/,$expiry_date)) {
142
        Date_to_Days(split /-/,$date) > Date_to_Days(split /-/,$expiry_date)) {
140
        $expiry = 1;
143
        $expiry = 1;
141
    }
144
    }
142
145
Lines 162-167 if ($borrowernumber_hold && !$action) { Link Here
162
                cardnumber          => $borrowerinfo->{'cardnumber'},
165
                cardnumber          => $borrowerinfo->{'cardnumber'},
163
                expiry              => $expiry,
166
                expiry              => $expiry,
164
                diffbranch          => $diffbranch,
167
                diffbranch          => $diffbranch,
168
                messages            => $messages,
169
                warnings            => $warnings
165
    );
170
    );
166
}
171
}
167
172
Lines 417-424 foreach my $biblionumber (@biblionumbers) { Link Here
417
                $num_available++;
422
                $num_available++;
418
            }
423
            }
419
            elsif ( C4::Context->preference('AllowHoldPolicyOverride') ) {
424
            elsif ( C4::Context->preference('AllowHoldPolicyOverride') ) {
420
425
                # If AllowHoldPolicyOverride is set, it should override EVERY restriction, not just branch item rules
421
# If AllowHoldPolicyOverride is set, it should override EVERY restriction, not just branch item rules
422
                $item->{override} = 1;
426
                $item->{override} = 1;
423
                $num_override++;
427
                $num_override++;
424
            }
428
            }
425
- 

Return to bug 4045