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

(-)a/C4/Items.pm (+6 lines)
Lines 1236-1241 $filter->{fromDate} = '01/01/2013'; #Filters only serial issues by the serialite Link Here
1236
$filter->{toDate} = '31/12/2014';   #Filters only serial issues by the serialitems.publisheddate
1236
$filter->{toDate} = '31/12/2014';   #Filters only serial issues by the serialitems.publisheddate
1237
                                          #The ending date in C4::Context->preference('dateformat') format
1237
                                          #The ending date in C4::Context->preference('dateformat') format
1238
$filter->{limit} = 15;              #Limits the returning set to this many items
1238
$filter->{limit} = 15;              #Limits the returning set to this many items
1239
$filter->{itemnumber} = 165;        #Returns the item with this itemnumber
1239
1240
1240
Filters are expected to be validated! If a filter is not defined, that filter is not present in the $filter-HASH
1241
Filters are expected to be validated! If a filter is not defined, that filter is not present in the $filter-HASH
1241
1242
Lines 1358-1363 sub GetItemsInfo { Link Here
1358
        }
1359
        }
1359
        push @$queryParams, $filter->{toDate};
1360
        push @$queryParams, $filter->{toDate};
1360
    }
1361
    }
1362
    if (exists $filter->{itemnumber}) {
1363
        push @$queryParams, $filter->{itemnumber};
1364
        $query .= " AND items.itemnumber = ?";
1365
    }
1366
1361
1367
1362
    $query .= "ORDER BY home.branchname, items.enumchron, LPAD( items.copynumber, 8, '0' ), items.dateaccessioned DESC" ;
1368
    $query .= "ORDER BY home.branchname, items.enumchron, LPAD( items.copynumber, 8, '0' ), items.dateaccessioned DESC" ;
1363
    if (exists $filter->{limit}) {
1369
    if (exists $filter->{limit}) {
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 272-277 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
272
('OpacShowLibrariesPulldownMobile','1',NULL,'Show the libraries pulldown on the mobile version of the OPAC.','YesNo'),
272
('OpacShowLibrariesPulldownMobile','1',NULL,'Show the libraries pulldown on the mobile version of the OPAC.','YesNo'),
273
('OpacShowRecentComments','0',NULL,'If ON a link to recent comments will appear in the OPAC masthead','YesNo'),
273
('OpacShowRecentComments','0',NULL,'If ON a link to recent comments will appear in the OPAC masthead','YesNo'),
274
('OPACShowUnusedAuthorities','1','','Show authorities that are not being used in the OPAC.','YesNo'),
274
('OPACShowUnusedAuthorities','1','','Show authorities that are not being used in the OPAC.','YesNo'),
275
('OPACShowPlaceItemLevelHold','0',NULL,'Allow placing a item-level hold from the detailed biblio view.','YesNo'),
275
('opacsmallimage','','','Enter a complete URL to an image to replace the default Koha logo','free'),
276
('opacsmallimage','','','Enter a complete URL to an image to replace the default Koha logo','free'),
276
('OpacStarRatings','all','disable|all|details',NULL,'Choice'),
277
('OpacStarRatings','all','disable|all|details',NULL,'Choice'),
277
('OpacSuppression','0','','Turn ON the OPAC Suppression feature, requires further setup, ask your system administrator for details','YesNo'),
278
('OpacSuppression','0','','Turn ON the OPAC Suppression feature, requires further setup, ask your system administrator for details','YesNo'),
(-)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. Be aware that for performance reasons the link is displayed even if a user couldn't place holds on the item.
140
        -
134
            - pref: OpacHighlightedWords
141
            - pref: OpacHighlightedWords
135
              choices:
142
              choices:
136
                  yes: Highlight
143
                  yes: Highlight
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt (-1 / +10 lines)
Lines 132-137 Link Here
132
                    null,
132
                    null,
133
                [% END %]
133
                [% END %]
134
                [% IF ( ShowCourseReservesHeader ) %]null,[% END %]
134
                [% IF ( ShowCourseReservesHeader ) %]null,[% END %]
135
                [% IF ( OPACShowPlaceItemLevelHold || isSerial ) %]null,[% END %]
135
            ]
136
            ]
136
        }));
137
        }));
137
138
Lines 1063-1069 YAHOO.util.Event.onContentReady("furtherm", function () { Link Here
1063
1064
1064
    [% IF ( lotsofholdingsitems ) %]
1065
    [% IF ( lotsofholdingsitems ) %]
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 1554-1559 YAHOO.util.Event.onContentReady("furtherm", function () { Link Here
1554
            <th>Item hold queue priority</th>
1555
            <th>Item hold queue priority</th>
1555
        [% END %]
1556
        [% END %]
1556
        [% IF ( ShowCourseReservesHeader ) %]<th id="item_coursereserves">Course reserves</th>[% END %]
1557
        [% IF ( ShowCourseReservesHeader ) %]<th id="item_coursereserves">Course reserves</th>[% END %]
1558
        [% IF ( OPACShowPlaceItemLevelHold || isSerial ) %]<th id="placeItemLevelHoldTh">Reserve</th>[% END %]
1557
        </tr></thead>
1559
        </tr></thead>
1558
	    <tbody>[% FOREACH ITEM_RESULT IN items %]
1560
	    <tbody>[% FOREACH ITEM_RESULT IN items %]
1559
      [% IF ITEM_RESULT.this_branch %]
1561
      [% IF ITEM_RESULT.this_branch %]
Lines 1634-1639 YAHOO.util.Event.onContentReady("furtherm", function () { Link Here
1634
                [% END %]
1636
                [% END %]
1635
            </td>
1637
            </td>
1636
        [% END %]
1638
        [% END %]
1639
        [% IF OPACShowPlaceItemLevelHold || isSerial %]
1640
            <td>
1641
                <a href="opac-reserve.pl?biblionumber=[% biblionumber %]&itemnumber=[% ITEM_RESULT.itemnumber %]">
1642
                    Place hold
1643
                </a>
1644
            </td>
1645
        [% END %]
1637
	    </tr>
1646
	    </tr>
1638
	    [% END %]</tbody>
1647
	    [% END %]</tbody>
1639
	</table>
1648
	</table>
(-)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 (-4 / +10 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 306-312 if ($session->param('busc')) { Link Here
306
306
307
        my $expanded_facet = $arrParamsBusc->{'expand'};
307
        my $expanded_facet = $arrParamsBusc->{'expand'};
308
        my $branches = GetBranches();
308
        my $branches = GetBranches();
309
        my $itemtypes = GetItemTypes;
310
        my @servers;
309
        my @servers;
311
        @servers = @{$arrParamsBusc->{'server'}} if $arrParamsBusc->{'server'};
310
        @servers = @{$arrParamsBusc->{'server'}} if $arrParamsBusc->{'server'};
312
        @servers = ("biblioserver") unless (@servers);
311
        @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);
316
        $sort_by[0] = $default_sort_by if !$sort_by[0] && defined($default_sort_by);
318
        my ($error, $results_hashref, $facets);
317
        my ($error, $results_hashref, $facets);
319
        eval {
318
        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'});
319
            ($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
        };
320
        };
322
        my $hits;
321
        my $hits;
323
        my @newresults;
322
        my @newresults;
Lines 705-711 if ( $show_holds_count || $show_priority) { Link Here
705
}
704
}
706
$template->param( show_priority => $has_hold ) ;
705
$template->param( show_priority => $has_hold ) ;
707
706
708
my $norequests = 1;
707
my $norequests = 1; #"No requests"-flag hides the "Place hold"-link in opac-detail-sidebar.inc
709
my %itemfields;
708
my %itemfields;
710
my (@itemloop, @otheritemloop);
709
my (@itemloop, @otheritemloop);
711
my $currentbranch = C4::Context->userenv ? C4::Context->userenv->{branch} : undef;
710
my $currentbranch = C4::Context->userenv ? C4::Context->userenv->{branch} : undef;
Lines 770-775 for my $itm (@items) { Link Here
770
    }
769
    }
771
}
770
}
772
771
772
#There is no point in enabling "Place hold" for Serials.
773
# Placing a title-level hold for a Serial is crazy since we don't want "any" item but instead the specific volume and number.
774
# Also choosing an item-level hold from opac-reserve.pl is problematic since there could be thousands of items.
775
$norequests = 1 if $template->{VARS}->{'isSerial'};
776
773
# Display only one tab if one items list is empty
777
# Display only one tab if one items list is empty
774
if (scalar(@itemloop) == 0 || scalar(@otheritemloop) == 0) {
778
if (scalar(@itemloop) == 0 || scalar(@otheritemloop) == 0) {
775
    $template->param(SeparateHoldings => 0);
779
    $template->param(SeparateHoldings => 0);
Lines 1224-1227 if ( length C4::Context->preference('NumberingFormulaParsingRegexp') < 3 ) { Link Here
1224
}
1228
}
1225
$template->{VARS}->{useFilterIssueInput} = 1 if (C4::Context->preference('FilterSerialsByIssue'));
1229
$template->{VARS}->{useFilterIssueInput} = 1 if (C4::Context->preference('FilterSerialsByIssue'));
1226
1230
1231
$template->param('OPACShowPlaceItemLevelHold',  C4::Context->preference('OPACShowPlaceItemLevelHold'));
1232
1227
output_html_with_http_headers $query, $cookie, $template->output;
1233
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/t/db_dependent/Items.t (-2 / +10 lines)
Lines 145-151 subtest 'GetHiddenItemnumbers tests' => sub { Link Here
145
145
146
subtest 'Filter items tests' => sub {
146
subtest 'Filter items tests' => sub {
147
147
148
    plan tests => 3;
148
    plan tests => 4;
149
149
150
    # Start transaction
150
    # Start transaction
151
    $dbh->{AutoCommit} = 0;
151
    $dbh->{AutoCommit} = 0;
Lines 165-170 subtest 'Filter items tests' => sub { Link Here
165
              holdingbranch => 'MPL', },
165
              holdingbranch => 'MPL', },
166
            $biblionumber
166
            $biblionumber
167
    );
167
    );
168
    my ($item3_bibnum, $item3_bibitemnum, $item3_itemnumber) = AddItem(
169
            { homebranch => 'IPT',
170
              holdingbranch => 'IPT', },
171
            $biblionumber
172
    );
168
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'});
Lines 177-182 subtest 'Filter items tests' => sub { Link Here
177
    # Testing the limit filter
182
    # Testing the limit filter
178
    @shouldBeEmpty = C4::Items::GetItemsInfo($biblionumber, {limit => 0});
183
    @shouldBeEmpty = C4::Items::GetItemsInfo($biblionumber, {limit => 0});
179
    is( scalar(@shouldBeEmpty), 0, "Filtering by limit");
184
    is( scalar(@shouldBeEmpty), 0, "Filtering by limit");
185
186
    # Testing the itemnumber filter
187
    my @shouldBeItem3 = C4::Items::GetItemsInfo($biblionumber, {itemnumber => $item3_itemnumber});
188
    is( $shouldBeItem3[0]->{itemnumber}, $item3_itemnumber, "Filtering by itemnumber");
180
};
189
};
181
190
182
# Helper method to set up a Biblio.
191
# Helper method to set up a Biblio.
183
- 

Return to bug 11157