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

(-)a/Koha/Hold.pm (+53 lines)
Lines 889-894 sub fill { Link Here
889
    return $self;
889
    return $self;
890
}
890
}
891
891
892
=head3 revert_waiting
893
894
    $hold->revert_waiting();
895
896
Reverts a 'waiting' hold back to a regular hold with a priority of 1.
897
898
=cut
899
900
sub revert_waiting {
901
    my ( $self, $params ) = @_;
902
903
    Koha::Exceptions::InvalidStatus->throw( invalid_status => 'hold_not_waiting' )
904
        unless $self->is_waiting;
905
906
    $self->_result->result_source->schema->txn_do(
907
        sub {
908
            my $original = C4::Context->preference('HoldsLog') ? $self->unblessed : undef;
909
910
            # Increment the priority of all other non-waiting
911
            # reserves for this bib record
912
            my $holds = Koha::Holds->search(
913
                {
914
                    biblionumber => $self->biblionumber,
915
                    priority     => { '>' => 0 }
916
                }
917
            )->update(
918
                { priority    => \'priority + 1' },
919
                { no_triggers => 1 }
920
            );
921
922
            ## Fix up the currently waiting reserve
923
            $self->set(
924
                {
925
                    priority       => 1,
926
                    found          => undef,
927
                    waitingdate    => undef,
928
                    expirationdate => $self->patron_expiration_date,
929
                    itemnumber     => $self->item_level_hold ? $self->itemnumber : undef,
930
                }
931
            )->store( { hold_reverted => 1 } );
932
933
            logaction( 'HOLDS', 'MODIFY', $self->id, $self, undef, $original )
934
                if C4::Context->preference('HoldsLog');
935
936
            C4::Reserves::_FixPriority( { biblionumber => $self->biblionumber } );
937
938
            Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue->new->enqueue( { biblio_ids => [ $self->biblionumber ] } )
939
                if C4::Context->preference('RealTimeHoldsQueue');
940
        }
941
    );
942
    return $self;
943
}
944
892
=head3 sub change_type
945
=head3 sub change_type
893
946
894
    $hold->change_type                # to record level
947
    $hold->change_type                # to record level
(-)a/t/db_dependent/Koha/Hold.t (-2 / +236 lines)
Lines 20-26 Link Here
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::NoWarnings;
22
use Test::NoWarnings;
23
use Test::More tests => 15;
23
use Test::More tests => 16;
24
24
25
use Test::Exception;
25
use Test::Exception;
26
use Test::MockModule;
26
use Test::MockModule;
Lines 29-34 use t::lib::Mocks; Link Here
29
use t::lib::TestBuilder;
29
use t::lib::TestBuilder;
30
use t::lib::Mocks;
30
use t::lib::Mocks;
31
31
32
use C4::Reserves qw(AddReserve);
33
32
use Koha::ActionLogs;
34
use Koha::ActionLogs;
33
use Koha::DateUtils qw(dt_from_string);
35
use Koha::DateUtils qw(dt_from_string);
34
use Koha::Holds;
36
use Koha::Holds;
Lines 1161-1163 subtest 'change_type() tests' => sub { Link Here
1161
1163
1162
    $schema->storage->txn_rollback;
1164
    $schema->storage->txn_rollback;
1163
};
1165
};
1164
- 
1166
1167
subtest 'revert_waiting() tests' => sub {
1168
1169
    plan tests => 3;
1170
1171
    subtest 'item-level holds tests' => sub {
1172
1173
        plan tests => 13;
1174
1175
        $schema->storage->txn_begin;
1176
1177
        my $item   = $builder->build_sample_item;
1178
        my $patron = $builder->build_object(
1179
            {
1180
                class => 'Koha::Patrons',
1181
                value => { branchcode => $item->homebranch }
1182
            }
1183
        );
1184
1185
        # Create item-level hold
1186
        my $hold = Koha::Holds->find(
1187
            AddReserve(
1188
                {
1189
                    branchcode     => $item->homebranch,
1190
                    borrowernumber => $patron->borrowernumber,
1191
                    biblionumber   => $item->biblionumber,
1192
                    priority       => 1,
1193
                    itemnumber     => $item->itemnumber,
1194
                }
1195
            )
1196
        );
1197
1198
        is( $hold->item_level_hold, 1, 'item_level_hold should be set when AddReserve is called with a specific item' );
1199
1200
        my $mock = Test::MockModule->new('Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue');
1201
        $mock->mock(
1202
            'enqueue',
1203
            sub {
1204
                my ( $self, $args ) = @_;
1205
                is_deeply(
1206
                    $args->{biblio_ids},
1207
                    [ $hold->biblionumber ],
1208
                    "AlterPriority triggers a holds queue update for the related biblio"
1209
                );
1210
            }
1211
        );
1212
1213
        t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 1 );
1214
        t::lib::Mocks::mock_preference( 'HoldsLog',           1 );
1215
1216
        # Mark it waiting
1217
        $hold->set_waiting();
1218
1219
        isnt( $hold->waitingdate, undef, "'waitingdate' set" );
1220
        is( $hold->priority, 0, "'priority' set to 0" );
1221
        ok( $hold->is_waiting, 'Hold set to waiting' );
1222
1223
        # Revert the waiting status
1224
        $hold->revert_waiting();
1225
1226
        is( $hold->waitingdate, undef, "'waitingdate' reset" );
1227
        ok( !$hold->is_waiting, 'Hold no longer set to waiting' );
1228
        is( $hold->priority, 1, "'priority' set to 1" );
1229
1230
        is(
1231
            $hold->itemnumber, $item->itemnumber,
1232
            'Itemnumber should not be removed when the waiting status is revert'
1233
        );
1234
1235
        my $log =
1236
            Koha::ActionLogs->search( { module => 'HOLDS', action => 'MODIFY', object => $hold->reserve_id } )->next;
1237
        my $expected = sprintf q{'timestamp' => '%s'}, $hold->timestamp;
1238
        like( $log->info, qr{$expected}, 'Timestamp logged is the current one' );
1239
        my $log_count =
1240
            Koha::ActionLogs->search( { module => 'HOLDS', action => 'MODIFY', object => $hold->reserve_id } )->count;
1241
1242
        t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 0 );
1243
        t::lib::Mocks::mock_preference( 'HoldsLog',           0 );
1244
1245
        $hold->set_waiting();
1246
1247
        # Revert the waiting status, RealTimeHoldsQueue => shouldn't add a test
1248
        $hold->revert_waiting();
1249
1250
        my $log_count_after =
1251
            Koha::ActionLogs->search( { module => 'HOLDS', action => 'MODIFY', object => $hold->reserve_id } )->count;
1252
        is( $log_count, $log_count_after, "No logging is added for ->revert_waiting() when HoldsLog is disabled" );
1253
1254
        # Set as 'processing' to test the exception behavior
1255
        $hold->found('P');
1256
        throws_ok { $hold->revert_waiting() }
1257
        'Koha::Exceptions::InvalidStatus',
1258
            "Hold is not in 'waiting' status, exception thrown";
1259
1260
        is( $@->invalid_status, 'hold_not_waiting', "'invalid_status' set the right value" );
1261
1262
        $schema->storage->txn_rollback;
1263
    };
1264
1265
    subtest 'biblio-level hold tests' => sub {
1266
1267
        plan tests => 8;
1268
1269
        $schema->storage->txn_begin;
1270
1271
        my $item   = $builder->build_sample_item;
1272
        my $patron = $builder->build_object(
1273
            {
1274
                class => 'Koha::Patrons',
1275
                value => { branchcode => $item->homebranch }
1276
            }
1277
        );
1278
1279
        # Create biblio-level hold
1280
        my $hold = Koha::Holds->find(
1281
            AddReserve(
1282
                {
1283
                    branchcode     => $item->homebranch,
1284
                    borrowernumber => $patron->borrowernumber,
1285
                    biblionumber   => $item->biblionumber,
1286
                    priority       => 1,
1287
                }
1288
            )
1289
        );
1290
1291
        is(
1292
            $hold->item_level_hold, 0,
1293
            'item_level_hold should not be set when AddReserve is called without a specific item'
1294
        );
1295
1296
        # Mark it waiting
1297
        $hold->set( { itemnumber => $item->itemnumber } )->set_waiting();
1298
        $hold->set_waiting();
1299
1300
        isnt( $hold->waitingdate, undef, "'waitingdate' set" );
1301
        is( $hold->priority, 0, "'priority' set to 0" );
1302
        ok( $hold->is_waiting, 'Hold set to waiting' );
1303
1304
        # Revert the waiting status
1305
        $hold->revert_waiting();
1306
1307
        is( $hold->waitingdate, undef, "'waitingdate' reset" );
1308
        ok( !$hold->is_waiting, 'Hold no longer set to waiting' );
1309
        is( $hold->priority,   1,     "'priority' set to 1" );
1310
        is( $hold->itemnumber, undef, "'itemnumber' unset" );
1311
1312
        $schema->storage->txn_rollback;
1313
    };
1314
1315
    subtest 'priority shift tests' => sub {
1316
1317
        plan tests => 4;
1318
1319
        $schema->storage->txn_begin;
1320
1321
        # Create the items and patrons we need
1322
        my $library = $builder->build_object( { class => 'Koha::Libraries' } );
1323
        my $itype   = $builder->build_object( { class => "Koha::ItemTypes", value => { notforloan => 0 } } );
1324
        my $item    = $builder->build_sample_item(
1325
            {
1326
                itype   => $itype->itemtype,
1327
                library => $library->branchcode
1328
            }
1329
        );
1330
        my $patron_1 = $builder->build_object( { class => "Koha::Patrons" } );
1331
        my $patron_2 = $builder->build_object( { class => "Koha::Patrons" } );
1332
        my $patron_3 = $builder->build_object( { class => "Koha::Patrons" } );
1333
        my $patron_4 = $builder->build_object( { class => "Koha::Patrons" } );
1334
1335
        # Place a hold on the title for both patrons
1336
        my $hold = Koha::Holds->find(
1337
            C4::Reserves::AddReserve(
1338
                {
1339
                    branchcode     => $library->branchcode,
1340
                    borrowernumber => $patron_1->borrowernumber,
1341
                    biblionumber   => $item->biblionumber,
1342
                    priority       => 1,
1343
                    itemnumber     => $item->itemnumber,
1344
                }
1345
            )
1346
        );
1347
1348
        C4::Reserves::AddReserve(
1349
            {
1350
                branchcode     => $library->branchcode,
1351
                borrowernumber => $patron_2->borrowernumber,
1352
                biblionumber   => $item->biblionumber,
1353
                priority       => 1,
1354
                itemnumber     => $item->itemnumber,
1355
            }
1356
        );
1357
1358
        C4::Reserves::AddReserve(
1359
            {
1360
                branchcode     => $library->branchcode,
1361
                borrowernumber => $patron_3->borrowernumber,
1362
                biblionumber   => $item->biblionumber,
1363
                priority       => 1,
1364
                itemnumber     => $item->itemnumber,
1365
            }
1366
        );
1367
1368
        C4::Reserves::AddReserve(
1369
            {
1370
                branchcode     => $library->branchcode,
1371
                borrowernumber => $patron_4->borrowernumber,
1372
                biblionumber   => $item->biblionumber,
1373
                priority       => 1,
1374
                itemnumber     => $item->itemnumber,
1375
            }
1376
        );
1377
1378
        is( $item->biblio->holds->count, 4, '4 holds on the biblio' );
1379
1380
        $hold->set_waiting()->discard_changes();
1381
        is( $hold->priority, 0, "'priority' set to 0" );
1382
1383
        $hold->revert_waiting()->discard_changes();
1384
        is( $hold->priority, 1, "'priority' set to 1" );
1385
1386
        my $holds = $item->biblio->holds;
1387
        is_deeply(
1388
            [
1389
                $holds->next->priority, $holds->next->priority,
1390
                $holds->next->priority, $holds->next->priority,
1391
            ],
1392
            [ 1, 2, 3, 4 ],
1393
            'priorities have been reordered'
1394
        );
1395
1396
        $schema->storage->txn_rollback;
1397
    };
1398
};

Return to bug 40058