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

(-)a/C4/Circulation.pm (-17 / +21 lines)
Lines 1107-1113 sub CanBookBeIssued { Link Here
1107
        # See if the item is on reserve.
1107
        # See if the item is on reserve.
1108
        my ( $restype, $res ) = C4::Reserves::CheckReserves( $item_object->itemnumber );
1108
        my ( $restype, $res ) = C4::Reserves::CheckReserves( $item_object->itemnumber );
1109
        if ($restype) {
1109
        if ($restype) {
1110
            my $resbor = $res->{'borrowernumber'};
1110
            my $resbor = $res->{patron_id};
1111
            if ( $resbor ne $patron->borrowernumber ) {
1111
            if ( $resbor ne $patron->borrowernumber ) {
1112
                my $patron = Koha::Patrons->find( $resbor );
1112
                my $patron = Koha::Patrons->find( $resbor );
1113
                if ( $restype eq "Waiting" )
1113
                if ( $restype eq "Waiting" )
Lines 1119-1127 sub CanBookBeIssued { Link Here
1119
                    $needsconfirmation{'ressurname'} = $patron->surname;
1119
                    $needsconfirmation{'ressurname'} = $patron->surname;
1120
                    $needsconfirmation{'rescardnumber'} = $patron->cardnumber;
1120
                    $needsconfirmation{'rescardnumber'} = $patron->cardnumber;
1121
                    $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber;
1121
                    $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber;
1122
                    $needsconfirmation{'resbranchcode'} = $res->{branchcode};
1122
                    $needsconfirmation{'resbranchcode'} = $res->{pickup_library_id};
1123
                    $needsconfirmation{'reswaitingdate'} = $res->{'waitingdate'};
1123
                    $needsconfirmation{'reswaitingdate'} = $res->{waiting_date};
1124
                    $needsconfirmation{'reserve_id'} = $res->{reserve_id};
1124
                    $needsconfirmation{'reserve_id'} = $res->{id};
1125
                }
1125
                }
1126
                elsif ( $restype eq "Reserved" ) {
1126
                elsif ( $restype eq "Reserved" ) {
1127
                    # The item is on reserve for someone else.
1127
                    # The item is on reserve for someone else.
Lines 1131-1138 sub CanBookBeIssued { Link Here
1131
                    $needsconfirmation{'rescardnumber'} = $patron->cardnumber;
1131
                    $needsconfirmation{'rescardnumber'} = $patron->cardnumber;
1132
                    $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber;
1132
                    $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber;
1133
                    $needsconfirmation{'resbranchcode'} = $patron->branchcode;
1133
                    $needsconfirmation{'resbranchcode'} = $patron->branchcode;
1134
                    $needsconfirmation{'resreservedate'} = $res->{reservedate};
1134
                    $needsconfirmation{'resreservedate'} = $res->{created_date};
1135
                    $needsconfirmation{'reserve_id'} = $res->{reserve_id};
1135
                    $needsconfirmation{'reserve_id'} = $res->{id};
1136
                }
1136
                }
1137
                elsif ( $restype eq "Transferred" ) {
1137
                elsif ( $restype eq "Transferred" ) {
1138
                    # The item is determined hold being transferred for someone else.
1138
                    # The item is determined hold being transferred for someone else.
Lines 1142-1149 sub CanBookBeIssued { Link Here
1142
                    $needsconfirmation{'rescardnumber'} = $patron->cardnumber;
1142
                    $needsconfirmation{'rescardnumber'} = $patron->cardnumber;
1143
                    $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber;
1143
                    $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber;
1144
                    $needsconfirmation{'resbranchcode'} = $patron->branchcode;
1144
                    $needsconfirmation{'resbranchcode'} = $patron->branchcode;
1145
                    $needsconfirmation{'resreservedate'} = $res->{reservedate};
1145
                    $needsconfirmation{'resreservedate'} = $res->{created_date};
1146
                    $needsconfirmation{'reserve_id'} = $res->{reserve_id};
1146
                    $needsconfirmation{'reserve_id'} = $res->{id};
1147
                }
1147
                }
1148
                elsif ( $restype eq "Processing" ) {
1148
                elsif ( $restype eq "Processing" ) {
1149
                    # The item is determined hold being processed for someone else.
1149
                    # The item is determined hold being processed for someone else.
Lines 1153-1160 sub CanBookBeIssued { Link Here
1153
                    $needsconfirmation{'rescardnumber'} = $patron->cardnumber;
1153
                    $needsconfirmation{'rescardnumber'} = $patron->cardnumber;
1154
                    $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber;
1154
                    $needsconfirmation{'resborrowernumber'} = $patron->borrowernumber;
1155
                    $needsconfirmation{'resbranchcode'} = $patron->branchcode;
1155
                    $needsconfirmation{'resbranchcode'} = $patron->branchcode;
1156
                    $needsconfirmation{'resreservedate'} = $res->{reservedate};
1156
                    $needsconfirmation{'resreservedate'} = $res->{created_date};
1157
                    $needsconfirmation{'reserve_id'} = $res->{reserve_id};
1157
                    $needsconfirmation{'reserve_id'} = $res->{id};
1158
                }
1158
                }
1159
            }
1159
            }
1160
        }
1160
        }
Lines 1297-1303 sub checkHighHolds { Link Here
1297
        due_date    => undef,
1297
        due_date    => undef,
1298
    };
1298
    };
1299
1299
1300
    my $holds = Koha::Holds->search( { biblionumber => $item->{'biblionumber'} } );
1300
    my $holds = Koha::Holds->search( { biblio_id => $item->{'biblionumber'} } );
1301
1301
1302
    if ( $holds->count() ) {
1302
    if ( $holds->count() ) {
1303
        $return_data->{outstanding} = $holds->count();
1303
        $return_data->{outstanding} = $holds->count();
Lines 1518-1527 sub AddIssue { Link Here
1518
                    }
1518
                    }
1519
                )->store;
1519
                )->store;
1520
                if ( $transfer->reason && $transfer->reason eq 'Reserve' ) {
1520
                if ( $transfer->reason && $transfer->reason eq 'Reserve' ) {
1521
                    my $hold = $item_object->holds->search( { found => 'T' } )->next;
1521
                    my $hold = $item_object->holds->search( { status => 'in_transit' } )->next;
1522
                    if ( $hold ) { # Is this really needed?
1522
                    if ( $hold ) { # Is this really needed?
1523
                        $hold->set( { found => undef } )->store;
1523
                        $hold->set( { status => 'placed' } )->store;
1524
                        C4::Reserves::ModReserveMinusPriority($item_object->itemnumber, $hold->reserve_id);
1524
                        C4::Reserves::ModReserveMinusPriority($item_object->itemnumber, $hold->id);
1525
                    }
1525
                    }
1526
                }
1526
                }
1527
            }
1527
            }
Lines 2878-2885 sub CanBookBeRenewed { Link Here
2878
    # If next hold is non priority, then check if any hold with priority (non_priority = 0) exists for the same biblionumber.
2878
    # If next hold is non priority, then check if any hold with priority (non_priority = 0) exists for the same biblionumber.
2879
    if ( $resfound && $resrec->{non_priority} ) {
2879
    if ( $resfound && $resrec->{non_priority} ) {
2880
        $resfound = Koha::Holds->search(
2880
        $resfound = Koha::Holds->search(
2881
            { biblionumber => $resrec->{biblionumber}, non_priority => 0 } )
2881
            {
2882
          ->count > 0;
2882
                biblio_id    => $resrec->{biblionumber},
2883
                non_priority => 0,
2884
                completed    => 0
2885
            }
2886
        )->count > 0;
2883
    }
2887
    }
2884
2888
2885
2889
Lines 2889-2895 sub CanBookBeRenewed { Link Here
2889
    if ( $resfound
2893
    if ( $resfound
2890
        && C4::Context->preference('AllowRenewalIfOtherItemsAvailable') )
2894
        && C4::Context->preference('AllowRenewalIfOtherItemsAvailable') )
2891
    {
2895
    {
2892
        my $item_holds = Koha::Holds->search( { itemnumber => $itemnumber, found => undef } )->count();
2896
        my $item_holds = Koha::Holds->search( { item_id => $itemnumber, status => 'placed' } )->count();
2893
        if ($item_holds) {
2897
        if ($item_holds) {
2894
            # There is an item level hold on this item, no other item can fill the hold
2898
            # There is an item level hold on this item, no other item can fill the hold
2895
            $resfound = 1;
2899
            $resfound = 1;
(-)a/C4/Members.pm (-1 / +1 lines)
Lines 233-239 sub patronflags { Link Here
233
        $flags{'ODUES'} = \%flaginfo;
233
        $flags{'ODUES'} = \%flaginfo;
234
    }
234
    }
235
235
236
    my $waiting_holds = $patron->holds->search({ found => 'W' });
236
    my $waiting_holds = $patron->holds->search({ status => 'waiting' });
237
    my $nowaiting = $waiting_holds->count;
237
    my $nowaiting = $waiting_holds->count;
238
    if ( $nowaiting > 0 ) {
238
    if ( $nowaiting > 0 ) {
239
        my %flaginfo;
239
        my %flaginfo;
(-)a/C4/Reserves.pm (-261 / +265 lines)
Lines 38-49 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;
43
use Koha::ItemTypes;
42
use Koha::ItemTypes;
44
use Koha::Items;
43
use Koha::Items;
45
use Koha::Libraries;
44
use Koha::Libraries;
46
use Koha::Old::Hold;
47
use Koha::Patrons;
45
use Koha::Patrons;
48
use Koha::Plugins;
46
use Koha::Plugins;
49
47
Lines 186-192 sub AddReserve { Link Here
186
    my $notes          = $params->{notes};
184
    my $notes          = $params->{notes};
187
    my $title          = $params->{title};
185
    my $title          = $params->{title};
188
    my $checkitem      = $params->{itemnumber};
186
    my $checkitem      = $params->{itemnumber};
189
    my $found          = $params->{found};
187
    my $found          = $params->{found} // 'placed';
190
    my $itemtype       = $params->{itemtype};
188
    my $itemtype       = $params->{itemtype};
191
    my $non_priority   = $params->{non_priority};
189
    my $non_priority   = $params->{non_priority};
192
190
Lines 217-223 sub AddReserve { Link Here
217
            && !$item->current_holds->count )
215
            && !$item->current_holds->count )
218
        {
216
        {
219
            $priority = 0;
217
            $priority = 0;
220
            $found = 'W';
218
            $found = 'waiting';
221
        }
219
        }
222
    }
220
    }
223
221
Lines 230-236 sub AddReserve { Link Here
230
    my $waitingdate;
228
    my $waitingdate;
231
229
232
    # If the reserv had the waiting status, we had the value of the resdate
230
    # If the reserv had the waiting status, we had the value of the resdate
233
    if ( $found && $found eq 'W' ) {
231
    if ( $found and $found eq 'waiting' ) {
234
        $waitingdate = $resdate;
232
        $waitingdate = $resdate;
235
    }
233
    }
236
234
Lines 240-261 sub AddReserve { Link Here
240
    # updates take place here
238
    # updates take place here
241
    my $hold = Koha::Hold->new(
239
    my $hold = Koha::Hold->new(
242
        {
240
        {
243
            borrowernumber => $borrowernumber,
241
            patron_id      => $borrowernumber,
244
            biblionumber   => $biblionumber,
242
            biblio_id      => $biblionumber,
245
            reservedate    => $resdate,
243
            created_date   => $resdate,
246
            branchcode     => $branch,
244
            pickup_library_id => $branch,
247
            priority       => $priority,
245
            priority       => $priority,
248
            reservenotes   => $notes,
246
            notes          => $notes,
249
            itemnumber     => $checkitem,
247
            item_id        => $checkitem,
250
            found          => $found,
248
            waiting_date   => $waitingdate,
251
            waitingdate    => $waitingdate,
249
            expiration_date => $expdate,
252
            expirationdate => $expdate,
250
            item_type      => $itemtype,
253
            itemtype       => $itemtype,
251
            item_level     => $checkitem ? 1 : 0,
254
            item_level_hold => $checkitem ? 1 : 0,
255
            non_priority   => $non_priority ? 1 : 0,
252
            non_priority   => $non_priority ? 1 : 0,
256
        }
253
        }
257
    )->store();
254
    )->store();
258
    $hold->set_waiting() if $found && $found eq 'W';
255
    $hold->set_waiting() if $found eq 'waiting';
259
256
260
    logaction( 'HOLDS', 'CREATE', $hold->id, Dumper($hold->unblessed) )
257
    logaction( 'HOLDS', 'CREATE', $hold->id, Dumper($hold->unblessed) )
261
        if C4::Context->preference('HoldsLog');
258
        if C4::Context->preference('HoldsLog');
Lines 394-400 sub CanItemBeReserved { Link Here
394
391
395
    # Check that the patron doesn't have an item level hold on this item already
392
    # Check that the patron doesn't have an item level hold on this item already
396
    return { status =>'itemAlreadyOnHold' }
393
    return { status =>'itemAlreadyOnHold' }
397
      if ( !$params->{ignore_hold_counts} && Koha::Holds->search( { borrowernumber => $borrowernumber, itemnumber => $itemnumber } )->count() );
394
      if ( !$params->{ignore_hold_counts} && Koha::Holds->search( { patron_id => $borrowernumber, item_id => $itemnumber, completed => 0 } )->count() );
398
395
399
    # Check that patron have not checked out this biblio (if AllowHoldsOnPatronsPossessions set)
396
    # Check that patron have not checked out this biblio (if AllowHoldsOnPatronsPossessions set)
400
    if ( !C4::Context->preference('AllowHoldsOnPatronsPossessions')
397
    if ( !C4::Context->preference('AllowHoldsOnPatronsPossessions')
Lines 406-420 sub CanItemBeReserved { Link Here
406
403
407
    my $querycount = q{
404
    my $querycount = q{
408
        SELECT count(*) AS count
405
        SELECT count(*) AS count
409
          FROM reserves
406
          FROM holds
410
     LEFT JOIN items USING (itemnumber)
407
     LEFT JOIN items ON (holds.item_id=items.itemnumber)
411
     LEFT JOIN biblioitems ON (reserves.biblionumber=biblioitems.biblionumber)
408
     LEFT JOIN biblioitems ON (holds.biblio_id=biblioitems.biblionumber)
412
     LEFT JOIN borrowers USING (borrowernumber)
409
     LEFT JOIN borrowers ON (holds.patron_id=borrowers.borrowernumber)
413
         WHERE borrowernumber = ?
410
         WHERE completed = 0 and borrowernumber = ?
414
    };
411
    };
415
412
416
    my $branchcode  = "";
413
    my $branchcode  = "";
417
    my $branchfield = "reserves.branchcode";
414
    my $branchfield = "holds.pickup_library_id";
418
415
419
    if ( $controlbranch eq "ItemHomeLibrary" ) {
416
    if ( $controlbranch eq "ItemHomeLibrary" ) {
420
        $branchfield = "items.homebranch";
417
        $branchfield = "items.homebranch";
Lines 451-460 sub CanItemBeReserved { Link Here
451
    my $holds_per_day    = $rights->{holds_per_day};
448
    my $holds_per_day    = $rights->{holds_per_day};
452
449
453
    my $search_params = {
450
    my $search_params = {
454
        borrowernumber => $borrowernumber,
451
        patron_id => $borrowernumber,
455
        biblionumber   => $item->biblionumber,
452
        biblio_id => $item->biblionumber,
453
        completed => 0,
456
    };
454
    };
457
    $search_params->{found} = undef if $params->{ignore_found_holds};
455
    $search_params->{status} = 'placed' if $params->{ignore_found_holds};
458
456
459
    my $holds = Koha::Holds->search($search_params);
457
    my $holds = Koha::Holds->search($search_params);
460
    if (   defined $holds_per_record && $holds_per_record ne '' ){
458
    if (   defined $holds_per_record && $holds_per_record ne '' ){
Lines 467-474 sub CanItemBeReserved { Link Here
467
    }
465
    }
468
466
469
    my $today_holds = Koha::Holds->search({
467
    my $today_holds = Koha::Holds->search({
470
        borrowernumber => $borrowernumber,
468
        patron_id    => $borrowernumber,
471
        reservedate    => dt_from_string->date
469
        created_date => dt_from_string->date,
470
        completed    => 0
472
    });
471
    });
473
472
474
    if (!$params->{ignore_hold_counts} && defined $holds_per_day && $holds_per_day ne ''
473
    if (!$params->{ignore_hold_counts} && defined $holds_per_day && $holds_per_day ne ''
Lines 524-530 sub CanItemBeReserved { Link Here
524
    if (!$params->{ignore_hold_counts} && $rule && defined( $rule->rule_value ) && $rule->rule_value ne '' ) {
523
    if (!$params->{ignore_hold_counts} && $rule && defined( $rule->rule_value ) && $rule->rule_value ne '' ) {
525
        my $total_holds_count = Koha::Holds->search(
524
        my $total_holds_count = Koha::Holds->search(
526
            {
525
            {
527
                borrowernumber => $borrower->{borrowernumber}
526
                patron_id => $borrower->{borrowernumber},
527
                completed => 0
528
            }
528
            }
529
        )->count();
529
        )->count();
530
530
Lines 602-611 sub CanReserveBeCanceledFromOpac { Link Here
602
    my ($reserve_id, $borrowernumber) = @_;
602
    my ($reserve_id, $borrowernumber) = @_;
603
603
604
    return unless $reserve_id and $borrowernumber;
604
    return unless $reserve_id and $borrowernumber;
605
    my $reserve = Koha::Holds->find($reserve_id) or return;
605
    my $hold = Koha::Holds->find($reserve_id);
606
606
607
    return 0 unless $reserve->borrowernumber == $borrowernumber;
607
    return 0 unless $hold->patron_id == $borrowernumber;
608
    return $reserve->is_cancelable_from_opac;
608
    return $hold->is_cancelable_from_opac;
609
}
609
}
610
610
611
=head2 GetOtherReserves
611
=head2 GetOtherReserves
Lines 623-641 sub GetOtherReserves { Link Here
623
    my ( undef, $checkreserves, undef ) = CheckReserves($itemnumber);
623
    my ( undef, $checkreserves, undef ) = CheckReserves($itemnumber);
624
    if ($checkreserves) {
624
    if ($checkreserves) {
625
        my $item = Koha::Items->find($itemnumber);
625
        my $item = Koha::Items->find($itemnumber);
626
        if ( $item->holdingbranch ne $checkreserves->{'branchcode'} ) {
626
        if ( $item->holdingbranch ne $checkreserves->{pickup_library_id} ) {
627
            $messages->{'transfert'} = $checkreserves->{'branchcode'};
627
            $messages->{'transfert'} = $checkreserves->{pickup_library_id};
628
            #minus priorities of others reservs
628
            #minus priorities of others reservs
629
            ModReserveMinusPriority(
629
            ModReserveMinusPriority(
630
                $itemnumber,
630
                $itemnumber,
631
                $checkreserves->{'reserve_id'},
631
                $checkreserves->{id},
632
            );
632
            );
633
633
634
            #launch the subroutine dotransfer
634
            #launch the subroutine dotransfer
635
            C4::Items::ModItemTransfer(
635
            C4::Items::ModItemTransfer(
636
                $itemnumber,
636
                $itemnumber,
637
                $item->holdingbranch,
637
                $item->holdingbranch,
638
                $checkreserves->{'branchcode'},
638
                $checkreserves->{pickup_library_id},
639
                'Reserve'
639
                'Reserve'
640
              ),
640
              ),
641
              ;
641
              ;
Lines 646-654 sub GetOtherReserves { Link Here
646
            $messages->{'waiting'} = 1;
646
            $messages->{'waiting'} = 1;
647
            ModReserveMinusPriority(
647
            ModReserveMinusPriority(
648
                $itemnumber,
648
                $itemnumber,
649
                $checkreserves->{'reserve_id'},
649
                $checkreserves->{id},
650
            );
650
            );
651
            ModReserveStatus($itemnumber,'W');
651
            ModReserveStatus($itemnumber,'waiting');
652
        }
652
        }
653
653
654
        $nextreservinfo = $checkreserves;
654
        $nextreservinfo = $checkreserves;
Lines 739-763 If several reserves exist, the reserve with the lower priority is given. Link Here
739
## multiple reserves for that bib can have the itemnumber set
739
## multiple reserves for that bib can have the itemnumber set
740
## the sub is only used once in the codebase.
740
## the sub is only used once in the codebase.
741
sub GetReserveStatus {
741
sub GetReserveStatus {
742
    my ($itemnumber) = @_;
742
    my ($item_id) = @_;
743
743
744
    my $dbh = C4::Context->dbh;
744
    my $holds_rs = Koha::Holds->search({ item_id => $item_id, completed => 0 }, { order_by => 'priority' });
745
745
746
    my ($sth, $found, $priority);
746
    if ( $holds_rs->count > 0 ) {
747
    if ( $itemnumber ) {
747
        # They are sorted by priority, pick the first one
748
        $sth = $dbh->prepare("SELECT found, priority FROM reserves WHERE itemnumber = ? order by priority LIMIT 1");
748
        my $hold = $holds_rs->next;
749
        $sth->execute($itemnumber);
750
        ($found, $priority) = $sth->fetchrow_array;
751
    }
752
749
753
    if(defined $found) {
750
        return 'Waiting'    if $hold->is_waiting and $hold->priority == 0;
754
        return 'Waiting'  if $found eq 'W' and $priority == 0;
751
        return 'Processing' if $hold->is_in_processing;
755
        return 'Processing'  if $found eq 'P';
752
        return 'Finished'   if $hold->status eq 'fulfilled';
756
        return 'Finished' if $found eq 'F';
753
        return 'Reserved'   if $hold->priority > 0;
757
    }
754
    }
758
755
759
    return 'Reserved' if defined $priority && $priority > 0;
760
761
    return ''; # empty string here will remove need for checking undef, or less log lines
756
    return ''; # empty string here will remove need for checking undef, or less log lines
762
}
757
}
763
758
Lines 796-802 sub CheckReserves { Link Here
796
    my $sth;
791
    my $sth;
797
    my $select;
792
    my $select;
798
    if (C4::Context->preference('item-level_itypes')){
793
    if (C4::Context->preference('item-level_itypes')){
799
	$select = "
794
    $select = "
800
           SELECT items.biblionumber,
795
           SELECT items.biblionumber,
801
           items.biblioitemnumber,
796
           items.biblioitemnumber,
802
           itemtypes.notforloan,
797
           itemtypes.notforloan,
Lines 811-817 sub CheckReserves { Link Here
811
        ";
806
        ";
812
    }
807
    }
813
    else {
808
    else {
814
	$select = "
809
    $select = "
815
           SELECT items.biblionumber,
810
           SELECT items.biblionumber,
816
           items.biblioitemnumber,
811
           items.biblioitemnumber,
817
           itemtypes.notforloan,
812
           itemtypes.notforloan,
Lines 864-874 sub CheckReserves { Link Here
864
859
865
        my $priority = 10000000;
860
        my $priority = 10000000;
866
        foreach my $res (@reserves) {
861
        foreach my $res (@reserves) {
867
            if ($res->{'found'} && $res->{'found'} eq 'W') {
862
            if ($res->{status} eq 'waiting') {
868
                return ( "Waiting", $res, \@reserves ); # Found it, it is waiting
863
                return ( "Waiting", $res, \@reserves ); # Found it, it is waiting
869
            } elsif ($res->{'found'} && $res->{'found'} eq 'P') {
864
            } elsif ($res->{status} eq 'processing') {
870
                return ( "Processing", $res, \@reserves ); # Found determinated hold, e. g. the transferred one
865
                return ( "Processing", $res, \@reserves ); # Found determinated hold, e. g. the transferred one
871
            } elsif ($res->{'found'} && $res->{'found'} eq 'T') {
866
            } elsif ($res->{status} eq 'in_transit') {
872
                return ( "Transferred", $res, \@reserves ); # Found determinated hold, e. g. the transferred one
867
                return ( "Transferred", $res, \@reserves ); # Found determinated hold, e. g. the transferred one
873
            } else {
868
            } else {
874
                my $patron;
869
                my $patron;
Lines 876-882 sub CheckReserves { Link Here
876
                my $local_hold_match;
871
                my $local_hold_match;
877
872
878
                if ($LocalHoldsPriority) {
873
                if ($LocalHoldsPriority) {
879
                    $patron = Koha::Patrons->find( $res->{borrowernumber} );
874
                    $patron = Koha::Patrons->find( $res->{patron_id} );
880
                    $item = Koha::Items->find($itemnumber);
875
                    $item = Koha::Items->find($itemnumber);
881
876
882
                    unless ($item->exclude_from_local_holds_priority || $patron->category->exclude_from_local_holds_priority) {
877
                    unless ($item->exclude_from_local_holds_priority || $patron->category->exclude_from_local_holds_priority) {
Lines 884-890 sub CheckReserves { Link Here
884
                            $item->$LocalHoldsPriorityItemControl;
879
                            $item->$LocalHoldsPriorityItemControl;
885
                        my $local_holds_priority_patron_branchcode =
880
                        my $local_holds_priority_patron_branchcode =
886
                            ( $LocalHoldsPriorityPatronControl eq 'PickupLibrary' )
881
                            ( $LocalHoldsPriorityPatronControl eq 'PickupLibrary' )
887
                            ? $res->{branchcode}
882
                            ? $res->{pickup_library_id}
888
                            : ( $LocalHoldsPriorityPatronControl eq 'HomeLibrary' )
883
                            : ( $LocalHoldsPriorityPatronControl eq 'HomeLibrary' )
889
                            ? $patron->branchcode
884
                            ? $patron->branchcode
890
                            : undef;
885
                            : undef;
Lines 895-904 sub CheckReserves { Link Here
895
                }
890
                }
896
891
897
                # See if this item is more important than what we've got so far
892
                # See if this item is more important than what we've got so far
898
                if ( ( $res->{'priority'} && $res->{'priority'} < $priority ) || $local_hold_match ) {
893
                if ( ( $res->{priority} && $res->{priority} < $priority ) || $local_hold_match ) {
899
                    $item ||= Koha::Items->find($itemnumber);
894
                    $item ||= Koha::Items->find($itemnumber);
900
                    next if $res->{itemtype} && $res->{itemtype} ne $item->effective_itemtype;
895
                    next if $res->{item_type} && $res->{item_type} ne $item->effective_itemtype;
901
                    $patron ||= Koha::Patrons->find( $res->{borrowernumber} );
896
                    $patron ||= Koha::Patrons->find( $res->{patron_id} );
902
                    my $branch = GetReservesControlBranch( $item->unblessed, $patron->unblessed );
897
                    my $branch = GetReservesControlBranch( $item->unblessed, $patron->unblessed );
903
                    my $branchitemrule = C4::Circulation::GetBranchItemRule($branch,$item->effective_itemtype);
898
                    my $branchitemrule = C4::Circulation::GetBranchItemRule($branch,$item->effective_itemtype);
904
                    next if ($branchitemrule->{'holdallowed'} eq 'not_allowed');
899
                    next if ($branchitemrule->{'holdallowed'} eq 'not_allowed');
Lines 906-915 sub CheckReserves { Link Here
906
                    my $library = Koha::Libraries->find({branchcode=>$item->homebranch});
901
                    my $library = Koha::Libraries->find({branchcode=>$item->homebranch});
907
                    next if (($branchitemrule->{'holdallowed'} eq 'from_local_hold_group') && (!$library->validate_hold_sibling({branchcode => $patron->branchcode}) ));
902
                    next if (($branchitemrule->{'holdallowed'} eq 'from_local_hold_group') && (!$library->validate_hold_sibling({branchcode => $patron->branchcode}) ));
908
                    my $hold_fulfillment_policy = $branchitemrule->{hold_fulfillment_policy};
903
                    my $hold_fulfillment_policy = $branchitemrule->{hold_fulfillment_policy};
909
                    next if ( ($hold_fulfillment_policy eq 'holdgroup') && (!$library->validate_hold_sibling({branchcode => $res->{branchcode}})) );
904
                    next if ( ($hold_fulfillment_policy eq 'holdgroup') && (!$library->validate_hold_sibling({branchcode => $res->{pickup_library_id}})) );
910
                    next if ( ($hold_fulfillment_policy eq 'homebranch') && ($res->{branchcode} ne $item->$hold_fulfillment_policy) );
905
                    next if ( ($hold_fulfillment_policy eq 'homebranch') && ($res->{pickup_library_id} ne $item->$hold_fulfillment_policy) );
911
                    next if ( ($hold_fulfillment_policy eq 'holdingbranch') && ($res->{branchcode} ne $item->$hold_fulfillment_policy) );
906
                    next if ( ($hold_fulfillment_policy eq 'holdingbranch') && ($res->{pickup_library_id} ne $item->$hold_fulfillment_policy) );
912
                    next unless $item->can_be_transferred( { to => Koha::Libraries->find( $res->{branchcode} ) } );
907
                    next unless $item->can_be_transferred( { to => Koha::Libraries->find( $res->{pickup_library_id} ) } );
913
                    $priority = $res->{'priority'};
908
                    $priority = $res->{'priority'};
914
                    $highest  = $res;
909
                    $highest  = $res;
915
                    last if $local_hold_match;
910
                    last if $local_hold_match;
Lines 943-962 sub CancelExpiredReserves { Link Here
943
    my $expireWaiting = C4::Context->preference('ExpireReservesMaxPickUpDelay');
938
    my $expireWaiting = C4::Context->preference('ExpireReservesMaxPickUpDelay');
944
939
945
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
940
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
946
    my $params = { expirationdate => { '<', $dtf->format_date($today) } };
941
    my $params = { expiration_date => { '<', $dtf->format_date($today) } };
947
    $params->{found} = [ { '!=', 'W' }, undef ]  unless $expireWaiting;
942
    $params->{status} = [ { '!=', 'waiting' }, undef ]  unless $expireWaiting;
948
943
949
    # FIXME To move to Koha::Holds->search_expired (?)
944
    # FIXME To move to Koha::Holds->search_expired (?)
950
    my $holds = Koha::Holds->search( $params );
945
    my $holds = Koha::Holds->search( $params );
951
946
952
    while ( my $hold = $holds->next ) {
947
    while ( my $hold = $holds->next ) {
953
        my $calendar = Koha::Calendar->new( branchcode => $hold->branchcode );
948
        my $calendar = Koha::Calendar->new( branchcode => $hold->pickup_library_id );
954
949
955
        next if !$cancel_on_holidays && $calendar->is_holiday( $today );
950
        next if !$cancel_on_holidays && $calendar->is_holiday( $today );
956
951
957
        my $cancel_params = {};
952
        my $cancel_params = {};
958
        $cancel_params->{cancellation_reason} = $cancellation_reason if defined($cancellation_reason);
953
        $cancel_params->{cancellation_reason} = $cancellation_reason if defined($cancellation_reason);
959
        if ( defined($hold->found) && $hold->found eq 'W' ) {
954
        if ( $hold->is_waiting ) {
960
            $cancel_params->{charge_cancel_fee} = 1;
955
            $cancel_params->{charge_cancel_fee} = 1;
961
        }
956
        }
962
        $hold->cancel( $cancel_params );
957
        $hold->cancel( $cancel_params );
Lines 967-980 sub CancelExpiredReserves { Link Here
967
962
968
  AutoUnsuspendReserves();
963
  AutoUnsuspendReserves();
969
964
970
Unsuspends all suspended reserves with a suspend_until date from before today.
965
Unsuspends all suspended reserves with a suspended_until date from before today.
971
966
972
=cut
967
=cut
973
968
974
sub AutoUnsuspendReserves {
969
sub AutoUnsuspendReserves {
975
    my $today = dt_from_string();
970
    my $today = dt_from_string();
976
971
977
    my @holds = Koha::Holds->search( { suspend_until => { '<=' => $today->ymd() } } );
972
    my @holds = Koha::Holds->search( { suspended_until_date => { '<=' => $today->ymd() } } );
978
973
979
    map { $_->resume() } @holds;
974
    map { $_->resume() } @holds;
980
}
975
}
Lines 1034-1043 sub ModReserve { Link Here
1034
1029
1035
    my $hold;
1030
    my $hold;
1036
    unless ( $reserve_id ) {
1031
    unless ( $reserve_id ) {
1037
        my $holds = Koha::Holds->search({ biblionumber => $biblionumber, borrowernumber => $borrowernumber, itemnumber => $itemnumber });
1032
        my $holds = Koha::Holds->search({ biblio_id => $biblionumber, patron_id => $borrowernumber, item_id => $itemnumber });
1038
        return unless $holds->count; # FIXME Should raise an exception
1033
        return unless $holds->count; # FIXME Should raise an exception
1039
        $hold = $holds->next;
1034
        $hold = $holds->next;
1040
        $reserve_id = $hold->reserve_id;
1035
        $reserve_id = $hold->id;
1041
    }
1036
    }
1042
1037
1043
    $hold ||= Koha::Holds->find($reserve_id);
1038
    $hold ||= Koha::Holds->find($reserve_id);
Lines 1046-1066 sub ModReserve { Link Here
1046
        $hold->cancel({ cancellation_reason => $cancellation_reason });
1041
        $hold->cancel({ cancellation_reason => $cancellation_reason });
1047
    }
1042
    }
1048
    elsif ($rank =~ /^\d+/ and $rank > 0) {
1043
    elsif ($rank =~ /^\d+/ and $rank > 0) {
1049
        logaction( 'HOLDS', 'MODIFY', $hold->reserve_id, Dumper($hold->unblessed) )
1044
        logaction( 'HOLDS', 'MODIFY', $hold->id, Dumper($hold->unblessed) )
1050
            if C4::Context->preference('HoldsLog');
1045
            if C4::Context->preference('HoldsLog');
1051
1046
1052
        my $properties = {
1047
        my $properties = {
1053
            priority    => $rank,
1048
            priority     => $rank,
1054
            branchcode  => $branchcode,
1049
            pickup_library_id => $branchcode,
1055
            itemnumber  => $itemnumber,
1050
            item_id      => $itemnumber,
1056
            found       => undef,
1051
            status       => 'placed',
1057
            waitingdate => undef
1052
            waiting_date => undef
1058
        };
1053
        };
1059
        if (exists $params->{reservedate}) {
1054
        if (exists $params->{reservedate}) {
1060
            $properties->{reservedate} = $params->{reservedate} || undef;
1055
            $properties->{created_date} = $params->{reservedate} || undef;
1061
        }
1056
        }
1062
        if (exists $params->{expirationdate}) {
1057
        if (exists $params->{expirationdate}) {
1063
            $properties->{expirationdate} = $params->{expirationdate} || undef;
1058
            $properties->{expiration_date} = $params->{expirationdate} || undef;
1064
        }
1059
        }
1065
1060
1066
        $hold->set($properties)->store();
1061
        $hold->set($properties)->store();
Lines 1072-1078 sub ModReserve { Link Here
1072
            } else {
1067
            } else {
1073
                # If the hold is suspended leave the hold suspended, but convert it to an indefinite hold.
1068
                # If the hold is suspended leave the hold suspended, but convert it to an indefinite hold.
1074
                # If the hold is not suspended, this does nothing.
1069
                # If the hold is not suspended, this does nothing.
1075
                $hold->set( { suspend_until => undef } )->store();
1070
                $hold->set( { suspended_until_date => undef } )->store();
1076
            }
1071
            }
1077
        }
1072
        }
1078
1073
Lines 1094-1130 whose keys are fields from the reserves table in the Koha database. Link Here
1094
1089
1095
sub ModReserveFill {
1090
sub ModReserveFill {
1096
    my ($res) = @_;
1091
    my ($res) = @_;
1097
    my $reserve_id = $res->{'reserve_id'};
1092
    my $reserve_id = $res->{'id'};
1098
1093
1099
    my $hold = Koha::Holds->find($reserve_id);
1094
    my $hold = Koha::Holds->find($reserve_id);
1100
    # get the priority on this record....
1095
    # get the priority on this record....
1101
    my $priority = $hold->priority;
1096
    my $priority = $hold->priority;
1102
1097
1103
    # update the hold statuses, no need to store it though, we will be deleting it anyway
1098
    # update the hold statuses, no need to store it though, we will be deleting it anyway
1099
    # FIXME: Add Koha::Hold->set_filled and add the correct log
1104
    $hold->set(
1100
    $hold->set(
1105
        {
1101
        {
1106
            found    => 'F',
1102
            status    => 'fulfilled',
1107
            priority => 0,
1103
            priority  => 0,
1104
            completed => 1,
1105
            completed_date => \'NOW()'
1108
        }
1106
        }
1109
    );
1107
    );
1110
1108
1111
    logaction( 'HOLDS', 'MODIFY', $hold->reserve_id, Dumper($hold->unblessed) )
1109
    logaction( 'HOLDS', 'MODIFY', $hold->id, Dumper($hold->unblessed) )
1112
        if C4::Context->preference('HoldsLog');
1110
        if C4::Context->preference('HoldsLog');
1113
1111
1114
    # FIXME Must call Koha::Hold->cancel ? => No, should call ->filled and add the correct log
1112
    $hold->store();
1115
    Koha::Old::Hold->new( $hold->unblessed() )->store();
1116
1117
    $hold->delete();
1118
1113
1119
    if ( C4::Context->preference('HoldFeeMode') eq 'any_time_is_collected' ) {
1114
    if ( C4::Context->preference('HoldFeeMode') eq 'any_time_is_collected' ) {
1120
        my $reserve_fee = GetReserveFee( $hold->borrowernumber, $hold->biblionumber );
1115
        my $reserve_fee = GetReserveFee( $hold->patron_id, $hold->biblio_id );
1121
        ChargeReserveFee( $hold->borrowernumber, $reserve_fee, $hold->biblio->title );
1116
        ChargeReserveFee( $hold->patron_id, $reserve_fee, $hold->biblio->title );
1122
    }
1117
    }
1123
1118
1124
    # now fix the priority on the others (if the priority wasn't
1119
    # now fix the priority on the others (if the priority wasn't
1125
    # already sorted!)....
1120
    # already sorted!)....
1126
    unless ( $priority == 0 ) {
1121
    unless ( $priority == 0 ) {
1127
        _FixPriority( { reserve_id => $reserve_id, biblionumber => $hold->biblionumber } );
1122
        _FixPriority( { reserve_id => $reserve_id, biblionumber => $hold->biblio_id } );
1128
    }
1123
    }
1129
}
1124
}
1130
1125
Lines 1146-1152 sub ModReserveStatus { Link Here
1146
    my ($itemnumber, $newstatus) = @_;
1141
    my ($itemnumber, $newstatus) = @_;
1147
    my $dbh = C4::Context->dbh;
1142
    my $dbh = C4::Context->dbh;
1148
1143
1149
    my $query = "UPDATE reserves SET found = ?, waitingdate = NOW() WHERE itemnumber = ? AND found IS NULL AND priority = 0";
1144
    my $query = "UPDATE holds SET status = ?, waiting_date = NOW() WHERE item_id = ? AND status='placed' AND priority = 0";
1150
    my $sth_set = $dbh->prepare($query);
1145
    my $sth_set = $dbh->prepare($query);
1151
    $sth_set->execute( $newstatus, $itemnumber );
1146
    $sth_set->execute( $newstatus, $itemnumber );
1152
1147
Lines 1192-1206 sub ModReserveAffect { Link Here
1192
    # Find hold by id if we have it
1187
    # Find hold by id if we have it
1193
    $hold = Koha::Holds->find( $reserve_id ) if $reserve_id;
1188
    $hold = Koha::Holds->find( $reserve_id ) if $reserve_id;
1194
    # Find item level hold for this item if there is one
1189
    # Find item level hold for this item if there is one
1195
    $hold ||= Koha::Holds->search( { borrowernumber => $borrowernumber, itemnumber => $itemnumber } )->next();
1190
    $hold ||= Koha::Holds->search( { patron_id => $borrowernumber, item_id => $itemnumber } )->next();
1196
    # Find record level hold if there is no item level hold
1191
    # Find record level hold if there is no item level hold
1197
    $hold ||= Koha::Holds->search( { borrowernumber => $borrowernumber, biblionumber => $biblionumber } )->next();
1192
    $hold ||= Koha::Holds->search( { patron_id => $borrowernumber, biblio_id => $biblionumber } )->next();
1198
1193
1199
    return unless $hold;
1194
    return unless $hold;
1200
1195
1201
    my $already_on_shelf = $hold->found && $hold->found eq 'W';
1196
    my $already_on_shelf = $hold->status eq 'waiting';
1202
1197
1203
    $hold->itemnumber($itemnumber);
1198
    $hold->item_id($itemnumber);
1204
1199
1205
    if ($transferToDo) {
1200
    if ($transferToDo) {
1206
        $hold->set_transfer();
1201
        $hold->set_transfer();
Lines 1210-1216 sub ModReserveAffect { Link Here
1210
        $hold->set_processing();
1205
        $hold->set_processing();
1211
    } else {
1206
    } else {
1212
        $hold->set_waiting($desk_id);
1207
        $hold->set_waiting($desk_id);
1213
        _koha_notify_reserve( $hold->reserve_id ) unless $already_on_shelf;
1208
        _koha_notify_reserve( $hold->id ) unless $already_on_shelf;
1214
        # Complete transfer if one exists
1209
        # Complete transfer if one exists
1215
        my $transfer = $hold->item->get_transfer;
1210
        my $transfer = $hold->item->get_transfer;
1216
        $transfer->receive if $transfer;
1211
        $transfer->receive if $transfer;
Lines 1234-1242 sub ModReserveAffect { Link Here
1234
            AND q.holdingbranch = t.source_branchcode
1229
            AND q.holdingbranch = t.source_branchcode
1235
        WHERE t.reserve_id = ?
1230
        WHERE t.reserve_id = ?
1236
    });
1231
    });
1237
    $std->execute($hold->reserve_id);
1232
    $std->execute($hold->id);
1238
1233
1239
    logaction( 'HOLDS', 'MODIFY', $hold->reserve_id, Dumper($hold->get_from_storage->unblessed) )
1234
    logaction( 'HOLDS', 'MODIFY', $hold->id, Dumper($hold->get_from_storage->unblessed) )
1240
        if C4::Context->preference('HoldsLog');
1235
        if C4::Context->preference('HoldsLog');
1241
1236
1242
    return;
1237
    return;
Lines 1253-1267 function to cancel reserv,check other reserves, and transfer document if it's ne Link Here
1253
sub ModReserveCancelAll {
1248
sub ModReserveCancelAll {
1254
    my $messages;
1249
    my $messages;
1255
    my $nextreservinfo;
1250
    my $nextreservinfo;
1256
    my ( $itemnumber, $borrowernumber, $cancellation_reason ) = @_;
1251
    my ( $item_id, $patron_id, $cancellation_reason ) = @_;
1257
1252
1258
    #step 1 : cancel the reservation
1253
    #step 1 : cancel the reservation
1259
    my $holds = Koha::Holds->search({ itemnumber => $itemnumber, borrowernumber => $borrowernumber });
1254
    my $holds = Koha::Holds->search({ item_id => $item_id, patron_id => $patron_id });
1260
    return unless $holds->count;
1255
    return unless $holds->count;
1261
    $holds->next->cancel({ cancellation_reason => $cancellation_reason });
1256
    $holds->next->cancel({ cancellation_reason => $cancellation_reason });
1262
1257
1263
    #step 2 launch the subroutine of the others reserves
1258
    #step 2 launch the subroutine of the others reserves
1264
    ( $messages, $nextreservinfo ) = GetOtherReserves($itemnumber);
1259
    ( $messages, $nextreservinfo ) = GetOtherReserves($item_id);
1265
1260
1266
    return ( $messages, $nextreservinfo->{borrowernumber} );
1261
    return ( $messages, $nextreservinfo->{borrowernumber} );
1267
}
1262
}
Lines 1275-1291 Reduce the values of queued list Link Here
1275
=cut
1270
=cut
1276
1271
1277
sub ModReserveMinusPriority {
1272
sub ModReserveMinusPriority {
1278
    my ( $itemnumber, $reserve_id ) = @_;
1273
    my ( $item_id, $reserve_id ) = @_;
1279
1274
1280
    #first step update the value of the first person on reserv
1275
    #first step update the value of the first person on reserv
1281
    my $dbh   = C4::Context->dbh;
1276
    my $dbh   = C4::Context->dbh;
1282
    my $query = "
1277
    my $query = "
1283
        UPDATE reserves
1278
        UPDATE holds
1284
        SET    priority = 0 , itemnumber = ?
1279
        SET    priority = 0 , item_id = ?
1285
        WHERE  reserve_id = ?
1280
        WHERE  id = ?
1286
    ";
1281
    ";
1287
    my $sth_upd = $dbh->prepare($query);
1282
    my $sth_upd = $dbh->prepare($query);
1288
    $sth_upd->execute( $itemnumber, $reserve_id );
1283
    $sth_upd->execute( $item_id, $reserve_id );
1289
    # second step update all others reserves
1284
    # second step update all others reserves
1290
    _FixPriority({ reserve_id => $reserve_id, rank => '0' });
1285
    _FixPriority({ reserve_id => $reserve_id, rank => '0' });
1291
}
1286
}
Lines 1429-1436 sub AlterPriority { Link Here
1429
    my $hold = Koha::Holds->find( $reserve_id );
1424
    my $hold = Koha::Holds->find( $reserve_id );
1430
    return unless $hold;
1425
    return unless $hold;
1431
1426
1432
    if ( $hold->cancellationdate ) {
1427
    if ( $hold->completed_date and $hold->status eq 'cancelled' ) {
1433
        warn "I cannot alter the priority for reserve_id $reserve_id, the reserve has been cancelled (" . $hold->cancellationdate . ')';
1428
        warn "I cannot alter the priority for reserve_id $reserve_id, the reserve has been cancelled (" . $hold->completed_date . ')';
1434
        return;
1429
        return;
1435
    }
1430
    }
1436
1431
Lines 1462-1468 sub ToggleLowestPriority { Link Here
1462
1457
1463
    my $dbh = C4::Context->dbh;
1458
    my $dbh = C4::Context->dbh;
1464
1459
1465
    my $sth = $dbh->prepare( "UPDATE reserves SET lowestPriority = NOT lowestPriority WHERE reserve_id = ?");
1460
    my $sth = $dbh->prepare( "UPDATE holds SET lowest_priority = NOT lowest_priority WHERE id = ?");
1466
    $sth->execute( $reserve_id );
1461
    $sth->execute( $reserve_id );
1467
1462
1468
    _FixPriority({ reserve_id => $reserve_id, rank => '999999' });
1463
    _FixPriority({ reserve_id => $reserve_id, rank => '999999' });
Lines 1522-1530 sub SuspendAll { Link Here
1522
    return unless ( $borrowernumber || $biblionumber );
1517
    return unless ( $borrowernumber || $biblionumber );
1523
1518
1524
    my $params;
1519
    my $params;
1525
    $params->{found}          = undef;
1520
    $params->{status} = 'placed';
1526
    $params->{borrowernumber} = $borrowernumber if $borrowernumber;
1521
    $params->{patron_id} = $borrowernumber if $borrowernumber;
1527
    $params->{biblionumber}   = $biblionumber if $biblionumber;
1522
    $params->{biblio_id} = $biblionumber if $biblionumber;
1528
1523
1529
    my @holds = Koha::Holds->search($params);
1524
    my @holds = Koha::Holds->search($params);
1530
1525
Lines 1584-1598 sub _FixPriority { Link Here
1584
    my $hold;
1579
    my $hold;
1585
    if ( $reserve_id ) {
1580
    if ( $reserve_id ) {
1586
        $hold = Koha::Holds->find( $reserve_id );
1581
        $hold = Koha::Holds->find( $reserve_id );
1587
        if (!defined $hold){
1588
            # may have already been checked out and hold fulfilled
1589
            $hold = Koha::Old::Holds->find( $reserve_id );
1590
        }
1591
        return unless $hold;
1582
        return unless $hold;
1592
    }
1583
    }
1593
1584
1594
    unless ( $biblionumber ) { # FIXME This is a very weird API
1585
    unless ( $biblionumber ) { # FIXME This is a very weird API
1595
        $biblionumber = $hold->biblionumber;
1586
        $biblionumber = $hold->biblio_id;
1596
    }
1587
    }
1597
1588
1598
    if ( $rank eq "del" ) { # FIXME will crash if called without $hold
1589
    if ( $rank eq "del" ) { # FIXME will crash if called without $hold
Lines 1602-1611 sub _FixPriority { Link Here
1602
1593
1603
        # make sure priority for waiting or in-transit items is 0
1594
        # make sure priority for waiting or in-transit items is 0
1604
        my $query = "
1595
        my $query = "
1605
            UPDATE reserves
1596
            UPDATE holds
1606
            SET    priority = 0
1597
            SET    priority = 0
1607
            WHERE reserve_id = ?
1598
            WHERE  id = ?
1608
            AND found IN ('W', 'T', 'P')
1599
            AND status IN ('waiting', 'in_transit', 'processing')
1609
        ";
1600
        ";
1610
        my $sth = $dbh->prepare($query);
1601
        my $sth = $dbh->prepare($query);
1611
        $sth->execute( $reserve_id );
1602
        $sth->execute( $reserve_id );
Lines 1614-1623 sub _FixPriority { Link Here
1614
1605
1615
    # get whats left
1606
    # get whats left
1616
    my $query = "
1607
    my $query = "
1617
        SELECT reserve_id, borrowernumber, reservedate
1608
        SELECT id
1618
        FROM   reserves
1609
        FROM   holds
1619
        WHERE  biblionumber   = ?
1610
        WHERE  biblio_id   = ?
1620
          AND  ((found <> 'W' AND found <> 'T' AND found <> 'P') OR found IS NULL)
1611
          AND  completed = 0
1612
          AND  status = 'placed'
1621
        ORDER BY priority ASC
1613
        ORDER BY priority ASC
1622
    ";
1614
    ";
1623
    my $sth = $dbh->prepare($query);
1615
    my $sth = $dbh->prepare($query);
Lines 1631-1637 sub _FixPriority { Link Here
1631
    my $i;
1623
    my $i;
1632
    my $key = -1;    # to allow for 0 to be a valid result
1624
    my $key = -1;    # to allow for 0 to be a valid result
1633
    for ( $i = 0 ; $i < @priority ; $i++ ) {
1625
    for ( $i = 0 ; $i < @priority ; $i++ ) {
1634
        if ( $reserve_id && $reserve_id == $priority[$i]->{'reserve_id'} ) {
1626
        if ( $reserve_id && $reserve_id == $priority[$i]->{'id'} ) {
1635
            $key = $i;    # save the index
1627
            $key = $i;    # save the index
1636
            last;
1628
            last;
1637
        }
1629
        }
Lines 1647-1671 sub _FixPriority { Link Here
1647
1639
1648
    # now fix the priority on those that are left....
1640
    # now fix the priority on those that are left....
1649
    $query = "
1641
    $query = "
1650
        UPDATE reserves
1642
        UPDATE holds
1651
        SET    priority = ?
1643
        SET    priority = ?
1652
        WHERE  reserve_id = ?
1644
        WHERE  id = ?
1653
    ";
1645
    ";
1654
    $sth = $dbh->prepare($query);
1646
    $sth = $dbh->prepare($query);
1655
    for ( my $j = 0 ; $j < @priority ; $j++ ) {
1647
    for ( my $j = 0 ; $j < @priority ; $j++ ) {
1656
        $sth->execute(
1648
        $sth->execute(
1657
            $j + 1,
1649
            $j + 1,
1658
            $priority[$j]->{'reserve_id'}
1650
            $priority[$j]->{'id'}
1659
        );
1651
        );
1660
    }
1652
    }
1661
1653
1662
    $sth = $dbh->prepare( "SELECT reserve_id FROM reserves WHERE lowestPriority = 1 ORDER BY priority" );
1654
    $sth = $dbh->prepare( "SELECT id FROM holds WHERE lowest_priority = 1 ORDER BY priority" );
1663
    $sth->execute();
1655
    $sth->execute();
1664
1656
1665
    unless ( $ignoreSetLowestRank ) {
1657
    unless ( $ignoreSetLowestRank ) {
1666
      while ( my $res = $sth->fetchrow_hashref() ) {
1658
      while ( my $res = $sth->fetchrow_hashref() ) {
1667
        _FixPriority({
1659
        _FixPriority({
1668
            reserve_id => $res->{'reserve_id'},
1660
            reserve_id => $res->{'id'},
1669
            rank => '999999',
1661
            rank => '999999',
1670
            ignoreSetLowestRank => 1
1662
            ignoreSetLowestRank => 1
1671
        });
1663
        });
Lines 1702-1730 sub _Findgroupreserve { Link Here
1702
    # TODO: consolidate at least the SELECT portion of the first 2 queries to a common $select var.
1694
    # TODO: consolidate at least the SELECT portion of the first 2 queries to a common $select var.
1703
    # check for exact targeted match
1695
    # check for exact targeted match
1704
    my $item_level_target_query = qq{
1696
    my $item_level_target_query = qq{
1705
        SELECT reserves.biblionumber        AS biblionumber,
1697
        SELECT holds.biblio_id         AS biblio_id,
1706
               reserves.borrowernumber      AS borrowernumber,
1698
               holds.patron_id         AS patron_id,
1707
               reserves.reservedate         AS reservedate,
1699
               holds.created_date      AS created_date,
1708
               reserves.branchcode          AS branchcode,
1700
               holds.pickup_library_id AS pickup_library_id,
1709
               reserves.cancellationdate    AS cancellationdate,
1701
               holds.completed_date   AS completed_date,
1710
               reserves.found               AS found,
1702
               holds.status            AS status,
1711
               reserves.reservenotes        AS reservenotes,
1703
               holds.notes             AS notes,
1712
               reserves.priority            AS priority,
1704
               holds.priority          AS priority,
1713
               reserves.timestamp           AS timestamp,
1705
               holds.timestamp         AS timestamp,
1714
               biblioitems.biblioitemnumber AS biblioitemnumber,
1706
               biblioitems.biblioitemnumber AS biblioitemnumber,
1715
               reserves.itemnumber          AS itemnumber,
1707
               holds.item_id           AS item_id,
1716
               reserves.reserve_id          AS reserve_id,
1708
               holds.id                AS id,
1717
               reserves.itemtype            AS itemtype,
1709
               holds.item_type         AS item_type,
1718
               reserves.non_priority        AS non_priority
1710
               holds.non_priority      AS non_priority
1719
        FROM reserves
1711
        FROM holds
1720
        JOIN biblioitems USING (biblionumber)
1712
        JOIN biblioitems ON (holds.biblio_id=biblioitems.biblionumber)
1721
        JOIN hold_fill_targets USING (reserve_id)
1713
        JOIN hold_fill_targets ON (
1722
        WHERE found IS NULL
1714
                holds.biblio_id=hold_fill_targets.biblionumber
1715
            AND holds.patron_id=hold_fill_targets.borrowernumber
1716
            AND holds.item_id=hold_fill_targets.itemnumber)
1717
        WHERE status='placed'
1723
        AND priority > 0
1718
        AND priority > 0
1724
        AND item_level_request = 1
1719
        AND completed = 0
1725
        AND hold_fill_targets.itemnumber = ?
1720
        AND item_level = 1
1726
        AND reservedate <= DATE_ADD(NOW(),INTERVAL ? DAY)
1721
        AND item_id = ?
1727
        AND suspend = 0
1722
        AND created_date <= DATE_ADD(NOW(),INTERVAL ? DAY)
1723
        AND suspended = 0
1728
        ORDER BY priority
1724
        ORDER BY priority
1729
    };
1725
    };
1730
    my $sth = $dbh->prepare($item_level_target_query);
1726
    my $sth = $dbh->prepare($item_level_target_query);
Lines 1732-1766 sub _Findgroupreserve { Link Here
1732
    my @results;
1728
    my @results;
1733
    if ( my $data = $sth->fetchrow_hashref ) {
1729
    if ( my $data = $sth->fetchrow_hashref ) {
1734
        push( @results, $data )
1730
        push( @results, $data )
1735
          unless any{ $data->{borrowernumber} eq $_ } @$ignore_borrowers ;
1731
          unless any{ $data->{patron_id} eq $_ } @$ignore_borrowers ;
1736
    }
1732
    }
1737
    return @results if @results;
1733
    return @results if @results;
1738
1734
1739
    # check for title-level targeted match
1735
    # check for title-level targeted match
1740
    my $title_level_target_query = qq{
1736
    my $title_level_target_query = qq{
1741
        SELECT reserves.biblionumber        AS biblionumber,
1737
        SELECT holds.biblio_id         AS biblio_id,
1742
               reserves.borrowernumber      AS borrowernumber,
1738
               holds.patron_id         AS patron_id,
1743
               reserves.reservedate         AS reservedate,
1739
               holds.created_date      AS created_date,
1744
               reserves.branchcode          AS branchcode,
1740
               holds.pickup_library_id AS pickup_library_id,
1745
               reserves.cancellationdate    AS cancellationdate,
1741
               holds.completed_date   AS completed_date,
1746
               reserves.found               AS found,
1742
               holds.status            AS status,
1747
               reserves.reservenotes        AS reservenotes,
1743
               holds.notes             AS notes,
1748
               reserves.priority            AS priority,
1744
               holds.priority          AS priority,
1749
               reserves.timestamp           AS timestamp,
1745
               holds.timestamp         AS timestamp,
1750
               biblioitems.biblioitemnumber AS biblioitemnumber,
1746
               biblioitems.biblioitemnumber AS biblioitemnumber,
1751
               reserves.itemnumber          AS itemnumber,
1747
               holds.item_id           AS item_id,
1752
               reserves.reserve_id          AS reserve_id,
1748
               holds.id                AS id,
1753
               reserves.itemtype            AS itemtype,
1749
               holds.item_type         AS item_type,
1754
               reserves.non_priority        AS non_priority
1750
               holds.non_priority      AS non_priority
1755
        FROM reserves
1751
        FROM holds
1756
        JOIN biblioitems USING (biblionumber)
1752
        JOIN biblioitems ON (holds.biblio_id=biblioitems.biblionumber)
1757
        JOIN hold_fill_targets USING (reserve_id)
1753
        JOIN hold_fill_targets ON (
1758
        WHERE found IS NULL
1754
                holds.biblio_id=hold_fill_targets.biblionumber
1755
            AND holds.patron_id=hold_fill_targets.borrowernumber)
1756
        WHERE status='placed'
1759
        AND priority > 0
1757
        AND priority > 0
1760
        AND item_level_request = 0
1758
        AND completed = 0
1759
        AND item_level = 0
1761
        AND hold_fill_targets.itemnumber = ?
1760
        AND hold_fill_targets.itemnumber = ?
1762
        AND reservedate <= DATE_ADD(NOW(),INTERVAL ? DAY)
1761
        AND created_date <= DATE_ADD(NOW(),INTERVAL ? DAY)
1763
        AND suspend = 0
1762
        AND suspended = 0
1764
        ORDER BY priority
1763
        ORDER BY priority
1765
    };
1764
    };
1766
    $sth = $dbh->prepare($title_level_target_query);
1765
    $sth = $dbh->prepare($title_level_target_query);
Lines 1768-1797 sub _Findgroupreserve { Link Here
1768
    @results = ();
1767
    @results = ();
1769
    if ( my $data = $sth->fetchrow_hashref ) {
1768
    if ( my $data = $sth->fetchrow_hashref ) {
1770
        push( @results, $data )
1769
        push( @results, $data )
1771
          unless any{ $data->{borrowernumber} eq $_ } @$ignore_borrowers ;
1770
          unless any{ $data->{patron_id} eq $_ } @$ignore_borrowers ;
1772
    }
1771
    }
1773
    return @results if @results;
1772
    return @results if @results;
1774
1773
1775
    my $query = qq{
1774
    my $query = qq{
1776
        SELECT reserves.biblionumber               AS biblionumber,
1775
        SELECT holds.biblio_id                  AS biblio_id,
1777
               reserves.borrowernumber             AS borrowernumber,
1776
               holds.patron_id                  AS patron_id,
1778
               reserves.reservedate                AS reservedate,
1777
               holds.created_date               AS created_date,
1779
               reserves.waitingdate                AS waitingdate,
1778
               holds.waiting_date               AS waiting_date,
1780
               reserves.branchcode                 AS branchcode,
1779
               holds.pickup_library_id          AS pickup_library_id,
1781
               reserves.cancellationdate           AS cancellationdate,
1780
               holds.completed_date             AS completed_date,
1782
               reserves.found                      AS found,
1781
               holds.status                     AS status,
1783
               reserves.reservenotes               AS reservenotes,
1782
               holds.notes                      AS notes,
1784
               reserves.priority                   AS priority,
1783
               holds.priority                   AS priority,
1785
               reserves.timestamp                  AS timestamp,
1784
               holds.timestamp                  AS timestamp,
1786
               reserves.itemnumber                 AS itemnumber,
1785
               holds.item_id                    AS item_id,
1787
               reserves.reserve_id                 AS reserve_id,
1786
               holds.id                         AS id,
1788
               reserves.itemtype                   AS itemtype,
1787
               holds.item_type                  AS item_type,
1789
               reserves.non_priority        AS non_priority
1788
               holds.non_priority               AS non_priority
1790
        FROM reserves
1789
        FROM holds
1791
        WHERE reserves.biblionumber = ?
1790
        WHERE holds.biblio_id = ?
1792
          AND (reserves.itemnumber IS NULL OR reserves.itemnumber = ?)
1791
          AND (holds.item_id IS NULL OR holds.item_id = ?)
1793
          AND reserves.reservedate <= DATE_ADD(NOW(),INTERVAL ? DAY)
1792
          AND holds.created_date <= DATE_ADD(NOW(),INTERVAL ? DAY)
1794
          AND suspend = 0
1793
          AND suspended = 0
1794
          AND completed = 0
1795
          ORDER BY priority
1795
          ORDER BY priority
1796
    };
1796
    };
1797
    $sth = $dbh->prepare($query);
1797
    $sth = $dbh->prepare($query);
Lines 1799-1805 sub _Findgroupreserve { Link Here
1799
    @results = ();
1799
    @results = ();
1800
    while ( my $data = $sth->fetchrow_hashref ) {
1800
    while ( my $data = $sth->fetchrow_hashref ) {
1801
        push( @results, $data )
1801
        push( @results, $data )
1802
          unless any{ $data->{borrowernumber} eq $_ } @$ignore_borrowers ;
1802
          unless any{ $data->{patron_id} eq $_ } @$ignore_borrowers ;
1803
    }
1803
    }
1804
    return @results;
1804
    return @results;
1805
}
1805
}
Lines 1835-1841 The following tables are availalbe witin the notice: Link Here
1835
sub _koha_notify_reserve {
1835
sub _koha_notify_reserve {
1836
    my $reserve_id = shift;
1836
    my $reserve_id = shift;
1837
    my $hold = Koha::Holds->find($reserve_id);
1837
    my $hold = Koha::Holds->find($reserve_id);
1838
    my $borrowernumber = $hold->borrowernumber;
1838
    my $borrowernumber = $hold->patron_id;
1839
1839
1840
    my $patron = Koha::Patrons->find( $borrowernumber );
1840
    my $patron = Koha::Patrons->find( $borrowernumber );
1841
1841
Lines 1847-1867 sub _koha_notify_reserve { Link Here
1847
            message_name => 'Hold_Filled'
1847
            message_name => 'Hold_Filled'
1848
    } );
1848
    } );
1849
1849
1850
    my $library = Koha::Libraries->find( $hold->branchcode );
1850
    my $library = Koha::Libraries->find( $hold->pickup_library_id );
1851
    my $admin_email_address = $library->from_email_address;
1851
    my $admin_email_address = $library->from_email_address;
1852
    $library = $library->unblessed;
1852
    $library = $library->unblessed;
1853
1853
1854
    # FIXME: Remove once we have a migration tool for notices
1855
    my $view_query = q{
1856
        SELECT *
1857
        FROM
1858
            reserves
1859
        WHERE
1860
            reserve_id = ?;
1861
    };
1862
    my $reserves_hash = C4::Context->dbh->selectrow_hashref( $view_query, undef, $hold->id );
1863
1854
    my %letter_params = (
1864
    my %letter_params = (
1855
        module => 'reserves',
1865
        module => 'reserves',
1856
        branchcode => $hold->branchcode,
1866
        branchcode => $hold->pickup_library_id,
1857
        lang => $patron->lang,
1867
        lang => $patron->lang,
1858
        tables => {
1868
        tables => {
1859
            'branches'       => $library,
1869
            'branches'       => $library,
1860
            'borrowers'      => $patron->unblessed,
1870
            'borrowers'      => $patron->unblessed,
1861
            'biblio'         => $hold->biblionumber,
1871
            'biblio'         => $hold->biblio_id,
1862
            'biblioitems'    => $hold->biblionumber,
1872
            'biblioitems'    => $hold->biblio_id,
1863
            'reserves'       => $hold->unblessed,
1873
            'reserves'       => $hold->unblessed,
1864
            'items'          => $hold->itemnumber,
1874
            'items'          => $hold->item_id,
1865
        },
1875
        },
1866
    );
1876
    );
1867
1877
Lines 1925-1931 sub _ShiftPriorityByDateAndPriority { Link Here
1925
    my ( $biblio, $resdate, $new_priority ) = @_;
1935
    my ( $biblio, $resdate, $new_priority ) = @_;
1926
1936
1927
    my $dbh = C4::Context->dbh;
1937
    my $dbh = C4::Context->dbh;
1928
    my $query = "SELECT priority FROM reserves WHERE biblionumber = ? AND ( reservedate > ? OR priority > ? ) ORDER BY priority ASC LIMIT 1";
1938
    my $query = "SELECT priority FROM holds WHERE biblio_id = ? AND ( created_date > ? OR priority > ? ) AND completed = 0 ORDER BY priority ASC LIMIT 1";
1929
    my $sth = $dbh->prepare( $query );
1939
    my $sth = $dbh->prepare( $query );
1930
    $sth->execute( $biblio, $resdate, $new_priority );
1940
    $sth->execute( $biblio, $resdate, $new_priority );
1931
    my $min_priority = $sth->fetchrow;
1941
    my $min_priority = $sth->fetchrow;
Lines 1933-1952 sub _ShiftPriorityByDateAndPriority { Link Here
1933
    $new_priority = $min_priority if ( $min_priority );
1943
    $new_priority = $min_priority if ( $min_priority );
1934
1944
1935
    # Shift the priority up by one; works in conjunction with the next SQL statement
1945
    # Shift the priority up by one; works in conjunction with the next SQL statement
1936
    $query = "UPDATE reserves
1946
    $query = "UPDATE holds
1937
              SET priority = priority+1
1947
              SET priority = priority+1
1938
              WHERE biblionumber = ?
1948
              WHERE biblio_id = ?
1939
              AND borrowernumber = ?
1949
              AND patron_id = ?
1940
              AND reservedate = ?
1950
              AND created_date = ?
1941
              AND found IS NULL";
1951
              AND status = 'placed'";
1942
    my $sth_update = $dbh->prepare( $query );
1952
    my $sth_update = $dbh->prepare( $query );
1943
1953
1944
    # Select all reserves for the biblio with priority greater than $new_priority, and order greatest to least
1954
    # Select all reserves for the biblio with priority greater than $new_priority, and order greatest to least
1945
    $query = "SELECT borrowernumber, reservedate FROM reserves WHERE priority >= ? AND biblionumber = ? ORDER BY priority DESC";
1955
    $query = "SELECT patron_id, created_date FROM holds WHERE priority >= ? AND biblio_id = ? ORDER BY priority DESC";
1946
    $sth = $dbh->prepare( $query );
1956
    $sth = $dbh->prepare( $query );
1947
    $sth->execute( $new_priority, $biblio );
1957
    $sth->execute( $new_priority, $biblio );
1948
    while ( my $row = $sth->fetchrow_hashref ) {
1958
    while ( my $row = $sth->fetchrow_hashref ) {
1949
	$sth_update->execute( $biblio, $row->{borrowernumber}, $row->{reservedate} );
1959
    $sth_update->execute( $biblio, $row->{patron_id}, $row->{created_date} );
1950
    }
1960
    }
1951
1961
1952
    return $new_priority;  # so the caller knows what priority they wind up receiving
1962
    return $new_priority;  # so the caller knows what priority they wind up receiving
Lines 1970-1978 sub MoveReserve { Link Here
1970
    my ( $restype, $res, undef ) = CheckReserves( $itemnumber, undef, $lookahead );
1980
    my ( $restype, $res, undef ) = CheckReserves( $itemnumber, undef, $lookahead );
1971
    return unless $res;
1981
    return unless $res;
1972
1982
1973
    my $biblionumber     =  $res->{biblionumber};
1983
    my $biblionumber = $res->{biblio_id};
1974
1984
1975
    if ($res->{borrowernumber} == $borrowernumber) {
1985
    if ($res->{patron_id} == $borrowernumber) {
1976
        ModReserveFill($res);
1986
        ModReserveFill($res);
1977
    }
1987
    }
1978
    else {
1988
    else {
Lines 1981-1988 sub MoveReserve { Link Here
1981
        # Find this item in the reserves
1991
        # Find this item in the reserves
1982
1992
1983
        my $borr_res  = Koha::Holds->search({
1993
        my $borr_res  = Koha::Holds->search({
1984
            borrowernumber => $borrowernumber,
1994
            patron_id => $borrowernumber,
1985
            biblionumber   => $biblionumber,
1995
            biblio_id => $biblionumber,
1986
        },{
1996
        },{
1987
            order_by       => 'priority'
1997
            order_by       => 'priority'
1988
        })->next();
1998
        })->next();
Lines 1996-2002 sub MoveReserve { Link Here
1996
            RevertWaitingStatus({ itemnumber => $itemnumber });
2006
            RevertWaitingStatus({ itemnumber => $itemnumber });
1997
        }
2007
        }
1998
        elsif ( $cancelreserve eq 'cancel' || $cancelreserve ) { # cancel reserves on this item
2008
        elsif ( $cancelreserve eq 'cancel' || $cancelreserve ) { # cancel reserves on this item
1999
            my $hold = Koha::Holds->find( $res->{reserve_id} );
2009
            my $hold = Koha::Holds->find( $res->{id} );
2000
            $hold->cancel;
2010
            $hold->cancel;
2001
        }
2011
        }
2002
    }
2012
    }
Lines 2013-2045 This shifts the holds from C<$from_biblio> to C<$to_biblio> and reorders them by Link Here
2013
sub MergeHolds {
2023
sub MergeHolds {
2014
    my ( $dbh, $to_biblio, $from_biblio ) = @_;
2024
    my ( $dbh, $to_biblio, $from_biblio ) = @_;
2015
    my $sth = $dbh->prepare(
2025
    my $sth = $dbh->prepare(
2016
        "SELECT count(*) as reserve_count FROM reserves WHERE biblionumber = ?"
2026
        "SELECT count(*) as reserve_count FROM holds WHERE biblio_id = ? AND completed = 0"
2017
    );
2027
    );
2018
    $sth->execute($from_biblio);
2028
    $sth->execute($from_biblio);
2019
    if ( my $data = $sth->fetchrow_hashref() ) {
2029
    if ( my $data = $sth->fetchrow_hashref() ) {
2020
2030
2021
        # holds exist on old record, if not we don't need to do anything
2031
        # holds exist on old record, if not we don't need to do anything
2022
        $sth = $dbh->prepare(
2032
        $sth = $dbh->prepare(
2023
            "UPDATE reserves SET biblionumber = ? WHERE biblionumber = ?");
2033
            "UPDATE holds SET biblio_id = ? WHERE biblio_id = ?");
2024
        $sth->execute( $to_biblio, $from_biblio );
2034
        $sth->execute( $to_biblio, $from_biblio );
2025
2035
2026
        # Reorder by date
2036
        # Reorder by date
2027
        # don't reorder those already waiting
2037
        # don't reorder those already waiting
2028
2038
2029
        $sth = $dbh->prepare(
2039
        $sth = $dbh->prepare(
2030
"SELECT * FROM reserves WHERE biblionumber = ? AND (found NOT IN ('W', 'T', 'P') OR found is NULL) ORDER BY reservedate ASC"
2040
            "SELECT id FROM holds WHERE biblio_id = ? AND status = 'placed' AND completed = 0 ORDER BY created_date ASC"
2031
        );
2041
        );
2032
        my $upd_sth = $dbh->prepare(
2042
        my $upd_sth = $dbh->prepare(
2033
"UPDATE reserves SET priority = ? WHERE biblionumber = ? AND borrowernumber = ?
2043
            "UPDATE holds SET priority = ? WHERE id = ? "
2034
        AND reservedate = ? AND (itemnumber = ? or itemnumber is NULL) "
2035
        );
2044
        );
2036
        $sth->execute( $to_biblio );
2045
        $sth->execute( $to_biblio );
2037
        my $priority = 1;
2046
        my $priority = 1;
2038
        while ( my $reserve = $sth->fetchrow_hashref() ) {
2047
        while ( my $reserve = $sth->fetchrow_hashref() ) {
2039
            $upd_sth->execute(
2048
            $upd_sth->execute(
2040
                $priority,                    $to_biblio,
2049
                $priority,
2041
                $reserve->{'borrowernumber'}, $reserve->{'reservedate'},
2050
                $reserve->{'id'}
2042
                $reserve->{'itemnumber'}
2043
            );
2051
            );
2044
            $priority++;
2052
            $priority++;
2045
        }
2053
        }
Lines 2062-2097 sub MergeHolds { Link Here
2062
2070
2063
sub RevertWaitingStatus {
2071
sub RevertWaitingStatus {
2064
    my ( $params ) = @_;
2072
    my ( $params ) = @_;
2065
    my $itemnumber = $params->{'itemnumber'};
2073
    my $item_id = $params->{'itemnumber'};
2066
2067
    return unless ( $itemnumber );
2068
2074
2069
    my $dbh = C4::Context->dbh;
2075
    return unless ( $item_id );
2070
2076
2071
    ## Get the waiting reserve we want to revert
2077
    ## Get the waiting reserve we want to revert
2072
    my $hold = Koha::Holds->search(
2078
    my $hold = Koha::Holds->search(
2073
        {
2079
        {
2074
            itemnumber => $itemnumber,
2080
            item_id => $item_id,
2075
            found => { not => undef },
2081
            status => 'waiting',
2076
        }
2082
        }
2077
    )->next;
2083
    )->next;
2078
2084
2079
    ## Increment the priority of all other non-waiting
2085
    ## Increment the priority of all other non-waiting
2080
    ## reserves for this bib record
2086
    ## reserves for this bib record
2081
    my $holds = Koha::Holds->search({ biblionumber => $hold->biblionumber, priority => { '>' => 0 } })
2087
    my $holds = Koha::Holds->search({ biblio_id => $hold->biblio_id, priority => { '>' => 0 } })
2082
                           ->update({ priority => \'priority + 1' }, { no_triggers => 1 });
2088
                           ->update({ priority => \'priority + 1' }, { no_triggers => 1 });
2083
2089
2084
    ## Fix up the currently waiting reserve
2090
    ## Fix up the currently waiting reserve
2085
    $hold->set(
2091
    $hold->set(
2086
        {
2092
        {
2087
            priority    => 1,
2093
            priority     => 1,
2088
            found       => undef,
2094
            status       => 'placed',
2089
            waitingdate => undef,
2095
            waiting_date => undef,
2090
            itemnumber  => $hold->item_level_hold ? $hold->itemnumber : undef,
2096
            item_id      => $hold->item_level ? $hold->item_id : undef,
2091
        }
2097
        }
2092
    )->store();
2098
    )->store();
2093
2099
2094
    _FixPriority( { biblionumber => $hold->biblionumber } );
2100
    _FixPriority( { biblionumber => $hold->biblio_id } );
2095
2101
2096
    return $hold;
2102
    return $hold;
2097
}
2103
}
Lines 2124-2136 available within the slip: Link Here
2124
2130
2125
sub ReserveSlip {
2131
sub ReserveSlip {
2126
    my ($args) = @_;
2132
    my ($args) = @_;
2127
    my $branchcode     = $args->{branchcode};
2133
    my $branchcode = $args->{branchcode};
2128
    my $reserve_id = $args->{reserve_id};
2134
    my $reserve_id = $args->{reserve_id};
2129
2135
2130
    my $hold = Koha::Holds->find($reserve_id);
2136
    my $hold = Koha::Holds->find($reserve_id);
2131
    return unless $hold;
2137
    return unless $hold;
2132
2138
2133
    my $patron = $hold->borrower;
2139
    my $patron = $hold->patron;
2134
    my $reserve = $hold->unblessed;
2140
    my $reserve = $hold->unblessed;
2135
2141
2136
    return  C4::Letters::GetPreparedLetter (
2142
    return  C4::Letters::GetPreparedLetter (
Lines 2140-2150 sub ReserveSlip { Link Here
2140
        lang => $patron->lang,
2146
        lang => $patron->lang,
2141
        tables => {
2147
        tables => {
2142
            'reserves'    => $reserve,
2148
            'reserves'    => $reserve,
2143
            'branches'    => $reserve->{branchcode},
2149
            'branches'    => $reserve->{pickup_library_id},
2144
            'borrowers'   => $reserve->{borrowernumber},
2150
            'borrowers'   => $reserve->{patron_id},
2145
            'biblio'      => $reserve->{biblionumber},
2151
            'biblio'      => $reserve->{biblio_id},
2146
            'biblioitems' => $reserve->{biblionumber},
2152
            'biblioitems' => $reserve->{biblio_id},
2147
            'items'       => $reserve->{itemnumber},
2153
            'items'       => $reserve->{item_id},
2148
        },
2154
        },
2149
    );
2155
    );
2150
}
2156
}
Lines 2198-2214 sub CalculatePriority { Link Here
2198
    my ( $biblionumber, $resdate ) = @_;
2204
    my ( $biblionumber, $resdate ) = @_;
2199
2205
2200
    my $sql = q{
2206
    my $sql = q{
2201
        SELECT COUNT(*) FROM reserves
2207
        SELECT COUNT(*) FROM holds
2202
        WHERE biblionumber = ?
2208
        WHERE biblio_id = ?
2203
        AND   priority > 0
2209
        AND   priority > 0
2204
        AND   (found IS NULL OR found = '')
2210
        AND   status='placed'
2205
    };
2211
    };
2206
    #skip found==W or found==T or found==P (waiting, transit or processing holds)
2212
    #skip status==waiting or status==in_transit or status==processing
2207
    if( $resdate ) {
2213
    if( $resdate ) {
2208
        $sql.= ' AND ( reservedate <= ? )';
2214
        $sql.= ' AND ( created_date <= ? )';
2209
    }
2215
    }
2210
    else {
2216
    else {
2211
        $sql.= ' AND ( reservedate < NOW() )';
2217
        $sql.= ' AND ( created_date < NOW() )';
2212
    }
2218
    }
2213
    my $dbh = C4::Context->dbh();
2219
    my $dbh = C4::Context->dbh();
2214
    my @row = $dbh->selectrow_array(
2220
    my @row = $dbh->selectrow_array(
Lines 2222-2247 sub CalculatePriority { Link Here
2222
2228
2223
=head2 IsItemOnHoldAndFound
2229
=head2 IsItemOnHoldAndFound
2224
2230
2225
    my $bool = IsItemFoundHold( $itemnumber );
2231
    my $bool = IsItemFoundHold( $item_id );
2226
2232
2227
    Returns true if the item is currently on hold
2233
    Returns true if the item is currently on hold
2228
    and that hold has a non-null found status ( W, T, etc. )
2234
    and that hold has a status of in_transit, processing
2235
    or waiting.
2229
2236
2230
=cut
2237
=cut
2231
2238
2232
sub IsItemOnHoldAndFound {
2239
sub IsItemOnHoldAndFound {
2233
    my ($itemnumber) = @_;
2240
    my ($item_id) = @_;
2234
2235
    my $rs = Koha::Database->new()->schema()->resultset('Reserve');
2236
2241
2237
    my $found = $rs->count(
2242
    return Koha::Holds->search(
2238
        {
2243
        {
2239
            itemnumber => $itemnumber,
2244
            item_id   => $item_id,
2240
            found      => { '!=' => undef }
2245
            status    => [ 'in_transit', 'processing', 'waiting' ],
2246
            completed => 0
2241
        }
2247
        }
2242
    );
2248
    )->count;
2243
2244
    return $found;
2245
}
2249
}
2246
2250
2247
=head2 GetMaxPatronHoldsForRecord
2251
=head2 GetMaxPatronHoldsForRecord
(-)a/C4/SIP/ILS/Patron.pm (-2 / +2 lines)
Lines 520-530 sub _get_outstanding_holds { Link Here
520
    my $borrowernumber = shift;
520
    my $borrowernumber = shift;
521
521
522
    my $patron = Koha::Patrons->find( $borrowernumber );
522
    my $patron = Koha::Patrons->find( $borrowernumber );
523
    my $holds = $patron->holds->search( { -or => [ { found => undef }, { found => { '!=' => 'W' } } ] } );
523
    my $holds = $patron->holds->search( { completed => 0, status => {'!=' => 'waiting'} } );
524
    my @holds;
524
    my @holds;
525
    while ( my $hold = $holds->next ) {
525
    while ( my $hold = $holds->next ) {
526
        my $item;
526
        my $item;
527
        if ($hold->itemnumber) {
527
        if ($hold->item_id) {
528
            $item = $hold->item;
528
            $item = $hold->item;
529
        }
529
        }
530
        else {
530
        else {
(-)a/C4/SIP/ILS/Transaction/Hold.pm (-1 / +1 lines)
Lines 86-92 sub drop_hold { Link Here
86
    }
86
    }
87
87
88
    my $item = Koha::Items->find({ barcode => $self->{item}->id });
88
    my $item = Koha::Items->find({ barcode => $self->{item}->id });
89
    my $holds = $item->holds->search({ borrowernumber => $patron->borrowernumber });
89
    my $holds = $item->holds->search({ patron_id => $patron->borrowernumber });
90
90
91
    return $self unless $holds->count;
91
    return $self unless $holds->count;
92
92
(-)a/C4/XSLT.pm (-1 / +1 lines)
Lines 316-322 sub buildKohaItemsNamespace { Link Here
316
        $items_rs = Koha::Items->new;
316
        $items_rs = Koha::Items->new;
317
    }
317
    }
318
318
319
    my $items = $items_rs->search( $query, { prefetch => [ 'branchtransfers', 'reserves' ] } );
319
    my $items = $items_rs->search( $query, { prefetch => [ 'branchtransfers', 'holds' ] } );
320
320
321
    my $shelflocations =
321
    my $shelflocations =
322
      { map { $_->{authorised_value} => $_->{opac_description} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => "", kohafield => 'items.location' } ) };
322
      { map { $_->{authorised_value} => $_->{opac_description} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => "", kohafield => 'items.location' } ) };
(-)a/Koha/Acquisition/Order.pm (-1 / +1 lines)
Lines 299-305 sub current_item_level_holds { Link Here
299
299
300
    return $biblio->current_holds->search(
300
    return $biblio->current_holds->search(
301
        {
301
        {
302
            itemnumber => {
302
            item_id => {
303
                -in => \@item_numbers
303
                -in => \@item_numbers
304
            }
304
            }
305
        }
305
        }
(-)a/Koha/Biblio.pm (-4 / +5 lines)
Lines 446-452 return the current holds placed on this record Link Here
446
sub holds {
446
sub holds {
447
    my ( $self, $params, $attributes ) = @_;
447
    my ( $self, $params, $attributes ) = @_;
448
    $attributes->{order_by} = 'priority' unless exists $attributes->{order_by};
448
    $attributes->{order_by} = 'priority' unless exists $attributes->{order_by};
449
    my $hold_rs = $self->_result->reserves->search( $params, $attributes );
449
    $params->{completed} = 0 unless exists $params->{completed};
450
    my $hold_rs = $self->_result->holds->search( $params, $attributes );
450
    return Koha::Holds->_new_from_dbic($hold_rs);
451
    return Koha::Holds->_new_from_dbic($hold_rs);
451
}
452
}
452
453
Lines 463-469 sub current_holds { Link Here
463
    my ($self) = @_;
464
    my ($self) = @_;
464
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
465
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
465
    return $self->holds(
466
    return $self->holds(
466
        { reservedate => { '<=' => $dtf->format_date(dt_from_string) } } );
467
        { completed => 0, created_date => { '<=' => $dtf->format_date(dt_from_string) } } );
467
}
468
}
468
469
469
=head3 biblioitem
470
=head3 biblioitem
Lines 524-531 Tells if this bibliographic record has items waiting or in transit. Link Here
524
sub has_items_waiting_or_intransit {
525
sub has_items_waiting_or_intransit {
525
    my ( $self ) = @_;
526
    my ( $self ) = @_;
526
527
527
    if ( Koha::Holds->search({ biblionumber => $self->id,
528
    if ( Koha::Holds->search({ biblio_id => $self->id,
528
                               found => ['W', 'T'] })->count ) {
529
                               status => ['waiting', 'in_transit'] })->count ) {
529
        return 1;
530
        return 1;
530
    }
531
    }
531
532
(-)a/Koha/Hold.pm (-14 / +17 lines)
Lines 369-375 sub is_in_processing { Link Here
369
369
370
Returns true if hold is a cancelable hold
370
Returns true if hold is a cancelable hold
371
371
372
Holds may be only canceled if they are not found.
372
Holds may be only canceled if they are not found or completed.
373
373
374
This is used from the OPAC.
374
This is used from the OPAC.
375
375
Lines 378-385 This is used from the OPAC. Link Here
378
sub is_cancelable_from_opac {
378
sub is_cancelable_from_opac {
379
    my ($self) = @_;
379
    my ($self) = @_;
380
380
381
    return 1 unless $self->is_found();
381
    if ( $self->completed or $self->is_found ) {
382
    return 0; # if ->is_in_transit or if ->is_waiting or ->is_in_processing
382
        return 0;
383
    }
384
385
    return 1;
383
}
386
}
384
387
385
=head3 is_at_destination
388
=head3 is_at_destination
Lines 591-601 sub store { Link Here
591
    if ( !$self->in_storage ) {
594
    if ( !$self->in_storage ) {
592
        if (
595
        if (
593
            C4::Context->preference('DefaultHoldExpirationdate')
596
            C4::Context->preference('DefaultHoldExpirationdate')
594
            and ( not defined $self->expirationdate
597
            and ( not defined $self->expiration_date
595
                or $self->expirationdate eq '' )
598
                or $self->expiration_date eq '' )
596
          )
599
          )
597
        {
600
        {
598
            $self->_set_default_expirationdate;
601
            $self->_set_default_expiration_date;
599
        }
602
        }
600
    }
603
    }
601
    else {
604
    else {
Lines 603-617 sub store { Link Here
603
        my %updated_columns = $self->_result->get_dirty_columns;
606
        my %updated_columns = $self->_result->get_dirty_columns;
604
        return $self->SUPER::store unless %updated_columns;
607
        return $self->SUPER::store unless %updated_columns;
605
608
606
        if ( exists $updated_columns{reservedate} ) {
609
        if ( exists $updated_columns{created_date} ) {
607
            if (
610
            if (
608
                C4::Context->preference('DefaultHoldExpirationdate')
611
                C4::Context->preference('DefaultHoldExpirationdate')
609
                and ( not exists $updated_columns{expirationdate}
612
                and ( not exists $updated_columns{expiration_date}
610
                    or exists $updated_columns{expirationdate}
613
                    or exists $updated_columns{expiration_date}
611
                    and $updated_columns{expirationdate} eq '' )
614
                    and $updated_columns{expiration_date} eq '' )
612
              )
615
              )
613
            {
616
            {
614
                $self->_set_default_expirationdate;
617
                $self->_set_default_expiration_date;
615
            }
618
            }
616
        }
619
        }
617
    }
620
    }
Lines 619-633 sub store { Link Here
619
    $self = $self->SUPER::store;
622
    $self = $self->SUPER::store;
620
}
623
}
621
624
622
sub _set_default_expirationdate {
625
sub _set_default_expiration_date {
623
    my $self = shift;
626
    my $self = shift;
624
627
625
    my $period = C4::Context->preference('DefaultHoldExpirationdatePeriod') || 0;
628
    my $period = C4::Context->preference('DefaultHoldExpirationdatePeriod') || 0;
626
    my $timeunit =
629
    my $timeunit =
627
      C4::Context->preference('DefaultHoldExpirationdateUnitOfTime') || 'days';
630
      C4::Context->preference('DefaultHoldExpirationdateUnitOfTime') || 'days';
628
631
629
    $self->expirationdate(
632
    $self->expiration_date(
630
        dt_from_string( $self->reservedate )->add( $timeunit => $period ) );
633
        dt_from_string( $self->created_date )->add( $timeunit => $period ) );
631
}
634
}
632
635
633
=head3 to_api_mapping
636
=head3 to_api_mapping
(-)a/Koha/Holds.pm (-4 / +4 lines)
Lines 122-128 Items that are not: Link Here
122
sub get_items_that_can_fill {
122
sub get_items_that_can_fill {
123
    my ( $self ) = @_;
123
    my ( $self ) = @_;
124
124
125
    my @biblionumbers = $self->get_column('biblionumber');
125
    my @biblionumbers = $self->get_column('biblio_id');
126
126
127
    my @branchtransfers = map { $_->itemnumber }
127
    my @branchtransfers = map { $_->itemnumber }
128
      Koha::Item::Transfers->search(
128
      Koha::Item::Transfers->search(
Lines 132-142 sub get_items_that_can_fill { Link Here
132
              collapse => 1,
132
              collapse => 1,
133
          }
133
          }
134
      );
134
      );
135
    my @waiting_holds = map { $_->itemnumber }
135
    my @waiting_holds = map { $_->item_id }
136
      Koha::Holds->search(
136
      Koha::Holds->search(
137
          { 'found' => 'W' },
137
          { status => 'waiting' },
138
          {
138
          {
139
              columns => ['itemnumber'],
139
              columns => ['item_id'],
140
              collapse => 1,
140
              collapse => 1,
141
          }
141
          }
142
      );
142
      );
(-)a/Koha/Item.pm (-8 / +10 lines)
Lines 283-289 sub safe_to_delete { Link Here
283
283
284
    # check it doesn't have a waiting reserve
284
    # check it doesn't have a waiting reserve
285
    return "book_reserved"
285
    return "book_reserved"
286
      if $self->holds->search( { found => [ 'W', 'T' ] } )->count;
286
      if $self->holds->search( { status => [ 'waiting', 'in_transit' ], completed => 0 } )->count;
287
287
288
    return "linked_analytics"
288
    return "linked_analytics"
289
      if C4::Items::GetAnalyticsCount( $self->itemnumber ) > 0;
289
      if C4::Items::GetAnalyticsCount( $self->itemnumber ) > 0;
Lines 292-298 sub safe_to_delete { Link Here
292
      if $self->biblio->items->count == 1
292
      if $self->biblio->items->count == 1
293
      && $self->biblio->holds->search(
293
      && $self->biblio->holds->search(
294
          {
294
          {
295
              itemnumber => undef,
295
              item_id => undef,
296
          }
296
          }
297
        )->count;
297
        )->count;
298
298
Lines 407-413 Return holds attached to an item, optionally accept a hashref of params to pass Link Here
407
407
408
sub holds {
408
sub holds {
409
    my ( $self,$params ) = @_;
409
    my ( $self,$params ) = @_;
410
    my $holds_rs = $self->_result->reserves->search($params);
410
    $params->{completed} = 0 unless exists $params->{completed};
411
    my $holds_rs = $self->_result->holds->search($params);
411
    return Koha::Holds->_new_from_dbic( $holds_rs );
412
    return Koha::Holds->_new_from_dbic( $holds_rs );
412
}
413
}
413
414
Lines 791-804 sub current_holds { Link Here
791
    my $attributes = { order_by => 'priority' };
792
    my $attributes = { order_by => 'priority' };
792
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
793
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
793
    my $params = {
794
    my $params = {
794
        itemnumber => $self->itemnumber,
795
        item_id => $self->itemnumber,
795
        suspend => 0,
796
        suspended => 0,
796
        -or => [
797
        -or => [
797
            reservedate => { '<=' => $dtf->format_date(dt_from_string) },
798
            created_date => { '<=' => $dtf->format_date(dt_from_string) },
798
            waitingdate => { '!=' => undef },
799
            waiting_date => { '!=' => undef },
799
        ],
800
        ],
801
        completed => 0
800
    };
802
    };
801
    my $hold_rs = $self->_result->reserves->search( $params, $attributes );
803
    my $hold_rs = $self->_result->holds->search( $params, $attributes );
802
    return Koha::Holds->_new_from_dbic($hold_rs);
804
    return Koha::Holds->_new_from_dbic($hold_rs);
803
}
805
}
804
806
(-)a/Koha/Patron.pm (-6 / +6 lines)
Lines 72-80 our $RESULTSET_PATRON_ID_MAPPING = { Link Here
72
    Message              => 'borrowernumber',
72
    Message              => 'borrowernumber',
73
    MessageQueue         => 'borrowernumber',
73
    MessageQueue         => 'borrowernumber',
74
    OldIssue             => 'borrowernumber',
74
    OldIssue             => 'borrowernumber',
75
    OldReserve           => 'borrowernumber',
76
    Rating               => 'borrowernumber',
75
    Rating               => 'borrowernumber',
77
    Reserve              => 'borrowernumber',
76
    Hold                 => 'patron_id',
78
    Review               => 'borrowernumber',
77
    Review               => 'borrowernumber',
79
    SearchHistory        => 'userid',
78
    SearchHistory        => 'userid',
80
    Statistic            => 'borrowernumber',
79
    Statistic            => 'borrowernumber',
Lines 1206-1213 Return all the holds placed by this patron Link Here
1206
=cut
1205
=cut
1207
1206
1208
sub holds {
1207
sub holds {
1209
    my ($self) = @_;
1208
    my ($self, $params) = @_;
1210
    my $holds_rs = $self->_result->reserves->search( {}, { order_by => 'reservedate' } );
1209
    $params->{completed} = 0 unless exists $params->{completed};
1210
    my $holds_rs = $self->_result->holds->search( $params, { order_by => 'created_date' } );
1211
    return Koha::Holds->_new_from_dbic($holds_rs);
1211
    return Koha::Holds->_new_from_dbic($holds_rs);
1212
}
1212
}
1213
1213
Lines 1221-1228 Return all the historical holds for this patron Link Here
1221
1221
1222
sub old_holds {
1222
sub old_holds {
1223
    my ($self) = @_;
1223
    my ($self) = @_;
1224
    my $old_holds_rs = $self->_result->old_reserves->search( {}, { order_by => 'reservedate' } );
1224
    my $old_holds_rs = $self->_result->holds->search( { completed => 1 }, { order_by => 'created_date' } );
1225
    return Koha::Old::Holds->_new_from_dbic($old_holds_rs);
1225
    return Koha::Holds->_new_from_dbic($old_holds_rs);
1226
}
1226
}
1227
1227
1228
=head3 return_claims
1228
=head3 return_claims
(-)a/Koha/REST/V1/Auth.pm (-11 / +9 lines)
Lines 318-327 sub validate_query_parameters { Link Here
318
Allows access to object for its owner.
318
Allows access to object for its owner.
319
319
320
There are endpoints that should allow access for the object owner even if they
320
There are endpoints that should allow access for the object owner even if they
321
do not have the required permission, e.g. access an own reserve. This can be
321
do not have the required permission, e.g. access an own hold. This can be
322
achieved by defining the operation as follows:
322
achieved by defining the operation as follows:
323
323
324
"/holds/{reserve_id}": {
324
"/holds/{hold_id}": {
325
    "get": {
325
    "get": {
326
        ...,
326
        ...,
327
        "x-koha-authorization": {
327
        "x-koha-authorization": {
Lines 385-391 sub check_object_ownership { Link Here
385
        borrowernumber  => \&_object_ownership_by_patron_id,
385
        borrowernumber  => \&_object_ownership_by_patron_id,
386
        patron_id       => \&_object_ownership_by_patron_id,
386
        patron_id       => \&_object_ownership_by_patron_id,
387
        checkout_id     => \&_object_ownership_by_checkout_id,
387
        checkout_id     => \&_object_ownership_by_checkout_id,
388
        reserve_id      => \&_object_ownership_by_reserve_id,
388
        hold_id      => \&_object_ownership_by_hold_id,
389
    };
389
    };
390
390
391
    foreach my $param ( keys %{ $parameters } ) {
391
    foreach my $param ( keys %{ $parameters } ) {
Lines 449-468 sub _object_ownership_by_checkout_id { Link Here
449
            && $user->borrowernumber == $issue->borrowernumber;
449
            && $user->borrowernumber == $issue->borrowernumber;
450
}
450
}
451
451
452
=head3 _object_ownership_by_reserve_id
452
=head3 _object_ownership_by_hold_id
453
453
454
Finds a Koha::Hold-object by C<$reserve_id> and checks if it
454
Finds a Koha::Hold-object by C<$hold_id> and checks if it
455
belongs to C<$user>.
455
belongs to C<$user>.
456
456
457
TODO: Also compare against old_reserves
458
459
=cut
457
=cut
460
458
461
sub _object_ownership_by_reserve_id {
459
sub _object_ownership_by_hold_id {
462
    my ($c, $user, $reserve_id) = @_;
460
    my ($c, $user, $hold_id) = @_;
463
461
464
    my $reserve = Koha::Holds->find($reserve_id);
462
    my $hold = Koha::Holds->find($hold_id);
465
    return $reserve && $user->borrowernumber == $reserve->borrowernumber;
463
    return $hold && $user->borrowernumber == $hold->borrowernumber;
466
}
464
}
467
465
468
=head3 _basic_auth
466
=head3 _basic_auth
(-)a/Koha/REST/V1/Holds.pm (-15 / +15 lines)
Lines 46-52 sub list { Link Here
46
    my $c = shift->openapi->valid_input or return;
46
    my $c = shift->openapi->valid_input or return;
47
47
48
    return try {
48
    return try {
49
        my $holds_set = Koha::Holds->new;
49
        my $holds_set = Koha::Holds->search({completed=>0});
50
        my $holds     = $c->objects->search( $holds_set );
50
        my $holds     = $c->objects->search( $holds_set );
51
        return $c->render( status => 200, openapi => $holds );
51
        return $c->render( status => 200, openapi => $holds );
52
    }
52
    }
Lines 77-89 sub add { Link Here
77
        my $item_type         = $body->{item_type};
77
        my $item_type         = $body->{item_type};
78
        my $expiration_date   = $body->{expiration_date};
78
        my $expiration_date   = $body->{expiration_date};
79
        my $notes             = $body->{notes};
79
        my $notes             = $body->{notes};
80
        my $hold_date         = $body->{hold_date};
80
        my $created_date      = $body->{created_date};
81
        my $non_priority      = $body->{non_priority};
81
        my $non_priority      = $body->{non_priority};
82
82
83
        my $overrides = $c->stash('koha.overrides');
83
        my $overrides = $c->stash('koha.overrides');
84
        my $can_override = $overrides->{any} && C4::Context->preference('AllowHoldPolicyOverride');
84
        my $can_override = $overrides->{any} && C4::Context->preference('AllowHoldPolicyOverride');
85
85
86
        if(!C4::Context->preference( 'AllowHoldDateInFuture' ) && $hold_date) {
86
        if(!C4::Context->preference( 'AllowHoldDateInFuture' ) && $created_date) {
87
            return $c->render(
87
            return $c->render(
88
                status  => 400,
88
                status  => 400,
89
                openapi => { error => "Hold date in future not allowed" }
89
                openapi => { error => "Hold date in future not allowed" }
Lines 195-201 sub add { Link Here
195
                borrowernumber   => $patron_id,
195
                borrowernumber   => $patron_id,
196
                biblionumber     => $biblio_id,
196
                biblionumber     => $biblio_id,
197
                priority         => $priority,
197
                priority         => $priority,
198
                reservation_date => $hold_date,
198
                reservation_date => $created_date,
199
                expiration_date  => $expiration_date,
199
                expiration_date  => $expiration_date,
200
                notes            => $notes,
200
                notes            => $notes,
201
                title            => $biblio->title,
201
                title            => $biblio->title,
Lines 249-255 sub edit { Link Here
249
249
250
    return try {
250
    return try {
251
        my $hold_id = $c->validation->param('hold_id');
251
        my $hold_id = $c->validation->param('hold_id');
252
        my $hold = Koha::Holds->find( $hold_id );
252
        my $hold    = Koha::Holds->search({id=>$hold_id, completed=>0})->next;
253
253
254
        unless ($hold) {
254
        unless ($hold) {
255
            return $c->render(
255
            return $c->render(
Lines 278-294 sub edit { Link Here
278
            );
278
            );
279
        }
279
        }
280
280
281
        $pickup_library_id //= $hold->branchcode;
281
        $pickup_library_id //= $hold->pickup_library_id;
282
        my $priority         = $body->{priority} // $hold->priority;
282
        my $priority         = $body->{priority} // $hold->priority;
283
        # suspended_until can also be set to undef
283
        # suspended_until can also be set to undef
284
        my $suspended_until   = exists $body->{suspended_until} ? $body->{suspended_until} : $hold->suspend_until;
284
        my $suspended_until   = exists $body->{suspended_until_date} ? $body->{suspended_until_date} : $hold->suspended_until_date;
285
285
286
        my $params = {
286
        my $params = {
287
            reserve_id    => $hold_id,
287
            reserve_id    => $hold_id,
288
            branchcode    => $pickup_library_id,
288
            branchcode    => $pickup_library_id,
289
            rank          => $priority,
289
            rank          => $priority,
290
            suspend_until => $suspended_until ? output_pref(dt_from_string($suspended_until, 'rfc3339')) : '',
290
            suspend_until => $suspended_until ? output_pref(dt_from_string($suspended_until, 'rfc3339')) : '',
291
            itemnumber    => $hold->itemnumber
291
            itemnumber    => $hold->item_id
292
        };
292
        };
293
293
294
        C4::Reserves::ModReserve($params);
294
        C4::Reserves::ModReserve($params);
Lines 314-320 sub delete { Link Here
314
    my $c = shift->openapi->valid_input or return;
314
    my $c = shift->openapi->valid_input or return;
315
315
316
    my $hold_id = $c->validation->param('hold_id');
316
    my $hold_id = $c->validation->param('hold_id');
317
    my $hold    = Koha::Holds->find($hold_id);
317
    my $hold    = Koha::Holds->search({id=>$hold_id, completed=>0})->next;
318
318
319
    unless ($hold) {
319
    unless ($hold) {
320
        return $c->render( status => 404, openapi => { error => "Hold not found." } );
320
        return $c->render( status => 404, openapi => { error => "Hold not found." } );
Lines 343-349 sub suspend { Link Here
343
    my $c = shift->openapi->valid_input or return;
343
    my $c = shift->openapi->valid_input or return;
344
344
345
    my $hold_id  = $c->validation->param('hold_id');
345
    my $hold_id  = $c->validation->param('hold_id');
346
    my $hold     = Koha::Holds->find($hold_id);
346
    my $hold     = Koha::Holds->search({id=>$hold_id, completed=>0})->next;
347
    my $body     = $c->req->json;
347
    my $body     = $c->req->json;
348
    my $end_date = ($body) ? $body->{end_date} : undef;
348
    my $end_date = ($body) ? $body->{end_date} : undef;
349
349
Lines 357-365 sub suspend { Link Here
357
        $hold->discard_changes;
357
        $hold->discard_changes;
358
        $c->res->headers->location( $c->req->url->to_string );
358
        $c->res->headers->location( $c->req->url->to_string );
359
        my $suspend_end_date;
359
        my $suspend_end_date;
360
        if ($hold->suspend_until) {
360
        if ($hold->suspended_until_date) {
361
            $suspend_end_date = output_pref({
361
            $suspend_end_date = output_pref({
362
                dt         => dt_from_string( $hold->suspend_until ),
362
                dt         => dt_from_string( $hold->suspended_until_date ),
363
                dateformat => 'rfc3339',
363
                dateformat => 'rfc3339',
364
                dateonly   => 1
364
                dateonly   => 1
365
                }
365
                }
Lines 391-397 sub resume { Link Here
391
    my $c = shift->openapi->valid_input or return;
391
    my $c = shift->openapi->valid_input or return;
392
392
393
    my $hold_id = $c->validation->param('hold_id');
393
    my $hold_id = $c->validation->param('hold_id');
394
    my $hold    = Koha::Holds->find($hold_id);
394
    my $hold    = Koha::Holds->search({id=>$hold_id, completed=>0})->next;
395
    my $body    = $c->req->json;
395
    my $body    = $c->req->json;
396
396
397
    unless ($hold) {
397
    unless ($hold) {
Lines 417-423 sub update_priority { Link Here
417
    my $c = shift->openapi->valid_input or return;
417
    my $c = shift->openapi->valid_input or return;
418
418
419
    my $hold_id = $c->validation->param('hold_id');
419
    my $hold_id = $c->validation->param('hold_id');
420
    my $hold = Koha::Holds->find($hold_id);
420
    my $hold = Koha::Holds->search({id=>$hold_id, completed=>0})->next;
421
421
422
    unless ($hold) {
422
    unless ($hold) {
423
        return $c->render(
423
        return $c->render(
Lines 465-471 sub pickup_locations { Link Here
465
    return try {
465
    return try {
466
        my $ps_set;
466
        my $ps_set;
467
467
468
        if ( $hold->itemnumber ) {
468
        if ( $hold->item_id ) {
469
            $ps_set = $hold->item->pickup_locations( { patron => $hold->patron } );
469
            $ps_set = $hold->item->pickup_locations( { patron => $hold->patron } );
470
        }
470
        }
471
        else {
471
        else {
(-)a/Koha/Template/Plugin/Biblio.pm (-4 / +7 lines)
Lines 29-39 use Koha::ArticleRequests; Link Here
29
use Koha::ArticleRequest::Status;
29
use Koha::ArticleRequest::Status;
30
30
31
sub HoldsCount {
31
sub HoldsCount {
32
    my ( $self, $biblionumber ) = @_;
32
    my ( $self, $biblio_id ) = @_;
33
34
    my $holds = Koha::Holds->search( { biblionumber => $biblionumber } );
35
33
36
    return $holds->count();
34
    return Koha::Holds->search(
35
        {
36
            biblio_id => $biblio_id,
37
            completed => 0
38
        }
39
    )->count;
37
}
40
}
38
41
39
sub ArticleRequestsActiveCount {
42
sub ArticleRequestsActiveCount {
(-)a/api/v1/swagger/definitions/hold.json (-3 / +11 lines)
Lines 9-15 Link Here
9
      "type": "integer",
9
      "type": "integer",
10
      "description": "Internal patron identifier"
10
      "description": "Internal patron identifier"
11
    },
11
    },
12
    "hold_date": {
12
    "created_date": {
13
      "type": ["string", "null"],
13
      "type": ["string", "null"],
14
      "format": "date",
14
      "format": "date",
15
      "description": "The date the hold was placed"
15
      "description": "The date the hold was placed"
Lines 45-51 Link Here
45
    },
45
    },
46
    "status": {
46
    "status": {
47
      "type": ["string", "null"],
47
      "type": ["string", "null"],
48
      "description": "A one letter code defining what the status of the hold is after it has been confirmed"
48
      "description": "the status the hold is ('placed', 'fulfilled', 'waiting', 'in_transit', 'cancelled')"
49
    },
49
    },
50
    "timestamp": {
50
    "timestamp": {
51
      "type": "string",
51
      "type": "string",
Lines 74-80 Link Here
74
      "type": "boolean",
74
      "type": "boolean",
75
      "description": "Controls if the hold is suspended"
75
      "description": "Controls if the hold is suspended"
76
    },
76
    },
77
    "suspended_until": {
77
    "suspended_until_date": {
78
      "type": ["string", "null"],
78
      "type": ["string", "null"],
79
      "format": "date-time",
79
      "format": "date-time",
80
      "description": "Date until which the hold has been suspended"
80
      "description": "Date until which the hold has been suspended"
Lines 90-95 Link Here
90
    "item_level": {
90
    "item_level": {
91
      "type": "boolean",
91
      "type": "boolean",
92
      "description": "If the hold is placed at item level"
92
      "description": "If the hold is placed at item level"
93
    },
94
    "completed": {
95
      "type": "boolean",
96
      "description": "If it has been completed (i.e. either 'fulfilled' or 'cancelled')"
97
    },
98
    "completed_date": {
99
      "type": ["string", "null"],
100
      "description": "the date this hold was completed (fulfilled or cancelled)"
93
    }
101
    }
94
  },
102
  },
95
  "additionalProperties": false
103
  "additionalProperties": false
(-)a/api/v1/swagger/paths/holds.json (-4 / +8 lines)
Lines 99-105 Link Here
99
          "type": "boolean"
99
          "type": "boolean"
100
        },
100
        },
101
        {
101
        {
102
          "name": "suspended_until",
102
          "name": "suspended_until_date",
103
          "in": "query",
103
          "in": "query",
104
          "description": "Suspended until",
104
          "description": "Suspended until",
105
          "type": "string"
105
          "type": "string"
Lines 228-234 Link Here
228
              "non_priority": {
228
              "non_priority": {
229
                "description": "Set this hold as non priority",
229
                "description": "Set this hold as non priority",
230
                "type": [ "boolean", "null" ]
230
                "type": [ "boolean", "null" ]
231
              }
231
              },
232
              "created_date": {
233
                "type": "string",
234
                "format": "date",
235
                "description": "The date the hold was placed"              }
232
            },
236
            },
233
            "required": [ "patron_id", "pickup_library_id" ],
237
            "required": [ "patron_id", "pickup_library_id" ],
234
            "additionalProperties": false
238
            "additionalProperties": false
Lines 320-326 Link Here
320
                "description": "Internal library identifier for the pickup library",
324
                "description": "Internal library identifier for the pickup library",
321
                "type": "string"
325
                "type": "string"
322
              },
326
              },
323
              "suspended_until": {
327
              "suspended_until_date": {
324
                "description": "Date until which the hold has been suspended",
328
                "description": "Date until which the hold has been suspended",
325
                "type": "string",
329
                "type": "string",
326
                "format": "date-time"
330
                "format": "date-time"
Lines 407-413 Link Here
407
                "description": "Internal library identifier for the pickup library",
411
                "description": "Internal library identifier for the pickup library",
408
                "type": "string"
412
                "type": "string"
409
              },
413
              },
410
              "suspended_until": {
414
              "suspended_until_date": {
411
                "description": "Date until which the hold has been suspended",
415
                "description": "Date until which the hold has been suspended",
412
                "type": "string",
416
                "type": "string",
413
                "format": "date-time"
417
                "format": "date-time"
(-)a/circ/circulation.pl (-1 / +1 lines)
Lines 454-460 if (@$barcodes) { Link Here
454
# BUILD HTML
454
# BUILD HTML
455
# show all reserves of this borrower, and the position of the reservation ....
455
# show all reserves of this borrower, and the position of the reservation ....
456
if ($patron) {
456
if ($patron) {
457
    my $holds = Koha::Holds->search( { borrowernumber => $borrowernumber } ); # FIXME must be Koha::Patron->holds
457
    my $holds = Koha::Holds->search( { patron_id => $borrowernumber } ); # FIXME must be Koha::Patron->holds
458
    my $waiting_holds = $holds->waiting;
458
    my $waiting_holds = $holds->waiting;
459
    $template->param(
459
    $template->param(
460
        holds_count  => $holds->count(),
460
        holds_count  => $holds->count(),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/holdshistory.tt (-16 / +16 lines)
Lines 74-114 Link Here
74
          <td>[% INCLUDE 'biblio-title.inc' biblio=hold.biblio link = 1 %]</td>
74
          <td>[% INCLUDE 'biblio-title.inc' biblio=hold.biblio link = 1 %]</td>
75
          <td>[% hold.biblio.author | html %]</td>
75
          <td>[% hold.biblio.author | html %]</td>
76
          <td>[% hold.item.barcode | html %]</td>
76
          <td>[% hold.item.barcode | html %]</td>
77
          <td>[% Branches.GetName( hold.branchcode ) | html %]</td>
77
          <td>[% Branches.GetName( hold.pickup_library_id ) | html %]</td>
78
          <td data-order="[% hold.reservedate | html %]">[% hold.reservedate | $KohaDates %]</td>
78
          <td data-order="[% hold.created_date | html %]">[% hold.created_date | $KohaDates %]</td>
79
          <td data-order="[% hold.expirationdate | html %]">
79
          <td data-order="[% hold.expiration_date | html %]">
80
                [% hold.expirationdate | $KohaDates %]
80
                [% hold.expiration_date | $KohaDates %]
81
          </td>
81
          </td>
82
          <td data-order="[% hold.waitingdate | html %]">
82
          <td data-order="[% hold.waiting_date | html %]">
83
                [% hold.waitingdate | $KohaDates %]
83
                [% hold.waiting_date | $KohaDates %]
84
          </td>
84
          </td>
85
          <td data-order="[% hold.cancellationdate | html %]">
85
          <td data-order="[% hold.completed_date | html %]">
86
                [% hold.cancellationdate | $KohaDates %]
86
                [% hold.completed_date | $KohaDates %]
87
          </td>
87
          </td>
88
          [% IF show_itemtype_column %]
88
          [% IF show_itemtype_column %]
89
            <td>
89
            <td>
90
              [% IF hold.itemtype %]
90
              [% IF hold.item_type %]
91
                  [% ItemTypes.GetDescription( hold.itemtype ) | html %]
91
                  [% ItemTypes.GetDescription( hold.item_type ) | html %]
92
              [% ELSE %]
92
              [% ELSE %]
93
                  <span>Any item type</span>
93
                  <span>Any item type</span>
94
              [% END %]
94
              [% END %]
95
            </td>
95
            </td>
96
          [% END %]
96
          [% END %]
97
          <td>
97
          <td>
98
          [% IF hold.found == 'F' %]
98
          [% IF    hold.status == 'fulfilled' %]
99
              Fulfilled
99
              Fulfilled
100
          [% ELSIF hold.cancellationdate %]
100
          [% ELSIF hold.status == 'cancelled' %]
101
              Cancelled
101
              Cancelled
102
                [% IF hold.cancellation_reason %]
102
                [% IF hold.cancellation_reason %]
103
                    ([% AuthorisedValues.GetByCode('HOLD_CANCELLATION', hold.cancellation_reason) | html %])
103
                    ([% AuthorisedValues.GetByCode('HOLD_CANCELLATION', hold.cancellation_reason) | html %])
104
                [% END %]
104
                [% END %]
105
          [% ELSIF hold.found == 'W' %]
105
          [% ELSIF hold.status == 'waiting' %]
106
              Waiting
106
              Waiting
107
          [% ELSIF hold.found == 'P' %]
107
          [% ELSIF hold.status == 'processing' %]
108
              Processing
108
              Processing
109
          [% ELSIF hold.found == 'T' %]
109
          [% ELSIF hold.status == 'in_transit' %]
110
              In transit
110
              In transit
111
          [% ELSE %]
111
          [% ELSIF hold.status == 'placed' %]
112
              Pending
112
              Pending
113
          [% END %]
113
          [% END %]
114
          </td>
114
          </td>
(-)a/members/holdshistory.pl (-11 / +1 lines)
Lines 53-59 unless ( $patron ) { Link Here
53
}
53
}
54
54
55
my $holds;
55
my $holds;
56
my $old_holds;
57
56
58
if ( $borrowernumber eq C4::Context->preference('AnonymousPatron') ){
57
if ( $borrowernumber eq C4::Context->preference('AnonymousPatron') ){
59
    # use of 'eq' in the above comparison is intentional -- the
58
    # use of 'eq' in the above comparison is intentional -- the
Lines 61-81 if ( $borrowernumber eq C4::Context->preference('AnonymousPatron') ){ Link Here
61
    $template->param( is_anonymous => 1 );
60
    $template->param( is_anonymous => 1 );
62
} else {
61
} else {
63
    $holds = $patron->holds;
62
    $holds = $patron->holds;
64
    $old_holds = $patron->old_holds;
65
66
    while (my $hold = $holds->next) {
67
        push @all_holds, $hold;
68
    }
69
70
    while (my $hold = $old_holds->next) {
71
        push @all_holds, $hold;
72
    }
73
}
63
}
74
64
75
$template->param(
65
$template->param(
76
    holdshistoryview => 1,
66
    holdshistoryview => 1,
77
    patron           => $patron,
67
    patron           => $patron,
78
    holds            => \@all_holds,
68
    holds            => $holds
79
);
69
);
80
70
81
output_html_with_http_headers $input, $cookie, $template->output;
71
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/reserve/request.pl (-19 / +54 lines)
Lines 349-357 foreach my $biblionumber (@biblionumbers) { Link Here
349
        # the patron places must be item level
349
        # the patron places must be item level
350
        my $holds = Koha::Holds->search(
350
        my $holds = Koha::Holds->search(
351
            {
351
            {
352
                borrowernumber => $patron->borrowernumber,
352
                patron_id => $patron->borrowernumber,
353
                biblionumber   => $biblionumber,
353
                biblio_id => $biblionumber,
354
                found          => undef,
354
                status    => 'placed',
355
            }
355
            }
356
        );
356
        );
357
        $force_hold_level = $holds->forced_hold_level();
357
        $force_hold_level = $holds->forced_hold_level();
Lines 368-374 foreach my $biblionumber (@biblionumbers) { Link Here
368
    }
368
    }
369
369
370
370
371
    my $count = Koha::Holds->search( { biblionumber => $biblionumber } )->count();
371
    my $count = Koha::Holds->search(
372
        {
373
            biblio_id => $biblionumber,
374
            completed => 0
375
        }
376
    )->count();
372
    my $totalcount = $count;
377
    my $totalcount = $count;
373
378
374
    # FIXME think @optionloop, is maybe obsolete, or  must be switchable by a systeme preference fixed rank or not
379
    # FIXME think @optionloop, is maybe obsolete, or  must be switchable by a systeme preference fixed rank or not
Lines 513-525 foreach my $biblionumber (@biblionumbers) { Link Here
513
            my $item_object = Koha::Items->find( $itemnumber );
518
            my $item_object = Koha::Items->find( $itemnumber );
514
            my $holds = $item_object->current_holds;
519
            my $holds = $item_object->current_holds;
515
            if ( my $first_hold = $holds->next ) {
520
            if ( my $first_hold = $holds->next ) {
516
                my $p = Koha::Patrons->find( $first_hold->borrowernumber );
521
                my $p = Koha::Patrons->find( $first_hold->patron_id );
517
522
518
                $item->{backgroundcolor} = 'reserved';
523
                $item->{backgroundcolor} = 'reserved';
519
                $item->{reservedate}     = output_pref({ dt => dt_from_string( $first_hold->reservedate ), dateonly => 1 }); # FIXME Should be formatted in the template
524
                $item->{reservedate}     = output_pref({ dt => dt_from_string( $first_hold->created_date ), dateonly => 1 }); # FIXME Should be formatted in the template
520
                $item->{ReservedFor}     = $p;
525
                $item->{ReservedFor}     = $p;
521
                $item->{ExpectedAtLibrary}     = $first_hold->branchcode;
526
                $item->{ExpectedAtLibrary}     = $first_hold->pickup_library_id;
522
                $item->{waitingdate} = $first_hold->waitingdate;
527
                $item->{waitingdate} = $first_hold->waiting_date;
523
            }
528
            }
524
529
525
            # Management of the notforloan document
530
            # Management of the notforloan document
Lines 647-653 foreach my $biblionumber (@biblionumbers) { Link Here
647
652
648
    # existingreserves building
653
    # existingreserves building
649
    my @reserveloop;
654
    my @reserveloop;
650
    my @reserves = Koha::Holds->search( { biblionumber => $biblionumber }, { order_by => 'priority' } );
655
    my @reserves = Koha::Holds->search(
656
        {
657
            biblio_id => $biblionumber,
658
            completed => 0
659
        },
660
        { order_by => 'priority' }
661
    );
651
    foreach my $res (
662
    foreach my $res (
652
        sort {
663
        sort {
653
            my $a_found = $a->found() || '';
664
            my $a_found = $a->found() || '';
Lines 673-683 foreach my $biblionumber (@biblionumbers) { Link Here
673
            $reserve{'holdingbranch'} = $res->item()->holdingbranch();
684
            $reserve{'holdingbranch'} = $res->item()->holdingbranch();
674
            $reserve{'biblionumber'}  = $res->item()->biblionumber();
685
            $reserve{'biblionumber'}  = $res->item()->biblionumber();
675
            $reserve{'barcodenumber'} = $res->item()->barcode();
686
            $reserve{'barcodenumber'} = $res->item()->barcode();
676
            $reserve{'wbrcode'}       = $res->branchcode();
687
            $reserve{'wbrcode'}       = $res->pickup_library_id;
677
            $reserve{'itemnumber'}    = $res->itemnumber();
688
            $reserve{'itemnumber'}    = $res->item_id;
678
            $reserve{'wbrname'}       = $res->branch()->branchname();
689
            $reserve{'wbrname'}       = $res->branch()->branchname();
690
<<<<<<< HEAD
679
            $reserve{'atdestination'} = $res->is_at_destination();
691
            $reserve{'atdestination'} = $res->is_at_destination();
680
            $reserve{'desk_name'}     = ( $res->desk() ) ? $res->desk()->desk_name() : '' ;
692
            $reserve{'desk_name'}     = ( $res->desk() ) ? $res->desk()->desk_name() : '' ;
693
=======
694
695
            if ( $reserve{'holdingbranch'} eq $reserve{'wbrcode'} ) {
696
697
                # Just because the holdingbranch matches the reserve branch doesn't mean the item
698
                # has arrived at the destination, check for an open transfer for the item as well
699
                my ( $transfertwhen, $transfertfrom, $transferto ) =
700
                  C4::Circulation::GetTransfers( $res->item_id );
701
                if ( not $transferto or $transferto ne $res->pickup_library_id ) {
702
                    $reserve{'atdestination'} = 1;
703
                }
704
            }
705
706
            # set found to 1 if reserve is waiting for patron pickup
707
>>>>>>> 324514e305 (Bug 25260: Adapt all the things)
681
            $reserve{'found'}     = $res->is_found();
708
            $reserve{'found'}     = $res->is_found();
682
            $reserve{'inprocessing'} = $res->is_in_processing();
709
            $reserve{'inprocessing'} = $res->is_in_processing();
683
            $reserve{'intransit'} = $res->is_in_transit();
710
            $reserve{'intransit'} = $res->is_in_transit();
Lines 690-713 foreach my $biblionumber (@biblionumbers) { Link Here
690
            }
717
            }
691
        }
718
        }
692
719
693
        $reserve{'expirationdate'} = $res->expirationdate;
720
        $reserve{'expirationdate'} = $res->expiration_date;
694
        $reserve{'date'}           = $res->reservedate;
721
        $reserve{'date'}           = $res->created_date;
695
        $reserve{'borrowernumber'} = $res->borrowernumber();
722
        $reserve{'borrowernumber'} = $res->patron_id;
696
        $reserve{'biblionumber'}   = $res->biblionumber();
723
        $reserve{'biblionumber'}   = $res->biblio_id;
697
        $reserve{'patron'}         = $res->borrower;
724
        $reserve{'patron'}         = $res->borrower;
698
        $reserve{'notes'}          = $res->reservenotes();
725
        $reserve{'notes'}          = $res->notes;
699
        $reserve{'waiting_date'}   = $res->waitingdate();
726
        $reserve{'waiting_date'}   = $res->waiting_date;
700
        $reserve{'ccode'}          = $res->item() ? $res->item()->ccode() : undef;
727
        $reserve{'ccode'}          = $res->item() ? $res->item()->ccode() : undef;
701
        $reserve{'barcode'}        = $res->item() ? $res->item()->barcode() : undef;
728
        $reserve{'barcode'}        = $res->item() ? $res->item()->barcode() : undef;
702
        $reserve{'priority'}       = $res->priority();
729
        $reserve{'priority'}       = $res->priority;
703
        $reserve{'lowestPriority'} = $res->lowestPriority();
730
        $reserve{'lowestPriority'} = $res->lowest_priority;
704
        $reserve{'optionloop'}     = \@optionloop;
731
        $reserve{'optionloop'}     = \@optionloop;
732
<<<<<<< HEAD
705
        $reserve{'suspend'}        = $res->suspend();
733
        $reserve{'suspend'}        = $res->suspend();
706
        $reserve{'suspend_until'}  = $res->suspend_until();
734
        $reserve{'suspend_until'}  = $res->suspend_until();
707
        $reserve{'reserve_id'}     = $res->reserve_id();
735
        $reserve{'reserve_id'}     = $res->reserve_id();
708
        $reserve{itemtype}         = $res->itemtype();
736
        $reserve{itemtype}         = $res->itemtype();
709
        $reserve{branchcode}       = $res->branchcode();
737
        $reserve{branchcode}       = $res->branchcode();
710
        $reserve{non_priority}     = $res->non_priority();
738
        $reserve{non_priority}     = $res->non_priority();
739
=======
740
        $reserve{'suspend'}        = $res->suspended;
741
        $reserve{'suspend_until'}  = $res->suspended_until_date;
742
        $reserve{'reserve_id'}     = $res->id;
743
        $reserve{itemtype}         = $res->item_type;
744
        $reserve{branchcode}       = $res->pickup_library_id;
745
>>>>>>> 324514e305 (Bug 25260: Adapt all the things)
711
        $reserve{object}           = $res;
746
        $reserve{object}           = $res;
712
747
713
        push( @reserveloop, \%reserve );
748
        push( @reserveloop, \%reserve );
(-)a/t/Koha/REST/Plugin/Query.t (-2 / +2 lines)
Lines 108-114 get '/dbic_merge_sorting_date' => sub { Link Here
108
    $attributes = $c->dbic_merge_sorting(
108
    $attributes = $c->dbic_merge_sorting(
109
        {
109
        {
110
            attributes => $attributes,
110
            attributes => $attributes,
111
            params     => { _match => 'exact', _order_by => [ '-hold_date' ] },
111
            params     => { _match => 'exact', _order_by => [ '-created_date' ] },
112
            result_set => $result_set
112
            result_set => $result_set
113
        }
113
        }
114
    );
114
    );
Lines 343-349 subtest 'dbic_merge_sorting() tests' => sub { Link Here
343
      ->json_is( '/a' => 'a', 'Existing values are kept (a)' )
343
      ->json_is( '/a' => 'a', 'Existing values are kept (a)' )
344
      ->json_is( '/b' => 'b', 'Existing values are kept (b)' )->json_is(
344
      ->json_is( '/b' => 'b', 'Existing values are kept (b)' )->json_is(
345
        '/order_by' => [
345
        '/order_by' => [
346
            { -desc => 'reservedate' }
346
            { -desc => 'created_date' }
347
        ]
347
        ]
348
      );
348
      );
349
349
(-)a/t/db_dependent/Circulation.t (-32 / +31 lines)
Lines 507-513 subtest "CanBookBeRenewed tests" => sub { Link Here
507
    my $expdate        = undef;
507
    my $expdate        = undef;
508
    my $notes          = '';
508
    my $notes          = '';
509
    my $checkitem      = undef;
509
    my $checkitem      = undef;
510
    my $found          = undef;
510
    my $found          = 'placed';
511
511
512
    my $issue = AddIssue( $renewing_borrower, $item_1->barcode);
512
    my $issue = AddIssue( $renewing_borrower, $item_1->barcode);
513
    my $datedue = dt_from_string( $issue->date_due() );
513
    my $datedue = dt_from_string( $issue->date_due() );
Lines 535-542 subtest "CanBookBeRenewed tests" => sub { Link Here
535
            reservation_date => $resdate,
535
            reservation_date => $resdate,
536
            expiration_date  => $expdate,
536
            expiration_date  => $expdate,
537
            notes            => $notes,
537
            notes            => $notes,
538
            itemnumber       => $checkitem,
538
            itemnumber       => $checkitem
539
            found            => $found,
540
        }
539
        }
541
    );
540
    );
542
541
Lines 566-596 subtest "CanBookBeRenewed tests" => sub { Link Here
566
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
565
    is( $renewokay, 1, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
567
566
568
    # Now let's add an item level hold, we should no longer be able to renew the item
567
    # Now let's add an item level hold, we should no longer be able to renew the item
569
    my $hold = Koha::Database->new()->schema()->resultset('Reserve')->create(
568
    my $hold = Koha::Hold->new(
570
        {
569
        {
571
            borrowernumber => $hold_waiting_borrowernumber,
570
            patron_id   => $hold_waiting_borrowernumber,
572
            biblionumber   => $biblio->biblionumber,
571
            biblio_id   => $biblio->biblionumber,
573
            itemnumber     => $item_1->itemnumber,
572
            item_id     => $item_1->itemnumber,
574
            branchcode     => $branch,
573
            pickup_library_id => $branch,
575
            priority       => 3,
574
            priority    => 3,
576
        }
575
        }
577
    );
576
    )->store;
578
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
577
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
579
    is( $renewokay, 0, 'Bug 13919 - Renewal possible with item level hold on item');
578
    is( $renewokay, 0, 'Bug 13919 - Renewal possible with item level hold on item');
580
    $hold->delete();
579
    $hold->delete();
581
580
582
    # Now let's add a waiting hold on the 3rd item, it's no longer available tp check out by just anyone, so we should no longer
581
    # Now let's add a waiting hold on the 3rd item, it's no longer available tp check out by just anyone, so we should no longer
583
    # be able to renew these items
582
    # be able to renew these items
584
    $hold = Koha::Database->new()->schema()->resultset('Reserve')->create(
583
    $hold = Koha::Hold->new(
585
        {
584
        {
586
            borrowernumber => $hold_waiting_borrowernumber,
585
            patron_id => $hold_waiting_borrowernumber,
587
            biblionumber   => $biblio->biblionumber,
586
            biblio_id   => $biblio->biblionumber,
588
            itemnumber     => $item_3->itemnumber,
587
            item_id     => $item_3->itemnumber,
589
            branchcode     => $branch,
588
            pickup_library_id     => $branch,
590
            priority       => 0,
589
            priority       => 0,
591
            found          => 'W'
590
            status          => 'waiting'
592
        }
591
        }
593
    );
592
    )->store;
594
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
593
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_1->itemnumber);
595
    is( $renewokay, 0, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
594
    is( $renewokay, 0, 'Bug 11634 - Allow renewal of item with unfilled holds if other available items can fill those holds');
596
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_2->itemnumber);
595
    ( $renewokay, $error ) = CanBookBeRenewed($renewing_borrowernumber, $item_2->itemnumber);
Lines 605-619 subtest "CanBookBeRenewed tests" => sub { Link Here
605
    is( $renewokay, 0, '(Bug 10663) Cannot renew, reserved');
604
    is( $renewokay, 0, '(Bug 10663) Cannot renew, reserved');
606
    is( $error, 'on_reserve', '(Bug 10663) Cannot renew, reserved (returned error is on_reserve)');
605
    is( $error, 'on_reserve', '(Bug 10663) Cannot renew, reserved (returned error is on_reserve)');
607
606
608
    my $reserveid = Koha::Holds->search({ biblionumber => $biblio->biblionumber, borrowernumber => $reserving_borrowernumber })->next->reserve_id;
607
    my $reserveid = Koha::Holds->search({ biblio_id => $biblio->biblionumber, patron_id => $reserving_borrowernumber })->next->id;
609
    my $reserving_borrower = Koha::Patrons->find( $reserving_borrowernumber )->unblessed;
608
    my $reserving_borrower = Koha::Patrons->find( $reserving_borrowernumber )->unblessed;
610
    AddIssue($reserving_borrower, $item_3->barcode);
609
    AddIssue($reserving_borrower, $item_3->barcode);
611
    my $reserve = $dbh->selectrow_hashref(
610
    my $reserve = $dbh->selectrow_hashref(
612
        'SELECT * FROM old_reserves WHERE reserve_id = ?',
611
        'SELECT * FROM holds WHERE id = ? AND completed = 1',
613
        { Slice => {} },
612
        { Slice => {} },
614
        $reserveid
613
        $reserveid
615
    );
614
    );
616
    is($reserve->{found}, 'F', 'hold marked completed when checking out item that fills it');
615
    is($reserve->{status}, 'fulfilled', 'hold marked completed when checking out item that fills it');
617
616
618
    # Item-level hold, renewal test
617
    # Item-level hold, renewal test
619
    AddReserve(
618
    AddReserve(
Lines 775-781 subtest "CanBookBeRenewed tests" => sub { Link Here
775
    $fines = Koha::Account::Lines->search( { borrowernumber => $renewing_borrower->{borrowernumber}, itemnumber => $item_7->itemnumber } );
774
    $fines = Koha::Account::Lines->search( { borrowernumber => $renewing_borrower->{borrowernumber}, itemnumber => $item_7->itemnumber } );
776
    $fines->delete();
775
    $fines->delete();
777
776
778
    $hold = Koha::Holds->search({ biblionumber => $biblio->biblionumber, borrowernumber => $reserving_borrowernumber })->next;
777
    $hold = Koha::Holds->search({ biblio_id => $biblio->biblionumber, patron_id => $reserving_borrowernumber })->next;
779
    $hold->cancel;
778
    $hold->cancel;
780
779
781
    # Bug 14101
780
    # Bug 14101
Lines 3450-3456 subtest 'Set waiting flag' => sub { Link Here
3450
    my ( $res, $rr ) = AddReturn( $item->barcode, $library_1->{branchcode} );
3449
    my ( $res, $rr ) = AddReturn( $item->barcode, $library_1->{branchcode} );
3451
    ModReserveAffect( $item->itemnumber, undef, $do_transfer, $reserve_id );
3450
    ModReserveAffect( $item->itemnumber, undef, $do_transfer, $reserve_id );
3452
    my $hold = Koha::Holds->find( $reserve_id );
3451
    my $hold = Koha::Holds->find( $reserve_id );
3453
    is( $hold->found, 'T', 'Hold is in transit' );
3452
    is( $hold->status, 'in_transit', 'Hold is in transit' );
3454
3453
3455
    my ( $status ) = CheckReserves($item->itemnumber);
3454
    my ( $status ) = CheckReserves($item->itemnumber);
3456
    is( $status, 'Transferred', 'Hold is not waiting yet');
3455
    is( $status, 'Transferred', 'Hold is not waiting yet');
Lines 3460-3466 subtest 'Set waiting flag' => sub { Link Here
3460
    AddReturn( $item->barcode, $library_2->{branchcode} );
3459
    AddReturn( $item->barcode, $library_2->{branchcode} );
3461
    ModReserveAffect( $item->itemnumber, undef, $do_transfer, $reserve_id );
3460
    ModReserveAffect( $item->itemnumber, undef, $do_transfer, $reserve_id );
3462
    $hold = Koha::Holds->find( $reserve_id );
3461
    $hold = Koha::Holds->find( $reserve_id );
3463
    is( $hold->found, 'W', 'Hold is waiting' );
3462
    is( $hold->status, 'waiting', 'Hold is waiting' );
3464
    ( $status ) = CheckReserves($item->itemnumber);
3463
    ( $status ) = CheckReserves($item->itemnumber);
3465
    is( $status, 'Waiting', 'Now the hold is waiting');
3464
    is( $status, 'Waiting', 'Now the hold is waiting');
3466
3465
Lines 3468-3479 subtest 'Set waiting flag' => sub { Link Here
3468
    set_userenv( $library_1 );
3467
    set_userenv( $library_1 );
3469
    (undef, my $messages, undef, undef ) = AddReturn ( $item->barcode, $library_1->{branchcode} );
3468
    (undef, my $messages, undef, undef ) = AddReturn ( $item->barcode, $library_1->{branchcode} );
3470
    $hold = Koha::Holds->find( $reserve_id );
3469
    $hold = Koha::Holds->find( $reserve_id );
3471
    is( $hold->found, undef, 'Hold is no longer marked waiting' );
3470
    is( $hold->status, 'placed', 'Hold is no longer marked waiting' );
3472
    is( $hold->priority, 1,  "Hold is now priority one again");
3471
    is( $hold->priority, 1,  "Hold is now priority one again");
3473
    is( $hold->waitingdate, undef, "Hold no longer has a waiting date");
3472
    is( $hold->waiting_date, undef, "Hold no longer has a waiting date");
3474
    is( $hold->itemnumber, $item->itemnumber, "Hold has retained its' itemnumber");
3473
    is( $hold->item_id, $item->itemnumber, "Hold has retained its' itemnumber");
3475
    is( $messages->{ResFound}->{ResFound}, "Reserved", "Hold is still returned");
3474
    is( $messages->{ResFound}->{ResFound}, "Reserved", "Hold is still returned");
3476
    is( $messages->{ResFound}->{found}, undef, "Hold is no longer marked found in return message");
3475
    is( $messages->{ResFound}->{status}, 'placed', "Hold is no longer marked found in return message");
3477
    is( $messages->{ResFound}->{priority}, 1, "Hold is priority 1 in return message");
3476
    is( $messages->{ResFound}->{priority}, 1, "Hold is priority 1 in return message");
3478
};
3477
};
3479
3478
Lines 4331-4343 subtest 'Filling a hold should cancel existing transfer' => sub { Link Here
4331
        biblionumber   => $item->biblionumber,
4330
        biblionumber   => $item->biblionumber,
4332
        itemnumber     => $item->itemnumber
4331
        itemnumber     => $item->itemnumber
4333
    });
4332
    });
4334
    my $reserves = Koha::Holds->search({ itemnumber => $item->itemnumber });
4333
    my $reserves = Koha::Holds->search({ item_id => $item->itemnumber });
4335
    is( $reserves->count, 1, "Reserve is placed");
4334
    is( $reserves->count, 1, "Reserve is placed");
4336
    ( undef, $message ) = AddReturn( $item->barcode, $libraryA->branchcode, undef, undef );
4335
    ( undef, $message ) = AddReturn( $item->barcode, $libraryA->branchcode, undef, undef );
4337
    my $reserve = $reserves->next;
4336
    my $reserve = $reserves->next;
4338
    ModReserveAffect( $item->itemnumber, $patron->borrowernumber, 0, $reserve->reserve_id );
4337
    ModReserveAffect( $item->itemnumber, $patron->borrowernumber, 0, $reserve->id );
4339
    $reserve->discard_changes;
4338
    $reserve->discard_changes;
4340
    ok( $reserve->found eq 'W', "Reserve is marked waiting" );
4339
    ok( $reserve->status eq 'waiting', "Reserve is marked waiting" );
4341
    is( Koha::Item::Transfers->search({ itemnumber => $item->itemnumber, datearrived => undef })->count, 0, "No outstanding transfers when hold is waiting");
4340
    is( Koha::Item::Transfers->search({ itemnumber => $item->itemnumber, datearrived => undef })->count, 0, "No outstanding transfers when hold is waiting");
4342
};
4341
};
4343
4342
Lines 4794-4800 subtest 'Checkout should correctly terminate a transfer' => sub { Link Here
4794
    GetOtherReserves( $item->itemnumber )
4793
    GetOtherReserves( $item->itemnumber )
4795
      ;    # To put the Reason, it's what does returns.pl...
4794
      ;    # To put the Reason, it's what does returns.pl...
4796
    my $hold = Koha::Holds->find($reserve_id);
4795
    my $hold = Koha::Holds->find($reserve_id);
4797
    is( $hold->found, 'T', 'Hold is in transit' );
4796
    is( $hold->status, 'in_transit', 'Hold is in transit' );
4798
    my $transfer = $item->get_transfer;
4797
    my $transfer = $item->get_transfer;
4799
    is( $transfer->frombranch, $library_1->branchcode );
4798
    is( $transfer->frombranch, $library_1->branchcode );
4800
    is( $transfer->tobranch,   $library_2->branchcode );
4799
    is( $transfer->tobranch,   $library_2->branchcode );
Lines 4805-4811 subtest 'Checkout should correctly terminate a transfer' => sub { Link Here
4805
    $transfer = $transfer->get_from_storage;
4804
    $transfer = $transfer->get_from_storage;
4806
    isnt( $transfer->datearrived, undef );
4805
    isnt( $transfer->datearrived, undef );
4807
    $hold = $hold->get_from_storage;
4806
    $hold = $hold->get_from_storage;
4808
    is( $hold->found, undef, 'Hold is waiting' );
4807
    is( $hold->status, 'placed', 'Hold is waiting' );
4809
    is( $hold->priority, 1, );
4808
    is( $hold->priority, 1, );
4810
};
4809
};
4811
4810
(-)a/t/db_dependent/Circulation/issue.t (-3 / +2 lines)
Lines 68-75 $dbh->do(q|DELETE FROM borrowers|); Link Here
68
$dbh->do(q|DELETE FROM categories|);
68
$dbh->do(q|DELETE FROM categories|);
69
$dbh->do(q|DELETE FROM accountlines|);
69
$dbh->do(q|DELETE FROM accountlines|);
70
$dbh->do(q|DELETE FROM circulation_rules|);
70
$dbh->do(q|DELETE FROM circulation_rules|);
71
$dbh->do(q|DELETE FROM reserves|);
71
$dbh->do(q|DELETE FROM holds|);
72
$dbh->do(q|DELETE FROM old_reserves|);
73
$dbh->do(q|DELETE FROM statistics|);
72
$dbh->do(q|DELETE FROM statistics|);
74
73
75
# Generate sample datas
74
# Generate sample datas
Lines 484-490 my $reserve_id = AddReserve( Link Here
484
ok( $reserve_id, 'The reserve should have been inserted' );
483
ok( $reserve_id, 'The reserve should have been inserted' );
485
AddIssue( $borrower_2, $barcode_1, dt_from_string, 'cancel' );
484
AddIssue( $borrower_2, $barcode_1, dt_from_string, 'cancel' );
486
my $hold = Koha::Holds->find( $reserve_id );
485
my $hold = Koha::Holds->find( $reserve_id );
487
is( $hold, undef, 'The reserve should have been correctly cancelled' );
486
is( $hold->status, 'cancelled', 'The reserve should have been correctly cancelled' );
488
487
489
# Unseen rewnewals
488
# Unseen rewnewals
490
t::lib::Mocks::mock_preference('UnseenRenewals', 1);
489
t::lib::Mocks::mock_preference('UnseenRenewals', 1);
(-)a/t/db_dependent/DecreaseLoanHighHolds.t (-9 / +9 lines)
Lines 88-103 for my $i ( 0 .. 5 ) { Link Here
88
    my $patron = $patrons[$i];
88
    my $patron = $patrons[$i];
89
    my $hold   = Koha::Hold->new(
89
    my $hold   = Koha::Hold->new(
90
        {
90
        {
91
            borrowernumber => $patron->id,
91
            patron_id => $patron->id,
92
            biblionumber   => $biblio->id,
92
            biblio_id   => $biblio->id,
93
            branchcode     => $library->{branchcode},
93
            pickup_library_id     => $library->{branchcode},
94
        }
94
        }
95
    )->store();
95
    )->store();
96
}
96
}
97
97
98
my $item   = shift(@items);
98
my $item   = shift(@items);
99
my $patron = shift(@patrons);
99
my $patron = shift(@patrons);
100
my $patron_hold = Koha::Holds->find({ borrowernumber => $patron->borrowernumber, biblionumber => $item->biblionumber });
100
my $patron_hold = Koha::Holds->find({ patron_id => $patron->borrowernumber, biblio_id => $item->biblionumber });
101
101
102
Koha::CirculationRules->set_rules(
102
Koha::CirculationRules->set_rules(
103
    {
103
    {
Lines 169-177 for my $i ( 5 .. 10 ) { Link Here
169
    my $patron = $patrons[$i];
169
    my $patron = $patrons[$i];
170
    my $hold   = Koha::Hold->new(
170
    my $hold   = Koha::Hold->new(
171
        {
171
        {
172
            borrowernumber => $patron->id,
172
            patron_id         => $patron->id,
173
            biblionumber   => $biblio->id,
173
            biblio_id         => $biblio->id,
174
            branchcode     => $library->{branchcode},
174
            pickup_library_id => $library->{branchcode},
175
        }
175
        }
176
    )->store();
176
    )->store();
177
}
177
}
Lines 218-228 $unholdable->store(); Link Here
218
$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
218
$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
219
is( $data->{exceeded}, 1, "Should exceed threshold with one withdrawn item" );
219
is( $data->{exceeded}, 1, "Should exceed threshold with one withdrawn item" );
220
220
221
$patron_hold->found('F')->store;
221
$patron_hold->set_waiting();
222
# 11 holds, threshold is 2 over 9 holdable items = 11
222
# 11 holds, threshold is 2 over 9 holdable items = 11
223
$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
223
$data = C4::Circulation::checkHighHolds( $item_hr, $patron_hr );
224
is( $data->{exceeded}, 1, "Should exceed threshold with one withdrawn item" );
224
is( $data->{exceeded}, 1, "Should exceed threshold with one withdrawn item" );
225
$patron_hold->found(undef)->store;
225
$patron_hold->status('placed')->store;
226
226
227
t::lib::Mocks::mock_preference('CircControl', 'PatronLibrary');
227
t::lib::Mocks::mock_preference('CircControl', 'PatronLibrary');
228
228
(-)a/t/db_dependent/Hold.t (-75 / +86 lines)
Lines 66-78 $item->store(); Link Here
66
66
67
my $hold = Koha::Hold->new(
67
my $hold = Koha::Hold->new(
68
    {
68
    {
69
        biblionumber   => $biblionumber,
69
        biblio_id      => $biblionumber,
70
        itemnumber     => $item->id(),
70
        item_id        => $item->id(),
71
        reservedate    => '2017-01-01',
71
        created_date   => '2017-01-01',
72
        waitingdate    => '2000-01-01',
72
        waiting_date   => '2000-01-01',
73
        borrowernumber => $borrower->{borrowernumber},
73
        patron_id      => $borrower->{borrowernumber},
74
        branchcode     => $branches[1]->{branchcode},
74
        pickup_library_id => $branches[1]->{branchcode},
75
        suspend        => 0,
75
        suspended      => 0,
76
        status         => 'placed'
76
    }
77
    }
77
);
78
);
78
$hold->store();
79
$hold->store();
Lines 83-104 my $today = dt_from_string; Link Here
83
is( $hold->age(), $today->delta_days( dt_from_string( '2017-01-01' ) )->in_units( 'days')  , "Age of hold is days from reservedate to now if calendar ignored");
84
is( $hold->age(), $today->delta_days( dt_from_string( '2017-01-01' ) )->in_units( 'days')  , "Age of hold is days from reservedate to now if calendar ignored");
84
is( $hold->age(1), $today->delta_days( dt_from_string( '2017-01-01' ) )->in_units( 'days' ) - 1 , "Age of hold is days from reservedate to now minus 1 if calendar used");
85
is( $hold->age(1), $today->delta_days( dt_from_string( '2017-01-01' ) )->in_units( 'days' ) - 1 , "Age of hold is days from reservedate to now minus 1 if calendar used");
85
86
86
is( $hold->suspend, 0, "Hold is not suspended" );
87
is( $hold->suspended, 0, "Hold is not suspended" );
87
$hold->suspend_hold();
88
$hold->suspend_hold();
88
is( $hold->suspend, 1, "Hold is suspended" );
89
is( $hold->suspended, 1, "Hold is suspended" );
89
$hold->resume();
90
$hold->resume();
90
is( $hold->suspend, 0, "Hold is not suspended" );
91
is( $hold->suspended, 0, "Hold is not suspended" );
91
my $dt = dt_from_string();
92
my $dt = dt_from_string();
92
$hold->suspend_hold( $dt );
93
$hold->suspend_hold( $dt );
93
$dt->truncate( to => 'day' );
94
$dt->truncate( to => 'day' );
94
is( $hold->suspend, 1, "Hold is suspended" );
95
is( $hold->suspended, 1, "Hold is suspended" );
95
is( $hold->suspend_until, "$dt", "Hold is suspended with a date, truncation takes place automatically" );
96
is( $hold->suspended_until_date, "$dt", "Hold is suspended with a date, truncation takes place automatically" );
96
$hold->suspend_hold;
97
$hold->suspend_hold;
97
is( $hold->suspend, 1, "Hold is suspended" );
98
is( $hold->suspended, 1, "Hold is suspended" );
98
is( $hold->suspend_until, undef, "Hold is suspended without a date" );
99
is( $hold->suspended_until_date, undef, "Hold is suspended without a date" );
99
$hold->resume();
100
$hold->resume();
100
is( $hold->suspend, 0, "Hold is not suspended" );
101
is( $hold->suspended, 0, "Hold is not suspended" );
101
is( $hold->suspend_until, undef, "Hold no longer has suspend_until date" );
102
is( $hold->suspended_until_date, undef, "Hold no longer has suspend_until date" );
102
103
103
$item = $hold->item();
104
$item = $hold->item();
104
105
Lines 107-143 ok( $hold_borrower, 'Got hold borrower' ); Link Here
107
is( $hold_borrower->borrowernumber(), $borrower->{borrowernumber}, 'Hold borrower matches correct borrower' );
108
is( $hold_borrower->borrowernumber(), $borrower->{borrowernumber}, 'Hold borrower matches correct borrower' );
108
109
109
t::lib::Mocks::mock_preference( 'ReservesMaxPickUpDelay', '5' );
110
t::lib::Mocks::mock_preference( 'ReservesMaxPickUpDelay', '5' );
110
$hold->found('T');
111
$hold->status('in_transit');
111
isnt( $hold->is_waiting, 1, 'The hold is not waiting (T)' );
112
isnt( $hold->is_waiting, 1, 'The hold is not waiting (T)' );
112
is( $hold->is_found, 1, 'The hold is found');
113
is( $hold->is_found, 1, 'The hold is found');
113
is( $hold->is_in_transit, 1, 'The hold is in transit' );
114
is( $hold->is_in_transit, 1, 'The hold is in transit' );
114
115
115
$hold->found('P');
116
$hold->status('processing');
116
is( $hold->is_found, 1, 'The hold is found');
117
is( $hold->is_found, 1, 'The hold is found');
117
is( $hold->is_in_processing, 1, 'The hold is in processing' );
118
is( $hold->is_in_processing, 1, 'The hold is in processing' );
118
119
119
$hold->found(q{});
120
$hold->status('placed');
120
isnt( $hold->is_waiting, 1, 'The hold is not waiting (W)' );
121
isnt( $hold->is_waiting, 1, 'The hold is not waiting (W)' );
121
is( $hold->is_found, 0, 'The hold is not found' );
122
is( $hold->is_found, 0, 'The hold is not found' );
122
ok( !$hold->is_in_transit, 'The hold is not in transit' );
123
ok( !$hold->is_in_transit, 'The hold is not in transit' );
123
ok( !$hold->is_in_processing, 'The hold is not in processing' );
124
ok( !$hold->is_in_processing, 'The hold is not in processing' );
124
125
125
# Test method is_cancelable_from_opac
126
# Test method is_cancelable_from_opac
126
$hold->found(undef);
127
$hold->status('placed');
127
is( $hold->is_cancelable_from_opac, 1, "Unfound hold is cancelable" );
128
is( $hold->is_cancelable_from_opac, 1, "Unfound hold is cancelable" );
128
$hold->found('W');
129
$hold->status('waiting');
129
is( $hold->is_cancelable_from_opac, 0, "Waiting hold is not cancelable" );
130
is( $hold->is_cancelable_from_opac, 0, "Waiting hold is not cancelable" );
130
$hold->found('T');
131
$hold->status('in_transit');
131
is( $hold->is_cancelable_from_opac, 0, "In transit hold is not cancelable" );
132
is( $hold->is_cancelable_from_opac, 0, "In transit hold is not cancelable" );
132
$hold->found('P');
133
$hold->status('processing');
133
is( $hold->is_cancelable_from_opac, 0, "In processing hold is not cancelable" );
134
is( $hold->is_cancelable_from_opac, 0, "In processing hold is not cancelable" );
134
135
135
# Test method is_at_destination
136
# Test method is_at_destination
136
$hold->found(undef);
137
$hold->status('placed');
137
ok( !$hold->is_at_destination(), "Unfound hold cannot be at destination" );
138
ok( !$hold->is_at_destination(), "Unfound hold cannot be at destination" );
138
$hold->found('T');
139
$hold->status('in_transit');
139
ok( !$hold->is_at_destination(), "In transit hold cannot be at destination" );
140
ok( !$hold->is_at_destination(), "In transit hold cannot be at destination" );
140
$hold->found('W');
141
$hold->status('waiting');
141
ok( !$hold->is_at_destination(), "Waiting hold where hold branchcode is not the same as the item's holdingbranch is not at destination" );
142
ok( !$hold->is_at_destination(), "Waiting hold where hold branchcode is not the same as the item's holdingbranch is not at destination" );
142
$item->holdingbranch( $branches[1]->{branchcode} );
143
$item->holdingbranch( $branches[1]->{branchcode} );
143
ok( $hold->is_at_destination(), "Waiting hold where hold branchcode is the same as the item's holdingbranch is at destination" );
144
ok( $hold->is_at_destination(), "Waiting hold where hold branchcode is the same as the item's holdingbranch is at destination" );
Lines 162-225 subtest "store() tests" => sub { Link Here
162
        'years' );
163
        'years' );
163
164
164
    my $hold = Koha::Hold->new(
165
    my $hold = Koha::Hold->new(
165
        {
166
        {   biblio_id         => $biblio->biblionumber,
166
            biblionumber   => $biblio->biblionumber,
167
            item_id           => $item->id,
167
            itemnumber     => $item->id,
168
            created_date      => '2020-11-30',
168
            reservedate    => '2020-11-30',
169
            waiting_date      => '2020-11-30',
169
            waitingdate    => '2020-11-30',
170
            patron_id         => $borrower->borrowernumber,
170
            borrowernumber => $borrower->borrowernumber,
171
            pickup_library_id => $library->branchcode,
171
            branchcode     => $library->branchcode,
172
            suspended         => 0,
172
            suspend        => 0,
173
        }
173
        }
174
    )->store;
174
    )->store;
175
    $hold->discard_changes;
175
    $hold->discard_changes;
176
176
177
    my $expected_date =
177
    my $expected_date =
178
      dt_from_string( $hold->reservedate )->add( years => 2 );
178
      dt_from_string( $hold->created_date )->add( years => 2 );
179
    is( $hold->expirationdate,
179
    is( $hold->expiration_date,
180
        $expected_date->ymd, 'Default expiration date for new hold is correctly set.' );
180
        $expected_date->ymd, 'Default expiration date for new hold is correctly set.' );
181
181
182
    my $passed_date =
182
    my $passed_date =
183
      dt_from_string( $hold->reservedate )->add( months => 2 );
183
      dt_from_string( $hold->created_date )->add( months => 2 );
184
    $hold = Koha::Hold->new(
184
    $hold = Koha::Hold->new(
185
        {
185
        {   biblio_id         => $biblio->biblionumber,
186
            biblionumber   => $biblio->biblionumber,
186
            item_id           => $item->id,
187
            itemnumber     => $item->id,
187
            created_date      => '2020-11-30',
188
            reservedate    => '2020-11-30',
188
            expiration_date   => $passed_date->ymd,
189
            expirationdate => $passed_date->ymd,
189
            waiting_date      => '2020-11-30',
190
            waitingdate    => '2020-11-30',
190
            patron_id         => $borrower->borrowernumber,
191
            borrowernumber => $borrower->borrowernumber,
191
            pickup_library_id => $library->branchcode,
192
            branchcode     => $library->branchcode,
192
            suspended         => 0,
193
            suspend        => 0,
194
        }
193
        }
195
    )->store;
194
    )->store;
196
    $hold->discard_changes;
195
    $hold->discard_changes;
197
196
198
    is( $hold->expirationdate,
197
    is( $hold->expiration_date,
199
        $passed_date->ymd, 'Passed expiration date for new hold is correctly set.' );
198
        $passed_date->ymd, 'Passed expiration date for new hold is correctly set.' );
200
199
201
    $passed_date->add( months => 1 );
200
    $passed_date->add( months => 1 );
202
    $hold->expirationdate($passed_date->ymd)->store();
201
    $hold->expiration_date($passed_date->ymd)->store();
203
    $hold->discard_changes;
202
    $hold->discard_changes;
204
203
205
    is( $hold->expirationdate,
204
    is( $hold->expiration_date,
206
        $passed_date->ymd, 'Passed expiration date when updating hold is correctly set.' );
205
        $passed_date->ymd, 'Passed expiration date when updating hold is correctly set.' );
207
206
208
    $hold->reservedate($passed_date->ymd)->store();
207
    $hold->created_date($passed_date->ymd)->store();
209
    $hold->discard_changes;
208
    $hold->discard_changes;
210
209
211
    is( $hold->expirationdate,
210
    is( $hold->expiration_date,
212
        $passed_date->add( years => 2 )->ymd, 'Default expiration date correctly set on reservedate update.' );
211
        $passed_date->add( years => 2 )->ymd, 'Default expiration date correctly set on reservedate update.' );
213
212
214
    $hold->set(
213
    $hold->set(
215
        {
214
        {
216
            reservedate    => $passed_date->ymd,
215
            created_date    => $passed_date->ymd,
217
            expirationdate => $passed_date->add( weeks => 2 )->ymd
216
            expiration_date => $passed_date->add( weeks => 2 )->ymd
218
        }
217
        }
219
    )->store();
218
    )->store();
220
    $hold->discard_changes;
219
    $hold->discard_changes;
221
220
222
    is( $hold->expirationdate,
221
    is( $hold->expiration_date,
223
        $passed_date->ymd, 'Passed expiration date when updating hold correctly set (Passing both reservedate and expirationdate.' );
222
        $passed_date->ymd, 'Passed expiration date when updating hold correctly set (Passing both reservedate and expirationdate.' );
224
223
225
    $schema->storage->txn_rollback();
224
    $schema->storage->txn_rollback();
Lines 234-264 subtest "delete() tests" => sub { Link Here
234
    # Disable logging
233
    # Disable logging
235
    t::lib::Mocks::mock_preference( 'HoldsLog', 0 );
234
    t::lib::Mocks::mock_preference( 'HoldsLog', 0 );
236
235
237
    my $hold = $builder->build({ source => 'Reserve' });
236
    my $hold    = $builder->build_object({ class => 'Koha::Holds' });
237
    my $hold_id = $hold->id;
238
    my $deleted = $hold->delete;
238
239
239
    my $hold_object = Koha::Holds->find( $hold->{ reserve_id } );
240
    my $deleted = $hold_object->delete;
241
    is( ref($deleted), 'Koha::Hold', 'Koha::Hold->delete should return the Koha::Hold object if the hold has been correctly deleted' );
240
    is( ref($deleted), 'Koha::Hold', 'Koha::Hold->delete should return the Koha::Hold object if the hold has been correctly deleted' );
242
    is( Koha::Holds->search({ reserve_id => $hold->{ reserve_id } })->count, 0,
241
    is( Koha::Holds->search({ id => $hold_id })->count, 0,
243
        "Koha::Hold->delete should have deleted the hold" );
242
        "Koha::Hold->delete should have deleted the hold" );
244
243
245
    my $number_of_logs = $schema->resultset('ActionLog')->search(
244
    my $number_of_logs = $schema->resultset('ActionLog')->search(
246
            { module => 'HOLDS', action => 'DELETE', object => $hold->{ reserve_id } } )->count;
245
            { module => 'HOLDS', action => 'DELETE', object => $hold_id } )->count;
247
    is( $number_of_logs, 0, 'With HoldsLogs, Koha::Hold->delete shouldn\'t have been logged' );
246
    is( $number_of_logs, 0, 'With HoldsLogs, Koha::Hold->delete shouldn\'t have been logged' );
248
247
249
    # Enable logging
248
    # Enable logging
250
    t::lib::Mocks::mock_preference( 'HoldsLog', 1 );
249
    t::lib::Mocks::mock_preference( 'HoldsLog', 1 );
251
250
252
    $hold = $builder->build({ source => 'Reserve' });
251
    $hold    = $builder->build_object({ class => 'Koha::Holds' });
252
    $hold_id = $hold->id;
253
    $deleted = $hold->delete;
253
254
254
    $hold_object = Koha::Holds->find( $hold->{ reserve_id } );
255
    $deleted = $hold_object->delete;
256
    is( ref($deleted), 'Koha::Hold', 'Koha::Hold->delete should return a Koha::Hold object if the hold has been correctly deleted' );
255
    is( ref($deleted), 'Koha::Hold', 'Koha::Hold->delete should return a Koha::Hold object if the hold has been correctly deleted' );
257
    is( Koha::Holds->search({ reserve_id => $hold->{ reserve_id } })->count, 0,
256
    is( Koha::Holds->search({ id => $hold_id })->count, 0,
258
        "Koha::Hold->delete should have deleted the hold" );
257
        "Koha::Hold->delete should have deleted the hold" );
259
258
260
    $number_of_logs = $schema->resultset('ActionLog')->search(
259
    $number_of_logs = $schema->resultset('ActionLog')->search(
261
            { module => 'HOLDS', action => 'DELETE', object => $hold->{ reserve_id } } )->count;
260
            { module => 'HOLDS', action => 'DELETE', object => $hold_id } )->count;
262
    is( $number_of_logs, 1, 'With HoldsLogs, Koha::Hold->delete should have been logged' );
261
    is( $number_of_logs, 1, 'With HoldsLogs, Koha::Hold->delete should have been logged' );
263
262
264
    $schema->storage->txn_rollback();
263
    $schema->storage->txn_rollback();
Lines 274-281 subtest 'suspend() tests' => sub { Link Here
274
    t::lib::Mocks::mock_preference( 'HoldsLog', 0 );
273
    t::lib::Mocks::mock_preference( 'HoldsLog', 0 );
275
274
276
    my $hold = $builder->build_object(
275
    my $hold = $builder->build_object(
277
        {   class => 'Koha::Holds',
276
        {
278
            value => { found => undef, suspend => 0, suspend_until => undef, waitingdate => undef }
277
            class => 'Koha::Holds',
278
            value => {
279
                status               => 'placed',
280
                suspended            => 0,
281
                suspended_until_date => undef,
282
                waiting_date         => undef
283
            }
279
        }
284
        }
280
    );
285
    );
281
286
Lines 284-290 subtest 'suspend() tests' => sub { Link Here
284
    is( ref($suspended) , 'Koha::Hold', 'suspend returns the Koha::Hold object' );
289
    is( ref($suspended) , 'Koha::Hold', 'suspend returns the Koha::Hold object' );
285
    is( $suspended->id, $hold->id, 'suspend returns the same object' );
290
    is( $suspended->id, $hold->id, 'suspend returns the same object' );
286
    ok( $suspended->is_suspended, 'The hold is suspended' );
291
    ok( $suspended->is_suspended, 'The hold is suspended' );
287
    is( $suspended->suspend_until, undef, 'It is an indefinite suspension' );
292
    is( $suspended->suspended_until_date, undef, 'It is an indefinite suspension' );
288
293
289
    # resume the hold
294
    # resume the hold
290
    $suspended->resume;
295
    $suspended->resume;
Lines 296-302 subtest 'suspend() tests' => sub { Link Here
296
    is( ref($suspended) , 'Koha::Hold', 'suspend returns the Koha::Hold object' );
301
    is( ref($suspended) , 'Koha::Hold', 'suspend returns the Koha::Hold object' );
297
    is( $suspended->id, $hold->id, 'suspend returns the same object' );
302
    is( $suspended->id, $hold->id, 'suspend returns the same object' );
298
    ok( $suspended->is_suspended, 'The hold is suspended' );
303
    ok( $suspended->is_suspended, 'The hold is suspended' );
299
    is( $suspended->suspend_until, $date->truncate( to => 'day' ), 'It is an indefinite suspension' );
304
    is( $suspended->suspended_until_date, $date->truncate( to => 'day' ), 'It is an indefinite suspension' );
300
305
301
    # resume the hold
306
    # resume the hold
302
    $suspended->resume;
307
    $suspended->resume;
Lines 309-315 subtest 'suspend() tests' => sub { Link Here
309
        'Koha::Exceptions::Hold::CannotSuspendFound',
314
        'Koha::Exceptions::Hold::CannotSuspendFound',
310
        'Exception is thrown when a found hold is tried to suspend';
315
        'Exception is thrown when a found hold is tried to suspend';
311
316
312
    is( $@->status, 'W', 'Exception gets the \'status\' parameter set correctly' );
317
    is( $@->status, 'waiting', 'Exception gets the \'status\' parameter set correctly' );
313
318
314
    # set hold found=T
319
    # set hold found=T
315
    $hold->set_transfer;
320
    $hold->set_transfer;
Lines 318-324 subtest 'suspend() tests' => sub { Link Here
318
        'Koha::Exceptions::Hold::CannotSuspendFound',
323
        'Koha::Exceptions::Hold::CannotSuspendFound',
319
        'Exception is thrown when a found hold is tried to suspend';
324
        'Exception is thrown when a found hold is tried to suspend';
320
325
321
    is( $@->status, 'T', 'Exception gets the \'status\' parameter set correctly' );
326
    is( $@->status, 'in_transit', 'Exception gets the \'status\' parameter set correctly' );
322
327
323
    # set hold found=T
328
    # set hold found=T
324
    $hold->set_processing();
329
    $hold->set_processing();
Lines 333-339 subtest 'suspend() tests' => sub { Link Here
333
    $holds_module->mock( 'is_found', 1 );
338
    $holds_module->mock( 'is_found', 1 );
334
339
335
    # bad data case
340
    # bad data case
336
    $hold->found('X');
341
    $hold->status('cancelled');
337
    throws_ok
342
    throws_ok
338
        { $hold->suspend_hold }
343
        { $hold->suspend_hold }
339
        'Koha::Exceptions::Hold::CannotSuspendFound',
344
        'Koha::Exceptions::Hold::CannotSuspendFound',
Lines 341-348 subtest 'suspend() tests' => sub { Link Here
341
346
342
    is( $@->error, 'Unhandled data exception on found hold (id='
347
    is( $@->error, 'Unhandled data exception on found hold (id='
343
                    . $hold->id
348
                    . $hold->id
344
                    . ', found='
349
                    . ', status='
345
                    . $hold->found
350
                    . $hold->status
346
                    . ')' , 'Exception gets the \'status\' parameter set correctly' );
351
                    . ')' , 'Exception gets the \'status\' parameter set correctly' );
347
352
348
    $holds_module->unmock( 'is_found' );
353
    $holds_module->unmock( 'is_found' );
Lines 354-361 subtest 'suspend() tests' => sub { Link Here
354
            { module => 'HOLDS', action => 'SUSPEND', object => $hold->id } )->count;
359
            { module => 'HOLDS', action => 'SUSPEND', object => $hold->id } )->count;
355
360
356
    $hold = $builder->build_object(
361
    $hold = $builder->build_object(
357
        {   class => 'Koha::Holds',
362
        {
358
            value => { suspend => 0, suspend_until => undef, waitingdate => undef, found => undef }
363
            class => 'Koha::Holds',
364
            value => {
365
                suspended            => 0,
366
                suspended_until_date => undef,
367
                waiting_date         => undef,
368
                status               => 'placed'
369
            }
359
        }
370
        }
360
    );
371
    );
361
372
(-)a/t/db_dependent/Holds.t (-45 / +43 lines)
Lines 48-54 my $category = $builder->build({ source => 'Category' }); Link Here
48
my $borrowers_count = 5;
48
my $borrowers_count = 5;
49
49
50
$dbh->do('DELETE FROM itemtypes');
50
$dbh->do('DELETE FROM itemtypes');
51
$dbh->do('DELETE FROM reserves');
51
$dbh->do('DELETE FROM holds');
52
$dbh->do('DELETE FROM circulation_rules');
52
$dbh->do('DELETE FROM circulation_rules');
53
my $insert_sth = $dbh->prepare('INSERT INTO itemtypes (itemtype) VALUES (?)');
53
my $insert_sth = $dbh->prepare('INSERT INTO itemtypes (itemtype) VALUES (?)');
54
$insert_sth->execute('CAN');
54
$insert_sth->execute('CAN');
Lines 98-107 is( $holds->next->priority, 5, "Reserve 5 has a priority of 5" ); Link Here
98
my $item = Koha::Items->find( $itemnumber );
98
my $item = Koha::Items->find( $itemnumber );
99
$holds = $item->current_holds;
99
$holds = $item->current_holds;
100
my $first_hold = $holds->next;
100
my $first_hold = $holds->next;
101
my $reservedate = $first_hold->reservedate;
101
my $reservedate = $first_hold->created_date;
102
my $borrowernumber = $first_hold->borrowernumber;
102
my $borrowernumber = $first_hold->patron_id;
103
my $branch_1code = $first_hold->branchcode;
103
my $branch_1code = $first_hold->pickup_library_id;
104
my $reserve_id = $first_hold->reserve_id;
104
my $reserve_id = $first_hold->id;
105
is( $reservedate, output_pref({ dt => dt_from_string, dateformat => 'iso', dateonly => 1 }), "holds_placed_today should return a valid reserve date");
105
is( $reservedate, output_pref({ dt => dt_from_string, dateformat => 'iso', dateonly => 1 }), "holds_placed_today should return a valid reserve date");
106
is( $borrowernumber, $borrowernumbers[0], "holds_placed_today should return a valid borrowernumber");
106
is( $borrowernumber, $borrowernumbers[0], "holds_placed_today should return a valid borrowernumber");
107
is( $branch_1code, $branch_1, "holds_placed_today should return a valid branchcode");
107
is( $branch_1code, $branch_1, "holds_placed_today should return a valid branchcode");
Lines 118-138 ok( $hold_item == $hold->item(), "item method returns stashed item" ); Link Here
118
my $hold_branch = $hold->branch();
118
my $hold_branch = $hold->branch();
119
ok( $hold_branch, "Got branch using branch() method" );
119
ok( $hold_branch, "Got branch using branch() method" );
120
ok( $hold_branch == $hold->branch(), "branch method returns stashed branch" );
120
ok( $hold_branch == $hold->branch(), "branch method returns stashed branch" );
121
my $hold_found = $hold->found();
121
my $hold_found = $hold->status();
122
$hold->set({ found => 'W'})->store();
122
$hold->set({ status => 'waiting' })->store();
123
is( Koha::Holds->waiting()->count(), 1, "Koha::Holds->waiting returns waiting holds" );
123
is( Koha::Holds->waiting()->count(), 1, "Koha::Holds->waiting returns waiting holds" );
124
is( Koha::Holds->unfilled()->count(), 4, "Koha::Holds->unfilled returns unfilled holds" );
124
is( Koha::Holds->unfilled()->count(), 4, "Koha::Holds->unfilled returns unfilled holds" );
125
125
126
my $patron = Koha::Patrons->find( $borrowernumbers[0] );
126
my $patron = Koha::Patrons->find( $borrowernumbers[0] );
127
$holds = $patron->holds;
127
$holds = $patron->holds;
128
is( $holds->next->borrowernumber, $borrowernumbers[0], "Test Koha::Patron->holds");
128
is( $holds->next->patron_id, $borrowernumbers[0], "Test Koha::Patron->holds");
129
129
130
130
131
$holds = $item->current_holds;
131
$holds = $item->current_holds;
132
$first_hold = $holds->next;
132
$first_hold = $holds->next;
133
$borrowernumber = $first_hold->borrowernumber;
133
$borrowernumber = $first_hold->patron_id;
134
$branch_1code = $first_hold->branchcode;
134
$branch_1code = $first_hold->pickup_library_id;
135
$reserve_id = $first_hold->reserve_id;
135
$reserve_id = $first_hold->id;
136
136
137
ModReserve({
137
ModReserve({
138
    reserve_id    => $reserve_id,
138
    reserve_id    => $reserve_id,
Lines 144-151 ModReserve({ Link Here
144
144
145
$hold = Koha::Holds->find( $reserve_id );
145
$hold = Koha::Holds->find( $reserve_id );
146
ok( $hold->priority eq '4', "Test ModReserve, priority changed correctly" );
146
ok( $hold->priority eq '4', "Test ModReserve, priority changed correctly" );
147
ok( $hold->suspend, "Test ModReserve, suspend hold" );
147
ok( $hold->suspended, "Test ModReserve, suspend hold" );
148
is( $hold->suspend_until, '2013-01-01 00:00:00', "Test ModReserve, suspend until date" );
148
is( $hold->suspended_until_date, '2013-01-01 00:00:00', "Test ModReserve, suspend until date" );
149
149
150
ModReserve({ # call without reserve_id
150
ModReserve({ # call without reserve_id
151
    rank          => '3',
151
    rank          => '3',
Lines 158-172 ok( $hold->priority eq '3', "Test ModReserve, priority changed correctly" ); Link Here
158
158
159
ToggleSuspend( $reserve_id );
159
ToggleSuspend( $reserve_id );
160
$hold = Koha::Holds->find( $reserve_id );
160
$hold = Koha::Holds->find( $reserve_id );
161
ok( ! $hold->suspend, "Test ToggleSuspend(), no date" );
161
ok( ! $hold->suspended, "Test ToggleSuspend(), no date" );
162
162
163
ToggleSuspend( $reserve_id, '2012-01-01' );
163
ToggleSuspend( $reserve_id, '2012-01-01' );
164
$hold = Koha::Holds->find( $reserve_id );
164
$hold = Koha::Holds->find( $reserve_id );
165
is( $hold->suspend_until, '2012-01-01 00:00:00', "Test ToggleSuspend(), with date" );
165
is( $hold->suspended_until_date, '2012-01-01 00:00:00', "Test ToggleSuspend(), with date" );
166
166
167
AutoUnsuspendReserves();
167
AutoUnsuspendReserves();
168
$hold = Koha::Holds->find( $reserve_id );
168
$hold = Koha::Holds->find( $reserve_id );
169
ok( ! $hold->suspend, "Test AutoUnsuspendReserves()" );
169
ok( ! $hold->suspended, "Test AutoUnsuspendReserves()" );
170
170
171
SuspendAll(
171
SuspendAll(
172
    borrowernumber => $borrowernumber,
172
    borrowernumber => $borrowernumber,
Lines 175-182 SuspendAll( Link Here
175
    suspend_until => '2012-01-01',
175
    suspend_until => '2012-01-01',
176
);
176
);
177
$hold = Koha::Holds->find( $reserve_id );
177
$hold = Koha::Holds->find( $reserve_id );
178
is( $hold->suspend, 1, "Test SuspendAll()" );
178
is( $hold->suspended, 1, "Test SuspendAll()" );
179
is( $hold->suspend_until, '2012-01-01 00:00:00', "Test SuspendAll(), with date" );
179
is( $hold->suspended_until_date, '2012-01-01 00:00:00', "Test SuspendAll(), with date" );
180
180
181
SuspendAll(
181
SuspendAll(
182
    borrowernumber => $borrowernumber,
182
    borrowernumber => $borrowernumber,
Lines 184-191 SuspendAll( Link Here
184
    suspend => 0,
184
    suspend => 0,
185
);
185
);
186
$hold = Koha::Holds->find( $reserve_id );
186
$hold = Koha::Holds->find( $reserve_id );
187
is( $hold->suspend, 0, "Test resuming with SuspendAll()" );
187
is( $hold->suspended, 0, "Test resuming with SuspendAll()" );
188
is( $hold->suspend_until, undef, "Test resuming with SuspendAll(), should have no suspend until date" );
188
is( $hold->suspended_until_date, undef, "Test resuming with SuspendAll(), should have no suspend until date" );
189
189
190
# Add a new hold for the borrower whose hold we canceled earlier, this time at the bib level
190
# Add a new hold for the borrower whose hold we canceled earlier, this time at the bib level
191
    AddReserve(
191
    AddReserve(
Lines 198-223 is( $hold->suspend_until, undef, "Test resuming with SuspendAll(), should have n Link Here
198
198
199
$patron = Koha::Patrons->find( $borrowernumber );
199
$patron = Koha::Patrons->find( $borrowernumber );
200
$holds = $patron->holds;
200
$holds = $patron->holds;
201
my $reserveid = Koha::Holds->search({ biblionumber => $biblio->biblionumber, borrowernumber => $borrowernumbers[0] })->next->reserve_id;
201
my $reserveid = Koha::Holds->search({ biblio_id => $biblio->biblionumber, patron_id => $borrowernumbers[0] })->next->id;
202
ModReserveMinusPriority( $itemnumber, $reserveid );
202
ModReserveMinusPriority( $itemnumber, $reserveid );
203
$holds = $patron->holds;
203
$holds = $patron->holds;
204
is( $holds->search({ itemnumber => $itemnumber })->count, 1, "Test ModReserveMinusPriority()" );
204
is( $holds->search({ item_id => $itemnumber })->count, 1, "Test ModReserveMinusPriority()" );
205
205
206
$holds = $biblio->holds;
206
$holds = $biblio->holds;
207
$hold = $holds->next;
207
$hold = $holds->next;
208
AlterPriority( 'top', $hold->reserve_id, undef, 2, 1, 6 );
208
AlterPriority( 'top', $hold->id, undef, 2, 1, 6 );
209
$hold = Koha::Holds->find( $reserveid );
209
$hold = Koha::Holds->find( $reserveid );
210
is( $hold->priority, '1', "Test AlterPriority(), move to top" );
210
is( $hold->priority, '1', "Test AlterPriority(), move to top" );
211
211
212
AlterPriority( 'down', $hold->reserve_id, undef, 2, 1, 6 );
212
AlterPriority( 'down', $hold->id, undef, 2, 1, 6 );
213
$hold = Koha::Holds->find( $reserveid );
213
$hold = Koha::Holds->find( $reserveid );
214
is( $hold->priority, '2', "Test AlterPriority(), move down" );
214
is( $hold->priority, '2', "Test AlterPriority(), move down" );
215
215
216
AlterPriority( 'up', $hold->reserve_id, 1, 3, 1, 6 );
216
AlterPriority( 'up', $hold->id, 1, 3, 1, 6 );
217
$hold = Koha::Holds->find( $reserveid );
217
$hold = Koha::Holds->find( $reserveid );
218
is( $hold->priority, '1', "Test AlterPriority(), move up" );
218
is( $hold->priority, '1', "Test AlterPriority(), move up" );
219
219
220
AlterPriority( 'bottom', $hold->reserve_id, undef, 2, 1, 6 );
220
AlterPriority( 'bottom', $hold->id, undef, 2, 1, 6 );
221
$hold = Koha::Holds->find( $reserveid );
221
$hold = Koha::Holds->find( $reserveid );
222
is( $hold->priority, '6', "Test AlterPriority(), move to bottom" );
222
is( $hold->priority, '6', "Test AlterPriority(), move to bottom" );
223
223
Lines 317-323 ok( Link Here
317
        }
317
        }
318
    );
318
    );
319
319
320
    my $hhh = Koha::Holds->search({ biblionumber => $biblio->biblionumber });
320
    my $hhh = Koha::Holds->search({ biblio_id => $biblio->biblionumber });
321
    my $hold3 = Koha::Holds->find( $reserveid3 );
321
    my $hold3 = Koha::Holds->find( $reserveid3 );
322
    is( $hold3->priority, 3, "The 3rd hold should have a priority set to 3" );
322
    is( $hold3->priority, 3, "The 3rd hold should have a priority set to 3" );
323
    ModReserve({ reserve_id => $reserveid1, rank => 'del' });
323
    ModReserve({ reserve_id => $reserveid1, rank => 'del' });
Lines 332-340 ok( defined( ( CheckReserves($itemnumber) )[1] ), "Hold can be trapped for damag Link Here
332
332
333
$hold = Koha::Hold->new(
333
$hold = Koha::Hold->new(
334
    {
334
    {
335
        borrowernumber => $borrowernumbers[0],
335
        patron_id => $borrowernumbers[0],
336
        itemnumber     => $itemnumber,
336
        item_id   => $itemnumber,
337
        biblionumber   => $biblio->biblionumber,
337
        biblio_id => $biblio->biblionumber,
338
    }
338
    }
339
)->store();
339
)->store();
340
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status},
340
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber )->{status},
Lines 349-365 ok( !defined( ( CheckReserves($itemnumber) )[1] ), "Hold cannot be trapped for d Link Here
349
# Items that are not for loan, but holdable should not be trapped until they are available for loan
349
# Items that are not for loan, but holdable should not be trapped until they are available for loan
350
t::lib::Mocks::mock_preference( 'TrapHoldsOnOrder', 0 );
350
t::lib::Mocks::mock_preference( 'TrapHoldsOnOrder', 0 );
351
Koha::Items->find($itemnumber)->damaged(0)->notforloan(-1)->store;
351
Koha::Items->find($itemnumber)->damaged(0)->notforloan(-1)->store;
352
Koha::Holds->search({ biblionumber => $biblio->id })->delete();
352
Koha::Holds->search({ biblio_id => $biblio->id })->delete();
353
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber)->{status}, 'OK', "Patron can place hold on item that is not for loan but holdable ( notforloan < 0 )" );
353
is( CanItemBeReserved( $borrowernumbers[0], $itemnumber)->{status}, 'OK', "Patron can place hold on item that is not for loan but holdable ( notforloan < 0 )" );
354
$hold = Koha::Hold->new(
354
$hold = Koha::Hold->new(
355
    {
355
    {
356
        borrowernumber => $borrowernumbers[0],
356
        patron_id         => $borrowernumbers[0],
357
        itemnumber     => $itemnumber,
357
        item_id           => $itemnumber,
358
        biblionumber   => $biblio->biblionumber,
358
        biblio_id         => $biblio->biblionumber,
359
        found          => undef,
359
        priority          => 1,
360
        priority       => 1,
360
        pickup_library_id => $branch_1,
361
        reservedate    => dt_from_string,
362
        branchcode     => $branch_1,
363
    }
361
    }
364
)->store();
362
)->store();
365
ok( !defined( ( CheckReserves($itemnumber) )[1] ), "Hold cannot be trapped for item that is not for loan but holdable ( notforloan < 0 )" );
363
ok( !defined( ( CheckReserves($itemnumber) )[1] ), "Hold cannot be trapped for item that is not for loan but holdable ( notforloan < 0 )" );
Lines 474-480 subtest 'CanItemBeReserved' => sub { Link Here
474
        my $itemnumber_2_cannot = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_cant, biblionumber => $biblionumber_can })->itemnumber;
472
        my $itemnumber_2_cannot = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_cant, biblionumber => $biblionumber_can })->itemnumber;
475
        my $itemnumber_3_cannot = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_cant_record, biblionumber => $biblionumber_record_cannot })->itemnumber;
473
        my $itemnumber_3_cannot = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_cant_record, biblionumber => $biblionumber_record_cannot })->itemnumber;
476
474
477
        Koha::Holds->search({borrowernumber => $borrowernumbers[0]})->delete;
475
        Koha::Holds->search({patron_id => $borrowernumbers[0]})->delete;
478
476
479
        t::lib::Mocks::mock_preference('item-level_itypes', 1);
477
        t::lib::Mocks::mock_preference('item-level_itypes', 1);
480
        is(
478
        is(
Lines 510-516 subtest 'CanItemBeReserved' => sub { Link Here
510
        my $itemnumber_21 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_2 })->itemnumber;
508
        my $itemnumber_21 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_2 })->itemnumber;
511
        my $itemnumber_22 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_2 })->itemnumber;
509
        my $itemnumber_22 = $builder->build_sample_item({ homebranch => $branch_1, holdingbranch => $branch_1, itype => $itemtype_can, biblionumber => $biblionumber_2 })->itemnumber;
512
510
513
        Koha::Holds->search({borrowernumber => $borrowernumbers[0]})->delete;
511
        Koha::Holds->search({patron_id => $borrowernumbers[0]})->delete;
514
512
515
        # Biblio-level hold
513
        # Biblio-level hold
516
        AddReserve({
514
        AddReserve({
Lines 527-533 subtest 'CanItemBeReserved' => sub { Link Here
527
            );
525
            );
528
        }
526
        }
529
527
530
        Koha::Holds->search({borrowernumber => $borrowernumbers[0]})->delete;
528
        Koha::Holds->search({patron_id => $borrowernumbers[0]})->delete;
531
        # Item-level hold
529
        # Item-level hold
532
        AddReserve({
530
        AddReserve({
533
            branch => $branch_1,
531
            branch => $branch_1,
Lines 669-675 is(CanItemBeReserved($borrowernumbers[0], $itemnumber)->{status}, 'OK', Link Here
669
t::lib::Mocks::mock_preference( 'item-level_itypes',     1 );
667
t::lib::Mocks::mock_preference( 'item-level_itypes',     1 );
670
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'PatronLibrary' );
668
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'PatronLibrary' );
671
669
672
$dbh->do('DELETE FROM reserves');
670
$dbh->do('DELETE FROM holds');
673
$dbh->do('DELETE FROM issues');
671
$dbh->do('DELETE FROM issues');
674
$dbh->do('DELETE FROM items');
672
$dbh->do('DELETE FROM items');
675
$dbh->do('DELETE FROM biblio');
673
$dbh->do('DELETE FROM biblio');
Lines 715-721 t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'PatronLibrary' ); Link Here
715
subtest 'Test max_holds per library/patron category' => sub {
713
subtest 'Test max_holds per library/patron category' => sub {
716
    plan tests => 6;
714
    plan tests => 6;
717
715
718
    $dbh->do('DELETE FROM reserves');
716
    $dbh->do('DELETE FROM holds');
719
717
720
    $biblio = $builder->build_sample_biblio;
718
    $biblio = $builder->build_sample_biblio;
721
    $itemnumber = $builder->build_sample_item({ library => $branch_1, biblionumber => $biblio->biblionumber})->itemnumber;
719
    $itemnumber = $builder->build_sample_item({ library => $branch_1, biblionumber => $biblio->biblionumber})->itemnumber;
Lines 743-749 subtest 'Test max_holds per library/patron category' => sub { Link Here
743
    }
741
    }
744
742
745
    my $count =
743
    my $count =
746
      Koha::Holds->search( { borrowernumber => $borrowernumbers[0] } )->count();
744
      Koha::Holds->search( { patron_id => $borrowernumbers[0] } )->count();
747
    is( $count, 3, 'Patron now has 3 holds' );
745
    is( $count, 3, 'Patron now has 3 holds' );
748
746
749
    my $ret = CanItemBeReserved( $borrowernumbers[0], $itemnumber );
747
    my $ret = CanItemBeReserved( $borrowernumbers[0], $itemnumber );
Lines 928-934 subtest 'CanItemBeReserved / holds_per_day tests' => sub { Link Here
928
    # Update last hold so reservedate is in the past, so 2 holds, but different day
926
    # Update last hold so reservedate is in the past, so 2 holds, but different day
929
    $hold = Koha::Holds->find($res_id);
927
    $hold = Koha::Holds->find($res_id);
930
    my $yesterday = dt_from_string() - DateTime::Duration->new( days => 1 );
928
    my $yesterday = dt_from_string() - DateTime::Duration->new( days => 1 );
931
    $hold->reservedate($yesterday)->store;
929
    $hold->created_date($yesterday)->store;
932
930
933
    is_deeply(
931
    is_deeply(
934
        CanItemBeReserved( $patron->borrowernumber, $itemnumber_2 ),
932
        CanItemBeReserved( $patron->borrowernumber, $itemnumber_2 ),
(-)a/t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t (-3 / +3 lines)
Lines 290-299 my $itemtype2 = $builder->build( Link Here
290
my $item3 = $builder->build_sample_item( { itype => $itemtype2 } );
290
my $item3 = $builder->build_sample_item( { itype => $itemtype2 } );
291
291
292
my $hold = $builder->build(
292
my $hold = $builder->build(
293
    {   source => 'Reserve',
293
    {   source => 'Hold',
294
        value  => {
294
        value  => {
295
            itemnumber => $item3->itemnumber,
295
            item_id => $item3->itemnumber,
296
            found      => 'T'
296
            status  => 'in_transit'
297
        }
297
        }
298
    }
298
    }
299
);
299
);
(-)a/t/db_dependent/Holds/HoldItemtypeLimit.t (-1 / +1 lines)
Lines 57-63 my $right_itemtype = $itemtype1->{itemtype}; Link Here
57
my $wrong_itemtype = $itemtype2->{itemtype};
57
my $wrong_itemtype = $itemtype2->{itemtype};
58
my $borrowernumber = $borrower->{borrowernumber};
58
my $borrowernumber = $borrower->{borrowernumber};
59
my $branchcode = $library->{branchcode};
59
my $branchcode = $library->{branchcode};
60
$dbh->do("DELETE FROM reserves");
60
$dbh->do("DELETE FROM holds");
61
$dbh->do("DELETE FROM issues");
61
$dbh->do("DELETE FROM issues");
62
$dbh->do("DELETE FROM items");
62
$dbh->do("DELETE FROM items");
63
$dbh->do("DELETE FROM biblio");
63
$dbh->do("DELETE FROM biblio");
(-)a/t/db_dependent/Holds/LocalHoldsPriority.t (-6 / +6 lines)
Lines 85-113 my ($status, $reserve, $all_reserves); Link Here
85
85
86
t::lib::Mocks::mock_preference( 'LocalHoldsPriority', 0 );
86
t::lib::Mocks::mock_preference( 'LocalHoldsPriority', 0 );
87
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
87
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
88
ok( $reserve->{borrowernumber} eq $borrowernumbers[0], "Received expected results with LocalHoldsPriority disabled" );
88
ok( $reserve->{patron_id} eq $borrowernumbers[0], "Received expected results with LocalHoldsPriority disabled" );
89
89
90
t::lib::Mocks::mock_preference( 'LocalHoldsPriority', 1 );
90
t::lib::Mocks::mock_preference( 'LocalHoldsPriority', 1 );
91
91
92
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'PickupLibrary' );
92
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'PickupLibrary' );
93
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'homebranch' );
93
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'homebranch' );
94
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
94
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
95
ok( $reserve->{borrowernumber} eq $borrowernumbers[2], "Received expected results with PickupLibrary/homebranch" );
95
ok( $reserve->{patron_id} eq $borrowernumbers[2], "Received expected results with PickupLibrary/homebranch" );
96
96
97
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'PickupLibrary' );
97
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'PickupLibrary' );
98
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'holdingbranch' );
98
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'holdingbranch' );
99
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
99
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
100
ok( $reserve->{borrowernumber} eq $borrowernumbers[1], "Received expected results with PickupLibrary/holdingbranch" );
100
ok( $reserve->{patron_id} eq $borrowernumbers[1], "Received expected results with PickupLibrary/holdingbranch" );
101
101
102
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'HomeLibrary' );
102
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'HomeLibrary' );
103
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'holdingbranch' );
103
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'holdingbranch' );
104
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
104
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
105
ok( $reserve->{borrowernumber} eq $borrowernumbers[2], "Received expected results with HomeLibrary/holdingbranch" );
105
ok( $reserve->{patron_id} eq $borrowernumbers[2], "Received expected results with HomeLibrary/holdingbranch" );
106
106
107
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'HomeLibrary' );
107
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityPatronControl', 'HomeLibrary' );
108
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'homebranch' );
108
t::lib::Mocks::mock_preference( 'LocalHoldsPriorityItemControl', 'homebranch' );
109
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
109
($status, $reserve, $all_reserves) = CheckReserves($itemnumber);
110
ok( $reserve->{borrowernumber} eq $borrowernumbers[3], "Received expected results with HomeLibrary/homebranch" );
110
ok( $reserve->{patron_id} eq $borrowernumbers[3], "Received expected results with HomeLibrary/homebranch" );
111
111
112
$schema->storage->txn_rollback;
112
$schema->storage->txn_rollback;
113
113
Lines 208-211 subtest "exclude from local holds" => sub { Link Here
208
    is($reserve->{borrowernumber}, $patron_nex_l2->borrowernumber, "Patron from other library is next checkout because item is excluded");
208
    is($reserve->{borrowernumber}, $patron_nex_l2->borrowernumber, "Patron from other library is next checkout because item is excluded");
209
209
210
    $schema->storage->txn_rollback;
210
    $schema->storage->txn_rollback;
211
};
211
};
(-)a/t/db_dependent/Holds/RevertWaitingStatus.t (-2 / +1 lines)
Lines 34-41 $schema->storage->txn_begin; Link Here
34
my $builder = t::lib::TestBuilder->new;
34
my $builder = t::lib::TestBuilder->new;
35
my $dbh = C4::Context->dbh;
35
my $dbh = C4::Context->dbh;
36
36
37
$dbh->do("DELETE FROM reserves");
37
$dbh->do("DELETE FROM holds");
38
$dbh->do("DELETE FROM old_reserves");
39
38
40
my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode};
39
my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode};
41
my $itemtype = $builder->build(
40
my $itemtype = $builder->build(
(-)a/t/db_dependent/Holds/WaitingReserves.t (-46 / +50 lines)
Lines 18-24 $schema->storage->txn_begin; Link Here
18
my $dbh = C4::Context->dbh;
18
my $dbh = C4::Context->dbh;
19
$dbh->do(q{DELETE FROM special_holidays});
19
$dbh->do(q{DELETE FROM special_holidays});
20
$dbh->do(q{DELETE FROM repeatable_holidays});
20
$dbh->do(q{DELETE FROM repeatable_holidays});
21
$dbh->do("DELETE FROM reserves");
21
$dbh->do(q{DELETE FROM holds});
22
22
23
my $builder = t::lib::TestBuilder->new();
23
my $builder = t::lib::TestBuilder->new();
24
24
Lines 77-92 $reserve1_reservedate->subtract(days => 20); Link Here
77
my $reserve1_expirationdate = $today->clone;
77
my $reserve1_expirationdate = $today->clone;
78
$reserve1_expirationdate->add(days => 6);
78
$reserve1_expirationdate->add(days => 6);
79
79
80
my $reserve1 = $builder->build({
80
my $r = $builder->build_object({
81
    source => 'Reserve',
81
    class => 'Koha::Holds',
82
    value => {
82
    value => {
83
        borrowernumber => $patron1->{borrowernumber},
83
        patron_id => $patron1->{borrowernumber},
84
        reservedate => $reserve1_reservedate->ymd,
84
        created_date => $reserve1_reservedate->ymd,
85
        expirationdate => undef,
85
        expiration_date => undef,
86
        biblionumber => $biblio->biblionumber,
86
        biblio_id => $biblio->biblionumber,
87
        branchcode => 'LIB1',
87
        pickup_library_id => 'LIB1',
88
        priority => 1,
88
        priority => 1,
89
        found => '',
89
        status => 'placed',
90
        completed => 0
90
    },
91
    },
91
});
92
});
92
93
Lines 94-137 t::lib::Mocks::mock_preference('ExpireReservesMaxPickUpDelay', 1); Link Here
94
t::lib::Mocks::mock_preference('ReservesMaxPickUpDelay', 6);
95
t::lib::Mocks::mock_preference('ReservesMaxPickUpDelay', 6);
95
96
96
ModReserveAffect( $item1->itemnumber, $patron1->{borrowernumber});
97
ModReserveAffect( $item1->itemnumber, $patron1->{borrowernumber});
97
my $r = Koha::Holds->find($reserve1->{reserve_id});
98
$r->discard_changes;
98
99
99
is($r->waitingdate, $today->ymd, 'Waiting date should be set to today' );
100
is($r->waiting_date, $today->ymd, 'Waiting date should be set to today' );
100
is($r->expirationdate, $reserve1_expirationdate->ymd, 'Expiration date should be set to today + 6' );
101
is($r->expiration_date, $reserve1_expirationdate->ymd, 'Expiration date should be set to today + 6' );
101
is($r->found, 'W', 'Reserve status is now "waiting"' );
102
is($r->status, 'waiting', 'Reserve status is now "waiting"' );
102
is($r->priority, 0, 'Priority should be 0' );
103
is($r->priority, 0, 'Priority should be 0' );
103
is($r->itemnumber, $item1->itemnumber, 'Item number should be set correctly' );
104
is($r->item_id, $item1->itemnumber, 'Item number should be set correctly' );
104
105
105
my $reserve2 = $builder->build({
106
my $r2 = $builder->build_object({
106
    source => 'Reserve',
107
    class => 'Koha::Holds',
107
    value => {
108
    value => {
108
        borrowernumber => $patron2->{borrowernumber},
109
        patron_id => $patron2->{borrowernumber},
109
        reservedate => $reserve1_reservedate->ymd,
110
        created_date => $reserve1_reservedate->ymd,
110
        expirationdate => undef,
111
        expiration_date => undef,
111
        biblionumber => $biblio2->biblionumber,
112
        biblio_id => $biblio2->biblionumber,
112
        branchcode => 'LIB1',
113
        pickup_library_id => 'LIB1',
113
        priority => 1,
114
        priority => 1,
114
        found => '',
115
        status => 'placed',
116
        completed => 0
115
    },
117
    },
116
});
118
});
117
119
118
ModReserveAffect( $item2->itemnumber, $patron2->{borrowernumber}, 1);
120
ModReserveAffect( $item2->itemnumber, $patron2->{borrowernumber}, 1);
119
my $r2 = Koha::Holds->find($reserve2->{reserve_id});
121
$r2->discard_changes;
120
122
121
is($r2->found, 'T', '2nd reserve - Reserve status is now "To transfer"' );
123
is($r2->status, 'in_transit', '2nd reserve - Reserve status is now "To transfer"' );
122
is($r2->priority, 0, '2nd reserve - Priority should be 0' );
124
is($r2->priority, 0, '2nd reserve - Priority should be 0' );
123
is($r2->itemnumber, $item2->itemnumber, '2nd reserve - Item number should be set correctly' );
125
is($r2->item_id, $item2->itemnumber, '2nd reserve - Item number should be set correctly' );
124
126
125
my $reserve3 = $builder->build({
127
my $r3 = $builder->build_object({
126
    source => 'Reserve',
128
    class => 'Koha::Holds',
127
    value => {
129
    value => {
128
        borrowernumber => $patron2->{borrowernumber},
130
        patron_id => $patron2->{borrowernumber},
129
        reservedate => $reserve1_reservedate->ymd,
131
        created_date => $reserve1_reservedate->ymd,
130
        expirationdate => undef,
132
        expiration_date => undef,
131
        biblionumber => $biblio3->biblionumber,
133
        biblio_id => $biblio3->biblionumber,
132
        branchcode => 'LIB1',
134
        pickup_library_id => 'LIB1',
133
        priority => 1,
135
        priority => 1,
134
        found => '',
136
        status => 'placed',
137
        completed => 0
135
    },
138
    },
136
});
139
});
137
140
Lines 174-202 ModReserveAffect( $item3->itemnumber, $patron2->{borrowernumber}); Link Here
174
my $expected_expiration = $today->clone;
177
my $expected_expiration = $today->clone;
175
$expected_expiration->add(days => 8);
178
$expected_expiration->add(days => 8);
176
179
177
my $r3 = Koha::Holds->find($reserve3->{reserve_id});
180
$r3->discard_changes;
178
is($r3->expirationdate, $expected_expiration->ymd, 'Expiration date should be set to today + 7' );
181
is($r3->expiration_date, $expected_expiration->ymd, 'Expiration date should be set to today + 7' );
179
182
180
my $reserve4_reservedate = $today->clone;
183
my $reserve4_reservedate = $today->clone;
181
my $requested_expiredate = $today->clone()->add(days => 6);
184
my $requested_expiredate = $today->clone()->add(days => 6);
182
185
183
my $reserve4 = $builder->build({
186
my $r4 = $builder->build_object({
184
    source => 'Reserve',
187
    class => 'Koha::Holds',
185
    value => {
188
    value => {
186
        borrowernumber => $patron2->{borrowernumber},
189
        patron_id => $patron2->{borrowernumber},
187
        reservedate => $reserve4_reservedate->ymd,
190
        created_date => $reserve4_reservedate->ymd,
188
        expirationdate => $requested_expiredate->ymd,
191
        expiration_date => $requested_expiredate->ymd,
189
        biblionumber => $biblio4->biblionumber,
192
        biblio_id => $biblio4->biblionumber,
190
        branchcode => 'LIB1',
193
        pickup_library_id => 'LIB1',
191
        priority => 1,
194
        priority => 1,
192
        found => '',
195
        status => 'placed',
196
        completed => 0
193
    },
197
    },
194
});
198
});
195
199
196
t::lib::Mocks::mock_preference('ReservesMaxPickUpDelay', 10);
200
t::lib::Mocks::mock_preference('ReservesMaxPickUpDelay', 10);
197
ModReserveAffect( $item4->itemnumber, $patron2->{borrowernumber}, 0, $reserve4->{reserve_id});
201
ModReserveAffect( $item4->itemnumber, $patron2->{borrowernumber}, 0, $r4->id );
198
202
199
my $r4 = Koha::Holds->find($reserve4->{reserve_id});
203
$r4->discard_changes;
200
is($r4->expirationdate, $requested_expiredate->ymd, 'Requested expiration date should be kept' );
204
is($r4->expiration_date, $requested_expiredate->ymd, 'Requested expiration date should be kept' );
201
205
202
$schema->storage->txn_rollback;
206
$schema->storage->txn_rollback;
(-)a/t/db_dependent/HoldsQueue.t (-25 / +24 lines)
Lines 111-117 foreach ( $borrower_branchcode, $least_cost_branch_code, @other_branches ) { Link Here
111
}
111
}
112
112
113
# Remove existing reserves, makes debugging easier
113
# Remove existing reserves, makes debugging easier
114
$dbh->do("DELETE FROM reserves");
114
$dbh->do("DELETE FROM holds");
115
my $bibitems = undef;
115
my $bibitems = undef;
116
my $priority = 1;
116
my $priority = 1;
117
# Make a reserve
117
# Make a reserve
Lines 124-130 AddReserve( Link Here
124
    }
124
    }
125
);
125
);
126
#                           $resdate, $expdate, $notes, $title, $checkitem, $found
126
#                           $resdate, $expdate, $notes, $title, $checkitem, $found
127
$dbh->do("UPDATE reserves SET reservedate = DATE_SUB( reservedate, INTERVAL 1 DAY )");
127
$dbh->do("UPDATE holds SET created_date = DATE_SUB( created_date, INTERVAL 1 DAY )");
128
128
129
# Tests
129
# Tests
130
my $use_cost_matrix_sth = $dbh->prepare("UPDATE systempreferences SET value = ? WHERE variable = 'UseTransportCostMatrix'");
130
my $use_cost_matrix_sth = $dbh->prepare("UPDATE systempreferences SET value = ? WHERE variable = 'UseTransportCostMatrix'");
Lines 289-302 $items_insert_sth->execute( $barcode + 0, $branchcodes[0], $branchcodes[0] ); Link Here
289
$items_insert_sth->execute( $barcode + 1, $branchcodes[1], $branchcodes[1] );
289
$items_insert_sth->execute( $barcode + 1, $branchcodes[1], $branchcodes[1] );
290
$items_insert_sth->execute( $barcode + 2, $branchcodes[1], $branchcodes[1] );
290
$items_insert_sth->execute( $barcode + 2, $branchcodes[1], $branchcodes[1] );
291
291
292
$dbh->do("DELETE FROM reserves");
292
$dbh->do("DELETE FROM holds");
293
my $sth = $dbh->prepare(q{
293
my $sth = $dbh->prepare(q{
294
    INSERT INTO reserves (
294
    INSERT INTO holds (
295
        borrowernumber,
295
        patron_id,
296
        biblionumber,
296
        biblio_id,
297
        branchcode,
297
        pickup_library_id,
298
        priority,
298
        priority,
299
        reservedate
299
        created_date
300
    ) VALUES ( ?,?,?,?, CURRENT_DATE() )
300
    ) VALUES ( ?,?,?,?, CURRENT_DATE() )
301
});
301
});
302
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
302
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
Lines 384-390 $dbh->do("DELETE FROM issues"); Link Here
384
t::lib::Mocks::mock_preference('LocalHoldsPriorityPatronControl', 'HomeLibrary');
384
t::lib::Mocks::mock_preference('LocalHoldsPriorityPatronControl', 'HomeLibrary');
385
t::lib::Mocks::mock_preference('LocalHoldsPriorityItemControl', 'homebranch');
385
t::lib::Mocks::mock_preference('LocalHoldsPriorityItemControl', 'homebranch');
386
C4::Context->clear_syspref_cache();
386
C4::Context->clear_syspref_cache();
387
$dbh->do("DELETE FROM reserves");
387
$dbh->do("DELETE FROM holds");
388
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
388
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
389
$sth->execute( $borrower2->{borrowernumber}, $biblionumber, $branchcodes[0], 2 );
389
$sth->execute( $borrower2->{borrowernumber}, $biblionumber, $branchcodes[0], 2 );
390
$sth->execute( $borrower3->{borrowernumber}, $biblionumber, $branchcodes[0], 3 );
390
$sth->execute( $borrower3->{borrowernumber}, $biblionumber, $branchcodes[0], 3 );
Lines 402-408 t::lib::Mocks::mock_preference('LocalHoldsPriorityPatronControl', 'HomeLibrary') Link Here
402
t::lib::Mocks::mock_preference('LocalHoldsPriorityItemControl', 'holdingbranch');
402
t::lib::Mocks::mock_preference('LocalHoldsPriorityItemControl', 'holdingbranch');
403
t::lib::Mocks::mock_preference( 'UseBranchTransferLimits', '1' );
403
t::lib::Mocks::mock_preference( 'UseBranchTransferLimits', '1' );
404
C4::Context->clear_syspref_cache();
404
C4::Context->clear_syspref_cache();
405
$dbh->do("DELETE FROM reserves");
405
$dbh->do("DELETE FROM holds");
406
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
406
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
407
$sth->execute( $borrower2->{borrowernumber}, $biblionumber, $branchcodes[1], 2 );
407
$sth->execute( $borrower2->{borrowernumber}, $biblionumber, $branchcodes[1], 2 );
408
408
Lines 444-450 t::lib::Mocks::mock_preference( 'UseBranchTransferLimits', '0' ); Link Here
444
t::lib::Mocks::mock_preference('LocalHoldsPriorityPatronControl', 'HomeLibrary');
444
t::lib::Mocks::mock_preference('LocalHoldsPriorityPatronControl', 'HomeLibrary');
445
t::lib::Mocks::mock_preference('LocalHoldsPriorityItemControl', 'holdingbranch');
445
t::lib::Mocks::mock_preference('LocalHoldsPriorityItemControl', 'holdingbranch');
446
C4::Context->clear_syspref_cache();
446
C4::Context->clear_syspref_cache();
447
$dbh->do("DELETE FROM reserves");
447
$dbh->do("DELETE FROM holds");
448
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
448
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
449
$sth->execute( $borrower2->{borrowernumber}, $biblionumber, $branchcodes[0], 2 );
449
$sth->execute( $borrower2->{borrowernumber}, $biblionumber, $branchcodes[0], 2 );
450
$sth->execute( $borrower3->{borrowernumber}, $biblionumber, $branchcodes[0], 3 );
450
$sth->execute( $borrower3->{borrowernumber}, $biblionumber, $branchcodes[0], 3 );
Lines 461-467 is( $holds_queue->[0]->{cardnumber}, $borrower3->{cardnumber}, "Holds queue givi Link Here
461
t::lib::Mocks::mock_preference('LocalHoldsPriorityPatronControl', 'PickupLibrary');
461
t::lib::Mocks::mock_preference('LocalHoldsPriorityPatronControl', 'PickupLibrary');
462
t::lib::Mocks::mock_preference('LocalHoldsPriorityItemControl', 'holdingbranch');
462
t::lib::Mocks::mock_preference('LocalHoldsPriorityItemControl', 'holdingbranch');
463
C4::Context->clear_syspref_cache();
463
C4::Context->clear_syspref_cache();
464
$dbh->do("DELETE FROM reserves");
464
$dbh->do("DELETE FROM holds");
465
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
465
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
466
$sth->execute( $borrower2->{borrowernumber}, $biblionumber, $branchcodes[0], 2 );
466
$sth->execute( $borrower2->{borrowernumber}, $biblionumber, $branchcodes[0], 2 );
467
$sth->execute( $borrower3->{borrowernumber}, $biblionumber, $branchcodes[2], 3 );
467
$sth->execute( $borrower3->{borrowernumber}, $biblionumber, $branchcodes[2], 3 );
Lines 478-484 is( $holds_queue->[0]->{cardnumber}, $borrower3->{cardnumber}, "Holds queue givi Link Here
478
t::lib::Mocks::mock_preference('LocalHoldsPriorityPatronControl', 'PickupLibrary');
478
t::lib::Mocks::mock_preference('LocalHoldsPriorityPatronControl', 'PickupLibrary');
479
t::lib::Mocks::mock_preference('LocalHoldsPriorityItemControl', 'homebranch');
479
t::lib::Mocks::mock_preference('LocalHoldsPriorityItemControl', 'homebranch');
480
C4::Context->clear_syspref_cache();
480
C4::Context->clear_syspref_cache();
481
$dbh->do("DELETE FROM reserves");
481
$dbh->do("DELETE FROM holds");
482
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
482
$sth->execute( $borrower1->{borrowernumber}, $biblionumber, $branchcodes[0], 1 );
483
$sth->execute( $borrower2->{borrowernumber}, $biblionumber, $branchcodes[0], 2 );
483
$sth->execute( $borrower2->{borrowernumber}, $biblionumber, $branchcodes[0], 2 );
484
$sth->execute( $borrower3->{borrowernumber}, $biblionumber, $branchcodes[2], 3 );
484
$sth->execute( $borrower3->{borrowernumber}, $biblionumber, $branchcodes[2], 3 );
Lines 501-507 $borrowernumber = $borrower3->{borrowernumber}; Link Here
501
my $library_A = $library1->{branchcode};
501
my $library_A = $library1->{branchcode};
502
my $library_B = $library2->{branchcode};
502
my $library_B = $library2->{branchcode};
503
my $library_C = $borrower3->{branchcode};
503
my $library_C = $borrower3->{branchcode};
504
$dbh->do("DELETE FROM reserves");
504
$dbh->do("DELETE FROM holds");
505
$dbh->do("DELETE FROM issues");
505
$dbh->do("DELETE FROM issues");
506
$dbh->do("DELETE FROM items");
506
$dbh->do("DELETE FROM items");
507
$dbh->do("DELETE FROM biblio");
507
$dbh->do("DELETE FROM biblio");
Lines 566-572 $itemtype = $builder->build({ source => 'Itemtype', value => { notforloan => 0 } Link Here
566
$borrowernumber = $borrower2->{borrowernumber};
566
$borrowernumber = $borrower2->{borrowernumber};
567
$library_A = $library1->{branchcode};
567
$library_A = $library1->{branchcode};
568
$library_B = $library2->{branchcode};
568
$library_B = $library2->{branchcode};
569
$dbh->do("DELETE FROM reserves");
569
$dbh->do("DELETE FROM holds");
570
$dbh->do("DELETE FROM issues");
570
$dbh->do("DELETE FROM issues");
571
$dbh->do("DELETE FROM items");
571
$dbh->do("DELETE FROM items");
572
$dbh->do("DELETE FROM biblio");
572
$dbh->do("DELETE FROM biblio");
Lines 619-625 $borrowernumber = $borrower3->{borrowernumber}; Link Here
619
$library_A = $library1->{branchcode};
619
$library_A = $library1->{branchcode};
620
$library_B = $library2->{branchcode};
620
$library_B = $library2->{branchcode};
621
$library_C = $library3->{branchcode};
621
$library_C = $library3->{branchcode};
622
$dbh->do("DELETE FROM reserves");
622
$dbh->do("DELETE FROM holds");
623
$dbh->do("DELETE FROM issues");
623
$dbh->do("DELETE FROM issues");
624
$dbh->do("DELETE FROM items");
624
$dbh->do("DELETE FROM items");
625
$dbh->do("DELETE FROM biblio");
625
$dbh->do("DELETE FROM biblio");
Lines 671-677 C4::HoldsQueue::CreateQueue(); Link Here
671
$holds_queue = $dbh->selectall_arrayref( "SELECT * FROM tmp_holdsqueue", { Slice => {} } );
671
$holds_queue = $dbh->selectall_arrayref( "SELECT * FROM tmp_holdsqueue", { Slice => {} } );
672
is( @$holds_queue, 1, "Hold where pickup branch matches home branch targeted" );
672
is( @$holds_queue, 1, "Hold where pickup branch matches home branch targeted" );
673
my $target_rs = $schema->resultset('HoldFillTarget');
673
my $target_rs = $schema->resultset('HoldFillTarget');
674
is( $target_rs->next->reserve_id, $reserve_id, "Reserve id correctly set in hold fill target for title level hold" );
674
is( $target_rs->next->id, $reserve_id, "Reserve id correctly set in hold fill target for title level hold" );
675
Koha::Holds->find( $reserve_id )->cancel;
675
Koha::Holds->find( $reserve_id )->cancel;
676
676
677
# Holding branch matches pickup branch
677
# Holding branch matches pickup branch
Lines 829-835 my $wrong_itemtype = $builder->build({ source => 'Itemtype', value => { notforlo Link Here
829
my $right_itemtype = $builder->build({ source => 'Itemtype', value => { notforloan => 0 } })->{itemtype};
829
my $right_itemtype = $builder->build({ source => 'Itemtype', value => { notforloan => 0 } })->{itemtype};
830
$borrowernumber = $borrower3->{borrowernumber};
830
$borrowernumber = $borrower3->{borrowernumber};
831
my $branchcode = $library1->{branchcode};
831
my $branchcode = $library1->{branchcode};
832
$dbh->do("DELETE FROM reserves");
832
$dbh->do("DELETE FROM holds");
833
$dbh->do("DELETE FROM issues");
833
$dbh->do("DELETE FROM issues");
834
$dbh->do("DELETE FROM items");
834
$dbh->do("DELETE FROM items");
835
$dbh->do("DELETE FROM biblio");
835
$dbh->do("DELETE FROM biblio");
Lines 982-988 subtest "Test Local Holds Priority - Bib level" => sub { Link Here
982
        $local_patron->borrowernumber,
982
        $local_patron->borrowernumber,
983
        "We should pick the local hold over the next available"
983
        "We should pick the local hold over the next available"
984
    );
984
    );
985
    is( $target_rs->next->reserve_id, $reserve_id2, "Reserve id correctly set in hold fill target" );
985
    is( $target_rs->next->id, $reserve_id2, "Reserve id correctly set in hold fill target" );
986
};
986
};
987
987
988
subtest "Test Local Holds Priority - Item level" => sub {
988
subtest "Test Local Holds Priority - Item level" => sub {
Lines 1205-1211 subtest "Test Local Holds Priority - Ensure no duplicate requests in holds queue Link Here
1205
1205
1206
    $dbh->do("DELETE FROM tmp_holdsqueue");
1206
    $dbh->do("DELETE FROM tmp_holdsqueue");
1207
    $dbh->do("DELETE FROM hold_fill_targets");
1207
    $dbh->do("DELETE FROM hold_fill_targets");
1208
    $dbh->do("DELETE FROM reserves");
1208
    $dbh->do("DELETE FROM holds");
1209
    $dbh->do("DELETE FROM circulation_rules");
1209
    $dbh->do("DELETE FROM circulation_rules");
1210
    Koha::Biblios->delete();
1210
    Koha::Biblios->delete();
1211
1211
Lines 1342-1348 subtest "Item level holds info is preserved (Bug 25738)" => sub { Link Here
1342
    my $queue_line_1 = $queue_rs->next;
1342
    my $queue_line_1 = $queue_rs->next;
1343
    is( $queue_line_1->item_level_request, 1, 'Request is correctly advertised as item-level' );
1343
    is( $queue_line_1->item_level_request, 1, 'Request is correctly advertised as item-level' );
1344
    my $target_rs = $schema->resultset('HoldFillTarget')->search({borrowernumber=>$patron_1->borrowernumber});;
1344
    my $target_rs = $schema->resultset('HoldFillTarget')->search({borrowernumber=>$patron_1->borrowernumber});;
1345
    is( $target_rs->next->reserve_id, $reserve_id_1, "Reserve id correctly set in hold fill target for item level hold" );
1345
    is( $target_rs->next->id, $reserve_id_1, "Reserve id correctly set in hold fill target for item level hold" );
1346
1346
1347
    my $queue_line_2 = $queue_rs->next;
1347
    my $queue_line_2 = $queue_rs->next;
1348
    is( $queue_line_2->item_level_request, 0, 'Request is correctly advertised as biblio-level' );
1348
    is( $queue_line_2->item_level_request, 0, 'Request is correctly advertised as biblio-level' );
Lines 1719-1735 subtest 'Remove holds on check-in match' => sub { Link Here
1719
            AND q.holdingbranch = t.source_branchcode
1719
            AND q.holdingbranch = t.source_branchcode
1720
        WHERE t.reserve_id = ?
1720
        WHERE t.reserve_id = ?
1721
    });
1721
    });
1722
    $sth->execute($hold->reserve_id);
1722
    $sth->execute($hold->id);
1723
    my ($count_1) = $sth->fetchrow_array;
1723
    my ($count_1) = $sth->fetchrow_array;
1724
1724
1725
    is( $count_1, 1, "Holds queue has one element" );
1725
    is( $count_1, 1, "Holds queue has one element" );
1726
1726
1727
    AddReturn( $item->barcode, $item->homebranch, undef, dt_from_string );
1727
    AddReturn( $item->barcode, $item->homebranch, undef, dt_from_string );
1728
1728
1729
    ModReserveAffect( $item->itemnumber, $hold->borrowernumber, 0,
1729
    ModReserveAffect( $item->itemnumber, $hold->patron_id, 0, $hold->id );
1730
        $hold->reserve_id );
1731
1730
1732
    $sth->execute($hold->reserve_id);
1731
    $sth->execute($hold->id);
1733
    my ($count_2) = $sth->fetchrow_array;
1732
    my ($count_2) = $sth->fetchrow_array;
1734
1733
1735
    is( $count_2, 0,
1734
    is( $count_2, 0,
(-)a/t/db_dependent/ILSDI_Services.t (-16 / +17 lines)
Lines 326-336 subtest 'Holds test' => sub { Link Here
326
    $item->damaged(0)->store;
326
    $item->damaged(0)->store;
327
327
328
    my $hold = $builder->build({
328
    my $hold = $builder->build({
329
        source => 'Reserve',
329
        source => 'Hold',
330
        value => {
330
        value => {
331
            borrowernumber => $patron->{borrowernumber},
331
            patron_id => $patron->{borrowernumber},
332
            biblionumber => $item->biblionumber,
332
            biblio_id => $item->biblionumber,
333
            itemnumber => $item->itemnumber
333
            item_id   => $item->itemnumber,
334
            completed => 0
334
        }
335
        }
335
    });
336
    });
336
337
Lines 551-565 subtest 'Holds test for branch transfer limits' => sub { Link Here
551
552
552
    $reply = C4::ILSDI::Services::HoldItem( $query );
553
    $reply = C4::ILSDI::Services::HoldItem( $query );
553
    is( $reply->{code}, undef, "Item hold, Item can be transferred" );
554
    is( $reply->{code}, undef, "Item hold, Item can be transferred" );
554
    my $hold = Koha::Holds->search({ itemnumber => $item->itemnumber, borrowernumber => $patron->{borrowernumber} })->next;
555
    my $hold = Koha::Holds->search({ item_id => $item->itemnumber, patron_id => $patron->{borrowernumber} })->next;
555
    is( $hold->branchcode, $pickup_branch->{branchcode}, 'The library id is correctly set' );
556
    is( $hold->pickup_library_id, $pickup_branch->{branchcode}, 'The library id is correctly set' );
556
557
557
    Koha::Holds->search()->delete();
558
    Koha::Holds->search()->delete();
558
559
559
    $reply = C4::ILSDI::Services::HoldTitle( $query );
560
    $reply = C4::ILSDI::Services::HoldTitle( $query );
560
    is( $reply->{code}, undef, "Record hold, Item con be transferred" );
561
    is( $reply->{code}, undef, "Record hold, Item con be transferred" );
561
    $hold = Koha::Holds->search({ biblionumber => $item->biblionumber, borrowernumber => $patron->{borrowernumber} })->next;
562
    $hold = Koha::Holds->search({ biblio_id => $item->biblionumber, patron_id => $patron->{borrowernumber} })->next;
562
    is( $hold->branchcode, $pickup_branch->{branchcode}, 'The library id is correctly set' );
563
    is( $hold->pickup_library_id, $pickup_branch->{branchcode}, 'The library id is correctly set' );
563
564
564
    $schema->storage->txn_rollback;
565
    $schema->storage->txn_rollback;
565
};
566
};
Lines 605-623 subtest 'Holds test with start_date and end_date' => sub { Link Here
605
606
606
    my $reply = C4::ILSDI::Services::HoldItem( $query );
607
    my $reply = C4::ILSDI::Services::HoldItem( $query );
607
    is ($reply->{pickup_location}, $pickup_library->branchname, "Item hold with date parameters was placed");
608
    is ($reply->{pickup_location}, $pickup_library->branchname, "Item hold with date parameters was placed");
608
    my $hold = Koha::Holds->search({ biblionumber => $item->biblionumber})->next();
609
    my $hold = Koha::Holds->search({ biblio_id => $item->biblionumber})->next();
609
    is( $hold->biblionumber, $item->biblionumber, "correct biblionumber");
610
    is( $hold->biblio_id, $item->biblionumber, "correct biblionumber");
610
    is( $hold->reservedate, '2020-03-20', "Item hold has correct start date" );
611
    is( $hold->created_date, '2020-03-20', "Item hold has correct start date" );
611
    is( $hold->expirationdate, '2020-04-22', "Item hold has correct end date" );
612
    is( $hold->expiration_date, '2020-04-22', "Item hold has correct end date" );
612
613
613
    $hold->delete();
614
    $hold->delete();
614
615
615
    $reply = C4::ILSDI::Services::HoldTitle( $query );
616
    $reply = C4::ILSDI::Services::HoldTitle( $query );
616
    is ($reply->{pickup_location}, $pickup_library->branchname, "Record hold with date parameters was placed");
617
    is ($reply->{pickup_location}, $pickup_library->branchname, "Record hold with date parameters was placed");
617
    $hold = Koha::Holds->search({ biblionumber => $item->biblionumber})->next();
618
    $hold = Koha::Holds->search({ biblio_id => $item->biblionumber})->next();
618
    is( $hold->biblionumber, $item->biblionumber, "correct biblionumber");
619
    is( $hold->biblio_id, $item->biblionumber, "correct biblionumber");
619
    is( $hold->reservedate, '2020-03-20', "Record hold has correct start date" );
620
    is( $hold->created_date, '2020-03-20', "Record hold has correct start date" );
620
    is( $hold->expirationdate, '2020-04-22', "Record hold has correct end date" );
621
    is( $hold->expiration_date, '2020-04-22', "Record hold has correct end date" );
621
622
622
    $schema->storage->txn_rollback;
623
    $schema->storage->txn_rollback;
623
};
624
};
(-)a/t/db_dependent/Items/GetItemsForInventory.t (-1 / +1 lines)
Lines 112-118 subtest 'Skip items with waiting holds' => sub { Link Here
112
            biblionumber   => $item_1->biblionumber,
112
            biblionumber   => $item_1->biblionumber,
113
            priority       => 1,
113
            priority       => 1,
114
            itemnumber     => $item_1->itemnumber,
114
            itemnumber     => $item_1->itemnumber,
115
            found          => 'W'
115
            found          => 'waiting'
116
        }
116
        }
117
    );
117
    );
118
    C4::Reserves::AddReserve(
118
    C4::Reserves::AddReserve(
(-)a/t/db_dependent/Items/MoveItemFromBiblio.t (-12 / +12 lines)
Lines 43-60 my $item3 = $builder->build_sample_item( Link Here
43
43
44
44
45
my $bib_level_hold_not_to_move = $builder->build(
45
my $bib_level_hold_not_to_move = $builder->build(
46
    {   source => 'Reserve',
46
    {   source => 'Hold',
47
        value  => { biblionumber => $from_biblio->biblionumber, },
47
        value  => { biblio_id => $from_biblio->biblionumber, },
48
    }
48
    }
49
);
49
);
50
my $item_level_hold_not_to_move = $builder->build(
50
my $item_level_hold_not_to_move = $builder->build(
51
    {   source => 'Reserve',
51
    {   source => 'Hold',
52
        value  => { biblionumber => $from_biblio->biblionumber, itemnumber => $item1->itemnumber },
52
        value  => { biblio_id => $from_biblio->biblionumber, item_id => $item1->itemnumber },
53
    }
53
    }
54
);
54
);
55
my $item_level_hold_to_move = $builder->build(
55
my $item_level_hold_to_move = $builder->build(
56
    {   source => 'Reserve',
56
    {   source => 'Hold',
57
        value  => { biblionumber => $from_biblio->biblionumber, itemnumber => $item2->itemnumber },
57
        value  => { biblio_id => $from_biblio->biblionumber, item_id => $item2->itemnumber },
58
    }
58
    }
59
);
59
);
60
60
Lines 73-85 is( $get_item2->biblionumber, $to_biblio->biblionumber, 'The item2 should have b Link Here
73
my $get_item3 = Koha::Items->find( $item3->itemnumber );
73
my $get_item3 = Koha::Items->find( $item3->itemnumber );
74
is( $get_item3->biblionumber, $to_biblio->biblionumber, 'The item3 should not have been moved' );
74
is( $get_item3->biblionumber, $to_biblio->biblionumber, 'The item3 should not have been moved' );
75
75
76
my $get_bib_level_hold    = Koha::Holds->find( $bib_level_hold_not_to_move->{reserve_id} );
76
my $get_bib_level_hold    = Koha::Holds->find( $bib_level_hold_not_to_move->{id} );
77
my $get_item_level_hold_1 = Koha::Holds->find( $item_level_hold_not_to_move->{reserve_id} );
77
my $get_item_level_hold_1 = Koha::Holds->find( $item_level_hold_not_to_move->{id} );
78
my $get_item_level_hold_2 = Koha::Holds->find( $item_level_hold_to_move->{reserve_id} );
78
my $get_item_level_hold_2 = Koha::Holds->find( $item_level_hold_to_move->{id} );
79
79
80
is( $get_bib_level_hold->biblionumber,    $from_biblio->biblionumber, 'MoveItemFromBiblio should not have moved the biblio-level hold' );
80
is( $get_bib_level_hold->biblio_id,    $from_biblio->biblionumber, 'MoveItemFromBiblio should not have moved the biblio-level hold' );
81
is( $get_item_level_hold_1->biblionumber, $from_biblio->biblionumber, 'MoveItemFromBiblio should not have moved the item-level hold placed on item 1' );
81
is( $get_item_level_hold_1->biblio_id, $from_biblio->biblionumber, 'MoveItemFromBiblio should not have moved the item-level hold placed on item 1' );
82
is( $get_item_level_hold_2->biblionumber, $to_biblio->biblionumber,   'MoveItemFromBiblio should have moved the item-level hold placed on item 2' );
82
is( $get_item_level_hold_2->biblio_id, $to_biblio->biblionumber,   'MoveItemFromBiblio should have moved the item-level hold placed on item 2' );
83
83
84
$schema->storage->txn_rollback;
84
$schema->storage->txn_rollback;
85
85
(-)a/t/db_dependent/Koha/Biblios.t (-9 / +9 lines)
Lines 77-83 subtest 'holds + current_holds' => sub { Link Here
77
    my $holds = $biblio->holds;
77
    my $holds = $biblio->holds;
78
    is( ref($holds), 'Koha::Holds', '->holds should return a Koha::Holds object' );
78
    is( ref($holds), 'Koha::Holds', '->holds should return a Koha::Holds object' );
79
    is( $holds->count, 1, '->holds should only return 1 hold' );
79
    is( $holds->count, 1, '->holds should only return 1 hold' );
80
    is( $holds->next->borrowernumber, $patron->borrowernumber, '->holds should return the correct hold' );
80
    is( $holds->next->patron_id, $patron->borrowernumber, '->holds should return the correct hold' );
81
    $holds->delete;
81
    $holds->delete;
82
82
83
    # Add a hold in the future
83
    # Add a hold in the future
Lines 98-122 subtest 'holds + current_holds' => sub { Link Here
98
};
98
};
99
99
100
subtest 'waiting_or_in_transit' => sub {
100
subtest 'waiting_or_in_transit' => sub {
101
101
    plan tests => 4;
102
    plan tests => 4;
103
102
    my $item = $builder->build_sample_item;
104
    my $item = $builder->build_sample_item;
103
    my $reserve = $builder->build({
105
    my $hold = $builder->build_object({
104
        source => 'Reserve',
106
        class => 'Koha::Holds',
105
        value => {
107
        value => {
106
            biblionumber => $item->biblionumber,
108
            biblio_id => $item->biblionumber,
107
            found => undef
108
        }
109
        }
109
    });
110
    });
110
111
111
    $reserve = Koha::Holds->find($reserve->{reserve_id});
112
    $biblio = $item->biblio;
112
    $biblio = $item->biblio;
113
113
114
    is($biblio->has_items_waiting_or_intransit, 0, 'Item is neither waiting nor in transit');
114
    is($biblio->has_items_waiting_or_intransit, 0, 'Item is neither waiting nor in transit');
115
115
116
    $reserve->found('W')->store;
116
    $hold->set_waiting();
117
    is($biblio->has_items_waiting_or_intransit, 1, 'Item is waiting');
117
    is($biblio->has_items_waiting_or_intransit, 1, 'Item is waiting');
118
118
119
    $reserve->found('T')->store;
119
    $hold->set_transfer();
120
    is($biblio->has_items_waiting_or_intransit, 1, 'Item is in transit');
120
    is($biblio->has_items_waiting_or_intransit, 1, 'Item is in transit');
121
121
122
    my $transfer = $builder->build({
122
    my $transfer = $builder->build({
Lines 128-134 subtest 'waiting_or_in_transit' => sub { Link Here
128
        }
128
        }
129
    });
129
    });
130
    my $t = Koha::Database->new()->schema()->resultset( 'Branchtransfer' )->find($transfer->{branchtransfer_id});
130
    my $t = Koha::Database->new()->schema()->resultset( 'Branchtransfer' )->find($transfer->{branchtransfer_id});
131
    $reserve->found(undef)->store;
131
    $hold->status('placed')->store;
132
    is($biblio->has_items_waiting_or_intransit, 1, 'Item has transfer');
132
    is($biblio->has_items_waiting_or_intransit, 1, 'Item has transfer');
133
};
133
};
134
134
(-)a/t/db_dependent/Koha/Club/Hold.t (-1 / +1 lines)
Lines 131-137 subtest 'add' => sub { Link Here
131
131
132
    my $hold = Koha::Holds->find($patron_hold->hold_id);
132
    my $hold = Koha::Holds->find($patron_hold->hold_id);
133
133
134
    is($patron_hold->patron_id, $hold->borrowernumber, 'Patron must be the same');
134
    is($patron_hold->patron_id, $hold->patron_id, 'Patron must be the same');
135
135
136
    $schema->storage->txn_rollback;
136
    $schema->storage->txn_rollback;
137
}
137
}
(-)a/t/db_dependent/Koha/Hold.t (-1 / +1 lines)
Lines 127-133 subtest 'set_pickup_location() tests' => sub { Link Here
127
127
128
    $item_hold->set_pickup_location({ library_id => $library_1->branchcode, force => 1 });
128
    $item_hold->set_pickup_location({ library_id => $library_1->branchcode, force => 1 });
129
    $item_hold->discard_changes;
129
    $item_hold->discard_changes;
130
    is( $item_hold->branchcode, $library_1->branchcode, 'branchcode changed because of \'force\'' );
130
    is( $item_hold->pickup_library_id, $library_1->branchcode, 'branchcode changed because of \'force\'' );
131
131
132
    $ret = $item_hold->set_pickup_location({ library_id => $library_2->id });
132
    $ret = $item_hold->set_pickup_location({ library_id => $library_2->id });
133
    is( ref($ret), 'Koha::Hold', 'self is returned' );
133
    is( ref($ret), 'Koha::Hold', 'self is returned' );
(-)a/t/db_dependent/Koha/Holds.t (-57 / +20 lines)
Lines 61-67 subtest 'DB constraints' => sub { Link Here
61
};
61
};
62
62
63
subtest 'cancel' => sub {
63
subtest 'cancel' => sub {
64
    plan tests => 12;
64
65
    plan tests => 13;
66
65
    my $biblioitem = $builder->build_object( { class => 'Koha::Biblioitems' } );
67
    my $biblioitem = $builder->build_object( { class => 'Koha::Biblioitems' } );
66
    my $library    = $builder->build_object( { class => 'Koha::Libraries' } );
68
    my $library    = $builder->build_object( { class => 'Koha::Libraries' } );
67
    my $itemtype   = $builder->build_object( { class => 'Koha::ItemTypes', value => { rentalcharge => 0 } } );
69
    my $itemtype   = $builder->build_object( { class => 'Koha::ItemTypes', value => { rentalcharge => 0 } } );
Lines 102-108 subtest 'cancel' => sub { Link Here
102
104
103
    # There are 3 holds on this records
105
    # There are 3 holds on this records
104
    my $nb_of_holds =
106
    my $nb_of_holds =
105
      Koha::Holds->search( { biblionumber => $item->biblionumber } )->count;
107
      Koha::Holds->search( { biblio_id => $item->biblionumber } )->count;
106
    is( $nb_of_holds, 3,
108
    is( $nb_of_holds, 3,
107
        'There should have 3 holds placed on this biblio record' );
109
        'There should have 3 holds placed on this biblio record' );
108
    my $first_hold  = $holds[0];
110
    my $first_hold  = $holds[0];
Lines 116-129 subtest 'cancel' => sub { Link Here
116
    # Remove the second hold, only 2 should still exist in DB and priorities must have been updated
118
    # Remove the second hold, only 2 should still exist in DB and priorities must have been updated
117
    my $is_cancelled = $second_hold->cancel;
119
    my $is_cancelled = $second_hold->cancel;
118
    is( ref($is_cancelled), 'Koha::Hold',
120
    is( ref($is_cancelled), 'Koha::Hold',
119
        'Koha::Hold->cancel should return the Koha::Hold (?)' )
121
        'Koha::Hold->cancel should return the Koha::Hold (?)' );
122
    $second_hold->discard_changes;
120
      ;    # This is can reconsidered
123
      ;    # This is can reconsidered
121
    is( $second_hold->in_storage, 0,
124
    is( $second_hold->in_storage, 1,
122
        'The hold has been cancelled and does not longer exist in DB' );
125
        'The hold has been cancelled and still exists on the DB' );
126
    is( $second_hold->status, 'cancelled', "Status is 'cancelled'" );
127
    ok( $second_hold->completed, 'Hold marked as comleted' );
128
123
    $nb_of_holds =
129
    $nb_of_holds =
124
      Koha::Holds->search( { biblionumber => $item->biblionumber } )->count;
130
      Koha::Holds->search( { biblio_id => $item->biblionumber, completed => 0 } )->count;
125
    is( $nb_of_holds, 2,
131
    is( $nb_of_holds, 2,
126
        'a hold has been cancelled, there should have only 2 holds placed on this biblio record'
132
        'a hold has been cancelled, there should have only 2 (not completed) holds placed on this biblio record'
127
    );
133
    );
128
134
129
    # discard_changes to refetch
135
    # discard_changes to refetch
Lines 166-172 subtest 'cancel' => sub { Link Here
166
    };
172
    };
167
173
168
    subtest 'waiting hold' => sub {
174
    subtest 'waiting hold' => sub {
169
        plan tests => 1;
175
        plan tests => 2;
170
        my $patron = $builder->build_object({ class => 'Koha::Patrons' });
176
        my $patron = $builder->build_object({ class => 'Koha::Patrons' });
171
        my $reserve_id = C4::Reserves::AddReserve(
177
        my $reserve_id = C4::Reserves::AddReserve(
172
            {
178
            {
Lines 176-187 subtest 'cancel' => sub { Link Here
176
                priority       => 1,
182
                priority       => 1,
177
                title          => "title for fee",
183
                title          => "title for fee",
178
                itemnumber     => $item->itemnumber,
184
                itemnumber     => $item->itemnumber,
179
                found          => 'W',
185
                status         => 'W',
180
            }
186
            }
181
        );
187
        );
182
        Koha::Holds->find( $reserve_id )->cancel;
188
        my $hold = Koha::Holds->find( $reserve_id );
183
        my $hold_old = Koha::Old::Holds->find( $reserve_id );
189
        $hold->cancel->discard_changes;
184
        is( $hold_old->found, 'W', 'The found column should have been kept and a hold is cancelled' );
190
        is( $hold->status, 'cancelled', 'The found column should have been kept and a hold is cancelled' );
191
        ok( $hold->completed, 'Hold is marked as completed' );
185
    };
192
    };
186
193
187
    subtest 'HoldsLog' => sub {
194
    subtest 'HoldsLog' => sub {
Lines 208-257 subtest 'cancel' => sub { Link Here
208
        $number_of_logs = $schema->resultset('ActionLog')->search( { module => 'HOLDS', action => 'CANCEL', object => $reserve_id } )->count;
215
        $number_of_logs = $schema->resultset('ActionLog')->search( { module => 'HOLDS', action => 'CANCEL', object => $reserve_id } )->count;
209
        is( $number_of_logs, 1, 'With HoldsLog, Koha::Hold->cancel should have logged' );
216
        is( $number_of_logs, 1, 'With HoldsLog, Koha::Hold->cancel should have logged' );
210
    };
217
    };
211
212
    subtest 'rollback' => sub {
213
        plan tests => 3;
214
        my $patron_category = $builder->build_object(
215
            {
216
                class => 'Koha::Patron::Categories',
217
                value => { reservefee => 0 }
218
            }
219
        );
220
        my $patron = $builder->build_object(
221
            {
222
                class => 'Koha::Patrons',
223
                value => { categorycode => $patron_category->categorycode }
224
            }
225
        );
226
        my $hold_info = {
227
            branchcode     => $library->branchcode,
228
            borrowernumber => $patron->borrowernumber,
229
            biblionumber   => $item->biblionumber,
230
            priority       => 1,
231
            title          => "title for fee",
232
            itemnumber     => $item->itemnumber,
233
        };
234
235
        t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelayCharge',42 );
236
        my $reserve_id = C4::Reserves::AddReserve($hold_info);
237
        my $hold       = Koha::Holds->find($reserve_id);
238
239
        # Add a row with the same id to make the cancel fails
240
        Koha::Old::Hold->new( $hold->unblessed )->store;
241
242
        warning_like {
243
            eval { $hold->cancel( { charge_cancel_fee => 1 } ) };
244
        }
245
        qr{.*DBD::mysql::st execute failed: Duplicate entry.*},
246
          'DBD should have raised an error about dup primary key';
247
248
        $hold = Koha::Holds->find($reserve_id);
249
        is( ref($hold), 'Koha::Hold', 'The hold should not have been deleted' );
250
        is( $patron->account->balance, 0,
251
'If the hold has not been cancelled, the patron should not have been charged'
252
        );
253
    };
254
255
};
218
};
256
219
257
subtest 'cancel with reason' => sub {
220
subtest 'cancel with reason' => sub {
Lines 477-483 subtest 'get_items_that_can_fill' => sub { Link Here
477
440
478
    my $holds = Koha::Holds->search(
441
    my $holds = Koha::Holds->search(
479
        {
442
        {
480
            reserve_id => [ $reserve_id_1, $reserve_id_2, $waiting_reserve_id, ]
443
            id => [ $reserve_id_1, $reserve_id_2, $waiting_reserve_id, ]
481
        }
444
        }
482
    );
445
    );
483
446
(-)a/t/db_dependent/Koha/Items.t (-6 / +6 lines)
Lines 1382-1395 subtest 'holds' => sub { Link Here
1382
        biblionumber => $biblio->biblionumber,
1382
        biblionumber => $biblio->biblionumber,
1383
    });
1383
    });
1384
    is($item->holds->count, 0, "Nothing returned if no holds");
1384
    is($item->holds->count, 0, "Nothing returned if no holds");
1385
    my $hold1 = $builder->build({ source => 'Reserve', value => { itemnumber=>$item->itemnumber, found => 'T' }});
1385
    my $hold1 = $builder->build({ source => 'Hold', value => { item_id=>$item->itemnumber, status => 'in_transit', completed => 0 }});
1386
    my $hold2 = $builder->build({ source => 'Reserve', value => { itemnumber=>$item->itemnumber, found => 'W' }});
1386
    my $hold2 = $builder->build({ source => 'Hold', value => { item_id=>$item->itemnumber, status => 'waiting', completed => 0 }});
1387
    my $hold3 = $builder->build({ source => 'Reserve', value => { itemnumber=>$item->itemnumber, found => 'W' }});
1387
    my $hold3 = $builder->build({ source => 'Hold', value => { item_id=>$item->itemnumber, status => 'waiting', completed => 0 }});
1388
1388
1389
    is($item->holds()->count,3,"Three holds found");
1389
    is($item->holds()->count,3,"Three holds found");
1390
    is($item->holds({found => 'W'})->count,2,"Two waiting holds found");
1390
    is($item->holds({status => 'waiting'})->count,2,"Two waiting holds found");
1391
    is_deeply($item->holds({found => 'T'})->next->unblessed,$hold1,"Found transit holds matches the hold");
1391
    is_deeply($item->holds({status => 'in_transit'})->next->unblessed,$hold1,"Found transit holds matches the hold");
1392
    is($item->holds({found => undef})->count, 0,"Nothing returned if no matching holds");
1392
    is($item->holds({status => 'placed'})->count, 0,"Nothing returned if no matching holds");
1393
};
1393
};
1394
1394
1395
subtest 'biblio' => sub {
1395
subtest 'biblio' => sub {
(-)a/t/db_dependent/Koha/Object.t (-2 / +2 lines)
Lines 272-278 subtest "to_api() tests" => sub { Link Here
272
272
273
    my $biblio = $builder->build_sample_biblio();
273
    my $biblio = $builder->build_sample_biblio();
274
    my $item = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
274
    my $item = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
275
    my $hold = $builder->build_object({ class => 'Koha::Holds', value => { itemnumber => $item->itemnumber } });
275
    my $hold = $builder->build_object({ class => 'Koha::Holds', value => { item_id => $item->itemnumber, completed => 0 } });
276
276
277
    my $embeds = { 'items' => {} };
277
    my $embeds = { 'items' => {} };
278
278
Lines 297-303 subtest "to_api() tests" => sub { Link Here
297
    ok(exists $biblio_api->{items}, 'Items where embedded in biblio results');
297
    ok(exists $biblio_api->{items}, 'Items where embedded in biblio results');
298
    is($biblio_api->{items}->[0]->{item_id}, $item->itemnumber, 'Item still matches');
298
    is($biblio_api->{items}->[0]->{item_id}, $item->itemnumber, 'Item still matches');
299
    ok(exists $biblio_api->{items}->[0]->{holds}, 'Holds info should be embedded');
299
    ok(exists $biblio_api->{items}->[0]->{holds}, 'Holds info should be embedded');
300
    is($biblio_api->{items}->[0]->{holds}->[0]->{hold_id}, $hold->reserve_id, 'Hold matches');
300
    is($biblio_api->{items}->[0]->{holds}->[0]->{hold_id}, $hold->id, 'Hold matches');
301
    is_deeply($biblio_api->{biblioitem}, $biblio->biblioitem->to_api, 'More than one root');
301
    is_deeply($biblio_api->{biblioitem}, $biblio->biblioitem->to_api, 'More than one root');
302
302
303
    my $hold_api = $hold->to_api(
303
    my $hold_api = $hold->to_api(
(-)a/t/db_dependent/Koha/Objects.t (-3 / +3 lines)
Lines 338-344 subtest "to_api() tests" => sub { Link Here
338
    my $hold_1   = $builder->build_object(
338
    my $hold_1   = $builder->build_object(
339
        {
339
        {
340
            class => 'Koha::Holds',
340
            class => 'Koha::Holds',
341
            value => { itemnumber => $item_1->itemnumber }
341
            value => { item_id => $item_1->itemnumber, completed => 0 }
342
        }
342
        }
343
    );
343
    );
344
344
Lines 347-353 subtest "to_api() tests" => sub { Link Here
347
    my $hold_2   = $builder->build_object(
347
    my $hold_2   = $builder->build_object(
348
        {
348
        {
349
            class => 'Koha::Holds',
349
            class => 'Koha::Holds',
350
            value => { itemnumber => $item_2->itemnumber }
350
            value => { item_id => $item_2->itemnumber, completed => 0 }
351
        }
351
        }
352
    );
352
    );
353
353
Lines 391-397 subtest "to_api() tests" => sub { Link Here
391
        ok(exists $biblio_api->{items}, 'Items where embedded in biblio results');
391
        ok(exists $biblio_api->{items}, 'Items where embedded in biblio results');
392
        is($biblio_api->{items}->[0]->{item_id}, $items[$i]->itemnumber, 'Item still matches');
392
        is($biblio_api->{items}->[0]->{item_id}, $items[$i]->itemnumber, 'Item still matches');
393
        ok(exists $biblio_api->{items}->[0]->{holds}, 'Holds info should be embedded');
393
        ok(exists $biblio_api->{items}->[0]->{holds}, 'Holds info should be embedded');
394
        is($biblio_api->{items}->[0]->{holds}->[0]->{hold_id}, $holds[$i]->reserve_id, 'Hold matches');
394
        is($biblio_api->{items}->[0]->{holds}->[0]->{hold_id}, $holds[$i]->id, 'Hold matches');
395
395
396
        $i++;
396
        $i++;
397
    }
397
    }
(-)a/t/db_dependent/Koha/Patrons.t (-8 / +8 lines)
Lines 469-476 subtest "delete" => sub { Link Here
469
    my $patron           = $builder->build( { source => 'Borrower' } );
469
    my $patron           = $builder->build( { source => 'Borrower' } );
470
    my $retrieved_patron = Koha::Patrons->find( $patron->{borrowernumber} );
470
    my $retrieved_patron = Koha::Patrons->find( $patron->{borrowernumber} );
471
    my $hold             = $builder->build(
471
    my $hold             = $builder->build(
472
        {   source => 'Reserve',
472
        {   source => 'Hold',
473
            value  => { borrowernumber => $patron->{borrowernumber} }
473
            value  => { patron_id => $patron->{borrowernumber}, completed => 0 }
474
        }
474
        }
475
    );
475
    );
476
    my $list = $builder->build(
476
    my $list = $builder->build(
Lines 485-493 subtest "delete" => sub { Link Here
485
485
486
    is( Koha::Patrons->find( $patron->{borrowernumber} ), undef, 'Koha::Patron->delete should have deleted the patron' );
486
    is( Koha::Patrons->find( $patron->{borrowernumber} ), undef, 'Koha::Patron->delete should have deleted the patron' );
487
487
488
    is (Koha::Old::Holds->search( { reserve_id => $hold->{ reserve_id } } )->count, 1, q|Koha::Patron->delete should have cancelled patron's holds| );
488
    is (Koha::Holds->search( { id => $hold->{id}, status => 'cancelled' } )->count, 1, q|Koha::Patron->delete should have cancelled patron's holds| );
489
489
490
    is( Koha::Holds->search( { borrowernumber => $patron->{borrowernumber} } )->count, 0, q|Koha::Patron->delete should have cancelled patron's holds 2| );
490
    is( Koha::Holds->search( { patron_id => $patron->{borrowernumber}, completed => 0 } )->count, 0, q|Koha::Patron->delete should have cancelled patron's holds 2| );
491
491
492
    is( Koha::Virtualshelves->search( { owner => $patron->{borrowernumber} } )->count, 0, q|Koha::Patron->delete should have deleted patron's lists| );
492
    is( Koha::Virtualshelves->search( { owner => $patron->{borrowernumber} } )->count, 0, q|Koha::Patron->delete should have deleted patron's lists| );
493
493
Lines 993-1000 subtest 'holds and old_holds' => sub { Link Here
993
    is( $holds->count, 2, 'There should be 2 holds placed by this patron' );
993
    is( $holds->count, 2, 'There should be 2 holds placed by this patron' );
994
994
995
    my $old_holds = $patron->old_holds;
995
    my $old_holds = $patron->old_holds;
996
    is( ref($old_holds), 'Koha::Old::Holds',
996
    is( ref($old_holds), 'Koha::Holds',
997
        'Koha::Patron->old_holds should return a Koha::Old::Holds objects' );
997
        'Koha::Patron->old_holds should return a Koha::Holds objects' );
998
    is( $old_holds->count, 0, 'There should not be any old holds yet');
998
    is( $old_holds->count, 0, 'There should not be any old holds yet');
999
999
1000
    my $hold = $holds->next;
1000
    my $hold = $holds->next;
Lines 1606-1612 subtest 'BorrowersLog tests' => sub { Link Here
1606
$schema->storage->txn_rollback;
1606
$schema->storage->txn_rollback;
1607
1607
1608
subtest 'Test Koha::Patrons::merge' => sub {
1608
subtest 'Test Koha::Patrons::merge' => sub {
1609
    plan tests => 110;
1609
    plan tests => 106;
1610
1610
1611
    my $schema = Koha::Database->new()->schema();
1611
    my $schema = Koha::Database->new()->schema();
1612
1612
Lines 2028-2034 subtest 'lock' => sub { Link Here
2028
    my $patron2 = $builder->build_object( { class => 'Koha::Patrons' } );
2028
    my $patron2 = $builder->build_object( { class => 'Koha::Patrons' } );
2029
    my $hold = $builder->build_object({
2029
    my $hold = $builder->build_object({
2030
        class => 'Koha::Holds',
2030
        class => 'Koha::Holds',
2031
        value => { borrowernumber => $patron1->borrowernumber },
2031
        value => { patron_id => $patron1->borrowernumber, completed => 0 },
2032
    });
2032
    });
2033
2033
2034
    t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 3 );
2034
    t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 3 );
(-)a/t/db_dependent/Koha/Z3950Responder/Session.t (-1 / +1 lines)
Lines 32-38 subtest 'add_item_status' => sub { Link Here
32
    my ( $itemtag, $itemsubfield ) = C4::Biblio::GetMarcFromKohaField( "items.itemnumber" );
32
    my ( $itemtag, $itemsubfield ) = C4::Biblio::GetMarcFromKohaField( "items.itemnumber" );
33
    my $item_marc_1 = C4::Items::GetMarcItem( $item_1->biblionumber, $item_1->itemnumber );
33
    my $item_marc_1 = C4::Items::GetMarcItem( $item_1->biblionumber, $item_1->itemnumber );
34
    my $item_field_1 = scalar $item_marc_1->field($itemtag);
34
    my $item_field_1 = scalar $item_marc_1->field($itemtag);
35
    $builder->build({ source => 'Reserve', value=> { itemnumber => $item_1->itemnumber } });
35
    $builder->build({ source => 'Hold', value=> { item_id => $item_1->itemnumber } });
36
    $builder->build(
36
    $builder->build(
37
        {
37
        {
38
            source => 'Branchtransfer',
38
            source => 'Branchtransfer',
(-)a/t/db_dependent/Koha/Z3950Responder/Session2.t (-1 / +1 lines)
Lines 55-61 subtest 'add_item_status' => sub { Link Here
55
    );
55
    );
56
    my $item_marc_1 = C4::Items::GetMarcItem( $item_1->biblionumber, $item_1->itemnumber );
56
    my $item_marc_1 = C4::Items::GetMarcItem( $item_1->biblionumber, $item_1->itemnumber );
57
    my $item_field_1 = scalar $item_marc_1->field('952');
57
    my $item_field_1 = scalar $item_marc_1->field('952');
58
    $builder->build({ source => 'Reserve', value=> { itemnumber => $item_1->itemnumber } });
58
    $builder->build({ source => 'Hold', value=> { item_id => $item_1->itemnumber } });
59
    $builder->build(
59
    $builder->build(
60
        {
60
        {
61
            source => 'Branchtransfer',
61
            source => 'Branchtransfer',
(-)a/t/db_dependent/Letters/TemplateToolkit.t (-8 / +11 lines)
Lines 70-77 my $hold = $builder->build_object( Link Here
70
    {
70
    {
71
        class => 'Koha::Holds',
71
        class => 'Koha::Holds',
72
        value => {
72
        value => {
73
            borrowernumber => $patron->{borrowernumber},
73
            patron_id => $patron->{borrowernumber},
74
            biblionumber   => $item->biblionumber
74
            biblio_id   => $item->biblionumber
75
        }
75
        }
76
    }
76
    }
77
);
77
);
Lines 197-208 $prepared_letter = GetPreparedLetter( Link Here
197
        module      => 'test',
197
        module      => 'test',
198
        letter_code => 'TEST_HOLD',
198
        letter_code => 'TEST_HOLD',
199
        tables      => {
199
        tables      => {
200
            reserves => { borrowernumber => $patron->{borrowernumber}, biblionumber => $item->biblionumber },
200
            holds => {
201
                patron_id => $patron->{borrowernumber},
202
                biblio_id => $item->biblionumber
203
            },
201
        },
204
        },
202
    )
205
    )
203
);
206
);
204
is( $prepared_letter->{content}, $hold->id(), 'Hold object used correctly for content' );
207
is( $prepared_letter->{content}, $hold->id(), 'Hold object used correctly for content' );
205
is( $prepared_letter->{title}, $hold->borrowernumber, 'Hold object used correctly for title' );
208
is( $prepared_letter->{title}, $hold->patron_id, 'Hold object used correctly for title' );
206
209
207
eval {
210
eval {
208
    $prepared_letter = GetPreparedLetter(
211
    $prepared_letter = GetPreparedLetter(
Lines 210-222 eval { Link Here
210
            module      => 'test',
213
            module      => 'test',
211
            letter_code => 'TEST_HOLD',
214
            letter_code => 'TEST_HOLD',
212
            tables      => {
215
            tables      => {
213
                reserves => [ $patron->{borrowernumber}, $item->biblionumber ],
216
                holds => [ $patron->{borrowernumber}, $item->biblionumber ],
214
            },
217
            },
215
        )
218
        )
216
    )
219
    )
217
};
220
};
218
my $croak = $@;
221
my $croak = $@;
219
like( $croak, qr{^Multiple foreign keys \(table reserves\) should be passed using an hashref.*}, "GetPreparedLetter should not be called with arrayref for multiple FK" );
222
like( $croak, qr{^Multiple foreign keys \(table holds\) should be passed using an hashref.*}, "GetPreparedLetter should not be called with arrayref for multiple FK" );
220
223
221
# Bug 16942
224
# Bug 16942
222
$prepared_letter = GetPreparedLetter(
225
$prepared_letter = GetPreparedLetter(
Lines 228-235 $prepared_letter = GetPreparedLetter( Link Here
228
            'borrowers'   => $patron,
231
            'borrowers'   => $patron,
229
            'biblio'      => $item->biblionumber,
232
            'biblio'      => $item->biblionumber,
230
            'biblioitems' => $item->biblioitemnumber,
233
            'biblioitems' => $item->biblioitemnumber,
231
            'reserves'    => $hold->unblessed,
234
            'holds'        => $hold->unblessed,
232
            'items'       => $hold->itemnumber,
235
            'items'       => $hold->item_id,
233
        }
236
        }
234
    )
237
    )
235
);
238
);
(-)a/t/db_dependent/Reserves.t (-75 / +64 lines)
Lines 123-129 my ($status, $reserve, $all_reserves) = CheckReserves($item->itemnumber, $barcod Link Here
123
123
124
is($status, "Reserved", "CheckReserves Test 1");
124
is($status, "Reserved", "CheckReserves Test 1");
125
125
126
ok(exists($reserve->{reserve_id}), 'CheckReserves() include reserve_id in its response');
126
ok(exists($reserve->{id}), 'CheckReserves() include reserve_id in its response');
127
127
128
($status, $reserve, $all_reserves) = CheckReserves($item->itemnumber);
128
($status, $reserve, $all_reserves) = CheckReserves($item->itemnumber);
129
is($status, "Reserved", "CheckReserves Test 2");
129
is($status, "Reserved", "CheckReserves Test 2");
Lines 267-280 ModReserveAffect($itemnum_cpl, $requesters{$branch_3}, 0); Link Here
267
267
268
# Now it should have different priorities.
268
# Now it should have different priorities.
269
my $biblio = Koha::Biblios->find( $bibnum2 );
269
my $biblio = Koha::Biblios->find( $bibnum2 );
270
my $holds = $biblio->holds({}, { order_by => 'reserve_id' });;
270
my $holds = $biblio->holds({}, { order_by => 'id' });;
271
is($holds->next->priority, 0, 'Item is correctly waiting');
271
is($holds->next->priority, 0, 'Item is correctly waiting');
272
is($holds->next->priority, 1, 'Item is correctly priority 1');
272
is($holds->next->priority, 1, 'Item is correctly priority 1');
273
is($holds->next->priority, 2, 'Item is correctly priority 2');
273
is($holds->next->priority, 2, 'Item is correctly priority 2');
274
274
275
my @reserves = Koha::Holds->search({ borrowernumber => $requesters{$branch_3} })->waiting();
275
my @reserves = Koha::Holds->search({ patron_id => $requesters{$branch_3} })->waiting();
276
is( @reserves, 1, 'GetWaiting got only the waiting reserve' );
276
is( @reserves, 1, 'GetWaiting got only the waiting reserve' );
277
is( $reserves[0]->borrowernumber(), $requesters{$branch_3}, 'GetWaiting got the reserve for the correct borrower' );
277
is( $reserves[0]->patron_id(), $requesters{$branch_3}, 'GetWaiting got the reserve for the correct borrower' );
278
278
279
279
280
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum2));
280
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum2));
Lines 312-318 my $messages; Link Here
312
# the one placed by the CPL patron, as the other two patron's hold
312
# the one placed by the CPL patron, as the other two patron's hold
313
# requests cannot be filled by that item per policy.
313
# requests cannot be filled by that item per policy.
314
(undef, $messages, undef, undef) = AddReturn('bug10272_CPL', $branch_2);
314
(undef, $messages, undef, undef) = AddReturn('bug10272_CPL', $branch_2);
315
is( $messages->{ResFound}->{borrowernumber},
315
is( $messages->{ResFound}->{patron_id},
316
    $requesters{$branch_1},
316
    $requesters{$branch_1},
317
    'restrictive library\'s items only fill requests by own patrons (bug 10272)');
317
    'restrictive library\'s items only fill requests by own patrons (bug 10272)');
318
318
Lines 324-342 is( $messages->{ResFound}->{borrowernumber}, Link Here
324
t::lib::Mocks::mock_preference( 'LocalHoldsPriority', '' );
324
t::lib::Mocks::mock_preference( 'LocalHoldsPriority', '' );
325
325
326
(undef, $messages, undef, undef) = AddReturn('bug10272_FPL', $branch_2);
326
(undef, $messages, undef, undef) = AddReturn('bug10272_FPL', $branch_2);
327
is( $messages->{ResFound}->{borrowernumber},
327
is( $messages->{ResFound}->{patron_id},
328
    $requesters{$branch_3},
328
    $requesters{$branch_3},
329
    'for generous library, its items fill first hold request in line (bug 10272)');
329
    'for generous library, its items fill first hold request in line (bug 10272)');
330
330
331
$biblio = Koha::Biblios->find( $biblionumber );
331
$biblio = Koha::Biblios->find( $biblionumber );
332
$holds = $biblio->holds;
332
$holds = $biblio->holds;
333
is($holds->count, 1, "Only one reserves for this biblio");
333
is($holds->count, 1, "Only one reserves for this biblio");
334
$holds->next->reserve_id;
335
334
336
# Tests for bug 9761 (ConfirmFutureHolds): new CheckReserves lookahead parameter, and corresponding change in AddReturn
335
# Tests for bug 9761 (ConfirmFutureHolds): new CheckReserves lookahead parameter, and corresponding change in AddReturn
337
# Note that CheckReserve uses its lookahead parameter and does not check ConfirmFutureHolds pref (it should be passed if needed like AddReturn does)
336
# Note that CheckReserve uses its lookahead parameter and does not check ConfirmFutureHolds pref (it should be passed if needed like AddReturn does)
338
# Test 9761a: Add a reserve without date, CheckReserve should return it
337
# Test 9761a: Add a reserve without date, CheckReserve should return it
339
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum));
338
$dbh->do("DELETE FROM holds WHERE biblio_id=?",undef,($bibnum));
340
AddReserve(
339
AddReserve(
341
    {
340
    {
342
        branchcode     => $branch_1,
341
        branchcode     => $branch_1,
Lines 404-410 is($new_count, $hold_notice_count + 1, 'patron not notified a second time (bug 1 Link Here
404
t::lib::Mocks::mock_preference('IndependentBranches', 0);
403
t::lib::Mocks::mock_preference('IndependentBranches', 0);
405
$item = Koha::Items->find($item->itemnumber);
404
$item = Koha::Items->find($item->itemnumber);
406
is(
405
is(
407
    $item->safe_delete,
406
    $item->safe_to_delete,
408
    'book_reserved',
407
    'book_reserved',
409
    'item that is captured to fill a hold cannot be deleted',
408
    'item that is captured to fill a hold cannot be deleted',
410
);
409
);
Lines 432-438 AddReserve( Link Here
432
431
433
$holds = $item->current_holds;
432
$holds = $item->current_holds;
434
my $dtf = Koha::Database->new->schema->storage->datetime_parser;
433
my $dtf = Koha::Database->new->schema->storage->datetime_parser;
435
my $future_holds = $holds->search({ reservedate => { '>' => $dtf->format_date( dt_from_string ) } } );
434
my $future_holds = $holds->search({ created_date => { '>' => $dtf->format_date( dt_from_string ) } } );
436
is( $future_holds->count, 0, 'current_holds does not return a future next available hold');
435
is( $future_holds->count, 0, 'current_holds does not return a future next available hold');
437
# 9788b: current_holds does not return future item level hold
436
# 9788b: current_holds does not return future item level hold
438
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum));
437
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum));
Lines 446-456 AddReserve( Link Here
446
        itemnumber       => $item->itemnumber,
445
        itemnumber       => $item->itemnumber,
447
    }
446
    }
448
); #item level hold
447
); #item level hold
449
$future_holds = $holds->search({ reservedate => { '>' => $dtf->format_date( dt_from_string ) } } );
448
$future_holds = $holds->search({ created_date => { '>' => $dtf->format_date( dt_from_string ) } } );
450
is( $future_holds->count, 0, 'current_holds does not return a future item level hold' );
449
is( $future_holds->count, 0, 'current_holds does not return a future item level hold' );
451
# 9788c: current_holds returns future wait (confirmed future hold)
450
# 9788c: current_holds returns future wait (confirmed future hold)
452
ModReserveAffect( $item->itemnumber,  $requesters{$branch_1} , 0); #confirm hold
451
ModReserveAffect( $item->itemnumber,  $requesters{$branch_1} , 0); #confirm hold
453
$future_holds = $holds->search({ reservedate => { '>' => $dtf->format_date( dt_from_string ) } } );
452
$future_holds = $holds->search({ created_date => { '>' => $dtf->format_date( dt_from_string ) } } );
454
is( $future_holds->count, 1, 'current_holds returns a future wait (confirmed future hold)' );
453
is( $future_holds->count, 1, 'current_holds returns a future wait (confirmed future hold)' );
455
# End of tests for bug 9788
454
# End of tests for bug 9788
456
455
Lines 534-542 is( CanReserveBeCanceledFromOpac(), undef, Link Here
534
    'CanReserveBeCanceledFromOpac should return undef if called without any parameter'
533
    'CanReserveBeCanceledFromOpac should return undef if called without any parameter'
535
);
534
);
536
is(
535
is(
537
    CanReserveBeCanceledFromOpac( $canres->{resserve_id} ),
536
    CanReserveBeCanceledFromOpac( $canres->{id} ),
538
    undef,
537
    undef,
539
    'CanReserveBeCanceledFromOpac should return undef if called without the reserve_id'
538
    'CanReserveBeCanceledFromOpac should return undef if called without the id'
540
);
539
);
541
is(
540
is(
542
    CanReserveBeCanceledFromOpac( undef, $requesters{CPL} ),
541
    CanReserveBeCanceledFromOpac( undef, $requesters{CPL} ),
Lines 544-561 is( Link Here
544
    'CanReserveBeCanceledFromOpac should return undef if called without borrowernumber'
543
    'CanReserveBeCanceledFromOpac should return undef if called without borrowernumber'
545
);
544
);
546
545
547
my $cancancel = CanReserveBeCanceledFromOpac($canres->{reserve_id}, $requesters{$branch_1});
546
my $cancancel = CanReserveBeCanceledFromOpac($canres->{id}, $requesters{$branch_1});
548
is($cancancel, 1, 'Can user cancel its own reserve');
547
is($cancancel, 1, 'Can user cancel its own reserve');
549
548
550
$cancancel = CanReserveBeCanceledFromOpac($canres->{reserve_id}, $requesters{$branch_2});
549
$cancancel = CanReserveBeCanceledFromOpac($canres->{id}, $requesters{$branch_2});
551
is($cancancel, 0, 'Other user cant cancel reserve');
550
is($cancancel, 0, 'Other user cant cancel reserve');
552
551
553
ModReserveAffect($item->itemnumber, $requesters{$branch_1}, 1);
552
ModReserveAffect($item->itemnumber, $requesters{$branch_1}, 1);
554
$cancancel = CanReserveBeCanceledFromOpac($canres->{reserve_id}, $requesters{$branch_1});
553
$cancancel = CanReserveBeCanceledFromOpac($canres->{id}, $requesters{$branch_1});
555
is($cancancel, 0, 'Reserve in transfer status cant be canceled');
554
is($cancancel, 0, 'Reserve in transfer status cant be canceled');
556
555
557
$dbh->do('DELETE FROM reserves', undef, ($bibnum));
556
$dbh->do('DELETE FROM reserves', undef, ($bibnum));
558
is( CanReserveBeCanceledFromOpac($canres->{resserve_id}, $requesters{$branch_1}), undef,
557
is( CanReserveBeCanceledFromOpac($canres->{id}, $requesters{$branch_1}), undef,
559
    'Cannot cancel a deleted hold' );
558
    'Cannot cancel a deleted hold' );
560
559
561
AddReserve(
560
AddReserve(
Lines 569-575 AddReserve( Link Here
569
(undef, $canres, undef) = CheckReserves($item->itemnumber);
568
(undef, $canres, undef) = CheckReserves($item->itemnumber);
570
569
571
ModReserveAffect($item->itemnumber, $requesters{$branch_1}, 0);
570
ModReserveAffect($item->itemnumber, $requesters{$branch_1}, 0);
572
$cancancel = CanReserveBeCanceledFromOpac($canres->{reserve_id}, $requesters{$branch_1});
571
$cancancel = CanReserveBeCanceledFromOpac($canres->{id}, $requesters{$branch_1});
573
is($cancancel, 0, 'Reserve in waiting status cant be canceled');
572
is($cancancel, 0, 'Reserve in waiting status cant be canceled');
574
573
575
# End of tests for bug 12876
574
# End of tests for bug 12876
Lines 637-643 Koha::CirculationRules->set_rules( Link Here
637
636
638
# tests for MoveReserve in relation to ConfirmFutureHolds (BZ 14526)
637
# tests for MoveReserve in relation to ConfirmFutureHolds (BZ 14526)
639
#   hold from A pos 1, today, no fut holds: MoveReserve should fill it
638
#   hold from A pos 1, today, no fut holds: MoveReserve should fill it
640
$dbh->do('DELETE FROM reserves', undef, ($bibnum));
639
$dbh->do('DELETE FROM holds');
641
t::lib::Mocks::mock_preference('ConfirmFutureHolds', 0);
640
t::lib::Mocks::mock_preference('ConfirmFutureHolds', 0);
642
t::lib::Mocks::mock_preference('AllowHoldDateInFuture', 1);
641
t::lib::Mocks::mock_preference('AllowHoldDateInFuture', 1);
643
AddReserve(
642
AddReserve(
Lines 658-664 AddReserve( Link Here
658
        borrowernumber => $borrowernumber,
657
        borrowernumber => $borrowernumber,
659
        biblionumber   => $bibnum,
658
        biblionumber   => $bibnum,
660
        priority       => 1,
659
        priority       => 1,
661
        found          => 'W',
660
        found          => 'waiting',
662
    }
661
    }
663
);
662
);
664
MoveReserve( $item->itemnumber, $borrowernumber );
663
MoveReserve( $item->itemnumber, $borrowernumber );
Lines 832-844 subtest 'ReservesNeedReturns' => sub { Link Here
832
    t::lib::Mocks::mock_preference('ReservesNeedReturns', 1); # Test with feature disabled
831
    t::lib::Mocks::mock_preference('ReservesNeedReturns', 1); # Test with feature disabled
833
    my $hold = place_item_hold( $patron, $item, $library, $priority );
832
    my $hold = place_item_hold( $patron, $item, $library, $priority );
834
    is( $hold->priority, $priority, 'If ReservesNeedReturns is 1, priority must not have been set to changed' );
833
    is( $hold->priority, $priority, 'If ReservesNeedReturns is 1, priority must not have been set to changed' );
835
    is( $hold->found, undef, 'If ReservesNeedReturns is 1, found must not have been set waiting' );
834
    is( $hold->status, 'placed', 'If ReservesNeedReturns is 1, status must not have been set waiting' );
836
    $hold->delete;
835
    $hold->delete;
837
836
838
    t::lib::Mocks::mock_preference('ReservesNeedReturns', 0); # '0' means 'Automatically mark a hold as found and waiting'
837
    t::lib::Mocks::mock_preference('ReservesNeedReturns', 0); # '0' means 'Automatically mark a hold as status and waiting'
839
    $hold = place_item_hold( $patron, $item, $library, $priority );
838
    $hold = place_item_hold( $patron, $item, $library, $priority );
840
    is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and no other status, priority must have been set to 0' );
839
    is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and no other status, priority must have been set to 0' );
841
    is( $hold->found, 'W', 'If ReservesNeedReturns is 0 and no other status, found must have been set waiting' );
840
    is( $hold->status, 'waiting', 'If ReservesNeedReturns is 0 and no other status, status must have been set waiting' );
842
    $hold->delete;
841
    $hold->delete;
843
842
844
    $item->onloan('2010-01-01')->store;
843
    $item->onloan('2010-01-01')->store;
Lines 854-864 subtest 'ReservesNeedReturns' => sub { Link Here
854
    t::lib::Mocks::mock_preference('AllowHoldsOnDamagedItems', 1); # '0' means damaged holds not allowed
853
    t::lib::Mocks::mock_preference('AllowHoldsOnDamagedItems', 1); # '0' means damaged holds not allowed
855
    $hold = place_item_hold( $patron, $item, $library, $priority );
854
    $hold = place_item_hold( $patron, $item, $library, $priority );
856
    is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and damaged holds allowed, priority must have been set to 0' );
855
    is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and damaged holds allowed, priority must have been set to 0' );
857
    is( $hold->found,  'W', 'If ReservesNeedReturns is 0 and damaged holds allowed, found must have been set waiting' );
856
    is( $hold->status,  'waiting', 'If ReservesNeedReturns is 0 and damaged holds allowed, status must have been set waiting' );
858
    $hold->delete;
857
    $hold->delete;
859
858
860
    my $hold_1 = place_item_hold( $patron, $item, $library, $priority );
859
    my $hold_1 = place_item_hold( $patron, $item, $library, $priority );
861
    is( $hold_1->found,  'W', 'First hold on item is set to waiting with ReservesNeedReturns set to 0' );
860
    is( $hold_1->status,  'waiting', 'First hold on item is set to waiting with ReservesNeedReturns set to 0' );
862
    is( $hold_1->priority, 0, 'First hold on item is set to waiting with ReservesNeedReturns set to 0' );
861
    is( $hold_1->priority, 0, 'First hold on item is set to waiting with ReservesNeedReturns set to 0' );
863
    $hold = place_item_hold( $patron_2, $item, $library, $priority );
862
    $hold = place_item_hold( $patron_2, $item, $library, $priority );
864
    is( $hold->priority, 1, 'If ReservesNeedReturns is 0 but item already on hold priority must be set to 1' );
863
    is( $hold->priority, 1, 'If ReservesNeedReturns is 0 but item already on hold priority must be set to 1' );
Lines 875-895 subtest 'ReservesNeedReturns' => sub { Link Here
875
    });
874
    });
876
    $item->damaged(0)->store;
875
    $item->damaged(0)->store;
877
    $hold = place_item_hold( $patron, $item, $library, $priority );
876
    $hold = place_item_hold( $patron, $item, $library, $priority );
878
    is( $hold->found, undef, 'If ReservesNeedReturns is 0 but item in transit the hold must not be set to waiting' );
877
    is( $hold->status, 'placed', 'If ReservesNeedReturns is 0 but item in transit the hold must not be set to waiting' );
879
    is( $hold->priority, 1,  'If ReservesNeedReturns is 0 but item in transit the hold must not be set to waiting' );
878
    is( $hold->priority, 1,  'If ReservesNeedReturns is 0 but item in transit the hold must not be set to waiting' );
880
    $hold->delete;
879
    $hold->delete;
881
    $transfer->delete;
880
    $transfer->delete;
882
881
883
    $hold = place_item_hold( $patron, $item, $library, $priority );
882
    $hold = place_item_hold( $patron, $item, $library, $priority );
884
    is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and no other status, priority must have been set to 0' );
883
    is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and no other status, priority must have been set to 0' );
885
    is( $hold->found, 'W', 'If ReservesNeedReturns is 0 and no other status, found must have been set waiting' );
884
    is( $hold->status, 'waiting', 'If ReservesNeedReturns is 0 and no other status, found must have been set waiting' );
886
    $hold_1 = place_item_hold( $patron, $item, $library, $priority );
885
    $hold_1 = place_item_hold( $patron, $item, $library, $priority );
887
    is( $hold_1->priority, 1, 'If ReservesNeedReturns is 0 but item has a hold priority is 1' );
886
    is( $hold_1->priority, 1, 'If ReservesNeedReturns is 0 but item has a hold priority is 1' );
888
    $hold_1->suspend(1)->store; # We suspend the hold
887
    $hold_1->suspended(1)->store; # We suspend the hold
889
    $hold->delete; # Delete the waiting hold
888
    $hold->delete; # Delete the waiting hold
890
    $hold = place_item_hold( $patron, $item, $library, $priority );
889
    $hold = place_item_hold( $patron, $item, $library, $priority );
891
    is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and other hold(s) suspended, priority must have been set to 0' );
890
    is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and other hold(s) suspended, priority must have been set to 0' );
892
    is( $hold->found, 'W', 'If ReservesNeedReturns is 0 and other  hold(s) suspended, found must have been set waiting' );
891
    is( $hold->status, 'waiting', 'If ReservesNeedReturns is 0 and other  hold(s) suspended, found must have been set waiting' );
893
892
894
893
895
894
Lines 935-940 subtest 'reserves.item_level_hold' => sub { Link Here
935
934
936
    subtest 'item level hold' => sub {
935
    subtest 'item level hold' => sub {
937
        plan tests => 2;
936
        plan tests => 2;
937
938
        $schema->storage->txn_begin;
939
938
        my $reserve_id = AddReserve(
940
        my $reserve_id = AddReserve(
939
            {
941
            {
940
                branchcode     => $item->homebranch,
942
                branchcode     => $item->homebranch,
Lines 946-965 subtest 'reserves.item_level_hold' => sub { Link Here
946
        );
948
        );
947
949
948
        my $hold = Koha::Holds->find($reserve_id);
950
        my $hold = Koha::Holds->find($reserve_id);
949
        is( $hold->item_level_hold, 1, 'item_level_hold should be set when AddReserve is called with a specific item' );
951
        is( $hold->item_level, 1, 'item_level should be set when AddReserve is called with a specific item' );
950
952
951
        # Mark it waiting
953
        ModReserveAffect( $item->itemnumber, $patron->borrowernumber );
952
        ModReserveAffect( $item->itemnumber, $patron->borrowernumber, 1 );
953
954
954
        # Revert the waiting status
955
        # Revert the waiting status
955
        C4::Reserves::RevertWaitingStatus(
956
        C4::Reserves::RevertWaitingStatus(
956
            { itemnumber => $item->itemnumber } );
957
            { itemnumber => $item->itemnumber } );
957
958
958
        $hold = Koha::Holds->find($reserve_id);
959
        $hold->discard_changes;
959
960
960
        is( $hold->itemnumber, $item->itemnumber, 'Itemnumber should not be removed when the waiting status is revert' );
961
        is( $hold->item_id, $item->itemnumber, 'Itemnumber should not be removed when the waiting status is revert' );
961
962
962
        $hold->delete;    # cleanup
963
        $schema->storage->txn_rollback;
963
    };
964
    };
964
965
965
    subtest 'biblio level hold' => sub {
966
    subtest 'biblio level hold' => sub {
Lines 974-992 subtest 'reserves.item_level_hold' => sub { Link Here
974
        );
975
        );
975
976
976
        my $hold = Koha::Holds->find($reserve_id);
977
        my $hold = Koha::Holds->find($reserve_id);
977
        is( $hold->item_level_hold, 0, 'item_level_hold should not be set when AddReserve is called without a specific item' );
978
        is( $hold->item_level, 0, 'item_level should not be set when AddReserve is called without a specific item' );
978
979
979
        # Mark it waiting
980
        # Mark it waiting
980
        ModReserveAffect( $item->itemnumber, $patron->borrowernumber, 1 );
981
        ModReserveAffect( $item->itemnumber, $patron->borrowernumber );
981
982
982
        $hold = Koha::Holds->find($reserve_id);
983
        $hold = Koha::Holds->find($reserve_id);
983
        is( $hold->itemnumber, $item->itemnumber, 'Itemnumber should be set on hold confirmation' );
984
        is( $hold->item_id, $item->itemnumber, 'Itemnumber should be set on hold confirmation' );
984
985
985
        # Revert the waiting status
986
        # Revert the waiting status
986
        C4::Reserves::RevertWaitingStatus( { itemnumber => $item->itemnumber } );
987
        C4::Reserves::RevertWaitingStatus( { itemnumber => $item->itemnumber } );
987
988
988
        $hold = Koha::Holds->find($reserve_id);
989
        $hold = Koha::Holds->find($reserve_id);
989
        is( $hold->itemnumber, undef, 'Itemnumber should be removed when the waiting status is revert' );
990
        is( $hold->item_id, undef, 'Itemnumber should be removed when the waiting status is revert' );
990
991
991
        $hold->delete;
992
        $hold->delete;
992
    };
993
    };
Lines 1024-1039 subtest 'MoveReserve additional test' => sub { Link Here
1024
            itemnumber     => $item_1->itemnumber,
1025
            itemnumber     => $item_1->itemnumber,
1025
        }
1026
        }
1026
    );
1027
    );
1027
    is($patron_1->holds->next()->reserve_id, $reserve_1, "The 1st patron has a hold");
1028
    is($patron_1->holds->next()->id, $reserve_1, "The 1st patron has a hold");
1028
    is($patron_2->holds->next()->reserve_id, $reserve_2, "The 2nd patron has a hold");
1029
    is($patron_2->holds->next()->id, $reserve_2, "The 2nd patron has a hold");
1029
1030
1030
    # Fake the holds queue
1031
    # Fake the holds queue
1031
    $dbh->do(q{INSERT INTO hold_fill_targets VALUES (?, ?, ?, ?, ?,?)},undef,($patron_1->borrowernumber,$biblio->biblionumber,$item_1->itemnumber,$item_1->homebranch,0,$reserve_1));
1032
    $dbh->do(q{INSERT INTO hold_fill_targets VALUES (?, ?, ?, ?, ?,?)},undef,($patron_1->borrowernumber,$biblio->biblionumber,$item_1->itemnumber,$item_1->homebranch,0,$reserve_1));
1032
1033
1033
    # The 2nd hold should be filed even if the item is preselected for the first hold
1034
    # The 2nd hold should be filed even if the item is preselected for the first hold
1034
    MoveReserve($item_1->itemnumber,$patron_2->borrowernumber);
1035
    MoveReserve($item_1->itemnumber,$patron_2->borrowernumber);
1035
    is($patron_2->holds->count, 0, "The 2nd patrons no longer has a hold");
1036
    is($patron_2->holds({ completed => 0 })->count, 0, "The 2nd patrons no longer has a hold");
1036
    is($patron_2->old_holds->next()->reserve_id, $reserve_2, "The 2nd patrons hold was filled and moved to old holds");
1037
    is($patron_2->holds({ completed => 1 })->next()->id, $reserve_2, "The 2nd patrons hold was filled and moved to old holds");
1037
1038
1038
};
1039
};
1039
1040
Lines 1089-1106 subtest 'CheckReserves additional tests' => sub { Link Here
1089
        {
1090
        {
1090
            class => "Koha::Holds",
1091
            class => "Koha::Holds",
1091
            value => {
1092
            value => {
1092
                found            => undef,
1093
                priority         => 1,
1093
                priority         => 1,
1094
                itemnumber       => undef,
1094
                item_id          => undef,
1095
                biblionumber     => $item->biblionumber,
1095
                biblio_id        => $item->biblionumber,
1096
                waitingdate      => undef,
1096
                item_level       => 0,
1097
                cancellationdate => undef,
1097
                lowest_priority  => 0,
1098
                item_level_hold  => 0,
1098
                expiration_date  => undef,
1099
                lowestPriority   => 0,
1100
                expirationdate   => undef,
1101
                suspend_until    => undef,
1102
                suspend          => 0,
1103
                itemtype         => undef,
1104
            }
1099
            }
1105
        }
1100
        }
1106
    );
1101
    );
Lines 1108-1126 subtest 'CheckReserves additional tests' => sub { Link Here
1108
        {
1103
        {
1109
            class => "Koha::Holds",
1104
            class => "Koha::Holds",
1110
            value => {
1105
            value => {
1111
                found            => undef,
1112
                priority         => 2,
1106
                priority         => 2,
1113
                biblionumber     => $item->biblionumber,
1107
                item_id          => $item->biblionumber,
1114
                borrowernumber   => $reserve1->borrowernumber,
1108
                patron_id        => $reserve1->patron_id,
1115
                itemnumber       => undef,
1109
                item_id          => undef,
1116
                waitingdate      => undef,
1110
                suspended_until  => undef,
1117
                cancellationdate => undef,
1111
                suspended        => 0,
1118
                item_level_hold  => 0,
1112
                item_type       => undef,
1119
                lowestPriority   => 0,
1120
                expirationdate   => undef,
1121
                suspend_until    => undef,
1122
                suspend          => 0,
1123
                itemtype         => undef,
1124
            }
1113
            }
1125
        }
1114
        }
1126
    );
1115
    );
Lines 1129-1136 subtest 'CheckReserves additional tests' => sub { Link Here
1129
        {
1118
        {
1130
            source => 'TmpHoldsqueue',
1119
            source => 'TmpHoldsqueue',
1131
            value  => {
1120
            value  => {
1132
                borrowernumber => $reserve1->borrowernumber,
1121
                borrowernumber => $reserve1->patron_id,
1133
                biblionumber   => $reserve1->biblionumber,
1122
                biblionumber   => $reserve1->biblio_id,
1134
            }
1123
            }
1135
        }
1124
        }
1136
    );
1125
    );
Lines 1138-1159 subtest 'CheckReserves additional tests' => sub { Link Here
1138
        {
1127
        {
1139
            source => 'HoldFillTarget',
1128
            source => 'HoldFillTarget',
1140
            value  => {
1129
            value  => {
1141
                borrowernumber     => $reserve1->borrowernumber,
1130
                borrowernumber     => $reserve1->patron_id,
1142
                biblionumber       => $reserve1->biblionumber,
1131
                biblionumber       => $reserve1->biblio_id,
1143
                itemnumber         => $item->itemnumber,
1132
                itemnumber         => $item->itemnumber,
1144
                item_level_request => 0,
1133
                item_level_request => 0,
1145
            }
1134
            }
1146
        }
1135
        }
1147
    );
1136
    );
1148
1137
1149
    ModReserveAffect( $item->itemnumber, $reserve1->borrowernumber, 1,
1138
    ModReserveAffect( $item->itemnumber, $reserve1->patron_id, 1,
1150
        $reserve1->reserve_id );
1139
        $reserve1->id );
1151
    my ( $status, $matched_reserve, $possible_reserves ) =
1140
    my ( $status, $matched_reserve, $possible_reserves ) =
1152
      CheckReserves( $item->itemnumber );
1141
      CheckReserves( $item->itemnumber );
1153
1142
1154
    is( $status, 'Transferred', "We found a reserve" );
1143
    is( $status, 'Transferred', "We found a reserve" );
1155
    is( $matched_reserve->{reserve_id},
1144
    is( $matched_reserve->{reserve_id},
1156
        $reserve1->reserve_id, "We got the Transit reserve" );
1145
        $reserve1->id, "We got the Transit reserve" );
1157
    is( scalar @$possible_reserves, 2, 'We do get both reserves' );
1146
    is( scalar @$possible_reserves, 2, 'We do get both reserves' );
1158
1147
1159
    my $patron_B = $builder->build_object({ class => "Koha::Patrons" });
1148
    my $patron_B = $builder->build_object({ class => "Koha::Patrons" });
Lines 1327-1333 subtest 'ModReserveAffect logging' => sub { Link Here
1327
    ok( $hold->is_waiting, 'Hold has been set waiting' );
1316
    ok( $hold->is_waiting, 'Hold has been set waiting' );
1328
    isnt( $hold->timestamp, $previous_timestamp, 'The timestamp has been modified' );
1317
    isnt( $hold->timestamp, $previous_timestamp, 'The timestamp has been modified' );
1329
1318
1330
    my $log = Koha::ActionLogs->search({ module => 'HOLDS', action => 'MODIFY', object => $hold->reserve_id })->next;
1319
    my $log = Koha::ActionLogs->search({ module => 'HOLDS', action => 'MODIFY', object => $hold->id })->next;
1331
    my $expected = sprintf q{'timestamp' => '%s'}, $hold->timestamp;
1320
    my $expected = sprintf q{'timestamp' => '%s'}, $hold->timestamp;
1332
    like( $log->info, qr{$expected}, 'Timestamp logged is the current one' );
1321
    like( $log->info, qr{$expected}, 'Timestamp logged is the current one' );
1333
};
1322
};
(-)a/t/db_dependent/Reserves/AutoUnsuspendReserves.t (-16 / +16 lines)
Lines 43-52 subtest 'AutoUnsuspendReserves test' => sub { Link Here
43
    my $hold_1 = $builder->build_object({
43
    my $hold_1 = $builder->build_object({
44
        class => 'Koha::Holds',
44
        class => 'Koha::Holds',
45
        value => {
45
        value => {
46
            expirationdate => undef,
46
            expiration_date => undef,
47
            cancellationdate => undef,
47
            completed_date  => undef,
48
            priority => 5,
48
            priority => 5,
49
            found => undef,
49
            status => 'placed',
50
        },
50
        },
51
    });
51
    });
52
52
Lines 56-65 subtest 'AutoUnsuspendReserves test' => sub { Link Here
56
    my $hold_2 = $builder->build_object({
56
    my $hold_2 = $builder->build_object({
57
        class => 'Koha::Holds',
57
        class => 'Koha::Holds',
58
        value => {
58
        value => {
59
            expirationdate => undef,
59
            expiration_date => undef,
60
            cancellationdate => undef,
60
            completed_date  => undef,
61
            priority => 6,
61
            priority => 6,
62
            found => undef,
62
            status => 'placed',
63
        },
63
        },
64
    });
64
    });
65
65
Lines 84-94 subtest 'AutoUnsuspendReserves test' => sub { Link Here
84
        my $hold_3 = $builder->build_object(
84
        my $hold_3 = $builder->build_object(
85
            {   class => 'Koha::Holds',
85
            {   class => 'Koha::Holds',
86
                value => {
86
                value => {
87
                    expirationdate   => undef,
87
                    expiration_date   => undef,
88
                    cancellationdate => undef,
88
                    completed_date    => undef,
89
                    priority         => 5,
89
                    priority          => 5,
90
                    found            => undef,
90
                    status            => 'placed',
91
                    suspend_until    => undef,
91
                    suspended_until_date => undef,
92
                }
92
                }
93
            }
93
            }
94
        );
94
        );
Lines 121-130 subtest 'AutoUnsuspendReserves test' => sub { Link Here
121
        my $hold_4 = $builder->build_object(
121
        my $hold_4 = $builder->build_object(
122
            {   class => 'Koha::Holds',
122
            {   class => 'Koha::Holds',
123
                value => {
123
                value => {
124
                    expirationdate   => undef,
124
                    expiration_date   => undef,
125
                    cancellationdate => undef,
125
                    completed_date    => undef,
126
                    priority         => 5,
126
                    priority          => 5,
127
                    found            => undef
127
                    status            => 'placed'
128
                }
128
                }
129
            }
129
            }
130
        );
130
        );
Lines 137-143 subtest 'AutoUnsuspendReserves test' => sub { Link Here
137
        AutoUnsuspendReserves();
137
        AutoUnsuspendReserves();
138
138
139
        $hold_4->discard_changes;
139
        $hold_4->discard_changes;
140
        ok(!defined($hold_4->suspend_until), 'Hold suspended until today should be unsuspended.');
140
        ok(!defined($hold_4->suspended_until_date), 'Hold suspended until today should be unsuspended.');
141
141
142
        my $new_logs_count = $schema->resultset('ActionLog')
142
        my $new_logs_count = $schema->resultset('ActionLog')
143
            ->search( { module => 'HOLDS', action => 'RESUME' } )->count;
143
            ->search( { module => 'HOLDS', action => 'RESUME' } )->count;
(-)a/t/db_dependent/Reserves/CancelExpiredReserves.t (-103 / +127 lines)
Lines 16-22 my $schema = Koha::Database->new->schema; Link Here
16
$schema->storage->txn_begin;
16
$schema->storage->txn_begin;
17
17
18
subtest 'CancelExpiredReserves tests incl. holidays' => sub {
18
subtest 'CancelExpiredReserves tests incl. holidays' => sub {
19
    plan tests => 4;
19
    plan tests => 6;
20
20
21
    my $builder = t::lib::TestBuilder->new();
21
    my $builder = t::lib::TestBuilder->new();
22
22
Lines 33-84 subtest 'CancelExpiredReserves tests incl. holidays' => sub { Link Here
33
    $reserve1_expirationdate->add(days => 1);
33
    $reserve1_expirationdate->add(days => 1);
34
34
35
    # Reserve not expired
35
    # Reserve not expired
36
    my $reserve1 = $builder->build({
36
    my $reserve1 = $builder->build_object(
37
        source => 'Reserve',
37
        {
38
        value => {
38
            class => 'Koha::Holds',
39
            reservedate => $reserve_reservedate,
39
            value => {
40
            expirationdate => $reserve1_expirationdate,
40
                created_date    => $reserve_reservedate,
41
            cancellationdate => undef,
41
                expiration_date => $reserve1_expirationdate,
42
            priority => 0,
42
                completed_date  => undef,
43
            found => 'W',
43
                priority        => 0,
44
        },
44
                status          => 'waiting',
45
    });
45
                completed       => 0,
46
            },
47
        }
48
    );
46
49
47
    CancelExpiredReserves();
50
    CancelExpiredReserves();
48
    my $r1 = Koha::Holds->find($reserve1->{reserve_id});
51
    my $r1 = Koha::Holds->find($reserve1->id);
49
    ok($r1, 'Reserve 1 should not be canceled.');
52
    ok($r1, 'Reserve 1 should not be canceled.');
50
53
51
    my $reserve2_expirationdate = $today->clone;
54
    my $reserve2_expirationdate = $today->clone;
52
    $reserve2_expirationdate->subtract(days => 1);
55
    $reserve2_expirationdate->subtract(days => 1);
53
56
54
    # Reserve expired
57
    # Reserve expired
55
    my $reserve2 = $builder->build({
58
    my $reserve2 = $builder->build_object(
56
        source => 'Reserve',
59
        {
57
        value => {
60
            class => 'Koha::Holds',
58
            reservedate => $reserve_reservedate,
61
            value => {
59
            expirationdate => $reserve2_expirationdate,
62
                created_date    => $reserve_reservedate,
60
            cancellationdate => undef,
63
                expiration_date => $reserve2_expirationdate,
61
            priority => 0,
64
                completed_date  => undef,
62
            found => 'W',
65
                priority        => 0,
63
        },
66
                status          => 'waiting',
64
    });
67
                completed       => 0,
68
            },
69
        }
70
    );
65
71
66
    CancelExpiredReserves();
72
    CancelExpiredReserves();
67
    my $r2 = Koha::Holds->find($reserve2->{reserve_id});
73
    my $r2 = Koha::Holds->find($reserve2->id);
68
    is($r2, undef,'reserve 2 should be canceled.');
74
    is(ref($r2), 'Koha::Hold', 'reserve 2 is still there.');
75
    is($r2->status, 'cancelled', 'reserve 2 should be canceled.');
76
    is($r2->completed, 1, 'reserve 2 should be completed.');
69
77
70
    # Reserve expired on holiday
78
    # Reserve expired on holiday
71
    my $reserve3 = $builder->build({
79
    my $reserve3 = $builder->build_object(
72
        source => 'Reserve',
80
        {
73
        value => {
81
            class => 'Koha::Holds',
74
            reservedate => $reserve_reservedate,
82
            value => {
75
            expirationdate => $reserve2_expirationdate,
83
                created_date      => $reserve_reservedate,
76
            branchcode => 'LIB1',
84
                expiration_date   => $reserve2_expirationdate,
77
            cancellationdate => undef,
85
                pickup_library_id => 'LIB1',
78
            priority => 0,
86
                completed_date    => undef,
79
            found => 'W',
87
                priority          => 0,
80
        },
88
                status            => 'waiting',
81
    });
89
            },
90
        }
91
    );
82
92
83
    Koha::Caches->get_instance()->flush_all();
93
    Koha::Caches->get_instance()->flush_all();
84
    my $holiday = $builder->build({
94
    my $holiday = $builder->build({
Lines 94-106 subtest 'CancelExpiredReserves tests incl. holidays' => sub { Link Here
94
    });
104
    });
95
105
96
    CancelExpiredReserves();
106
    CancelExpiredReserves();
97
    my $r3 = Koha::Holds->find($reserve3->{reserve_id});
107
    $reserve3->discard_changes;
98
    ok($r3,'Reserve 3 should not be canceled.');
108
    is($reserve3->status, 'waiting','Reserve 3 should not be canceled.');
99
109
100
    t::lib::Mocks::mock_preference('ExpireReservesOnHolidays', 1);
110
    t::lib::Mocks::mock_preference('ExpireReservesOnHolidays', 1);
101
    CancelExpiredReserves();
111
    CancelExpiredReserves();
102
    $r3 = Koha::Holds->find($reserve3->{reserve_id});
112
    $reserve3->discard_changes;
103
    is($r3, undef,'Reserve 3 should be canceled.');
113
    is($reserve3->status, 'cancelled', 'Reserve 3 should be cancelled.');
104
};
114
};
105
115
106
subtest 'Test handling of waiting reserves by CancelExpiredReserves' => sub {
116
subtest 'Test handling of waiting reserves by CancelExpiredReserves' => sub {
Lines 119-163 subtest 'Test handling of waiting reserves by CancelExpiredReserves' => sub { Link Here
119
    my $expdate = dt_from_string->add( days => -2 );
129
    my $expdate = dt_from_string->add( days => -2 );
120
    my $notexpdate = dt_from_string->add( days => 2 );
130
    my $notexpdate = dt_from_string->add( days => 2 );
121
131
122
    my $hold1 = Koha::Hold->new({
132
    my $hold1 = Koha::Hold->new(
123
        branchcode => $branchcode,
133
        {
124
        borrowernumber => $borrowernumber,
134
            pickup_library_id => $branchcode,
125
        biblionumber => $item->biblionumber,
135
            patron_id         => $borrowernumber,
126
        priority => 1,
136
            biblio_id         => $item->biblionumber,
127
        reservedate => $resdate,
137
            priority          => 1,
128
        expirationdate => $notexpdate,
138
            created_date      => $resdate,
129
        found => undef,
139
            expiration_date   => $notexpdate,
130
    })->store;
140
            status            => 'placed',
131
141
        }
132
    my $hold2 = Koha::Hold->new({
142
    )->store;
133
        branchcode => $branchcode,
143
134
        borrowernumber => $borrowernumber,
144
    my $hold2 = Koha::Hold->new(
135
        biblionumber => $item->biblionumber,
145
        {
136
        priority => 2,
146
            pickup_library_id => $branchcode,
137
        reservedate => $resdate,
147
            patron_id         => $borrowernumber,
138
        expirationdate => $expdate,
148
            biblio_id         => $item->biblionumber,
139
        found => undef,
149
            priority          => 2,
140
    })->store;
150
            created_date      => $resdate,
141
151
            expiration_date   => $expdate,
142
    my $hold3 = Koha::Hold->new({
152
            status            => 'placed',
143
        branchcode => $branchcode,
153
        }
144
        borrowernumber => $borrowernumber,
154
    )->store;
145
        biblionumber => $item->biblionumber,
155
146
        itemnumber => $itemnumber,
156
    my $hold3 = Koha::Hold->new(
147
        priority => 0,
157
        {
148
        reservedate => $resdate,
158
            pickup_library_id => $branchcode,
149
        expirationdate => $expdate,
159
            patron_id         => $borrowernumber,
150
        found => 'W',
160
            biblio_id         => $item->biblionumber,
151
    })->store;
161
            item_id           => $itemnumber,
162
            priority          => 0,
163
            created_date      => $resdate,
164
            expiration_date   => $expdate,
165
            status            => 'waiting',
166
        }
167
    )->store;
152
168
153
    t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 0 );
169
    t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 0 );
154
    CancelExpiredReserves();
170
    CancelExpiredReserves();
155
    my $count1 = Koha::Holds->search->count;
171
    my $count1 = Koha::Holds->search({ completed => 0 })->count;
156
    is( $count1, 2, 'Only the non-waiting expired holds should be cancelled');
172
    is( $count1, 2, 'Only the non-waiting expired holds should be cancelled');
157
173
158
    t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 1 );
174
    t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 1 );
159
    CancelExpiredReserves();
175
    CancelExpiredReserves();
160
    my $count2 = Koha::Holds->search->count;
176
    my $count2 = Koha::Holds->search({ completed => 0 })->count;
161
    is( $count2, 1, 'Also the waiting expired hold should be cancelled now');
177
    is( $count2, 1, 'Also the waiting expired hold should be cancelled now');
162
178
163
};
179
};
Lines 169-226 subtest 'Test handling of in transit reserves by CancelExpiredReserves' => sub { Link Here
169
185
170
    t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 1 );
186
    t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 1 );
171
    my $expdate = dt_from_string->add( days => -2 );
187
    my $expdate = dt_from_string->add( days => -2 );
172
    my $reserve = $builder->build({
188
    my $reserve = $builder->build_object({
173
        source => 'Reserve',
189
        class => 'Koha::Holds',
174
        value  => {
190
        value  => {
175
            expirationdate => '2018-01-01',
191
            expiration_date      => '2018-01-01',
176
            found => 'T',
192
            status               => 'in_transit',
177
            cancellationdate => undef,
193
            suspended            => 0,
178
            suspend => 0,
194
            completed            => 0,
179
            suspend_until => undef
195
            cancellation_date    => undef,
196
            suspended_until_date => undef,
180
        }
197
        }
181
    });
198
    });
182
    my $count = Koha::Holds->search->count;
199
200
    my $active = Koha::Holds->search({ completed => 0 });
201
    my $count = $active->count;
202
183
    CancelExpiredReserves();
203
    CancelExpiredReserves();
184
    is(Koha::Holds->search->count, $count-1, "Transit hold is cancelled if ExpireReservesMaxPickUpDelay set");
204
    is($active->count, $count-1, "Transit hold is cancelled if ExpireReservesMaxPickUpDelay set");
185
205
186
    t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 0 );
206
    t::lib::Mocks::mock_preference( 'ExpireReservesMaxPickUpDelay', 0 );
187
    my $reserve2 = $builder->build({
207
    my $reserve2 = $builder->build_object({
188
        source => 'Reserve',
208
        class => 'Koha::Holds',
189
        value  => {
209
        value  => {
190
            expirationdate => '2018-01-01',
210
            expiration_date      => '2018-01-01',
191
            found => 'T',
211
            status               => 'in_transit',
192
            cancellationdate => undef,
212
            cancellation_date    => undef,
193
            suspend => 0,
213
            suspended            => 0,
194
            suspend_until => undef
214
            suspended_until_date => undef,
215
            completed            => 0,
195
        }
216
        }
196
    });
217
    });
197
    CancelExpiredReserves();
218
    CancelExpiredReserves();
198
    is(Koha::Holds->search->count, $count-1, "Transit hold is cancelled if ExpireReservesMaxPickUpDelay unset");
219
    is($active->count, $count-1, "Transit hold is cancelled if ExpireReservesMaxPickUpDelay unset");
199
220
200
};
221
};
201
222
202
subtest 'Test handling of cancellation reason if passed' => sub {
223
subtest 'Test handling of cancellation reason if passed' => sub {
203
    plan tests => 2;
224
    plan tests => 3;
204
225
205
    my $builder = t::lib::TestBuilder->new();
226
    my $builder = t::lib::TestBuilder->new();
206
227
207
    my $expdate = dt_from_string->add( days => -2 );
228
    my $expdate = dt_from_string->add( days => -2 );
208
    my $reserve = $builder->build({
229
    my $hold = $builder->build_object(
209
        source => 'Reserve',
230
        {   class => 'Koha::Holds',
210
        value  => {
231
            value => {
211
            expirationdate => '2018-01-01',
232
                expiration_date    => '2018-01-01',
212
            found => 'T',
233
                status             => 'in_transit',
213
            cancellationdate => undef,
234
                cancellation_date  => undef,
214
            suspend => 0,
235
                suspended          => 0,
215
            suspend_until => undef
236
                suspend_until_date => undef
237
            }
216
        }
238
        }
217
    });
239
    );
218
    my $reserve_id = $reserve->{reserve_id};
240
219
    my $count = Koha::Holds->search->count;
241
    # Cancel the hold
220
    CancelExpiredReserves("EXPIRED");
242
    CancelExpiredReserves("EXPIRED");
221
    is(Koha::Holds->search->count, $count-1, "Hold is cancelled when reason is passed");
243
    $hold->discard_changes;
222
    my $old_reserve = Koha::Old::Holds->find($reserve_id);
244
223
    is($old_reserve->cancellation_reason, 'EXPIRED', "Hold cancellation_reason was set correctly");
245
    is( $hold->status, 'cancelled', "Hold is cancelled when reason is passed");
246
    is( $hold->completed, 1, "Hold is completed");
247
    is( $hold->cancellation_reason, 'EXPIRED', "Hold cancellation_reason was set correctly");
224
};
248
};
225
249
226
$schema->storage->txn_rollback;
250
$schema->storage->txn_rollback;
(-)a/t/db_dependent/Reserves/GetReserveFee.t (-7 / +7 lines)
Lines 119-137 subtest 'Integration with AddReserve' => sub { Link Here
119
        plan tests => 3;
119
        plan tests => 3;
120
120
121
        t::lib::Mocks::mock_preference('HoldFeeMode', 'not_always');
121
        t::lib::Mocks::mock_preference('HoldFeeMode', 'not_always');
122
        $dbh->do( "DELETE FROM reserves     WHERE biblionumber=?", undef, $biblio->biblionumber );
122
        $dbh->do( "DELETE FROM holds        WHERE biblio_id=?",      undef, $biblio->biblionumber );
123
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
123
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
124
        addreserve( $patron1->{borrowernumber} );
124
        addreserve( $patron1->{borrowernumber} );
125
        is( acctlines( $patron1->{borrowernumber} ), 0, 'not_always - No fee charged for patron 1 if not issued' );
125
        is( acctlines( $patron1->{borrowernumber} ), 0, 'not_always - No fee charged for patron 1 if not issued' );
126
126
127
        t::lib::Mocks::mock_preference('HoldFeeMode', 'any_time_is_placed');
127
        t::lib::Mocks::mock_preference('HoldFeeMode', 'any_time_is_placed');
128
        $dbh->do( "DELETE FROM reserves     WHERE biblionumber=?", undef, $biblio->biblionumber );
128
        $dbh->do( "DELETE FROM holds        WHERE biblio_id=?",      undef, $biblio->biblionumber );
129
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
129
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
130
        addreserve( $patron1->{borrowernumber} );
130
        addreserve( $patron1->{borrowernumber} );
131
        is( acctlines( $patron1->{borrowernumber} ), 1, 'any_time_is_placed - Patron should be always charged' );
131
        is( acctlines( $patron1->{borrowernumber} ), 1, 'any_time_is_placed - Patron should be always charged' );
132
132
133
        t::lib::Mocks::mock_preference('HoldFeeMode', 'any_time_is_collected');
133
        t::lib::Mocks::mock_preference('HoldFeeMode', 'any_time_is_collected');
134
        $dbh->do( "DELETE FROM reserves     WHERE biblionumber=?", undef, $biblio->biblionumber );
134
        $dbh->do( "DELETE FROM holds        WHERE biblio_id=?",      undef, $biblio->biblionumber );
135
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
135
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
136
        addreserve( $patron1->{borrowernumber} );
136
        addreserve( $patron1->{borrowernumber} );
137
        is( acctlines( $patron1->{borrowernumber} ), 0, 'any_time_is_collected - Patron should not be charged when placing a hold' );
137
        is( acctlines( $patron1->{borrowernumber} ), 0, 'any_time_is_collected - Patron should not be charged when placing a hold' );
Lines 143-154 subtest 'Integration with AddReserve' => sub { Link Here
143
        C4::Circulation::AddIssue( $patron2, $item1->barcode, '2015-12-31', 0, undef, 0, {} );
143
        C4::Circulation::AddIssue( $patron2, $item1->barcode, '2015-12-31', 0, undef, 0, {} );
144
144
145
        t::lib::Mocks::mock_preference('HoldFeeMode', 'not_always');
145
        t::lib::Mocks::mock_preference('HoldFeeMode', 'not_always');
146
        $dbh->do( "DELETE FROM reserves     WHERE biblionumber=?", undef, $biblio->biblionumber );
146
        $dbh->do( "DELETE FROM holds        WHERE biblio_id=?",      undef, $biblio->biblionumber );
147
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
147
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
148
        addreserve( $patron1->{borrowernumber} );
148
        addreserve( $patron1->{borrowernumber} );
149
        is( acctlines( $patron1->{borrowernumber} ), 0, 'not_always - Patron should not be charged if items are not all checked out' );
149
        is( acctlines( $patron1->{borrowernumber} ), 0, 'not_always - Patron should not be charged if items are not all checked out' );
150
150
151
        $dbh->do( "DELETE FROM reserves     WHERE biblionumber=?", undef, $biblio->biblionumber );
151
        $dbh->do( "DELETE FROM holds        WHERE biblio_id=?",      undef, $biblio->biblionumber );
152
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
152
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
153
        addreserve( $patron3->{borrowernumber} );
153
        addreserve( $patron3->{borrowernumber} );
154
        addreserve( $patron1->{borrowernumber} );
154
        addreserve( $patron1->{borrowernumber} );
Lines 156-162 subtest 'Integration with AddReserve' => sub { Link Here
156
        is( acctlines( $patron1->{borrowernumber} ), 1, 'not_always - Patron should be charged if all the items are not checked out and at least 1 hold is already placed' );
156
        is( acctlines( $patron1->{borrowernumber} ), 1, 'not_always - Patron should be charged if all the items are not checked out and at least 1 hold is already placed' );
157
157
158
        C4::Circulation::AddIssue( $patron3, $item2->barcode, '2015-12-31', 0, undef, 0, {} );
158
        C4::Circulation::AddIssue( $patron3, $item2->barcode, '2015-12-31', 0, undef, 0, {} );
159
        $dbh->do( "DELETE FROM reserves     WHERE biblionumber=?", undef, $biblio->biblionumber );
159
        $dbh->do( "DELETE FROM holds        WHERE biblio_id=?", undef, $biblio->biblionumber );
160
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
160
        $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
161
        addreserve( $patron1->{borrowernumber} );
161
        addreserve( $patron1->{borrowernumber} );
162
        is( acctlines( $patron1->{borrowernumber} ), 1, 'not_always - Patron should be charged if all items are checked out' );
162
        is( acctlines( $patron1->{borrowernumber} ), 1, 'not_always - Patron should be charged if all items are checked out' );
Lines 167-173 subtest 'Integration with AddIssue' => sub { Link Here
167
    plan tests => 5;
167
    plan tests => 5;
168
168
169
    $dbh->do( "DELETE FROM issues       WHERE borrowernumber = ?", undef, $patron1->{borrowernumber} );
169
    $dbh->do( "DELETE FROM issues       WHERE borrowernumber = ?", undef, $patron1->{borrowernumber} );
170
    $dbh->do( "DELETE FROM reserves     WHERE biblionumber=?", undef, $biblio->biblionumber );
170
    $dbh->do( "DELETE FROM holds        WHERE biblio_id=?",      undef, $biblio->biblionumber );
171
    $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
171
    $dbh->do( "DELETE FROM accountlines WHERE borrowernumber=?", undef, $patron1->{borrowernumber} );
172
172
173
    t::lib::Mocks::mock_preference('HoldFeeMode', 'not_always');
173
    t::lib::Mocks::mock_preference('HoldFeeMode', 'not_always');
(-)a/t/db_dependent/Reserves/MultiplePerRecord.t (-9 / +9 lines)
Lines 184-208 is( $max, 9, 'GetMaxPatronHoldsForRecord returns max of 9 because Library specif Link Here
184
184
185
Koha::CirculationRules->delete();
185
Koha::CirculationRules->delete();
186
186
187
my $holds = Koha::Holds->search( { borrowernumber => $patron->{borrowernumber} } );
187
my $holds = Koha::Holds->search( { patron_id => $patron->{borrowernumber} } );
188
is( $holds->forced_hold_level, undef, "No holds does not force an item or record level hold" );
188
is( $holds->forced_hold_level, undef, "No holds does not force an item or record level hold" );
189
189
190
# Test Koha::Holds::forced_hold_level
190
# Test Koha::Holds::forced_hold_level
191
my $hold = Koha::Hold->new({
191
my $hold = Koha::Hold->new({
192
    borrowernumber => $patron->{borrowernumber},
192
    patron_id => $patron->{borrowernumber},
193
    reservedate => '1981-06-10',
193
    created_date => '1981-06-10',
194
    biblionumber => $biblio->biblionumber,
194
    biblio_id => $biblio->biblionumber,
195
    branchcode => $library->{branchcode},
195
    pickup_library_id => $library->{branchcode},
196
    priority => 1,
196
    priority => 1,
197
})->store();
197
})->store();
198
198
199
$holds = Koha::Holds->search( { borrowernumber => $patron->{borrowernumber} } );
199
$holds = Koha::Holds->search( { patron_id => $patron->{borrowernumber} } );
200
is( $holds->forced_hold_level, 'record', "Record level hold forces record level holds" );
200
is( $holds->forced_hold_level, 'record', "Record level hold forces record level holds" );
201
201
202
$hold->itemnumber( $item1->itemnumber );
202
$hold->item_id( $item1->itemnumber );
203
$hold->store();
203
$hold->store();
204
204
205
$holds = Koha::Holds->search( { borrowernumber => $patron->{borrowernumber} } );
205
$holds = Koha::Holds->search( { patron_id => $patron->{borrowernumber} } );
206
is( $holds->forced_hold_level, 'item', "Item level hold forces item level holds" );
206
is( $holds->forced_hold_level, 'item', "Item level hold forces item level holds" );
207
207
208
$hold->delete();
208
$hold->delete();
Lines 247-253 ok( $hold_id, 'Second hold was placed' ); Link Here
247
$can = CanBookBeReserved($patron->{borrowernumber}, $biblio->biblionumber);
247
$can = CanBookBeReserved($patron->{borrowernumber}, $biblio->biblionumber);
248
is( $can->{status}, 'tooManyHoldsForThisRecord', 'Third hold exceeds limit of holds per record' );
248
is( $can->{status}, 'tooManyHoldsForThisRecord', 'Third hold exceeds limit of holds per record' );
249
249
250
Koha::Holds->find($hold_id)->found("W")->store;
250
Koha::Holds->find($hold_id)->set_waiting;
251
$can = CanBookBeReserved($patron->{borrowernumber}, $biblio->biblionumber);
251
$can = CanBookBeReserved($patron->{borrowernumber}, $biblio->biblionumber);
252
is( $can->{status}, 'tooManyHoldsForThisRecord', 'Third hold exceeds limit of holds per record' );
252
is( $can->{status}, 'tooManyHoldsForThisRecord', 'Third hold exceeds limit of holds per record' );
253
253
(-)a/t/db_dependent/Reserves/ReserveSlip.t (-13 / +14 lines)
Lines 31-37 $schema->storage->txn_begin; Link Here
31
31
32
my $dbh = C4::Context->dbh;
32
my $dbh = C4::Context->dbh;
33
$dbh->do(q|DELETE FROM letter|);
33
$dbh->do(q|DELETE FROM letter|);
34
$dbh->do(q|DELETE FROM reserves|);
34
$dbh->do(q|DELETE FROM holds|);
35
35
36
my $builder = t::lib::TestBuilder->new();
36
my $builder = t::lib::TestBuilder->new();
37
my $library = $builder->build(
37
my $library = $builder->build(
Lines 66-89 my $item2 = $builder->build_sample_item( Link Here
66
66
67
my $hold1 = Koha::Hold->new(
67
my $hold1 = Koha::Hold->new(
68
    {
68
    {
69
        biblionumber   => $biblio->biblionumber,
69
        biblio_id         => $biblio->biblionumber,
70
        itemnumber     => $item1->itemnumber,
70
        item_id           => $item1->itemnumber,
71
        waitingdate    => '2000-01-01',
71
        waiting_date      => '2000-01-01',
72
        borrowernumber => $patron->{borrowernumber},
72
        patron_id         => $patron->{borrowernumber},
73
        branchcode     => $library->{branchcode},
73
        pickup_library_id => $library->{branchcode},
74
    }
74
    }
75
)->store;
75
)->store;
76
76
77
my $hold2 = Koha::Hold->new(
77
my $hold2 = Koha::Hold->new(
78
    {
78
    {
79
        biblionumber   => $biblio->biblionumber,
79
        biblio_id         => $biblio->biblionumber,
80
        itemnumber     => $item2->itemnumber,
80
        item_id           => $item2->itemnumber,
81
        waitingdate    => '2000-01-01',
81
        waiting_date      => '2000-01-01',
82
        borrowernumber => $patron->{borrowernumber},
82
        patron_id         => $patron->{borrowernumber},
83
        branchcode     => $library->{branchcode},
83
        pickup_library_id => $library->{branchcode},
84
    }
84
    }
85
)->store;
85
)->store;
86
86
87
87
my $letter = $builder->build(
88
my $letter = $builder->build(
88
    {
89
    {
89
        source => 'Letter',
90
        source => 'Letter',
Lines 101-113 my $letter = $builder->build( Link Here
101
is ( ReserveSlip(), undef, "No hold slip returned if invalid or undef borrowernumber and/or biblionumber" );
102
is ( ReserveSlip(), undef, "No hold slip returned if invalid or undef borrowernumber and/or biblionumber" );
102
is ( ReserveSlip({
103
is ( ReserveSlip({
103
        branchcode     => $library->{branchcode},
104
        branchcode     => $library->{branchcode},
104
        reserve_id     => $hold1->reserve_id,
105
        reserve_id     => $hold1->id,
105
    })->{code},
106
    })->{code},
106
    'HOLD_SLIP', "Get a hold slip from library, patron and biblio" );
107
    'HOLD_SLIP', "Get a hold slip from library, patron and biblio" );
107
108
108
is (ReserveSlip({
109
is (ReserveSlip({
109
        branchcode     => $library->{branchcode},
110
        branchcode     => $library->{branchcode},
110
        reserve_id     => $hold1->reserve_id,
111
        reserve_id     => $hold1->id,
111
    })->{content},
112
    })->{content},
112
    sprintf( "Hold found for %s: Please pick up %s with barcode %s at %s.", $patron->{firstname}, $biblio->title, $item1->barcode, $library->{branchcode}),"Hold slip contains correctly parsed content");
113
    sprintf( "Hold found for %s: Please pick up %s with barcode %s at %s.", $patron->{firstname}, $biblio->title, $item1->barcode, $library->{branchcode}),"Hold slip contains correctly parsed content");
113
114
(-)a/t/db_dependent/TestBuilder.t (-6 / +11 lines)
Lines 67-75 subtest 'Start with some trivial tests' => sub { Link Here
67
subtest 'Build all sources' => sub {
67
subtest 'Build all sources' => sub {
68
    plan tests => 1;
68
    plan tests => 1;
69
69
70
    my $excluded_sources = {
71
        Reserve    => 1, # view
72
        OldReserve => 1, # view
73
    };
70
    my @sources = $builder->schema->sources;
74
    my @sources = $builder->schema->sources;
71
    my @source_in_failure;
75
    my @source_in_failure;
72
    for my $source ( @sources ) {
76
    for my $source ( grep { not $excluded_sources->{$_} } @sources ) {
73
        my $res;
77
        my $res;
74
        # Skip the source if it is a view
78
        # Skip the source if it is a view
75
        next if $schema->source($source)->isa('DBIx::Class::ResultSource::View');
79
        next if $schema->source($source)->isa('DBIx::Class::ResultSource::View');
Lines 250-260 subtest 'Test build with NULL values' => sub { Link Here
250
    is( $info->{is_nullable} && $item && !defined( $item->{barcode} ), 1,
254
    is( $info->{is_nullable} && $item && !defined( $item->{barcode} ), 1,
251
        'Barcode can be NULL' );
255
        'Barcode can be NULL' );
252
    # Nullable FK
256
    # Nullable FK
253
    $params = { source => 'Reserve', value  => { itemnumber => undef }};
257
    $params = { source => 'Hold', value  => { item_id => undef }};
254
    my $reserve = $builder->build( $params );
258
    my $hold = $builder->build( $params );
255
    $info = $schema->source( 'Reserve' )->column_info( 'itemnumber' );
259
    $info = $schema->source( 'Hold' )->column_info( 'item_id' );
256
    is( $reserve && $info->{is_nullable} && $info->{is_foreign_key} &&
260
    is( $hold && $info->{is_nullable} && $info->{is_foreign_key} &&
257
        !defined( $reserve->{itemnumber} ), 1, 'Nullable FK' );
261
        !defined( $hold->{item_id} ), 1, 'Nullable FK' );
258
};
262
};
259
263
260
264
Lines 396-401 subtest 'build_object() tests' => sub { Link Here
396
            $module =~ s|^.*/(Koha.*)\.pm$|$1|;
400
            $module =~ s|^.*/(Koha.*)\.pm$|$1|;
397
            $module =~ s|/|::|g;
401
            $module =~ s|/|::|g;
398
            next if $module eq 'Koha::Objects';
402
            next if $module eq 'Koha::Objects';
403
            next if $module eq 'Koha::Old::Holds'; #This is a view now
399
            eval "require $module";
404
            eval "require $module";
400
            my $object = $builder->build_object( { class => $module } );
405
            my $object = $builder->build_object( { class => $module } );
401
            is( ref($object), $module->object_class, "Testing $module" );
406
            is( ref($object), $module->object_class, "Testing $module" );
(-)a/t/db_dependent/XSLT.t (-4 / +5 lines)
Lines 117-126 subtest 'buildKohaItemsNamespace status tests' => sub { Link Here
117
    like($xml,qr{<status>In transit</status>},"In-transit status takes precedence over Damaged");
117
    like($xml,qr{<status>In transit</status>},"In-transit status takes precedence over Damaged");
118
118
119
    my $hold = $builder->build_object({ class => 'Koha::Holds', value => {
119
    my $hold = $builder->build_object({ class => 'Koha::Holds', value => {
120
        biblionumber => $item->biblionumber,
120
        biblio_id => $item->biblionumber,
121
        itemnumber   => $item->itemnumber,
121
        item_id   => $item->itemnumber,
122
        found        => 'W',
122
        status    => 'waiting',
123
        priority     => 0,
123
        priority  => 0,
124
        completed => 0,
124
        }
125
        }
125
    });
126
    });
126
    $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]);
127
    $xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]);
(-)a/t/db_dependent/api/v1/holds.t (-46 / +55 lines)
Lines 162-169 my $post_data = { Link Here
162
    expiration_date   => output_pref( { dt => $expiration_date, dateformat => 'rfc3339', dateonly => 1 } ),
162
    expiration_date   => output_pref( { dt => $expiration_date, dateformat => 'rfc3339', dateonly => 1 } ),
163
};
163
};
164
my $patch_data = {
164
my $patch_data = {
165
    priority        => 2,
165
    priority             => 2,
166
    suspended_until => output_pref( { dt => $suspended_until, dateformat => 'rfc3339' } ),
166
    suspended_until_date => output_pref( { dt => $suspended_until, dateformat => 'rfc3339' } ),
167
};
167
};
168
168
169
subtest "Test endpoints without authentication" => sub {
169
subtest "Test endpoints without authentication" => sub {
Lines 320-326 subtest 'test AllowHoldDateInFuture' => sub { Link Here
320
320
321
    plan tests => 6;
321
    plan tests => 6;
322
322
323
    $dbh->do('DELETE FROM reserves');
323
    $dbh->do('DELETE FROM holds');
324
324
325
    my $future_hold_date = DateTime->now->add(days => 10)->truncate( to => 'day' );
325
    my $future_hold_date = DateTime->now->add(days => 10)->truncate( to => 'day' );
326
326
Lines 329-336 subtest 'test AllowHoldDateInFuture' => sub { Link Here
329
        biblio_id         => $biblio_1->biblionumber,
329
        biblio_id         => $biblio_1->biblionumber,
330
        item_id           => $item_1->itemnumber,
330
        item_id           => $item_1->itemnumber,
331
        pickup_library_id => $branchcode,
331
        pickup_library_id => $branchcode,
332
        expiration_date   => output_pref( { dt => $expiration_date,  dateformat => 'rfc3339', dateonly => 1 } ),
332
        expiration_date   => output_pref({ dt => $expiration_date, dateformat => 'rfc3339', dateonly => 1 }),
333
        hold_date         => output_pref( { dt => $future_hold_date, dateformat => 'rfc3339', dateonly => 1 } ),
333
        created_date      => output_pref({ dt => $future_hold_date, dateformat => 'rfc3339', dateonly => 1 }),
334
    };
334
    };
335
335
336
    t::lib::Mocks::mock_preference( 'AllowHoldDateInFuture', 0 );
336
    t::lib::Mocks::mock_preference( 'AllowHoldDateInFuture', 0 );
Lines 349-355 subtest 'test AllowHoldDateInFuture' => sub { Link Here
349
349
350
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
350
    $t->post_ok( "//$userid_3:$password@/api/v1/holds" => json => $post_data )
351
      ->status_is(201)
351
      ->status_is(201)
352
      ->json_is('/hold_date', output_pref({ dt => $future_hold_date, dateformat => 'rfc3339', dateonly => 1 }));
352
      ->json_is('/created_date', output_pref({ dt => $future_hold_date, dateformat => 'rfc3339', dateonly => 1 }));
353
};
353
};
354
354
355
$schema->storage->txn_rollback;
355
$schema->storage->txn_rollback;
Lines 471-477 subtest 'suspend and resume tests' => sub { Link Here
471
471
472
    my $hold = $builder->build_object(
472
    my $hold = $builder->build_object(
473
        {   class => 'Koha::Holds',
473
        {   class => 'Koha::Holds',
474
            value => { suspend => 0, suspend_until => undef, waitingdate => undef, found => undef }
474
            value => {
475
                suspended    => 0,
476
                waiting_date => undef,
477
                suspended_until_date => undef,
478
                completed => 0
479
            }
475
        }
480
        }
476
    );
481
    );
477
482
Lines 482-488 subtest 'suspend and resume tests' => sub { Link Here
482
    $hold->discard_changes;    # refresh object
487
    $hold->discard_changes;    # refresh object
483
488
484
    ok( $hold->is_suspended, 'Hold is suspended' );
489
    ok( $hold->is_suspended, 'Hold is suspended' );
485
    $t->json_is('/end_date', undef, 'Hold suspension has no end date');
490
    $t->json_is('/suspended_until_date', undef, 'Hold suspension has no end date');
486
491
487
    my $end_date = output_pref({
492
    my $end_date = output_pref({
488
      dt         => dt_from_string( undef ),
493
      dt         => dt_from_string( undef ),
Lines 498-504 subtest 'suspend and resume tests' => sub { Link Here
498
    $t->json_is(
503
    $t->json_is(
499
      '/end_date',
504
      '/end_date',
500
      output_pref({
505
      output_pref({
501
        dt         => dt_from_string( $hold->suspend_until ),
506
        dt         => dt_from_string( $hold->suspended_until_date ),
502
        dateformat => 'rfc3339',
507
        dateformat => 'rfc3339',
503
        dateonly   => 1
508
        dateonly   => 1
504
      }),
509
      }),
Lines 531-543 subtest 'suspend and resume tests' => sub { Link Here
531
536
532
    $t->post_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )
537
    $t->post_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )
533
      ->status_is( 400, 'Cannot suspend waiting hold' )
538
      ->status_is( 400, 'Cannot suspend waiting hold' )
534
      ->json_is( '/error', 'Found hold cannot be suspended. Status=W' );
539
      ->json_is( '/error', 'Found hold cannot be suspended. Status=waiting' );
535
540
536
    $hold->set_transfer->discard_changes;
541
    $hold->set_transfer->discard_changes;
537
542
538
    $t->post_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )
543
    $t->post_ok( "//$userid:$password@/api/v1/holds/" . $hold->id . "/suspension" )
539
      ->status_is( 400, 'Cannot suspend hold on transfer' )
544
      ->status_is( 400, 'Cannot suspend hold on transfer' )
540
      ->json_is( '/error', 'Found hold cannot be suspended. Status=T' );
545
      ->json_is( '/error', 'Found hold cannot be suspended. Status=in_transit' );
541
546
542
    $schema->storage->txn_rollback;
547
    $schema->storage->txn_rollback;
543
};
548
};
Lines 837-856 subtest 'pickup_locations() tests' => sub { Link Here
837
        {
842
        {
838
            class => 'Koha::Holds',
843
            class => 'Koha::Holds',
839
            value => {
844
            value => {
840
                itemnumber     => undef,
845
                item_id   => undef,
841
                biblionumber   => $item->biblionumber,
846
                biblio_id => $item->biblionumber,
842
                borrowernumber => $patron->borrowernumber
847
                patron_id => $patron->borrowernumber,
848
                completed => 0,
843
            }
849
            }
844
        }
850
        }
845
    );
851
    );
852
846
    # item-level hold
853
    # item-level hold
847
    my $hold_2 = $builder->build_object(
854
    my $hold_2 = $builder->build_object(
848
        {
855
        {
849
            class => 'Koha::Holds',
856
            class => 'Koha::Holds',
850
            value => {
857
            value => {
851
                itemnumber     => $item->itemnumber,
858
                item_id   => $item->itemnumber,
852
                biblionumber   => $item->biblionumber,
859
                biblio_id => $item->biblionumber,
853
                borrowernumber => $patron->borrowernumber
860
                patron_id => $patron->borrowernumber,
861
                completed => 0,
854
            }
862
            }
855
        }
863
        }
856
    );
864
    );
Lines 943-952 subtest 'edit() tests' => sub { Link Here
943
        {
951
        {
944
            class => "Koha::Holds",
952
            class => "Koha::Holds",
945
            value => {
953
            value => {
946
                biblionumber => $biblio->biblionumber,
954
                biblio_id         => $biblio->biblionumber,
947
                branchcode   => $library_3->branchcode,
955
                pickup_library_id => $library_3->branchcode,
948
                itemnumber   => undef,
956
                item_id           => undef,
949
                priority     => 1,
957
                priority          => 1,
958
                completed         => 0,
950
            }
959
            }
951
        }
960
        }
952
    );
961
    );
Lines 970-976 subtest 'edit() tests' => sub { Link Here
970
      ->json_is({ error => 'The supplied pickup location is not valid' });
979
      ->json_is({ error => 'The supplied pickup location is not valid' });
971
980
972
    $biblio_hold->discard_changes;
981
    $biblio_hold->discard_changes;
973
    is( $biblio_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
982
    is( $biblio_hold->pickup_library_id, $library_3->branchcode, 'pickup_library_id remains untouched' );
974
983
975
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $biblio_hold->id
984
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $biblio_hold->id
976
          => { 'x-koha-override' => 'any' }
985
          => { 'x-koha-override' => 'any' }
Lines 991-997 subtest 'edit() tests' => sub { Link Here
991
      ->status_is(200);
1000
      ->status_is(200);
992
1001
993
    $biblio_hold->discard_changes;
1002
    $biblio_hold->discard_changes;
994
    is( $biblio_hold->branchcode, $library_2->id, 'Pickup location changed correctly' );
1003
    is( $biblio_hold->pickup_library_id, $library_2->id, 'Pickup location changed correctly' );
995
1004
996
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1005
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
997
          . $biblio_hold->id
1006
          . $biblio_hold->id
Lines 999-1015 subtest 'edit() tests' => sub { Link Here
999
      ->status_is(200);
1008
      ->status_is(200);
1000
1009
1001
    $biblio_hold->discard_changes;
1010
    $biblio_hold->discard_changes;
1002
    is( $biblio_hold->branchcode, $library_2->id, 'Pickup location changed correctly' );
1011
    is( $biblio_hold->pickup_library_id, $library_2->id, 'Pickup location changed correctly' );
1003
1012
1004
    # Test item-level holds
1013
    # Test item-level holds
1005
    my $item_hold = $builder->build_object(
1014
    my $item_hold = $builder->build_object(
1006
        {
1015
        {
1007
            class => "Koha::Holds",
1016
            class => "Koha::Holds",
1008
            value => {
1017
            value => {
1009
                biblionumber => $biblio->biblionumber,
1018
                biblio_id         => $biblio->biblionumber,
1010
                branchcode   => $library_3->branchcode,
1019
                pickup_library_id => $library_3->branchcode,
1011
                itemnumber   => $item->itemnumber,
1020
                item_id           => $item->itemnumber,
1012
                priority     => 1,
1021
                priority          => 1,
1022
                completed         => 0,
1013
            }
1023
            }
1014
        }
1024
        }
1015
    );
1025
    );
Lines 1033-1039 subtest 'edit() tests' => sub { Link Here
1033
      ->json_is({ error => 'The supplied pickup location is not valid' });
1043
      ->json_is({ error => 'The supplied pickup location is not valid' });
1034
1044
1035
    $item_hold->discard_changes;
1045
    $item_hold->discard_changes;
1036
    is( $item_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
1046
    is( $item_hold->pickup_library_id, $library_3->branchcode, 'branchcode remains untouched' );
1037
1047
1038
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $item_hold->id
1048
    $t->patch_ok( "//$userid:$password@/api/v1/holds/" . $item_hold->id
1039
          => { 'x-koha-override' => 'any' }
1049
          => { 'x-koha-override' => 'any' }
Lines 1059-1065 subtest 'edit() tests' => sub { Link Here
1059
      ->status_is(200);
1069
      ->status_is(200);
1060
1070
1061
    $item_hold->discard_changes;
1071
    $item_hold->discard_changes;
1062
    is( $item_hold->branchcode, $library_2->id, 'Pickup location changed correctly' );
1072
    is( $item_hold->pickup_library_id, $library_2->id, 'Pickup location changed correctly' );
1063
1073
1064
    $schema->storage->txn_rollback;
1074
    $schema->storage->txn_rollback;
1065
};
1075
};
Lines 1131-1140 subtest 'add() tests' => sub { Link Here
1131
        {
1141
        {
1132
            class => "Koha::Holds",
1142
            class => "Koha::Holds",
1133
            value => {
1143
            value => {
1134
                biblionumber => $biblio->biblionumber,
1144
                biblio_id         => $biblio->biblionumber,
1135
                branchcode   => $library_3->branchcode,
1145
                pickup_library_id => $library_3->branchcode,
1136
                itemnumber   => undef,
1146
                item_id           => undef,
1137
                priority     => 1,
1147
                priority          => 1,
1138
            }
1148
            }
1139
        }
1149
        }
1140
    );
1150
    );
Lines 1160-1169 subtest 'add() tests' => sub { Link Here
1160
        {
1170
        {
1161
            class => "Koha::Holds",
1171
            class => "Koha::Holds",
1162
            value => {
1172
            value => {
1163
                biblionumber => $biblio->biblionumber,
1173
                biblio_id         => $biblio->biblionumber,
1164
                branchcode   => $library_3->branchcode,
1174
                pickup_library_id => $library_3->branchcode,
1165
                itemnumber   => $item->itemnumber,
1175
                item_id           => $item->itemnumber,
1166
                priority     => 1,
1176
                priority          => 1,
1167
            }
1177
            }
1168
        }
1178
        }
1169
    );
1179
    );
Lines 1250-1256 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1250
      ->status_is(200)
1260
      ->status_is(200)
1251
      ->json_is({ pickup_library_id => $library_2->branchcode });
1261
      ->json_is({ pickup_library_id => $library_2->branchcode });
1252
1262
1253
    is( $hold->discard_changes->branchcode->branchcode, $library_2->branchcode, 'pickup library adjusted correctly' );
1263
    is( $hold->discard_changes->pickup_library_id, $library_2->branchcode, 'pickup library adjusted correctly' );
1254
1264
1255
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1265
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1256
          . $hold->id
1266
          . $hold->id
Lines 1258-1264 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1258
      ->status_is(400)
1268
      ->status_is(400)
1259
      ->json_is({ error => '[The supplied pickup location is not valid]' });
1269
      ->json_is({ error => '[The supplied pickup location is not valid]' });
1260
1270
1261
    is( $hold->discard_changes->branchcode->branchcode, $library_2->branchcode, 'pickup library unchanged' );
1271
    is( $hold->discard_changes->pickup_library_id, $library_2->branchcode, 'pickup library unchanged' );
1262
1272
1263
    # item-level hold
1273
    # item-level hold
1264
    $hold = Koha::Holds->find(
1274
    $hold = Koha::Holds->find(
Lines 1280-1286 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1280
      ->status_is(400)
1290
      ->status_is(400)
1281
      ->json_is({ error => '[The supplied pickup location is not valid]' });
1291
      ->json_is({ error => '[The supplied pickup location is not valid]' });
1282
1292
1283
    is( $hold->discard_changes->branchcode->branchcode, $library_1->branchcode, 'pickup library unchanged' );
1293
    is( $hold->discard_changes->pickup_library_id, $library_1->branchcode, 'pickup library unchanged' );
1284
1294
1285
    t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 1 );
1295
    t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 1 );
1286
1296
Lines 1293-1299 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1293
      ->status_is(200)
1303
      ->status_is(200)
1294
      ->json_is({ pickup_library_id => $library_2->branchcode });
1304
      ->json_is({ pickup_library_id => $library_2->branchcode });
1295
1305
1296
    is( $hold->discard_changes->branchcode->branchcode, $library_2->branchcode, 'pickup library changed' );
1306
    is( $hold->discard_changes->pickup_library_id, $library_2->branchcode, 'pickup library changed' );
1297
1307
1298
    t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 0 );
1308
    t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 0 );
1299
1309
Lines 1303-1309 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1303
      ->status_is(200)
1313
      ->status_is(200)
1304
      ->json_is({ pickup_library_id => $library_2->branchcode });
1314
      ->json_is({ pickup_library_id => $library_2->branchcode });
1305
1315
1306
    is( $hold->discard_changes->branchcode->branchcode, $library_2->branchcode, 'pickup library adjusted correctly' );
1316
    is( $hold->discard_changes->pickup_library_id, $library_2->branchcode, 'pickup library adjusted correctly' );
1307
1317
1308
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1318
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1309
          . $hold->id
1319
          . $hold->id
Lines 1311-1317 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1311
      ->status_is(400)
1321
      ->status_is(400)
1312
      ->json_is({ error => '[The supplied pickup location is not valid]' });
1322
      ->json_is({ error => '[The supplied pickup location is not valid]' });
1313
1323
1314
    is( $hold->discard_changes->branchcode->branchcode, $library_2->branchcode, 'invalid pickup library not used' );
1324
    is( $hold->discard_changes->pickup_library_id, $library_2->branchcode, 'invalid pickup library not used' );
1315
1325
1316
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1326
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
1317
          . $hold->id
1327
          . $hold->id
Lines 1321-1327 subtest 'PUT /holds/{hold_id}/pickup_location tests' => sub { Link Here
1321
      ->status_is(400)
1331
      ->status_is(400)
1322
      ->json_is({ error => '[The supplied pickup location is not valid]' });
1332
      ->json_is({ error => '[The supplied pickup location is not valid]' });
1323
1333
1324
    is( $hold->discard_changes->branchcode->branchcode, $library_2->branchcode, 'invalid pickup library not used, even if x-koha-override is passed' );
1334
    is( $hold->discard_changes->pickup_library_id, $library_2->branchcode, 'invalid pickup library not used, even if x-koha-override is passed' );
1325
1335
1326
    $schema->storage->txn_rollback;
1336
    $schema->storage->txn_rollback;
1327
};
1337
};
1328
- 

Return to bug 25260