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

(-)a/C4/Reserves.pm (-77 / +2 lines)
Lines 38-45 use Koha::Calendar; Link Here
38
use Koha::CirculationRules;
38
use Koha::CirculationRules;
39
use Koha::Database;
39
use Koha::Database;
40
use Koha::DateUtils;
40
use Koha::DateUtils;
41
use Koha::Hold;
42
use Koha::Holds;
41
use Koha::Holds;
42
use Koha::HoldGroups;
43
use Koha::ItemTypes;
43
use Koha::ItemTypes;
44
use Koha::Items;
44
use Koha::Items;
45
use Koha::Libraries;
45
use Koha::Libraries;
Lines 141-148 BEGIN { Link Here
141
141
142
        GetMaxPatronHoldsForRecord
142
        GetMaxPatronHoldsForRecord
143
143
144
        &AddHoldGroup
145
        &DeleteHoldGroup
146
        &GetHoldGroupHolds
144
        &GetHoldGroupHolds
147
    );
145
    );
148
    @EXPORT_OK = qw( MergeHolds );
146
    @EXPORT_OK = qw( MergeHolds );
Lines 591-638 sub CanReserveBeCanceledFromOpac { Link Here
591
    return $reserve->is_cancelable_from_opac;
589
    return $reserve->is_cancelable_from_opac;
592
}
590
}
593
591
594
# TODO: Should be moved to Koha::Objects
595
596
=head2 GetHoldCount
597
598
  $number = &GetHoldCount($borrowernumber);
599
600
this function returns the number of reservation for a borrower given on input arg.
601
602
=cut
603
604
sub GetHoldCount {
605
    my ($borrowernumber) = @_;
606
607
    my $dbh = C4::Context->dbh;
608
609
    my $count = 0; #added by 15516
610
    my $query = "
611
        SELECT COUNT(*) AS counter
612
        FROM reserves
613
        WHERE borrowernumber = ?
614
        AND hold_group_id is NULL"; #added by 15516
615
    my $sth = $dbh->prepare($query);
616
    $sth->execute($borrowernumber);
617
    my $row = $sth->fetchrow_hashref;
618
619
    # section added by 15516
620
    $count += $row->{counter};
621
622
    $query = "
623
        SELECT COUNT(DISTINCT hold_group_id) AS counter
624
        FROM reserves
625
        WHERE borrowernumber = ?
626
        AND hold_group_id is not NULL
627
    ";
628
    $sth = $dbh->prepare($query);
629
    $sth->execute($borrowernumber);
630
    $row = $sth->fetchrow_hashref;
631
    $count += $row->{counter};
632
    # end of section added by 15516
633
    return $count;
634
}
635
636
=head2 GetOtherReserves
592
=head2 GetOtherReserves
637
593
638
  ($messages,$nextreservinfo)=$GetOtherReserves(itemnumber);
594
  ($messages,$nextreservinfo)=$GetOtherReserves(itemnumber);
Lines 1252-1258 sub ModReserveAffect { Link Here
1252
            WHERE hold_group_id = ?
1208
            WHERE hold_group_id = ?
1253
              AND reserve_id != ?
1209
              AND reserve_id != ?
1254
        }, undef, $hold->hold_group_id, $hold->reserve_id);
1210
        }, undef, $hold->hold_group_id, $hold->reserve_id);
1255
        DeleteHoldGroup($hold->hold_group_id);
1211
        Koha::HoldGroups->find($hold->hold_group_id)->delete;
1256
    }
1212
    }
1257
1213
1258
    _FixPriority( { biblionumber => $biblionumber } );
1214
    _FixPriority( { biblionumber => $biblionumber } );
Lines 2357-2393 sub GetHoldRule { Link Here
2357
    return $rules;
2313
    return $rules;
2358
}
2314
}
2359
2315
2360
=head2 AddHoldGroup
2361
2362
    my $hold_group_id = AddHoldGroup();
2363
2364
Creates a new hold group and returns its ID
2365
2366
=cut
2367
2368
sub AddHoldGroup {
2369
    my $dbh = C4::Context->dbh;
2370
2371
    $dbh->do('INSERT INTO hold_group VALUES ()');
2372
    return $dbh->last_insert_id(undef, undef, 'hold_group', undef);
2373
}
2374
2375
=head2 DeleteHoldGroup
2376
2377
    DeleteHoldGroup($hold_group_id);
2378
2379
Delete a hold group. Reserves that belong to this group are not removed.
2380
2381
=cut
2382
2383
sub DeleteHoldGroup {
2384
    my ($hold_group_id) = @_;
2385
2386
    my $dbh = C4::Context->dbh;
2387
    my $query = 'DELETE FROM hold_group WHERE hold_group_id = ?';
2388
    $dbh->do($query, undef, $hold_group_id);
2389
}
2390
2391
=head2 GetHoldGroupHolds
2316
=head2 GetHoldGroupHolds
2392
2317
2393
    my @reserves = GetHoldGroupHolds($hold_group_id);
2318
    my @reserves = GetHoldGroupHolds($hold_group_id);
(-)a/Koha/HoldGroup.pm (+63 lines)
Line 0 Link Here
1
package Koha::HoldGroup;
2
3
# Copyright 2020 Koha Development team
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use base qw(Koha::Object);
23
24
=head1 NAME
25
26
Koha::HoldGroup - Koha Hold Group object class
27
28
=head1 API
29
30
=head2 Class Methods
31
32
=cut
33
34
=head3 holds
35
36
$holds = $hold_group->holds
37
38
Return all holds associated with this group
39
40
=cut
41
42
sub holds {
43
    my ($self) = @_;
44
45
    my $holds_rs = $self->_result->reserves;
46
    return Koha::Holds->_new_from_dbic($holds_rs);
47
}
48
49
=head3 _type
50
51
=cut
52
53
sub _type {
54
    return 'HoldGroup';
55
}
56
57
=head1 AUTHORS
58
59
Josef Moravec <josef.moravec@gmail.com>
60
61
=cut
62
63
1;
(-)a/Koha/HoldGroups.pm (+60 lines)
Line 0 Link Here
1
package Koha::HoldGroups;
2
3
# Copyright Koha Development team 2020
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Koha::Database;
23
24
use Koha::HoldGroup;
25
26
use base qw(Koha::Objects);
27
28
=head1 NAME
29
30
Koha::HoldGroups - Koha Hold Group object set class
31
32
=head1 API
33
34
=head2 Class Methods
35
36
=cut
37
38
=head3 _type
39
40
=cut
41
42
sub _type {
43
    return 'HoldGroup';
44
}
45
46
=head3 object_class
47
48
=cut
49
50
sub object_class {
51
    return 'Koha::HoldGroup';
52
}
53
54
=head1 AUTHOR
55
56
Josef Moravec <josef.moravec@gmail.com>
57
58
=cut
59
60
1;
(-)a/Koha/Holds.pm (+15 lines)
Lines 92-97 sub forced_hold_level { Link Here
92
    return;
92
    return;
93
}
93
}
94
94
95
=head3 count_grouped
96
97
$holds->count_grouped();
98
99
Return number of hold, where hold group is counted as one hold
100
101
=cut
102
103
sub count_grouped {
104
    my ($self) = @_;
105
    my $holds_without_group_count = $self->search({ hold_group_id => undef })->count();
106
    my $hold_groups_count = $self->search({ hold_group_id => { '!=' => undef }}, { group_by => 'me.hold_group_id' })->count();
107
    return $holds_without_group_count + $hold_groups_count;
108
}
109
95
=head3 type
110
=head3 type
96
111
97
=cut
112
=cut
(-)a/Koha/Template/Plugin/Biblio.pm (-8 lines)
Lines 63-74 sub CanArticleRequest { Link Here
63
    return $biblio ? $biblio->can_article_request( $borrower ) : 0;
63
    return $biblio ? $biblio->can_article_request( $borrower ) : 0;
64
}
64
}
65
65
66
sub Get {
67
    my ($self, $biblionumber) = @_;
68
69
    my $biblio = Koha::Biblios->find($biblionumber);
70
71
    return $biblio;
72
}
73
74
1;
66
1;
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/hold-group.tt (-4 / +4 lines)
Lines 1-11 Link Here
1
[% USE Biblio %]
2
[% INCLUDE 'doc-head-open.inc' %]
1
[% INCLUDE 'doc-head-open.inc' %]
3
  <title>Koha &rsaquo; Circulation &rsaquo; Holds &rsaquo; Holds group ([% hold_group_id | html %])</title>
2
  <title>Koha &rsaquo; Circulation &rsaquo; Holds &rsaquo; Holds group ([% hold_group.id | html %])</title>
4
  [% INCLUDE 'doc-head-close.inc' %]
3
  [% INCLUDE 'doc-head-close.inc' %]
5
</head>
4
</head>
6
<body id="hold.hold-group">
5
<body id="hold.hold-group">
7
  <h1>Holds group ([% hold_group_id | html %])</h1>
6
  <h1>Holds group ([% hold_group.id | html %])</h1>
8
  <div id="main">
7
  <div id="main">
8
    [% holds = hold_group.holds %]
9
    [% IF holds.size %]
9
    [% IF holds.size %]
10
      <table>
10
      <table>
11
        <thead>
11
        <thead>
Lines 17-23 Link Here
17
        </thead>
17
        </thead>
18
        <tbody>
18
        <tbody>
19
          [% FOREACH hold IN holds %]
19
          [% FOREACH hold IN holds %]
20
            [% biblio = Biblio.Get(hold.biblionumber) %]
20
            [% biblio = hold.biblio %]
21
            <tr>
21
            <tr>
22
              <td><a href="/cgi-bin/koha/hold.request.pl?biblionumber=[% biblio.biblionumber | uri %]">[% biblio.title | html %]</a></td>
22
              <td><a href="/cgi-bin/koha/hold.request.pl?biblionumber=[% biblio.biblionumber | uri %]">[% biblio.title | html %]</a></td>
23
              <td>[% hold.priority | html %]</td>
23
              <td>[% hold.priority | html %]</td>
(-)a/opac/opac-reserve.pl (-2 / +1 lines)
Lines 195-202 foreach my $biblioNumber (@biblionumbers) { Link Here
195
if ( $query->param('place_reserve') ) {
195
if ( $query->param('place_reserve') ) {
196
    my $reserve_cnt = 0;
196
    my $reserve_cnt = 0;
197
    if ($maxreserves) {
197
    if ($maxreserves) {
198
        # TODO: Should be: $reserve_cnt = $patron->holds->count;
198
        $reserve_cnt = $patron->holds->count_grouped;
199
        $reserve_cnt = GetHoldCount( $borrowernumber );
200
    }
199
    }
201
200
202
    # List is composed of alternating biblio/item/branch
201
    # List is composed of alternating biblio/item/branch
(-)a/reserve/hold-group.pl (-5 / +3 lines)
Lines 20-42 use CGI qw( -utf8 ); Link Here
20
20
21
use C4::Auth;
21
use C4::Auth;
22
use C4::Output;
22
use C4::Output;
23
use C4::Reserves;
23
use Koha::HoldGroups;
24
24
25
my $cgi = new CGI;
25
my $cgi = new CGI;
26
my ($template, $loggedinuser, $cookie) = get_template_and_user({
26
my ($template, $loggedinuser, $cookie) = get_template_and_user({
27
    template_name   => "reserve/hold-group.tt",
27
    template_name   => "reserve/hold-group.tt",
28
    query           => $cgi,
28
    query           => $cgi,
29
    type            => "intranet",
29
    type            => "intranet",
30
    authnotrequired => 0,
31
    flagsrequired   => { circulate => 'circulate_remaining_permissions' },
30
    flagsrequired   => { circulate => 'circulate_remaining_permissions' },
32
});
31
});
33
32
34
my $hold_group_id = $cgi->param('hold_group_id');
33
my $hold_group_id = $cgi->param('hold_group_id');
35
my @holds = GetHoldGroupHolds($hold_group_id);
34
my $hold_group = Koha::HoldGroups->find($hold_group_id);
36
35
37
$template->param(
36
$template->param(
38
    hold_group_id => $hold_group_id,
37
    hold_group => $hold_group,
39
    holds => \@holds,
40
);
38
);
41
39
42
output_html_with_http_headers $cgi, $cookie, $template->output;
40
output_html_with_http_headers $cgi, $cookie, $template->output;
(-)a/reserve/placerequest.pl (-3 / +4 lines)
Lines 32-37 use C4::Circulation; Link Here
32
use C4::Members;
32
use C4::Members;
33
use C4::Auth qw/checkauth/;
33
use C4::Auth qw/checkauth/;
34
34
35
use Koha::HoldGroups;
35
use Koha::Items;
36
use Koha::Items;
36
use Koha::Patrons;
37
use Koha::Patrons;
37
38
Lines 77-85 my $found; Link Here
77
78
78
if ( $type eq 'str8' && $borrower ) {
79
if ( $type eq 'str8' && $borrower ) {
79
80
80
    my $hold_group_id;
81
    my $hold_group;
81
    if ((@biblionumbers > 1) && $requestany) {
82
    if ((@biblionumbers > 1) && $requestany) {
82
        $hold_group_id = AddHoldGroup();
83
        $hold_group = Koha::HoldGroups->new->store;
83
    }
84
    }
84
85
85
    foreach my $biblionumber ( keys %bibinfos ) {
86
    foreach my $biblionumber ( keys %bibinfos ) {
Lines 144-150 if ( $type eq 'str8' && $borrower ) { Link Here
144
                        found            => $found,
145
                        found            => $found,
145
                        itemtype         => $itemtype,
146
                        itemtype         => $itemtype,
146
                        non_priority     => $non_priority,
147
                        non_priority     => $non_priority,
147
                        hold_group_id    => $hold_group_id,
148
                        hold_group_id    => $hold_group ? $hold_group->id : undef,
148
                    }
149
                    }
149
                );
150
                );
150
            }
151
            }
(-)a/t/db_dependent/Koha/HoldGroup.t (+53 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2020 Koha Development team
4
#
5
# This file is part of Koha
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Test::More tests => 1;
23
24
use t::lib::TestBuilder;
25
26
my $schema  = Koha::Database->new->schema;
27
my $builder = t::lib::TestBuilder->new;
28
29
subtest 'holds tests' => sub {
30
31
    plan tests => 2;
32
33
    $schema->storage->txn_begin;
34
35
    my $patron     = $builder->build_object({ class => 'Koha::Patrons' });
36
    my $hold_group = $builder->build_object({ class => 'Koha::HoldGroups' });
37
    my $hold       = $builder->build_object(
38
        {
39
            class => 'Koha::Holds',
40
            value => {
41
                borrowernumber => $patron->borrowernumber,
42
                hold_group_id  => $hold_group->hold_group_id,
43
            }
44
        }
45
    );
46
47
    my $holds = $hold_group->holds;
48
    is( ref($holds), 'Koha::Holds', 'Right type' );
49
    my $hold_from_group = $holds->next;
50
    is( $hold_from_group->id, $hold->id, 'Right object' );
51
52
    $schema->storage->txn_rollback;
53
};
(-)a/t/db_dependent/Koha/Holds.t (-1 / +72 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 5;
22
use Test::More tests => 6;
23
use Test::Warn;
23
use Test::Warn;
24
24
25
use C4::Reserves;
25
use C4::Reserves;
Lines 410-413 subtest 'Desks' => sub { Link Here
410
410
411
$schema->storage->txn_rollback;
411
$schema->storage->txn_rollback;
412
412
413
subtest 'count_grouped' => sub {
414
    plan tests => 3;
415
    $schema->storage->txn_begin;
416
417
    my $patron = $builder->build_object({
418
        class => 'Koha::Patrons',
419
    });
420
    my $patron_id = $patron->borrowernumber;
421
422
    my $hold1 = $builder->build_object({
423
            class => 'Koha::Holds',
424
            value => {
425
                borrowernumber => $patron_id,
426
                hold_group_id => undef,
427
            },
428
        });
429
430
    is($patron->holds->count_grouped, 1, 'Test patron has 1 hold.');
431
432
    my $hold_group = $builder->build_object({
433
        class => 'Koha::HoldGroups',
434
    });
435
436
    my $hold2 = $builder->build_object({
437
        class => 'Koha::Holds',
438
        value => {
439
            borrowernumber => $patron_id,
440
            hold_group_id => $hold_group->hold_group_id,
441
        }
442
    });
443
    my $hold3 = $builder->build_object({
444
        class => 'Koha::Holds',
445
        value => {
446
            borrowernumber => $patron_id,
447
            hold_group_id => $hold_group->hold_group_id,
448
        }
449
    });
450
451
    is($patron->holds->count_grouped, 2, 'Test patron has 2 holds.');
452
453
    my $hold_group2 = $builder->build_object({
454
        class => 'Koha::HoldGroups',
455
    });
456
457
    my $hold4 = $builder->build_object({
458
        class => 'Koha::Holds',
459
        value => {
460
            borrowernumber => $patron_id,
461
            hold_group_id => $hold_group2->hold_group_id,
462
        }
463
    });
464
    my $hold5 = $builder->build_object({
465
        class => 'Koha::Holds',
466
        value => {
467
            borrowernumber => $patron_id,
468
            hold_group_id => $hold_group2->hold_group_id,
469
        }
470
    });
471
    my $hold6 = $builder->build_object({
472
        class => 'Koha::Holds',
473
        value => {
474
            borrowernumber => $patron_id,
475
            hold_group_id => $hold_group2->hold_group_id,
476
        }
477
    });
478
479
    is($patron->holds->count_grouped, 3, 'Test patron has 3 holds.');
480
481
    $schema->storage->txn_rollback;
482
};
483
413
1;
484
1;
(-)a/t/db_dependent/Reserves/HoldCount.t (-117 lines)
Lines 1-116 Link Here
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::More tests => 3;
21
use t::lib::TestBuilder;
22
23
use C4::Context;
24
use C4::Biblio;
25
use C4::Items;
26
use C4::Reserves;
27
28
use Koha::Database;
29
30
31
32
my $dbh = C4::Context->dbh;
33
$dbh->{AutoCommit} = 0;
34
$dbh->{RaiseError} = 1;
35
36
my $builder = t::lib::TestBuilder->new();
37
38
my $categorycode = $builder->build({ source => 'Category' })->{ categorycode };
39
my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode };
40
my $borrower = $builder->build({
41
    source => 'Borrower',
42
    value => {
43
        branchcode   => $branchcode,
44
        categorycode => $categorycode
45
    }
46
});
47
my $borrowernumber = $borrower->{borrowernumber};
48
49
my $biblio = $builder->build( { source => 'Biblio', } );
50
my $biblionumber = $biblio->{biblionumber};
51
52
# Use AddReserve instead of TestBuilder because i don't manage
53
# to make TestBuilder set hold_group_id to null. Idea ?
54
my $reserve_id = AddReserve($branchcode, $borrowernumber,
55
$biblionumber, $biblionumber, 1, undef, undef, undef
56
$biblio->{title}, undef, undef, undef);
57
58
is(GetHoldCount($borrowernumber), 1, 'Test borrower has 1 reserve.');
59
60
my $reserves_group = $builder->build({
61
    source => 'HoldGroup',
62
    value => {
63
        hold_group_id => 1
64
    }
65
});
66
67
my $reserve2 = $builder->build({
68
    source => 'Reserve',
69
    value => {
70
        borrowernumber => $borrowernumber,
71
        hold_group_id => 1
72
    }
73
});
74
my $reserve3 = $builder->build({
75
    source => 'Reserve',
76
    value => {
77
        borrowernumber => $borrowernumber,
78
        hold_group_id => 1
79
    }
80
});
81
82
is(GetHoldCount($borrowernumber), 2, 'Test borrower has 2 reserve.');
83
84
my $reserves_group2 = $builder->build({
85
    source => 'HoldGroup',
86
    value => {
87
        hold_group_id => 2
88
    }
89
});
90
my $hold_group_id2 = $reserves_group2->{hold_group_id};
91
92
my $reserve4 = $builder->build({
93
    source => 'Reserve',
94
    value => {
95
        borrowernumber => $borrowernumber,
96
        hold_group_id => 2
97
    }
98
});
99
my $reserve5 = $builder->build({
100
    source => 'Reserve',
101
    value => {
102
        borrowernumber => $borrowernumber,
103
        hold_group_id => 2
104
    }
105
});
106
my $reserve6 = $builder->build({
107
    source => 'Reserve',
108
    value => {
109
        borrowernumber => $borrowernumber,
110
        hold_group_id => 2
111
    }
112
});
113
114
is(GetHoldCount($borrowernumber), 3, 'Test borrower has 2 reserve.');
115
116
$dbh->rollback;
117
- 

Return to bug 15516