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

(-)a/Koha/Patron.pm (-1 / +152 lines)
Lines 1318-1323 sub move_to_deleted { Link Here
1318
    return Koha::Database->new->schema->resultset('Deletedborrower')->create($patron_infos);
1318
    return Koha::Database->new->schema->resultset('Deletedborrower')->create($patron_infos);
1319
}
1319
}
1320
1320
1321
=head3 can_place_holds
1322
1323
    my $result = $patron->can_place_holds();
1324
    my $result = $patron->can_place_holds(
1325
        {
1326
            overrides        => { debt_limit => 1, card_lost => 1 },
1327
            no_short_circuit => 1
1328
        }
1329
    );
1330
1331
    if ( $patron->can_place_holds() ) {
1332
        # patron can place holds
1333
    } else {
1334
        my @messages = $result->messages;
1335
        # handle error messages
1336
    }
1337
1338
Checks if a patron is allowed to place holds based on various patron conditions.
1339
1340
=head4 Parameters
1341
1342
=over 4
1343
1344
=item * C<$options> (optional) - Hashref with the following keys:
1345
1346
=over 8
1347
1348
=item * C<overrides> - Hashref of checks to skip. Keys should match error message codes.
1349
1350
=item * C<no_short_circuit> - Boolean. If true, performs all checks and collects all error messages instead of stopping at first failure. Default: false.
1351
1352
=back
1353
1354
=back
1355
1356
=head4 Returns
1357
1358
Koha::Result::Boolean object - true if patron can place holds, false otherwise.
1359
When false, the result object contains error messages with details about why
1360
holds are blocked.
1361
1362
=head4 Error Messages
1363
1364
The following error message codes may be returned:
1365
1366
=over 4
1367
1368
=item * C<expired> - Patron account has expired and expired patrons are blocked from placing holds
1369
1370
=item * C<debt_limit> - Patron owes more than the maximum allowed outstanding amount
1371
1372
=item * C<bad_address> - Patron's address is marked as incorrect
1373
1374
=item * C<card_lost> - Patron's library card is marked as lost
1375
1376
=item * C<restricted> - Patron account is restricted/debarred
1377
1378
=item * C<hold_limit> - Patron has reached the maximum number of allowed holds
1379
1380
=back
1381
1382
Error messages may include additional payload data with relevant details
1383
(amounts, limits, counts, etc.).
1384
1385
=cut
1386
1387
sub can_place_holds {
1388
    my ( $self, $options ) = @_;
1389
    $options //= {};
1390
1391
    my $overrides        = $options->{overrides}        // {};
1392
    my $no_short_circuit = $options->{no_short_circuit} // 0;
1393
1394
    my $result = Koha::Result::Boolean->new(1);
1395
1396
    # expired patron check
1397
    unless ( $overrides->{expired} ) {
1398
        if ( $self->is_expired && $self->category->effective_BlockExpiredPatronOpacActions_contains('hold') ) {
1399
            $result->set_value(0);
1400
            $result->add_message( { message => 'expired', type => 'error' } );
1401
1402
            return $result unless $no_short_circuit;
1403
        }
1404
    }
1405
1406
    # debt check
1407
    unless ( $overrides->{debt_limit} ) {
1408
        my $max_outstanding = C4::Context->preference("maxoutstanding");
1409
        my $outstanding     = $self->account->balance;
1410
1411
        if ( $max_outstanding && $outstanding && ( $outstanding > $max_outstanding ) ) {
1412
            $result->set_value(0);
1413
            $result->add_message(
1414
                {
1415
                    message => 'debt_limit', type => 'error',
1416
                    payload => { total_outstanding => $outstanding, max_outstanding => $max_outstanding }
1417
                }
1418
            );
1419
1420
            return $result unless $no_short_circuit;
1421
        }
1422
    }
1423
1424
    # check address marked as incorrect
1425
    unless ( $overrides->{bad_address} ) {
1426
        if ( $self->gonenoaddress ) {
1427
            $result->set_value(0);
1428
            $result->add_message( { message => 'bad_address', type => 'error' } );
1429
1430
            return $result unless $no_short_circuit;
1431
        }
1432
    }
1433
1434
    # check lost card
1435
    unless ( $overrides->{card_lost} ) {
1436
        if ( $self->lost ) {
1437
            $result->set_value(0);
1438
            $result->add_message( { message => 'card_lost', type => 'error' } );
1439
            return $result unless $no_short_circuit;
1440
        }
1441
    }
1442
1443
    # check restrictions
1444
    unless ( $overrides->{restricted} ) {
1445
        if ( $self->is_debarred ) {
1446
            $result->set_value(0);
1447
            $result->add_message( { message => 'restricted', type => 'error' } );
1448
1449
            return $result unless $no_short_circuit;
1450
        }
1451
    }
1452
1453
    # check max reserves
1454
    unless ( $overrides->{hold_limit} ) {
1455
        my $max_holds   = C4::Context->preference("maxreserves");
1456
        my $holds_count = $self->holds->count;
1457
        if ( $max_holds && ( $holds_count >= $max_holds ) ) {
1458
            $result->set_value(0);
1459
            $result->add_message(
1460
                {
1461
                    message => 'hold_limit', type => 'error',
1462
                    payload => { total_holds => $holds_count, max_holds => $max_holds }
1463
                }
1464
            );
1465
1466
            return $result unless $no_short_circuit;
1467
        }
1468
    }
1469
1470
    return $result;
1471
}
1472
1321
=head3 can_request_article
1473
=head3 can_request_article
1322
1474
1323
    if ( $patron->can_request_article( $library->id ) ) { ... }
1475
    if ( $patron->can_request_article( $library->id ) ) { ... }
1324
- 

Return to bug 40101