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

(-)a/C4/Reserves.pm (-19 / +41 lines)
Lines 199-204 sub AddReserve { Link Here
199
    my $itemtype       = $params->{itemtype};
199
    my $itemtype       = $params->{itemtype};
200
    my $non_priority   = $params->{non_priority};
200
    my $non_priority   = $params->{non_priority};
201
    my $item_group_id  = $params->{item_group_id};
201
    my $item_group_id  = $params->{item_group_id};
202
    my $hold_group_id  = $params->{hold_group_id};
202
203
203
    $resdate ||= dt_from_string;
204
    $resdate ||= dt_from_string;
204
205
Lines 259-264 sub AddReserve { Link Here
259
            itemtype       => $itemtype,
260
            itemtype       => $itemtype,
260
            item_level_hold => $checkitem ? 1 : 0,
261
            item_level_hold => $checkitem ? 1 : 0,
261
            non_priority   => $non_priority ? 1 : 0,
262
            non_priority   => $non_priority ? 1 : 0,
263
            hold_group_id  => $hold_group_id,
262
        }
264
        }
263
    )->store();
265
    )->store();
264
    $hold->set_waiting() if $found && $found eq 'W';
266
    $hold->set_waiting() if $found && $found eq 'W';
Lines 565-582 sub CanItemBeReserved { Link Here
565
                borrowernumber => $patron->borrowernumber,
567
                borrowernumber => $patron->borrowernumber,
566
                biblionumber   => $item->biblionumber,
568
                biblionumber   => $item->biblionumber,
567
            };
569
            };
568
            my $holds = Koha::Holds->search($search_params);
570
            my $holds_count = Koha::Holds->count_holds($search_params);
569
            return _cache { status => "tooManyHoldsForThisRecord", limit => $holds_per_record } if $holds->count() >= $holds_per_record;
571
            return _cache { status => "tooManyHoldsForThisRecord", limit => $holds_per_record }
572
                if $holds_count >= $holds_per_record;
570
        }
573
        }
571
    }
574
    }
572
575
573
    if (!$params->{ignore_hold_counts} && defined $holds_per_day && $holds_per_day ne '')
576
    if (!$params->{ignore_hold_counts} && defined $holds_per_day && $holds_per_day ne '')
574
    {
577
    {
575
        my $today_holds = Koha::Holds->search({
578
        my $today_holds_count = Koha::Holds->count_holds(
576
            borrowernumber => $patron->borrowernumber,
579
            {
577
            reservedate    => dt_from_string->date
580
                borrowernumber => $patron->borrowernumber,
578
        });
581
                reservedate    => dt_from_string->date
579
        return _cache { status => 'tooManyReservesToday', limit => $holds_per_day } if $today_holds->count() >= $holds_per_day;
582
            }
583
        );
584
        return _cache { status => 'tooManyReservesToday', limit => $holds_per_day }
585
            if $today_holds_count >= $holds_per_day;
580
    }
586
    }
581
587
582
    # we check if it's ok or not
588
    # we check if it's ok or not
Lines 1247-1252 sub ModReserveAffect { Link Here
1247
1253
1248
    $hold->itemnumber($itemnumber);
1254
    $hold->itemnumber($itemnumber);
1249
1255
1256
    my @reserve_ids;
1257
    push @reserve_ids, $hold->reserve_id;
1258
1250
    if ($transferToDo) {
1259
    if ($transferToDo) {
1251
        $hold->set_transfer();
1260
        $hold->set_transfer();
1252
    } elsif (C4::Context->preference('HoldsNeedProcessingSIP')
1261
    } elsif (C4::Context->preference('HoldsNeedProcessingSIP')
Lines 1259-1264 sub ModReserveAffect { Link Here
1259
        # Complete transfer if one exists
1268
        # Complete transfer if one exists
1260
        my $transfer = $hold->item->get_transfer;
1269
        my $transfer = $hold->item->get_transfer;
1261
        $transfer->receive if $transfer;
1270
        $transfer->receive if $transfer;
1271
1272
        # if this hold was part of a group, cancel other holds in the group
1273
        if ( $hold->hold_group_id ) {
1274
            my @holds = $hold->hold_group->holds->as_list;
1275
            foreach my $h (@holds) {
1276
                push @reserve_ids, $h->reserve_id;
1277
                $h->cancel unless $h->reserve_id == $hold->reserve_id;
1278
            }
1279
        }
1262
    }
1280
    }
1263
1281
1264
    _koha_notify_hold_changed( $hold ) if $notify_library;
1282
    _koha_notify_hold_changed( $hold ) if $notify_library;
Lines 1270-1287 sub ModReserveAffect { Link Here
1270
      CartToShelf( $itemnumber );
1288
      CartToShelf( $itemnumber );
1271
    }
1289
    }
1272
1290
1273
    my $std = $dbh->prepare(q{
1291
    foreach my $id (@reserve_ids) {
1274
        DELETE  q, t
1292
        my $std = $dbh->prepare(
1275
        FROM    tmp_holdsqueue q
1293
            q{
1276
        INNER JOIN hold_fill_targets t
1294
            DELETE  q, t
1277
        ON  q.borrowernumber = t.borrowernumber
1295
            FROM    tmp_holdsqueue q
1278
            AND q.biblionumber = t.biblionumber
1296
            INNER JOIN hold_fill_targets t
1279
            AND q.itemnumber = t.itemnumber
1297
            ON  q.borrowernumber = t.borrowernumber
1280
            AND q.item_level_request = t.item_level_request
1298
                AND q.biblionumber = t.biblionumber
1281
            AND q.holdingbranch = t.source_branchcode
1299
                AND q.itemnumber = t.itemnumber
1282
        WHERE t.reserve_id = ?
1300
                AND q.item_level_request = t.item_level_request
1283
    });
1301
                AND q.holdingbranch = t.source_branchcode
1284
    $std->execute($hold->reserve_id);
1302
            WHERE t.reserve_id = ?
1303
        }
1304
        );
1305
        $std->execute($id);
1306
    }
1285
1307
1286
    logaction( 'HOLDS', 'MODIFY', $hold->reserve_id, $hold )
1308
    logaction( 'HOLDS', 'MODIFY', $hold->reserve_id, $hold )
1287
        if C4::Context->preference('HoldsLog');
1309
        if C4::Context->preference('HoldsLog');
(-)a/Koha/Hold.pm (+28 lines)
Lines 41-46 use Koha::Plugins; Link Here
41
use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue;
41
use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue;
42
42
43
use Koha::Exceptions;
43
use Koha::Exceptions;
44
use Koha::HoldGroups;
44
use Koha::Exceptions::Hold;
45
use Koha::Exceptions::Hold;
45
46
46
use base qw(Koha::Object);
47
use base qw(Koha::Object);
Lines 856-861 sub fill { Link Here
856
            C4::Log::logaction( 'HOLDS', 'FILL', $self->id, $self )
857
            C4::Log::logaction( 'HOLDS', 'FILL', $self->id, $self )
857
                if C4::Context->preference('HoldsLog');
858
                if C4::Context->preference('HoldsLog');
858
859
860
            # if this hold was part of a group, cancel other holds in the group
861
            if ( $self->hold_group_id ) {
862
                my @holds = $self->hold_group->holds->as_list;
863
                foreach my $h (@holds) {
864
                    $h->cancel unless $h->reserve_id == $self->id;
865
                }
866
            }
867
859
            Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue->new->enqueue(
868
            Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue->new->enqueue(
860
                {
869
                {
861
                    biblio_ids => [ $old_me->biblionumber ]
870
                    biblio_ids => [ $old_me->biblionumber ]
Lines 961-966 sub _set_default_expirationdate { Link Here
961
        dt_from_string( $self->reservedate )->add( $timeunit => $period ) );
970
        dt_from_string( $self->reservedate )->add( $timeunit => $period ) );
962
}
971
}
963
972
973
=head3 hold_group
974
975
    my $hold_group = $hold->hold_group;
976
    my $hold_group_id = $hold_group->id if $hold_group;
977
978
Return the Koha::HoldGroup object of a hold if part of a hold group
979
980
=cut
981
982
sub hold_group {
983
    my ($self) = @_;
984
985
    if ( $self->hold_group_id ) {
986
        return Koha::HoldGroups->find( $self->hold_group_id );
987
    }
988
989
    return;
990
}
991
964
=head3 _move_to_old
992
=head3 _move_to_old
965
993
966
my $is_moved = $hold->_move_to_old;
994
my $is_moved = $hold->_move_to_old;
(-)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->search;
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 (+26 lines)
Lines 201-206 sub filter_out_has_cancellation_requests { Link Here
201
        { join => 'cancellation_requests' } );
201
        { join => 'cancellation_requests' } );
202
}
202
}
203
203
204
=head3 count_holds
205
206
    $holds->count_holds( $search_params );
207
208
This overwrites the default count().
209
210
Return the number of holds, where a hold group is counted as one hold.
211
212
=cut
213
214
sub count_holds {
215
    my ( $self, $search_params ) = @_;
216
217
    $search_params = {
218
        hold_group_id => undef,
219
    };
220
    my $holds_without_group_count = $self->search($search_params)->count();
221
222
    $search_params = {
223
        hold_group_id => { '!=', undef },
224
    };
225
    my $hold_groups_count = $self->search( $search_params, { group_by => 'me.hold_group_id' } )->count();
226
227
    return $holds_without_group_count + $hold_groups_count;
228
}
229
204
=head2 Internal methods
230
=head2 Internal methods
205
231
206
=head3 _type
232
=head3 _type
(-)a/t/db_dependent/Koha/Holds.t (-1 / +89 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 11;
22
use Test::More tests => 12;
23
use Test::Warn;
23
use Test::Warn;
24
24
25
use C4::Circulation qw( AddIssue );
25
use C4::Circulation qw( AddIssue );
Lines 667-672 subtest 'Test Koha::Hold::item_group' => sub { Link Here
667
        'Koha::Hold::item_group returns the correct item_group' );
667
        'Koha::Hold::item_group returns the correct item_group' );
668
};
668
};
669
669
670
subtest 'count_holds' => sub {
671
    plan tests => 3;
672
    $schema->storage->txn_begin;
673
674
    my $patron = $builder->build_object(
675
        {
676
            class => 'Koha::Patrons',
677
        }
678
    );
679
    my $patron_id = $patron->borrowernumber;
680
681
    my $hold1 = $builder->build_object(
682
        {
683
            class => 'Koha::Holds',
684
            value => {
685
                borrowernumber => $patron_id,
686
                hold_group_id  => undef,
687
            },
688
        }
689
    );
690
691
    is( $patron->holds->count_holds, 1, 'Test patron has 1 hold.' );
692
693
    my $hold_group = $builder->build_object(
694
        {
695
            class => 'Koha::HoldGroups',
696
        }
697
    );
698
699
    my $hold2 = $builder->build_object(
700
        {
701
            class => 'Koha::Holds',
702
            value => {
703
                borrowernumber => $patron_id,
704
                hold_group_id  => $hold_group->hold_group_id,
705
            }
706
        }
707
    );
708
    my $hold3 = $builder->build_object(
709
        {
710
            class => 'Koha::Holds',
711
            value => {
712
                borrowernumber => $patron_id,
713
                hold_group_id  => $hold_group->hold_group_id,
714
            }
715
        }
716
    );
717
718
    is( $patron->holds->count_holds, 2, 'Test patron has 2 holds.' );
719
720
    my $hold_group2 = $builder->build_object(
721
        {
722
            class => 'Koha::HoldGroups',
723
        }
724
    );
725
726
    my $hold4 = $builder->build_object(
727
        {
728
            class => 'Koha::Holds',
729
            value => {
730
                borrowernumber => $patron_id,
731
                hold_group_id  => $hold_group2->hold_group_id,
732
            }
733
        }
734
    );
735
    my $hold5 = $builder->build_object(
736
        {
737
            class => 'Koha::Holds',
738
            value => {
739
                borrowernumber => $patron_id,
740
                hold_group_id  => $hold_group2->hold_group_id,
741
            }
742
        }
743
    );
744
    my $hold6 = $builder->build_object(
745
        {
746
            class => 'Koha::Holds',
747
            value => {
748
                borrowernumber => $patron_id,
749
                hold_group_id  => $hold_group2->hold_group_id,
750
            }
751
        }
752
    );
753
754
    is( $patron->holds->count_holds, 3, 'Test patron has 3 holds.' );
755
756
    $schema->storage->txn_rollback;
757
};
670
758
671
$schema->storage->txn_rollback;
759
$schema->storage->txn_rollback;
672
760
(-)a/t/db_dependent/Reserves/HoldGroup.t (-1 / +53 lines)
Line 0 Link Here
0
- 
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
};

Return to bug 15516