|
Lines 19-25
Link Here
|
| 19 |
|
19 |
|
| 20 |
use Modern::Perl; |
20 |
use Modern::Perl; |
| 21 |
|
21 |
|
| 22 |
use Test::More tests => 39; |
22 |
use Test::More tests => 40; |
| 23 |
use Test::Exception; |
23 |
use Test::Exception; |
| 24 |
use Test::Warn; |
24 |
use Test::Warn; |
| 25 |
use Time::Fake; |
25 |
use Time::Fake; |
|
Lines 29-35
use Koha::Database;
Link Here
|
| 29 |
use Koha::DateUtils qw(dt_from_string); |
29 |
use Koha::DateUtils qw(dt_from_string); |
| 30 |
use Koha::ArticleRequests; |
30 |
use Koha::ArticleRequests; |
| 31 |
use Koha::Patrons; |
31 |
use Koha::Patrons; |
| 32 |
use Koha::List::Patron qw(AddPatronList AddPatronsToList); |
32 |
use Koha::List::Patron qw(AddPatronList AddPatronsToList); |
|
|
33 |
use Koha::Patron::Debarments qw(AddDebarment); |
| 33 |
use Koha::Patron::Relationships; |
34 |
use Koha::Patron::Relationships; |
| 34 |
use C4::Circulation qw( AddIssue AddReturn ); |
35 |
use C4::Circulation qw( AddIssue AddReturn ); |
| 35 |
|
36 |
|
|
Lines 2868-2870
subtest 'ill_requests() tests' => sub {
Link Here
|
| 2868 |
|
2869 |
|
| 2869 |
$schema->storage->txn_rollback; |
2870 |
$schema->storage->txn_rollback; |
| 2870 |
}; |
2871 |
}; |
|
|
2872 |
|
| 2873 |
subtest 'can_place_holds() tests' => sub { |
| 2874 |
|
| 2875 |
plan tests => 7; |
| 2876 |
|
| 2877 |
subtest "'expired' tests" => sub { |
| 2878 |
|
| 2879 |
plan tests => 4; |
| 2880 |
|
| 2881 |
$schema->storage->txn_begin; |
| 2882 |
|
| 2883 |
t::lib::Mocks::mock_preference( 'BlockExpiredPatronOpacActions', 'hold' ); |
| 2884 |
|
| 2885 |
my $patron = $builder->build_object( |
| 2886 |
{ |
| 2887 |
class => 'Koha::Patrons', |
| 2888 |
value => { dateexpiry => \'DATE_ADD(NOW(), INTERVAL -1 DAY)' } |
| 2889 |
} |
| 2890 |
); |
| 2891 |
|
| 2892 |
my $result = $patron->can_place_holds(); |
| 2893 |
ok( !$result, 'expired, cannot place holds' ); |
| 2894 |
|
| 2895 |
my $messages = $result->messages(); |
| 2896 |
is( $messages->[0]->type, 'error' ); |
| 2897 |
is( $messages->[0]->message, 'expired' ); |
| 2898 |
|
| 2899 |
ok( $patron->can_place_holds( { overrides => { expired => 1 } } ), "Override works for 'expired'" ); |
| 2900 |
|
| 2901 |
$schema->storage->txn_rollback; |
| 2902 |
}; |
| 2903 |
|
| 2904 |
subtest "'debt_limit' tests" => sub { |
| 2905 |
|
| 2906 |
plan tests => 7; |
| 2907 |
|
| 2908 |
$schema->storage->txn_begin; |
| 2909 |
|
| 2910 |
# Add a patron, making sure it is not (yet) expired |
| 2911 |
my $patron = $builder->build_object( { class => 'Koha::Patrons', } ); |
| 2912 |
$patron->account->add_debit( { amount => 10, interface => 'opac', type => 'ACCOUNT' } ); |
| 2913 |
|
| 2914 |
t::lib::Mocks::mock_preference( 'maxoutstanding', undef ); |
| 2915 |
|
| 2916 |
ok( $patron->can_place_holds(), "No 'maxoutstanding', can place holds" ); |
| 2917 |
|
| 2918 |
t::lib::Mocks::mock_preference( 'maxoutstanding', '5' ); |
| 2919 |
|
| 2920 |
my $result = $patron->can_place_holds(); |
| 2921 |
ok( !$result, 'debt, cannot place holds' ); |
| 2922 |
|
| 2923 |
my $messages = $result->messages(); |
| 2924 |
is( $messages->[0]->type, 'error' ); |
| 2925 |
is( $messages->[0]->message, 'debt_limit' ); |
| 2926 |
is( $messages->[0]->payload->{total_outstanding}, 10 ); |
| 2927 |
is( $messages->[0]->payload->{max_outstanding}, 5 ); |
| 2928 |
|
| 2929 |
ok( $patron->can_place_holds( { overrides => { debt_limit => 1 } } ), "Override works for 'debt_limit'" ); |
| 2930 |
|
| 2931 |
$schema->storage->txn_rollback; |
| 2932 |
}; |
| 2933 |
|
| 2934 |
subtest "'bad_address' tests" => sub { |
| 2935 |
|
| 2936 |
plan tests => 4; |
| 2937 |
|
| 2938 |
$schema->storage->txn_begin; |
| 2939 |
|
| 2940 |
# Add a patron, making sure it is not (yet) expired |
| 2941 |
my $patron = $builder->build_object( |
| 2942 |
{ |
| 2943 |
class => 'Koha::Patrons', |
| 2944 |
value => { |
| 2945 |
gonenoaddress => 1, |
| 2946 |
} |
| 2947 |
} |
| 2948 |
); |
| 2949 |
|
| 2950 |
my $result = $patron->can_place_holds(); |
| 2951 |
ok( !$result, 'flagged for bad address, cannot place holds' ); |
| 2952 |
|
| 2953 |
my $messages = $result->messages(); |
| 2954 |
is( $messages->[0]->type, 'error' ); |
| 2955 |
is( $messages->[0]->message, 'bad_address' ); |
| 2956 |
|
| 2957 |
ok( $patron->can_place_holds( { overrides => { bad_address => 1 } } ), "Override works for 'bad_address'" ); |
| 2958 |
|
| 2959 |
$schema->storage->txn_rollback; |
| 2960 |
}; |
| 2961 |
|
| 2962 |
subtest "'card_lost' tests" => sub { |
| 2963 |
|
| 2964 |
plan tests => 4; |
| 2965 |
|
| 2966 |
$schema->storage->txn_begin; |
| 2967 |
|
| 2968 |
# Add a patron, making sure it is not (yet) expired |
| 2969 |
my $patron = $builder->build_object( |
| 2970 |
{ |
| 2971 |
class => 'Koha::Patrons', |
| 2972 |
value => { |
| 2973 |
lost => 1, |
| 2974 |
} |
| 2975 |
} |
| 2976 |
); |
| 2977 |
|
| 2978 |
my $result = $patron->can_place_holds(); |
| 2979 |
ok( !$result, 'flagged for lost card, cannot place holds' ); |
| 2980 |
|
| 2981 |
my $messages = $result->messages(); |
| 2982 |
is( $messages->[0]->type, 'error' ); |
| 2983 |
is( $messages->[0]->message, 'card_lost' ); |
| 2984 |
|
| 2985 |
ok( $patron->can_place_holds( { overrides => { card_lost => 1 } } ), "Override works for 'card_lost'" ); |
| 2986 |
|
| 2987 |
$schema->storage->txn_rollback; |
| 2988 |
}; |
| 2989 |
|
| 2990 |
subtest "'restricted' tests" => sub { |
| 2991 |
|
| 2992 |
plan tests => 4; |
| 2993 |
|
| 2994 |
$schema->storage->txn_begin; |
| 2995 |
|
| 2996 |
# Add a patron, making sure it is not (yet) expired |
| 2997 |
my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 2998 |
AddDebarment( { borrowernumber => $patron->borrowernumber } ); |
| 2999 |
$patron->discard_changes(); |
| 3000 |
|
| 3001 |
my $result = $patron->can_place_holds(); |
| 3002 |
ok( !$result, 'restricted, cannot place holds' ); |
| 3003 |
|
| 3004 |
my $messages = $result->messages(); |
| 3005 |
is( $messages->[0]->type, 'error' ); |
| 3006 |
is( $messages->[0]->message, 'restricted' ); |
| 3007 |
|
| 3008 |
ok( $patron->can_place_holds( { overrides => { restricted => 1 } } ), "Override works for 'restricted'" ); |
| 3009 |
|
| 3010 |
$schema->storage->txn_rollback; |
| 3011 |
}; |
| 3012 |
|
| 3013 |
subtest "'hold_limit' tests" => sub { |
| 3014 |
|
| 3015 |
plan tests => 5; |
| 3016 |
|
| 3017 |
$schema->storage->txn_begin; |
| 3018 |
|
| 3019 |
# Add a patron, making sure it is not (yet) expired |
| 3020 |
my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 3021 |
|
| 3022 |
# Add a hold |
| 3023 |
$builder->build_object( { class => 'Koha::Holds', value => { borrowernumber => $patron->borrowernumber } } ); |
| 3024 |
|
| 3025 |
t::lib::Mocks::mock_preference( 'maxreserves', undef ); |
| 3026 |
|
| 3027 |
ok( $patron->can_place_holds(), "No 'maxreserves', can place holds" ); |
| 3028 |
|
| 3029 |
t::lib::Mocks::mock_preference( 'maxreserves', 1 ); |
| 3030 |
|
| 3031 |
my $result = $patron->can_place_holds(); |
| 3032 |
ok( !$result, 'hold limit reached, cannot place holds' ); |
| 3033 |
|
| 3034 |
my $messages = $result->messages(); |
| 3035 |
is( $messages->[0]->type, 'error' ); |
| 3036 |
is( $messages->[0]->message, 'hold_limit' ); |
| 3037 |
|
| 3038 |
ok( $patron->can_place_holds( { overrides => { hold_limit => 1 } } ), "Override works for 'hold_limit'" ); |
| 3039 |
|
| 3040 |
$schema->storage->txn_rollback; |
| 3041 |
}; |
| 3042 |
|
| 3043 |
subtest "'no_short_circuit' tests" => sub { |
| 3044 |
|
| 3045 |
plan tests => 9; |
| 3046 |
|
| 3047 |
$schema->storage->txn_begin; |
| 3048 |
|
| 3049 |
# Create a patron with multiple issues |
| 3050 |
my $patron = $builder->build_object( |
| 3051 |
{ |
| 3052 |
class => 'Koha::Patrons', |
| 3053 |
value => { |
| 3054 |
dateexpiry => \'DATE_ADD(NOW(), INTERVAL -1 DAY)', # expired |
| 3055 |
gonenoaddress => 1, # bad address |
| 3056 |
lost => 1, # card lost |
| 3057 |
} |
| 3058 |
} |
| 3059 |
); |
| 3060 |
|
| 3061 |
# Add debt |
| 3062 |
$patron->account->add_debit( { amount => 10, interface => 'opac', type => 'ACCOUNT' } ); |
| 3063 |
|
| 3064 |
# Add restriction |
| 3065 |
AddDebarment( { borrowernumber => $patron->borrowernumber } ); |
| 3066 |
$patron->discard_changes(); |
| 3067 |
|
| 3068 |
# Mock preferences |
| 3069 |
t::lib::Mocks::mock_preference( 'BlockExpiredPatronOpacActions', 'hold' ); |
| 3070 |
t::lib::Mocks::mock_preference( 'maxoutstanding', '5' ); |
| 3071 |
|
| 3072 |
# Test short-circuit behavior (default) |
| 3073 |
my $result = $patron->can_place_holds(); |
| 3074 |
ok( !$result, 'patron cannot place holds' ); |
| 3075 |
my $messages = $result->messages(); |
| 3076 |
is( scalar @$messages, 1, 'short-circuit: only one error message returned' ); |
| 3077 |
|
| 3078 |
# Test no_short_circuit behavior |
| 3079 |
$result = $patron->can_place_holds( { no_short_circuit => 1 } ); |
| 3080 |
ok( !$result, 'patron still cannot place holds with no_short_circuit' ); |
| 3081 |
$messages = $result->messages(); |
| 3082 |
is( scalar @$messages, 5, 'no_short_circuit: all error messages collected' ); |
| 3083 |
|
| 3084 |
# Verify we got all expected error types |
| 3085 |
my %message_types = map { $_->message => 1 } @$messages; |
| 3086 |
ok( $message_types{expired}, "'expired' error included" ); |
| 3087 |
ok( $message_types{debt_limit}, "'debt_limit' error included" ); |
| 3088 |
ok( $message_types{bad_address}, "'bad_address' error included" ); |
| 3089 |
ok( $message_types{card_lost}, "'card_lost' error included" ); |
| 3090 |
ok( $message_types{restricted}, "'restricted' error included" ); |
| 3091 |
|
| 3092 |
$schema->storage->txn_rollback; |
| 3093 |
}; |
| 3094 |
}; |