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

(-)a/C4/Items.pm (-19 / +25 lines)
Lines 1219-1225 $filter->{fromDate} = '01/01/2013'; #Filters only serial issues by the serialite Link Here
1219
$filter->{toDate} = '31/12/2014';   #Filters only serial issues by the serialitems.publisheddate
1219
$filter->{toDate} = '31/12/2014';   #Filters only serial issues by the serialitems.publisheddate
1220
                                          #The ending date in C4::Context->preference('dateformat') format
1220
                                          #The ending date in C4::Context->preference('dateformat') format
1221
$filter->{limit} = 15;              #Limits the returning set to this many items
1221
$filter->{limit} = 15;              #Limits the returning set to this many items
1222
1222
$filter->{itemnumber} = 165;        #Returns the item with this itemnumber
1223
                                          
1223
Filters are expected to be validated! If a filter is not defined, that filter is not present in the $filter-HASH
1224
Filters are expected to be validated! If a filter is not defined, that filter is not present in the $filter-HASH
1224
1225
1225
=cut
1226
=cut
Lines 1227-1246 Filters are expected to be validated! If a filter is not defined, that filter is Link Here
1227
sub GetItemsInfo {
1228
sub GetItemsInfo {
1228
    my ( $biblionumber, $filter ) = @_;
1229
    my ( $biblionumber, $filter ) = @_;
1229
    my $dbh   = C4::Context->dbh;
1230
    my $dbh   = C4::Context->dbh;
1230
1231
    
1231
    #Prepare the filter
1232
    #Prepare the filter
1232
    my $filterEnumchron = 0;
1233
    my $filterEnumchron = 0;
1233
    my $enumchronSQLRegexp;
1234
    my $enumchronSQLRegexp;
1234
    if (defined $filter && ref $filter eq 'HASH') {
1235
    if (defined $filter && ref $filter eq 'HASH') {
1235
1236
        
1236
        #Items enumchron can be filtered by volume or number or both.
1237
        #Items enumchron can be filtered by volume or number or both.
1237
        #Because the format of enumchron
1238
        #Because the format of enumchron 
1238
        #For performance reasons regexp's need to be as simple as possible.
1239
        #For performance reasons regexp's need to be as simple as possible.
1239
        ## It is entirely possible to search with just volume or just number or just issue.
1240
        ## It is entirely possible to search with just volume or just number or just issue.
1240
        ##  We don't know which filters are used so it is safer and more efficient to just
1241
        ##  We don't know which filters are used so it is safer and more efficient to just
1241
        ##  prepare the enumeration parsing SQL every time.
1242
        ##  prepare the enumeration parsing SQL every time.
1242
        $enumchronSQLRegexp = C4::Context->preference('NumberingFormulaParsingRegexp');
1243
        $enumchronSQLRegexp = C4::Context->preference('NumberingFormulaParsingRegexp');
1243
1244
        
1244
        if (exists $filter->{volume}) {
1245
        if (exists $filter->{volume}) {
1245
            $filterEnumchron = 1;
1246
            $filterEnumchron = 1;
1246
            $enumchronSQLRegexp =~ s/volume/$filter->{volume}/;
1247
            $enumchronSQLRegexp =~ s/volume/$filter->{volume}/;
Lines 1261-1274 sub GetItemsInfo { Link Here
1261
        }
1262
        }
1262
        else {
1263
        else {
1263
            $enumchronSQLRegexp =~ s/issue/[0-9]*/;
1264
            $enumchronSQLRegexp =~ s/issue/[0-9]*/;
1264
        }
1265
        }   
1265
    }
1266
    }
1266
    #If we know that this item is a serial, we can better optimize our big SQL.
1267
    #If we know that this item is a serial, we can better optimize our big SQL.
1267
    # This is especially useful when we want to filter based on the publication date.
1268
    # This is especially useful when we want to filter based on the publication date.
1268
    # SELECTing a huge blob of serials just to remove unnecessary ones will be really sloooow.
1269
    # SELECTing a huge blob of serials just to remove unnecessary ones will be really sloooow.
1269
    my $search = C4::SQLHelper::SearchInTable("biblio",{biblionumber => $biblionumber}, undef, undef, ['serial'], undef, "exact");
1270
    my $search = C4::SQLHelper::SearchInTable("biblio",{biblionumber => $biblionumber}, undef, undef, ['serial'], undef, "exact");
1270
    my $serial = $search->[0]->{serial};
1271
    my $serial = $search->[0]->{serial};
1271
1272
    
1272
    # note biblioitems.* must be avoided to prevent large marc and marcxml fields from killing performance.
1273
    # note biblioitems.* must be avoided to prevent large marc and marcxml fields from killing performance.
1273
    #Because it is uncertain how many parameters the SQL query needs, we need to build the parameters dynamically
1274
    #Because it is uncertain how many parameters the SQL query needs, we need to build the parameters dynamically
1274
    # This is because we cannot predict what filters our users use.
1275
    # This is because we cannot predict what filters our users use.
Lines 1294-1301 sub GetItemsInfo { Link Here
1294
           holding.branchname,
1295
           holding.branchname,
1295
           holding.opac_info as branch_opac_info ";
1296
           holding.opac_info as branch_opac_info ";
1296
    if ($serial) {
1297
    if ($serial) {
1297
        $query .= ",
1298
        $query .= ", 
1298
           serial.serialseq,
1299
           serial.serialseq, 
1299
           serial.publisheddate ";
1300
           serial.publisheddate ";
1300
    }
1301
    }
1301
    $query .= "
1302
    $query .= "
Lines 1306-1320 sub GetItemsInfo { Link Here
1306
     LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
1307
     LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
1307
     LEFT JOIN itemtypes   ON   itemtypes.itemtype         = "
1308
     LEFT JOIN itemtypes   ON   itemtypes.itemtype         = "
1308
     . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype');
1309
     . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype');
1309
1310
     
1310
    if ($serial) {
1311
    if ($serial) {
1311
        $query .= "
1312
        $query .= " 
1312
           LEFT JOIN serialitems ON serialitems.itemnumber = items.itemnumber
1313
           LEFT JOIN serialitems ON serialitems.itemnumber = items.itemnumber 
1313
           LEFT JOIN serial ON serialitems.serialid = serial.serialid ";
1314
           LEFT JOIN serial ON serialitems.serialid = serial.serialid ";          
1314
    }
1315
    }
1315
1316
    
1316
    $query .= " WHERE items.biblionumber = ? ";
1317
    $query .= " WHERE items.biblionumber = ? ";
1317
1318
    
1318
    if (exists $filter->{branch}) {
1319
    if (exists $filter->{branch}) {
1319
        $query .= " AND items.holdingbranch = ?";
1320
        $query .= " AND items.holdingbranch = ?";
1320
        push @$queryParams, $filter->{branch};
1321
        push @$queryParams, $filter->{branch};
Lines 1341-1353 sub GetItemsInfo { Link Here
1341
        }
1342
        }
1342
        push @$queryParams, $filter->{toDate};
1343
        push @$queryParams, $filter->{toDate};
1343
    }
1344
    }
1344
1345
    if (exists $filter->{itemnumber}) {
1346
        push @$queryParams, $filter->{itemnumber};
1347
        $query .= " AND items.itemnumber = ?";
1348
    }
1349
    
1350
    
1345
    $query .= "ORDER BY home.branchname, items.enumchron, LPAD( items.copynumber, 8, '0' ), items.dateaccessioned DESC" ;
1351
    $query .= "ORDER BY home.branchname, items.enumchron, LPAD( items.copynumber, 8, '0' ), items.dateaccessioned DESC" ;
1346
    if (exists $filter->{limit}) {
1352
    if (exists $filter->{limit}) {
1347
        push @$queryParams, $filter->{limit};
1353
        push @$queryParams, $filter->{limit};
1348
        $query .= " LIMIT ?";
1354
        $query .= " LIMIT ?";
1349
    }
1355
    }
1350
1356
    
1351
    my $sth = $dbh->prepare($query);
1357
    my $sth = $dbh->prepare($query);
1352
    $sth->execute(@$queryParams);
1358
    $sth->execute(@$queryParams);
1353
    my $i = 0;
1359
    my $i = 0;
Lines 1359-1365 sub GetItemsInfo { Link Here
1359
        WHERE  itemnumber = ?"
1365
        WHERE  itemnumber = ?"
1360
       );
1366
       );
1361
1367
1362
1368
    
1363
	while ( my $data = $sth->fetchrow_hashref ) {
1369
	while ( my $data = $sth->fetchrow_hashref ) {
1364
        my $datedue = '';
1370
        my $datedue = '';
1365
        $isth->execute( $data->{'itemnumber'} );
1371
        $isth->execute( $data->{'itemnumber'} );
Lines 1372-1378 sub GetItemsInfo { Link Here
1372
            $datedue                = $idata->{'date_due'};
1378
            $datedue                = $idata->{'date_due'};
1373
            if (C4::Context->preference("IndependentBranches")){
1379
            if (C4::Context->preference("IndependentBranches")){
1374
                my $userenv = C4::Context->userenv;
1380
                my $userenv = C4::Context->userenv;
1375
                if ( ($userenv) && ( $userenv->{flags} % 2 != 1 ) ) {
1381
                if ( ($userenv) && ( $userenv->{flags} % 2 != 1 ) ) { 
1376
                    $data->{'NOTSAMEBRANCH'} = 1 if ($idata->{'bcode'} ne $userenv->{branch});
1382
                    $data->{'NOTSAMEBRANCH'} = 1 if ($idata->{'bcode'} ne $userenv->{branch});
1377
                }
1383
                }
1378
            }
1384
            }
(-)a/catalogue/detail.pl (+6 lines)
Lines 143-148 my $dat = &GetBiblioData($biblionumber); Link Here
143
my $subscriptionsnumber = CountSubscriptionFromBiblionumber($biblionumber);
143
my $subscriptionsnumber = CountSubscriptionFromBiblionumber($biblionumber);
144
my @subscriptions       = GetSubscriptions( $dat->{title}, $dat->{issn}, undef, $biblionumber );
144
my @subscriptions       = GetSubscriptions( $dat->{title}, $dat->{issn}, undef, $biblionumber );
145
my @subs;
145
my @subs;
146
if (scalar(@subscriptions)) {
147
	$template->param('isSerial',1);
148
}
149
146
150
147
foreach my $subscription (@subscriptions) {
151
foreach my $subscription (@subscriptions) {
148
    my %cell;
152
    my %cell;
Lines 412-415 if (C4::Context->preference('TagsEnabled') and $tag_quantity = C4::Context->pref Link Here
412
my ( $holdcount, $holds ) = C4::Reserves::GetReservesFromBiblionumber($biblionumber,1);
416
my ( $holdcount, $holds ) = C4::Reserves::GetReservesFromBiblionumber($biblionumber,1);
413
$template->param( holdcount => $holdcount, holds => $holds );
417
$template->param( holdcount => $holdcount, holds => $holds );
414
418
419
$template->param('ShowPlaceItemLevelHold',  C4::Context->preference('ShowPlaceItemLevelHold'));
420
415
output_html_with_http_headers $query, $cookie, $template->output;
421
output_html_with_http_headers $query, $cookie, $template->output;
(-)a/installer/data/mysql/sysprefs.sql (+2 lines)
Lines 270-275 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
270
('OpacShowLibrariesPulldownMobile','1',NULL,'Show the libraries pulldown on the mobile version of the OPAC.','YesNo'),
270
('OpacShowLibrariesPulldownMobile','1',NULL,'Show the libraries pulldown on the mobile version of the OPAC.','YesNo'),
271
('OpacShowRecentComments','0',NULL,'If ON a link to recent comments will appear in the OPAC masthead','YesNo'),
271
('OpacShowRecentComments','0',NULL,'If ON a link to recent comments will appear in the OPAC masthead','YesNo'),
272
('OPACShowUnusedAuthorities','1','','Show authorities that are not being used in the OPAC.','YesNo'),
272
('OPACShowUnusedAuthorities','1','','Show authorities that are not being used in the OPAC.','YesNo'),
273
('OPACShowPlaceItemLevelHold','0',NULL,'Allow placing a item-level hold from the detailed biblio view.','YesNo'),
273
('opacsmallimage','','','Enter a complete URL to an image to replace the default Koha logo','free'),
274
('opacsmallimage','','','Enter a complete URL to an image to replace the default Koha logo','free'),
274
('OpacStarRatings','all','disable|all|details',NULL,'Choice'),
275
('OpacStarRatings','all','disable|all|details',NULL,'Choice'),
275
('OpacSuppression','0','','Turn ON the OPAC Suppression feature, requires further setup, ask your system administrator for details','YesNo'),
276
('OpacSuppression','0','','Turn ON the OPAC Suppression feature, requires further setup, ask your system administrator for details','YesNo'),
Lines 341-346 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
341
('ShowPatronImageInWebBasedSelfCheck','0','','If ON, displays patron image when a patron uses web-based self-checkout','YesNo'),
342
('ShowPatronImageInWebBasedSelfCheck','0','','If ON, displays patron image when a patron uses web-based self-checkout','YesNo'),
342
('ShowReviewer','full','none|full|first|surname|firstandinitial|username','Choose how a commenter\'s identity is presented alongside comments in the OPAC','Choice'),
343
('ShowReviewer','full','none|full|first|surname|firstandinitial|username','Choose how a commenter\'s identity is presented alongside comments in the OPAC','Choice'),
343
('ShowReviewerPhoto','1','','If ON, photo of reviewer will be shown beside comments in OPAC','YesNo'),
344
('ShowReviewerPhoto','1','','If ON, photo of reviewer will be shown beside comments in OPAC','YesNo'),
345
('ShowPlaceItemLevelHold','0',NULL,'Allow placing a item-level hold from the detailed biblio view.','YesNo'),
344
('singleBranchMode','0',NULL,'Operate in Single-branch mode, hide branch selection in the OPAC','YesNo'),
346
('singleBranchMode','0',NULL,'Operate in Single-branch mode, hide branch selection in the OPAC','YesNo'),
345
('SlipCSS','',NULL,'Slips CSS url.','free'),
347
('SlipCSS','',NULL,'Slips CSS url.','free'),
346
('SMSSendDriver','','','Sets which SMS::Send driver is used to send SMS messages.','free'),
348
('SMSSendDriver','','','Sets which SMS::Send driver is used to send SMS messages.','free'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref (+7 lines)
Lines 18-23 Cataloging: Link Here
18
                  yes: Display
18
                  yes: Display
19
                  no: "Don't Display"
19
                  no: "Don't Display"
20
            - easy ways to create analytical record relationships
20
            - easy ways to create analytical record relationships
21
        -
22
            - pref: ShowPlaceItemLevelHold
23
              default: 0
24
              choices:
25
                  yes: "Allow"
26
                  no : "Don't allow"
27
            - placing a item-level hold from the detailed biblio view. This is always enabled for serials because serials need only item-level holds.
21
    Spine Labels:
28
    Spine Labels:
22
        -
29
        -
23
            - When using the quick spine label printer,
30
            - When using the quick spine label printer,
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref (+7 lines)
Lines 131-136 OPAC: Link Here
131
                  no: "Don't show"
131
                  no: "Don't show"
132
            - the item's barcode on the holdings tab.
132
            - the item's barcode on the holdings tab.
133
        -
133
        -
134
            - pref: OPACShowPlaceItemLevelHold
135
              default: 0
136
              choices:
137
                  yes: "Allow"
138
                  no : "Don't allow"
139
            - placing a item-level hold from the detailed biblio view. This is always enabled for serials because serials need only item-level holds.
140
        -
134
            - pref: OpacHighlightedWords
141
            - pref: OpacHighlightedWords
135
              choices:
142
              choices:
136
                  yes: Highlight
143
                  yes: Highlight
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt (+8 lines)
Lines 422-427 function verify_images() { Link Here
422
                [% IF ( hostrecords ) %]<th>Host records</th>[% END %]
422
                [% IF ( hostrecords ) %]<th>Host records</th>[% END %]
423
                [% IF ( analyze ) %]<th>Used in</th><th></th>[% END %]
423
                [% IF ( analyze ) %]<th>Used in</th><th></th>[% END %]
424
                [% IF ( ShowCourseReserves ) %]<th>Course Reserves</th>[% END %]
424
                [% IF ( ShowCourseReserves ) %]<th>Course Reserves</th>[% END %]
425
                [% IF ( ShowPlaceItemLevelHold || isSerial ) %]<th id="placeItemLevelHoldTh">Reserve</th>[% END %]
425
            </tr>
426
            </tr>
426
        </thead>
427
        </thead>
427
        <tbody>
428
        <tbody>
Lines 590-595 function verify_images() { Link Here
590
                       [% END %]
591
                       [% END %]
591
                    </td>
592
                    </td>
592
                [% END %]
593
                [% END %]
594
                [% IF ( ShowPlaceItemLevelHold || isSerial ) %]
595
                    <td>
596
                        <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% biblionumber %]&itemnumber=[% item.itemnumber %]">
597
                            Place hold
598
                        </a>
599
                    </td>
600
                [% END %]
593
                </tr>
601
                </tr>
594
            [% END %]
602
            [% END %]
595
        </tbody>
603
        </tbody>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (-3 / +14 lines)
Lines 191-197 function checkMultiHold() { Link Here
191
  [% END %]
191
  [% END %]
192
192
193
  [% UNLESS ( multi_hold ) %]
193
  [% UNLESS ( multi_hold ) %]
194
    <h1>Place a hold on [% INCLUDE 'biblio-default-view.inc' %][% title |html %]</a></h1>
194
    <h1>Place a hold on [% INCLUDE 'biblio-default-view.inc' %][% title |html %]</a>
195
        [% IF targetItemTitle %] - <a href="/cgi-bin/koha/catalogue/moredetail.pl?type=&itemnumber=[% targetItemnumber %]&biblionumber=[% biblionumber %]&bi=[% biblioitemnumber %]#item[% targetItemnumber %]">[% targetItemTitle %]</a>[% END %]
196
    </h1>
195
  [% ELSE %]
197
  [% ELSE %]
196
    <h1>Confirm Holds</h1>
198
    <h1>Confirm Holds</h1>
197
  [% END %]
199
  [% END %]
Lines 208-213 function checkMultiHold() { Link Here
208
                <input type="text" size="40" id="patron" class="focus" name="findborrower" />
210
                <input type="text" size="40" id="patron" class="focus" name="findborrower" />
209
                <input type="submit" value="Search" />
211
                <input type="submit" value="Search" />
210
                <input type="hidden" name="biblionumber" value="[% biblionumber %]" />
212
                <input type="hidden" name="biblionumber" value="[% biblionumber %]" />
213
                [% IF targetItemnumber %]<input type="hidden" name="itemnumber" value="[% targetItemnumber %]" />[% END %]
211
            </fieldset>
214
            </fieldset>
212
        [% ELSE %]
215
        [% ELSE %]
213
          <fieldset>
216
          <fieldset>
Lines 221-226 function checkMultiHold() { Link Here
221
            [% END %]
224
            [% END %]
222
            </select>
225
            </select>
223
            <input type="hidden" name="biblionumber" value="[% biblionumber %]" /><fieldset class="action"><input type="submit" value="Select" /></fieldset></fieldset>
226
            <input type="hidden" name="biblionumber" value="[% biblionumber %]" /><fieldset class="action"><input type="submit" value="Select" /></fieldset></fieldset>
227
            [% IF targetItemnumber %]<input type="hidden" name="itemnumber" value="[% targetItemnumber %]" />[% END %]
224
228
225
        [% END %]
229
        [% END %]
226
        [% IF ( multi_hold ) %]
230
        [% IF ( multi_hold ) %]
Lines 344-351 function checkMultiHold() { Link Here
344
	</li>
348
	</li>
345
349
346
        [% UNLESS ( multi_hold ) %]
350
        [% UNLESS ( multi_hold ) %]
347
          <li> <label for="requestany">Place a hold on the next available copy </label>
351
          <li>
352
            [% UNLESS targetItemnumber %]
353
               <label for="requestany">Place a hold on the next available copy </label>
348
               <input type="checkbox" id="requestany" name="request" checked="checked" value="Any" />
354
               <input type="checkbox" id="requestany" name="request" checked="checked" value="Any" />
355
            [% END %]
349
               <input type="hidden" name="biblioitem" value="[% biblioitemnumber %]" />
356
               <input type="hidden" name="biblioitem" value="[% biblioitemnumber %]" />
350
               <input type="hidden" name="alreadyreserved" value="[% alreadyreserved %]" />
357
               <input type="hidden" name="alreadyreserved" value="[% alreadyreserved %]" />
351
          </li>
358
          </li>
Lines 395-401 function checkMultiHold() { Link Here
395
        <tr class="[% itemloo.backgroundcolor %]">
402
        <tr class="[% itemloo.backgroundcolor %]">
396
            <td>
403
            <td>
397
            [% IF ( itemloo.available ) %]
404
            [% IF ( itemloo.available ) %]
398
                <input type="radio" name="checkitem" value="[% itemloo.itemnumber %]" />
405
                [% IF targetItemnumber %]
406
                    <input type="radio" name="checkitem" checked="checked" value="[% itemloo.itemnumber %]" />
407
                [% ELSE %]
408
                    <input type="radio" name="checkitem" value="[% itemloo.itemnumber %]" />
409
                [% END %]
399
            [% ELSIF ( itemloo.override ) %]
410
            [% ELSIF ( itemloo.override ) %]
400
                <input type="radio" name="checkitem" class="needsoverride" value="[% itemloo.itemnumber %]" />
411
                <input type="radio" name="checkitem" class="needsoverride" value="[% itemloo.itemnumber %]" />
401
                <img src="/intranet-tmpl/[% theme %]/img/famfamfam/silk/error.png" alt="Requires override of hold policy" />
412
                <img src="/intranet-tmpl/[% theme %]/img/famfamfam/silk/error.png" alt="Requires override of hold policy" />
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt (-9 / +18 lines)
Lines 68-74 Link Here
68
            $(".highlight_toggle").toggle();
68
            $(".highlight_toggle").toggle();
69
        }
69
        }
70
    [% END %]
70
    [% END %]
71
// ------------------------------ //
71
// ------------------------------ //    
72
//>>> Document READY starts here! //
72
//>>> Document READY starts here! //
73
// ------------------------------ //
73
// ------------------------------ //
74
     $(document).ready(function() { 
74
     $(document).ready(function() { 
Lines 132-143 Link Here
132
                    null,
132
                    null,
133
                [% END %]
133
                [% END %]
134
                [% IF ( ShowCourseReservesHeader ) %]null,[% END %]
134
                [% IF ( ShowCourseReservesHeader ) %]null,[% END %]
135
                [% IF ( isSerial ) %]null,[% END %]
135
            ]
136
            ]
136
        }));
137
        }));
137
138
138
        //Bind the datepicker
139
        //Bind the datepicker
139
        $('.datepicker').datepicker();
140
        $('.datepicker').datepicker();
140
141
        
141
        [% IF ( query_desc ) %][% IF ( OpacHighlightedWords ) %]var query_desc = "[% query_desc |replace("'", "\'") |replace('\n', '\\n') |replace('\r', '\\r') |html %]";
142
        [% IF ( query_desc ) %][% IF ( OpacHighlightedWords ) %]var query_desc = "[% query_desc |replace("'", "\'") |replace('\n', '\\n') |replace('\r', '\\r') |html %]";
142
            q_array = query_desc.split(" ");
143
            q_array = query_desc.split(" ");
143
            highlightOn();
144
            highlightOn();
Lines 1053-1069 YAHOO.util.Event.onContentReady("furtherm", function () { Link Here
1053
1054
1054
1055
1055
<div id="holdings">
1056
<div id="holdings">
1056
1057
    
1057
    [% IF ( showFilter ) %]
1058
    [% IF ( showFilter ) %]
1058
        [%# Display the items filtering form used to filter the shown items. See the end of this file! %]
1059
        [%# Display the items filtering form used to filter the shown items. See the end of this file! %]
1059
        [% INCLUDE filter_form tab="holdings" %]
1060
        [% INCLUDE filter_form tab="holdings" %]
1060
    [% END %]
1061
    [% END %]
1061
1062
    
1062
[% IF ( itemloop.size ) %]
1063
[% IF ( itemloop.size ) %]    
1063
1064
    
1064
    [% IF ( lotsofitems ) %]
1065
    [% IF ( lotsofitems ) %]
1065
        <p>
1066
        <p>
1066
            [% IF noBranchItems %]
1067
            [% IF userBranchNotDefined %]
1067
                Limiting items to the most recent received last year.</br>
1068
                Limiting items to the most recent received last year.</br>
1068
            [% ELSE %]
1069
            [% ELSE %]
1069
                Showing only the most recent items from your branch.</br>
1070
                Showing only the most recent items from your branch.</br>
Lines 1550-1555 YAHOO.util.Event.onContentReady("furtherm", function () { Link Here
1550
            <th>Item hold queue priority</th>
1551
            <th>Item hold queue priority</th>
1551
        [% END %]
1552
        [% END %]
1552
        [% IF ( ShowCourseReservesHeader ) %]<th id="item_coursereserves">Course reserves</th>[% END %]
1553
        [% IF ( ShowCourseReservesHeader ) %]<th id="item_coursereserves">Course reserves</th>[% END %]
1554
        [% IF ( isSerial ) %]<th id="placeItemLevelHoldTh">Reserve</th>[% END %]
1553
        </tr></thead>
1555
        </tr></thead>
1554
	    <tbody>[% FOREACH ITEM_RESULT IN items %]
1556
	    <tbody>[% FOREACH ITEM_RESULT IN items %]
1555
      [% IF ITEM_RESULT.this_branch %]
1557
      [% IF ITEM_RESULT.this_branch %]
Lines 1630-1635 YAHOO.util.Event.onContentReady("furtherm", function () { Link Here
1630
                [% END %]
1632
                [% END %]
1631
            </td>
1633
            </td>
1632
        [% END %]
1634
        [% END %]
1635
        [% IF OPACShowPlaceItemLevelHold || isSerial %]
1636
            <td>
1637
                <a href="opac-reserve.pl?biblionumber=[% biblionumber %]&itemnumber=[% ITEM_RESULT.itemnumber %]">
1638
                    Place hold
1639
                </a>
1640
            </td>
1641
        [% END %]
1633
	    </tr>
1642
	    </tr>
1634
	    [% END %]</tbody>
1643
	    [% END %]</tbody>
1635
	</table>
1644
	</table>
Lines 1654-1660 YAHOO.util.Event.onContentReady("furtherm", function () { Link Here
1654
    <form id="issuesFilter" method="get" action="/cgi-bin/koha/opac-detail.pl">
1663
    <form id="issuesFilter" method="get" action="/cgi-bin/koha/opac-detail.pl">
1655
        <input type="hidden" name="biblionumber" id="biblionumber" value="[% biblionumber %]"/>
1664
        <input type="hidden" name="biblionumber" id="biblionumber" value="[% biblionumber %]"/>
1656
        <input type="hidden" name="viewallitems" id="viewallitems" value="1"/>
1665
        <input type="hidden" name="viewallitems" id="viewallitems" value="1"/>
1657
1666
        
1658
        <fieldset>
1667
        <fieldset>
1659
            <table>
1668
            <table>
1660
                <tr><td>
1669
                <tr><td>
Lines 1686-1692 YAHOO.util.Event.onContentReady("furtherm", function () { Link Here
1686
                            </label>
1695
                            </label>
1687
                        </td><td>
1696
                        </td><td>
1688
                            <input type="number" id="filterVolume" name="filterVolume" min="0" max="9999" maxlength="4" value="[% filter.volume %]">
1697
                            <input type="number" id="filterVolume" name="filterVolume" min="0" max="9999" maxlength="4" value="[% filter.volume %]">
1689
                        </td>
1698
                        </td>   
1690
                    </tr><tr>
1699
                    </tr><tr>
1691
                        <td>
1700
                        <td>
1692
                            <label for="filterNumber">
1701
                            <label for="filterNumber">
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tt (-6 / +10 lines)
Lines 425-430 Link Here
425
                            <!-- ITEM HOLDS -->
425
                            <!-- ITEM HOLDS -->
426
426
427
                                <li class="radio">
427
                                <li class="radio">
428
                                 [% UNLESS singleItemLevelHold %]
428
                                  [% UNLESS ( bibitemloo.holdable ) %]
429
                                  [% UNLESS ( bibitemloo.holdable ) %]
429
                                    <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]"
430
                                    <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]"
430
                                           id="reqany_[% bibitemloo.biblionumber %]"
431
                                           id="reqany_[% bibitemloo.biblionumber %]"
Lines 437-447 Link Here
437
                                           id="reqany_[% bibitemloo.biblionumber %]"
438
                                           id="reqany_[% bibitemloo.biblionumber %]"
438
                                           class="selectany"
439
                                           class="selectany"
439
                                           value="Any"
440
                                           value="Any"
440
                                           checked="checked"
441
                                           [% UNLESS singleItemLevelHold %] checked="checked" [% END %]
441
                                    />
442
                                    />
442
                                  [% END %]
443
                                  [% END %]
443
444
444
                                  <label for="reqany_[% bibitemloo.biblionumber %]">Next available copy</label>
445
                                  <label for="reqany_[% bibitemloo.biblionumber %]">Next available copy</label>
446
                                 [% END %][%# IF singleItemLevelHold %]
445
                                  [% UNLESS ( bibitemloo.holdable ) %]
447
                                  [% UNLESS ( bibitemloo.holdable ) %]
446
                                    <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]"
448
                                    <input type="radio" name="reqtype_[% bibitemloo.biblionumber %]"
447
                                           id="reqspecific_[% bibitemloo.biblionumber %]"
449
                                           id="reqspecific_[% bibitemloo.biblionumber %]"
Lines 454-467 Link Here
454
                                           id="reqspecific_[% bibitemloo.biblionumber %]"
456
                                           id="reqspecific_[% bibitemloo.biblionumber %]"
455
                                           class="selectspecific"
457
                                           class="selectspecific"
456
                                           value="Specific"
458
                                           value="Specific"
459
                                           [% IF singleItemLevelHold %] checked="checked" [% END %]
457
                                    />
460
                                    />
458
                                  [% END %]
461
                                  [% END %]
459
                                  <label for="reqspecific_[% bibitemloo.biblionumber %]">A specific copy</label>
462
                                  <label for="reqspecific_[% bibitemloo.biblionumber %]">A specific copy</label>
460
                                </li>
463
                                </li>
461
464
462
                            [% END %]
465
                            [% END %]
463
                </ul>
464
                        [% END %]
466
                        [% END %]
467
                </ul>
465
                  [% IF ( OPACItemHolds ) %]
468
                  [% IF ( OPACItemHolds ) %]
466
                  [% IF ( bibitemloo.holdable ) %]
469
                  [% IF ( bibitemloo.holdable ) %]
467
470
Lines 489-495 Link Here
489
                              <td class="copy">
492
                              <td class="copy">
490
                                [% IF ( itemLoo.available ) %]
493
                                [% IF ( itemLoo.available ) %]
491
                                  <input type="radio" class="checkitem checkitem_[% bibitemloo.biblionumber %]" name="checkitem_[% bibitemloo.biblionumber %]"
494
                                  <input type="radio" class="checkitem checkitem_[% bibitemloo.biblionumber %]" name="checkitem_[% bibitemloo.biblionumber %]"
492
                                         value="[% itemLoo.itemnumber %]" />
495
                                         value="[% itemLoo.itemnumber %]"
496
                                         [% IF singleItemLevelHold %] checked="checked" [% END %]
497
                                         />
493
                                [% ELSE %]
498
                                [% ELSE %]
494
                                  <input disabled="disabled" type="radio" class="checkitem" name="checkitem" value="[% itemLoo.itemnumber %]" />
499
                                  <input disabled="disabled" type="radio" class="checkitem" name="checkitem" value="[% itemLoo.itemnumber %]" />
495
                                  <img src="/opac-tmpl/lib/famfamfam/silk/cross.png" alt="Cannot be put on hold" title="Cannot be put on hold" />
500
                                  <img src="/opac-tmpl/lib/famfamfam/silk/cross.png" alt="Cannot be put on hold" title="Cannot be put on hold" />
Lines 540-551 Link Here
540
                        </table>
545
                        </table>
541
                    </div>
546
                    </div>
542
547
543
                </fieldset>
544
                  [% END %]<!-- OPACItemHolds -->
545
546
                  [% END %]<!-- bib_available -->
548
                  [% END %]<!-- bib_available -->
547
549
550
                  [% END %]<!-- OPACItemHolds -->
548
            </div>
551
            </div>
552
                </fieldset>
549
                [% END %]
553
                [% END %]
550
554
551
              [% END %] <!-- if message -->
555
              [% END %] <!-- if message -->
(-)a/opac/opac-detail.pl (-23 / +16 lines)
Lines 77-83 $biblionumber = int($biblionumber); Link Here
77
##>> Handling the Serial issue filter parameters from the user
77
##>> Handling the Serial issue filter parameters from the user
78
##
78
##
79
# We can filter issues based on these five values.
79
# We can filter issues based on these five values.
80
my $filterBranchLimiter = $query->param('filterBranchLimiter') ? $query->param('filterBranchLimiter') : undef;
80
my $filterBranchLimiter = $query->param('filterBranchLimiter') ? $query->param('filterBranchLimiter') : '_ShowAll';
81
my $filterVolume = $query->param('filterVolume') ? $query->param('filterVolume') : undef;
81
my $filterVolume = $query->param('filterVolume') ? $query->param('filterVolume') : undef;
82
my $filterNumber = $query->param('filterNumber') ? $query->param('filterNumber') : undef;
82
my $filterNumber = $query->param('filterNumber') ? $query->param('filterNumber') : undef;
83
my $filterIssue = $query->param('filterIssue') ? $query->param('filterIssue') : undef;
83
my $filterIssue = $query->param('filterIssue') ? $query->param('filterIssue') : undef;
Lines 153-159 my $itemsCount = GetItemsCount($biblionumber); Link Here
153
my $lotsofitems = 0;
153
my $lotsofitems = 0;
154
if ($itemsCount > C4::Context->preference('OPACmaxItemsOnDetail') &&
154
if ($itemsCount > C4::Context->preference('OPACmaxItemsOnDetail') &&
155
    !($query->param('viewallitems')) ) {
155
    !($query->param('viewallitems')) ) {
156
156
    
157
    $lotsofitems = 1;
157
    $lotsofitems = 1;
158
    $template->param('lotsofitems' => $lotsofitems);
158
    $template->param('lotsofitems' => $lotsofitems);
159
}
159
}
Lines 162-196 my @all_items; Link Here
162
if ($lotsofitems) {
162
if ($lotsofitems) {
163
    #Spare the poor old DB from this possibly excruciatinly huge read operation.
163
    #Spare the poor old DB from this possibly excruciatinly huge read operation.
164
    if (! scalar(%$filter)) { #Is the $filter empty?
164
    if (! scalar(%$filter)) { #Is the $filter empty?
165
166
        #Limit the amount of results to the system preference
167
        $filter->{limit} = C4::Context->preference('OPACmaxItemsOnDetail');
168
169
        #Limit display of Items based on the users branch
165
        #Limit display of Items based on the users branch
170
        if (C4::Context->userenv){
166
        if (C4::Context->userenv){
171
            $filter->{branch} = C4::Context->userenv->{branch};
167
            $filter->{branch} = C4::Context->userenv->{branch};
172
            $filterBranchLimiter = $filter->{branch}; #Making the branches loop react to this!
168
            $filterBranchLimiter = $filter->{branch}; #Making the branches loop react to this!
173
174
            @all_items = GetItemsInfo($biblionumber, $filter);
175
        }
169
        }
176
        #Or if branch cannot be defined or has no items, then display Items only from the past year
170
        #Or if branch cannot be defined, then display Items only from the past year
177
        if( ! (scalar(@all_items)) ) {
171
        else {
178
            delete $filter->{branch}; #Remove the branch filter as it gave no results
179
            undef $filterBranchLimiter;
180
181
            my $now = DateTime->now();
172
            my $now = DateTime->now();
182
            $now->set_year(  ($now->year() - 1)  );
173
            $now->set_year(  ($now->year() - 1)  );
183
            $filter->{fromDate} = Koha::DateUtils::output_pref({ dt => $now, dateformat => 'iso'});
174
            $filter->{fromDate} = Koha::DateUtils::output_pref({ dt => $now, dateformat => 'iso'});
184
            $template->param('noBranchItems' => 1);
175
            $template->param('userBranchNotDefined' => 1);
185
            @all_items = GetItemsInfo($biblionumber, $filter);
186
        }
176
        }
187
177
        $filter->{limit} = C4::Context->preference('OPACmaxItemsOnDetail');
188
    }
178
    }
189
}
179
}
190
#If we haven't found our items yet, then pull them using whatever we've got.
180
@all_items = GetItemsInfo($biblionumber, $filter);
191
if( ! (scalar(@all_items)) ) {
192
    @all_items = GetItemsInfo($biblionumber, $filter);
193
}
194
181
195
182
196
##Prepare the custom branches loop containing the _ShowAll entry to show issues from all libraries.
183
##Prepare the custom branches loop containing the _ShowAll entry to show issues from all libraries.
Lines 306-312 if ($session->param('busc')) { Link Here
306
293
307
        my $expanded_facet = $arrParamsBusc->{'expand'};
294
        my $expanded_facet = $arrParamsBusc->{'expand'};
308
        my $branches = GetBranches();
295
        my $branches = GetBranches();
309
        my $itemtypes = GetItemTypes;
310
        my @servers;
296
        my @servers;
311
        @servers = @{$arrParamsBusc->{'server'}} if $arrParamsBusc->{'server'};
297
        @servers = @{$arrParamsBusc->{'server'}} if $arrParamsBusc->{'server'};
312
        @servers = ("biblioserver") unless (@servers);
298
        @servers = ("biblioserver") unless (@servers);
Lines 317-323 if ($session->param('busc')) { Link Here
317
        $sort_by[0] = $default_sort_by if !$sort_by[0] && defined($default_sort_by);
303
        $sort_by[0] = $default_sort_by if !$sort_by[0] && defined($default_sort_by);
318
        my ($error, $results_hashref, $facets);
304
        my ($error, $results_hashref, $facets);
319
        eval {
305
        eval {
320
            ($error, $results_hashref, $facets) = getRecords($arrParamsBusc->{'query'},$arrParamsBusc->{'simple_query'},\@sort_by,\@servers,$results_per_page,$offset,$expanded_facet,$branches,$itemtypes,$arrParamsBusc->{'query_type'},$arrParamsBusc->{'scan'});
306
            ($error, $results_hashref, $facets) = getRecords($arrParamsBusc->{'query'},$arrParamsBusc->{'simple_query'},\@sort_by,\@servers,$results_per_page,$offset,$expanded_facet,$branches,$arrParamsBusc->{'query_type'},$arrParamsBusc->{'scan'});
321
        };
307
        };
322
        my $hits;
308
        my $hits;
323
        my @newresults;
309
        my @newresults;
Lines 705-711 if ( $show_holds_count || $show_priority) { Link Here
705
}
691
}
706
$template->param( show_priority => $has_hold ) ;
692
$template->param( show_priority => $has_hold ) ;
707
693
708
my $norequests = 1;
694
my $norequests = 1; #"No requests"-flag hides the "Place hold"-link in opac-detail-sidebar.inc
709
my %itemfields;
695
my %itemfields;
710
my (@itemloop, @otheritemloop);
696
my (@itemloop, @otheritemloop);
711
my $currentbranch = C4::Context->userenv ? C4::Context->userenv->{branch} : undef;
697
my $currentbranch = C4::Context->userenv ? C4::Context->userenv->{branch} : undef;
Lines 770-775 for my $itm (@items) { Link Here
770
    }
756
    }
771
}
757
}
772
758
759
#There is no point in enabling "Place hold" for Serials.
760
# Placing a title-level hold for a Serial is crazy since we don't want "any" item but instead the specific volume and number.
761
# Also choosing an item-level hold from opac-reserve.pl is problematic since there could be thousands of items.
762
$norequests = 1 if $template->{VARS}->{'isSerial'};
763
773
# Display only one tab if one items list is empty
764
# Display only one tab if one items list is empty
774
if (scalar(@itemloop) == 0 || scalar(@otheritemloop) == 0) {
765
if (scalar(@itemloop) == 0 || scalar(@otheritemloop) == 0) {
775
    $template->param(SeparateHoldings => 0);
766
    $template->param(SeparateHoldings => 0);
Lines 1217-1220 if ( length C4::Context->preference('NumberingFormulaParsingRegexp') < 3 ) { Link Here
1217
}
1208
}
1218
$template->{VARS}->{useFilterIssueInput} = 1 if (C4::Context->preference('FilterSerialsByIssue'));
1209
$template->{VARS}->{useFilterIssueInput} = 1 if (C4::Context->preference('FilterSerialsByIssue'));
1219
1210
1211
$template->param('OPACShowPlaceItemLevelHold',  C4::Context->preference('OPACShowPlaceItemLevelHold'));
1212
1220
output_html_with_http_headers $query, $cookie, $template->output;
1213
output_html_with_http_headers $query, $cookie, $template->output;
(-)a/opac/opac-reserve.pl (-3 / +11 lines)
Lines 73-80 if ($borr->{reservefee} > 0){ Link Here
73
my $branches = GetBranches();
73
my $branches = GetBranches();
74
my $itemTypes = GetItemTypes();
74
my $itemTypes = GetItemTypes();
75
75
76
# There are two ways of calling this script, with a single biblio num
76
# There are three ways of calling this script, with a single biblio num
77
# or multiple biblio nums.
77
# or multiple biblio nums or as a itemhold, where the target item has already been chosen.
78
my $targetItemnumber = $query->param('itemnumber') ? $query->param('itemnumber') : undef;
79
$template->param('singleItemLevelHold' => 1);
78
my $biblionumbers = $query->param('biblionumbers');
80
my $biblionumbers = $query->param('biblionumbers');
79
my $reserveMode = $query->param('reserve_mode');
81
my $reserveMode = $query->param('reserve_mode');
80
if ($reserveMode && ($reserveMode eq 'single')) {
82
if ($reserveMode && ($reserveMode eq 'single')) {
Lines 127-134 foreach my $biblioNumber (@biblionumbers) { Link Here
127
129
128
    my $biblioData = GetBiblioData($biblioNumber);
130
    my $biblioData = GetBiblioData($biblioNumber);
129
    $biblioDataHash{$biblioNumber} = $biblioData;
131
    $biblioDataHash{$biblioNumber} = $biblioData;
132
    my @itemInfos;
130
133
131
    my @itemInfos = GetItemsInfo($biblioNumber);
134
    if ($targetItemnumber) { #We just want the one item so use the filters to find it!
135
        @itemInfos = GetItemsInfo($biblioNumber, {itemnumber => $targetItemnumber});
136
    }
137
    else {
138
        @itemInfos = GetItemsInfo($biblioNumber);
139
    }
132
140
133
    my $marcrecord= GetMarcBiblio($biblioNumber);
141
    my $marcrecord= GetMarcBiblio($biblioNumber);
134
142
(-)a/reserve/request.pl (-1 / +21 lines)
Lines 57-66 my ( $template, $borrowernumber, $cookie, $flags ) = get_template_and_user( Link Here
57
    }
57
    }
58
);
58
);
59
59
60
my $targetItemnumber = $input->param('itemnumber') ? $input->param('itemnumber') : undef;
61
if ($targetItemnumber) {
62
    $template->param('targetItemnumber', $targetItemnumber);
63
    my $targetItem = C4::Items::GetItem($targetItemnumber);
64
    if ($targetItem->{enumchron}) {
65
        $template->param('targetItemTitle', $targetItem->{enumchron});
66
    }
67
    elsif ($targetItem->{barcode}) {
68
        $template->param('targetItemTitle', $targetItem->{barcode});
69
    }
70
    else {
71
        $template->param('targetItemTitle', $targetItem->{itemnumber});
72
    }
73
}
74
75
60
my $multihold = $input->param('multi_hold');
76
my $multihold = $input->param('multi_hold');
61
$template->param(multi_hold => $multihold);
77
$template->param(multi_hold => $multihold);
62
my $showallitems = $input->param('showallitems');
78
my $showallitems = $input->param('showallitems');
63
79
80
64
# get Branches and Itemtypes
81
# get Branches and Itemtypes
65
my $branches = GetBranches();
82
my $branches = GetBranches();
66
my $itemtypes = GetItemTypes();
83
my $itemtypes = GetItemTypes();
Lines 243-249 foreach my $biblionumber (@biblionumbers) { Link Here
243
    my @itemnumbers;
260
    my @itemnumbers;
244
261
245
    ## $items is array of 'item' table numbers
262
    ## $items is array of 'item' table numbers
246
    if (my $items = get_itemnumbers_of($biblionumber)->{$biblionumber}){
263
    if ($targetItemnumber) { #If we just want to place a hold on one item
264
        push @itemnumbers, $targetItemnumber;
265
    }
266
    elsif (my $items = get_itemnumbers_of($biblionumber)->{$biblionumber}){
247
        @itemnumbers  = @$items;
267
        @itemnumbers  = @$items;
248
    }
268
    }
249
    my @hostitems = get_hostitemnumbers_of($biblionumber);
269
    my @hostitems = get_hostitemnumbers_of($biblionumber);
(-)a/t/db_dependent/Items.t (-9 / +13 lines)
Lines 144-151 subtest 'GetHiddenItemnumbers tests' => sub { Link Here
144
144
145
145
146
subtest 'Filter items tests' => sub {
146
subtest 'Filter items tests' => sub {
147
147
    
148
    plan tests => 3;
148
    plan tests => 2;
149
149
150
    # Start transaction
150
    # Start transaction
151
    $dbh->{AutoCommit} = 0;
151
    $dbh->{AutoCommit} = 0;
Lines 165-182 subtest 'Filter items tests' => sub { Link Here
165
              holdingbranch => 'MPL', },
165
              holdingbranch => 'MPL', },
166
            $biblionumber
166
            $biblionumber
167
    );
167
    );
168
168
    my ($item3_bibnum, $item3_bibitemnum, $item3_itemnumber) = AddItem(
169
            { homebranch => 'IPT',
170
              holdingbranch => 'IPT', },
171
            $biblionumber
172
    );
173
    
169
    # Testing the branch filter
174
    # Testing the branch filter
170
    my @shouldBeItem2 = C4::Items::GetItemsInfo($biblionumber, {branch => 'MPL'});
175
    my @shouldBeItem2 = C4::Items::GetItemsInfo($biblionumber, {branch => 'MPL'});
171
    is( $shouldBeItem2[0]->{itemnumber}, $item2_itemnumber, "Filtering by branch");
176
    is( $shouldBeItem2[0]->{itemnumber}, $item2_itemnumber, "Filtering by branch");
172
177
    
173
    # Testing the dates filter
178
    # Testing the dates filter
174
    my @shouldBeEmpty = C4::Items::GetItemsInfo($biblionumber, {toDate => '01/01/1933'});
179
    my @shouldBeEmpty = C4::Items::GetItemsInfo($biblionumber, {toDate => '01/01/1933'});
175
    is( scalar(@shouldBeEmpty), 0, "Filtering by date");
180
    is( scalar(@shouldBeEmpty), 0, "Filtering by date");
176
181
    
177
    # Testing the limit filter
182
    # Testing the itemnumber filter
178
    @shouldBeEmpty = C4::Items::GetItemsInfo($biblionumber, {limit => 0});
183
    my @shouldBeItem3 = C4::Items::GetItemsInfo($biblionumber, {itemnumber => $item3_itemnumber});
179
    is( scalar(@shouldBeEmpty), 0, "Filtering by limit");
184
    is( $shouldBeItem3[0]->{itemnumber}, $item3_itemnumber, "Filtering by itemnumber");
180
};
185
};
181
186
182
# Helper method to set up a Biblio.
187
# Helper method to set up a Biblio.
183
- 

Return to bug 11157