Bug 26355: Add unit tests
Signed-off-by: Christopher Brannon <cbrannon@cdalibrary.org> Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com> Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
parent
d04923b3b9
commit
a76eb18bed
|
|
@ -121,6 +121,7 @@ sub submit {
|
|||
$response->{confirmation_sent} = 1 if $result->{sent};
|
||||
}
|
||||
|
||||
$c->res->headers->location( $c->req->url->to_string );
|
||||
return $c->render(
|
||||
status => 201,
|
||||
openapi => $response
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
use Modern::Perl;
|
||||
|
||||
use Test::More tests => 48;
|
||||
use Test::More tests => 50;
|
||||
use Test::NoWarnings;
|
||||
use Test::Exception;
|
||||
use Test::Warn;
|
||||
|
|
@ -722,7 +722,7 @@ subtest 'messaging_preferences() tests' => sub {
|
|||
|
||||
subtest 'to_api() tests' => sub {
|
||||
|
||||
plan tests => 6;
|
||||
plan tests => 7;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
|
|
@ -760,6 +760,9 @@ subtest 'to_api() tests' => sub {
|
|||
ok( exists $patron_json->{algo} );
|
||||
is( $patron_json->{algo}, 'algo' );
|
||||
|
||||
my $patron_eligible = $patron->to_api( { user => $consumer } );
|
||||
ok( exists $patron_eligible->{self_renewal_available} );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
|
|
@ -3799,3 +3802,142 @@ subtest 'fixup_cardnumber and autoMemberNumValue counter' => sub {
|
|||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest "is_eligible_for_self_renewal" => sub {
|
||||
plan tests => 8;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $category = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Patron::Categories',
|
||||
value => {
|
||||
self_renewal_enabled => 0, self_renewal_availability_start => 10, self_renewal_if_expired => 10,
|
||||
self_renewal_fines_block => 10, noissuescharge => 10
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
my $patron = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Patrons',
|
||||
value => { categorycode => $category->categorycode, dateexpiry => dt_from_string(), debarred => undef }
|
||||
}
|
||||
);
|
||||
|
||||
is( $patron->is_eligible_for_self_renewal, 0, "Category not enabled" );
|
||||
|
||||
$category->self_renewal_enabled(1)->store();
|
||||
$patron->delete()->store()->discard_changes();
|
||||
is( $patron->is_eligible_for_self_renewal, 1, "Category now enabled" );
|
||||
|
||||
$patron->debarred('2026-01-01')->store;
|
||||
is( $patron->is_eligible_for_self_renewal, 0, "Patron debarred" );
|
||||
$patron->debarred(undef)->store;
|
||||
$patron->delete()->store()->discard_changes();
|
||||
|
||||
# Move expiry date outside the window
|
||||
$patron->dateexpiry( dt_from_string()->add( days => 11 ) )->store;
|
||||
is( $patron->is_eligible_for_self_renewal, 0, "Patron not yet within the expiry window" );
|
||||
|
||||
# Shift the expiry window to cover new expiry date
|
||||
$category->self_renewal_availability_start(12)->store();
|
||||
$patron->delete()->store()->discard_changes();
|
||||
is( $patron->is_eligible_for_self_renewal, 1, "Patron is back within the expiry window" );
|
||||
|
||||
# Shift the date to now already be expired
|
||||
$patron->dateexpiry( dt_from_string()->subtract( days => 11 ) )->store;
|
||||
is( $patron->is_eligible_for_self_renewal, 0, "Patron can only self renew within 10 days of expiry" );
|
||||
|
||||
# Expand the expiry window
|
||||
$category->self_renewal_if_expired(12)->store();
|
||||
$patron->delete()->store()->discard_changes();
|
||||
is( $patron->is_eligible_for_self_renewal, 1, "Patron is back within the expiry window" );
|
||||
|
||||
t::lib::Mocks::mock_preference( 'noissuescharge', 10 );
|
||||
|
||||
my $fee1 = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Account::Lines',
|
||||
value => {
|
||||
borrowernumber => $patron->borrowernumber,
|
||||
amountoutstanding => 11,
|
||||
debit_type_code => 'OVERDUE',
|
||||
}
|
||||
}
|
||||
)->store;
|
||||
is( $patron->is_eligible_for_self_renewal, 0, "Patron is outside the charge limits" );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest "request_modification" => sub {
|
||||
plan tests => 5;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $patron = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Patrons',
|
||||
}
|
||||
);
|
||||
|
||||
my $modification_data = { firstname => 'Newname', changed_fields => 'firstname' };
|
||||
t::lib::Mocks::mock_preference( 'OPACPatronDetails', 1 );
|
||||
t::lib::Mocks::mock_preference( 'AutoApprovePatronProfileSettings', 0 );
|
||||
|
||||
$patron->request_modification($modification_data);
|
||||
|
||||
my @modifications = Koha::Patron::Modifications->search( { borrowernumber => $patron->borrowernumber } )->as_list;
|
||||
is( scalar(@modifications), 1, "New modification has replaced any existing mods" );
|
||||
|
||||
my $modification = $modifications[0];
|
||||
is( $modification->changed_fields, 'firstname', 'Fields correctly set' );
|
||||
is( $modification->firstname, $modification_data->{firstname}, 'Fields correctly set' );
|
||||
|
||||
t::lib::Mocks::mock_preference( 'AutoApprovePatronProfileSettings', 1 );
|
||||
$patron->request_modification($modification_data);
|
||||
|
||||
@modifications = Koha::Patron::Modifications->search( { borrowernumber => $patron->borrowernumber } )->as_list;
|
||||
is( scalar(@modifications), 0, "New modification has been approved and deleted" );
|
||||
is( $patron->discard_changes()->firstname, $modification_data->{firstname}, 'Name updated' );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest "create_expiry_notice_parameters" => sub {
|
||||
plan tests => 1;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $library = $builder->build_object( { class => 'Koha::Libraries' } );
|
||||
|
||||
my $patron = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Patrons',
|
||||
value => { branchcode => $library->branchcode }
|
||||
}
|
||||
);
|
||||
|
||||
my $expected_return = {
|
||||
'letter_params' => {
|
||||
'borrowernumber' => $patron->borrowernumber,
|
||||
'branchcode' => $library->branchcode,
|
||||
'tables' => {
|
||||
'borrowers' => $patron->borrowernumber,
|
||||
'branches' => $library->branchcode
|
||||
},
|
||||
'module' => 'members',
|
||||
'letter_code' => 'MEMBERSHIP_RENEWED',
|
||||
'lang' => $patron->lang
|
||||
},
|
||||
'message_name' => 'Patron_Expiry',
|
||||
'forceprint' => 0
|
||||
};
|
||||
|
||||
my $letter_params = $patron->create_expiry_notice_parameters(
|
||||
{ letter_code => 'MEMBERSHIP_RENEWED', forceprint => 0, is_notice_mandatory => 0 } );
|
||||
|
||||
is_deeply( $letter_params, $expected_return, 'Letter params generated correctly' );
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
use Modern::Perl;
|
||||
|
||||
use Test::NoWarnings;
|
||||
use Test::More tests => 2;
|
||||
use Test::More tests => 3;
|
||||
use Test::Mojo;
|
||||
|
||||
use t::lib::TestBuilder;
|
||||
|
|
@ -66,11 +66,8 @@ subtest 'list() tests' => sub {
|
|||
|
||||
$t->get_ok("//$userid:$password@/api/v1/patron_categories")->status_is(200);
|
||||
|
||||
$t->get_ok("//$userid:$password@/api/v1/patron_categories?q={\"me.categorycode\":\"TEST\"}")
|
||||
->status_is(200)
|
||||
->json_has('/0/name')
|
||||
->json_is( '/0/name' => 'Test' )
|
||||
->json_hasnt('/1');
|
||||
$t->get_ok("//$userid:$password@/api/v1/patron_categories?q={\"me.categorycode\":\"TEST\"}")->status_is(200)
|
||||
->json_has('/0/name')->json_is( '/0/name' => 'Test' )->json_hasnt('/1');
|
||||
|
||||
# Off limits search
|
||||
|
||||
|
|
@ -95,19 +92,79 @@ subtest 'list() tests' => sub {
|
|||
my $off_limits_userid = $off_limits_librarian->userid;
|
||||
|
||||
$t->get_ok("//$off_limits_userid:$off_limits_password@/api/v1/patron_categories?q={\"me.categorycode\":\"TEST\"}")
|
||||
->status_is(200)
|
||||
->json_hasnt('/0');
|
||||
->status_is(200)->json_hasnt('/0');
|
||||
|
||||
# Off limits librarian category has changed to one within limits
|
||||
|
||||
$off_limits_librarian->branchcode( $library->branchcode )->store;
|
||||
|
||||
$t->get_ok("//$off_limits_userid:$off_limits_password@/api/v1/patron_categories?q={\"me.categorycode\":\"TEST\"}")
|
||||
->status_is(200)
|
||||
->json_has('/0/name')
|
||||
->json_is( [ $category->to_api ] )
|
||||
->json_hasnt('/1');
|
||||
->status_is(200)->json_has('/0/name')->json_is( [ $category->to_api ] )->json_hasnt('/1');
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
|
||||
};
|
||||
|
||||
subtest 'add() tests' => sub {
|
||||
|
||||
plan tests => 9;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $library = $builder->build_object( { class => 'Koha::Libraries' } );
|
||||
|
||||
my $librarian = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Patrons',
|
||||
value => { flags => 2**3, categorycode => 'TEST', branchcode => $library->branchcode } # parameters flag = 3
|
||||
}
|
||||
);
|
||||
|
||||
my $password = 'thePassword123';
|
||||
$librarian->set_password( { password => $password, skip_validation => 1 } );
|
||||
my $userid = $librarian->userid;
|
||||
|
||||
my $patron = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Patrons',
|
||||
value => { flags => 0 }
|
||||
}
|
||||
);
|
||||
|
||||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||||
my $unauth_userid = $patron->userid;
|
||||
|
||||
my $category = {
|
||||
patron_category_id => 'new',
|
||||
name => "A new category",
|
||||
};
|
||||
|
||||
# Unauthorized attempt to write
|
||||
$t->post_ok( "//$unauth_userid:$password@/api/v1/patron_categories" => json => $category )->status_is(403);
|
||||
|
||||
# Authorized attempt to write invalid data
|
||||
my $category_with_invalid_field = {
|
||||
blah => "Category Blah",
|
||||
name => "Won't work"
|
||||
};
|
||||
|
||||
$t->post_ok( "//$userid:$password@/api/v1/patron_categories" => json => $category_with_invalid_field )
|
||||
->status_is(400)->json_is(
|
||||
"/errors" => [
|
||||
{
|
||||
message => "Properties not allowed: blah.",
|
||||
path => "/body"
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
# Authorized attempt to write
|
||||
my $patron_category_id =
|
||||
$t->post_ok( "//$userid:$password@/api/v1/patron_categories" => json => $category )
|
||||
->status_is( 201, 'REST3.2.1' )->header_like(
|
||||
Location => qr|^\/api\/v1\/patron_categories/\d*|,
|
||||
'REST3.4.1'
|
||||
)->json_is( '/name' => $category->{name} )->tx->res->json->{patron_category_id};
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -125,16 +125,13 @@ subtest 'list() tests' => sub {
|
|||
|
||||
$t->get_ok("//$userid:$password@/api/v1/patrons")->status_is( 200, 'list_borrowers makes /patrons accessible' );
|
||||
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons?cardnumber=" . $librarian->cardnumber )
|
||||
->status_is(200)
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons?cardnumber=" . $librarian->cardnumber )->status_is(200)
|
||||
->json_is( '/0/cardnumber' => $librarian->cardnumber );
|
||||
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons?q={\"cardnumber\":\"" . $librarian->cardnumber . "\"}" )
|
||||
->status_is(200)
|
||||
->json_is( '/0/cardnumber' => $librarian->cardnumber );
|
||||
->status_is(200)->json_is( '/0/cardnumber' => $librarian->cardnumber );
|
||||
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons?address2=" . $librarian->address2 )
|
||||
->status_is(200)
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons?address2=" . $librarian->address2 )->status_is(200)
|
||||
->json_is( '/0/address2' => $librarian->address2 );
|
||||
|
||||
subtest 'restricted & expired' => sub {
|
||||
|
|
@ -148,19 +145,13 @@ subtest 'list() tests' => sub {
|
|||
$t->get_ok( "//$userid:$password@/api/v1/patrons?restricted="
|
||||
. Mojo::JSON->true
|
||||
. "&cardnumber="
|
||||
. $patron->cardnumber )
|
||||
->status_is(200)
|
||||
->json_has('/0/restricted')
|
||||
->json_is( '/0/restricted' => Mojo::JSON->true )
|
||||
->json_has('/0/expired')
|
||||
->json_is( '/0/expired' => Mojo::JSON->false )
|
||||
->json_hasnt('/1');
|
||||
. $patron->cardnumber )->status_is(200)->json_has('/0/restricted')
|
||||
->json_is( '/0/restricted' => Mojo::JSON->true )->json_has('/0/expired')
|
||||
->json_is( '/0/expired' => Mojo::JSON->false )->json_hasnt('/1');
|
||||
|
||||
$patron->dateexpiry( dt_from_string->subtract( days => 2 ) )->store;
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
|
||||
->status_is(200)
|
||||
->json_has('/expired')
|
||||
->json_is( '/expired' => Mojo::JSON->true );
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )->status_is(200)
|
||||
->json_has('/expired')->json_is( '/expired' => Mojo::JSON->true );
|
||||
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons?"
|
||||
. 'q={"extended_attributes.type":"CODE"}' => { 'x-koha-embed' => 'extended_attributes' } )
|
||||
|
|
@ -189,15 +180,13 @@ subtest 'list() tests' => sub {
|
|||
$t->get_ok( "//$userid:$password@/api/v1/patrons?date_of_birth="
|
||||
. $date_of_birth
|
||||
. "&cardnumber="
|
||||
. $patron->cardnumber )
|
||||
->status_is(200)
|
||||
. $patron->cardnumber )->status_is(200)
|
||||
->json_is( '/0/patron_id' => $patron->id, 'Filtering by date works' );
|
||||
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons?last_seen="
|
||||
. $last_seen_rfc3339
|
||||
. "&cardnumber="
|
||||
. $patron->cardnumber )
|
||||
->status_is(200)
|
||||
. $patron->cardnumber )->status_is(200)
|
||||
->json_is( '/0/patron_id' => $patron->id, 'Filtering by date-time works' );
|
||||
|
||||
my $q = encode_json(
|
||||
|
|
@ -207,8 +196,7 @@ subtest 'list() tests' => sub {
|
|||
}
|
||||
);
|
||||
|
||||
$t->get_ok("//$userid:$password@/api/v1/patrons?q=$q")
|
||||
->status_is(200)
|
||||
$t->get_ok("//$userid:$password@/api/v1/patrons?q=$q")->status_is(200)
|
||||
->json_is( '/0/patron_id' => $patron->id, 'Filtering by date works' );
|
||||
|
||||
$q = encode_json(
|
||||
|
|
@ -218,8 +206,7 @@ subtest 'list() tests' => sub {
|
|||
}
|
||||
);
|
||||
|
||||
$t->get_ok("//$userid:$password@/api/v1/patrons?q=$q")
|
||||
->status_is(200)
|
||||
$t->get_ok("//$userid:$password@/api/v1/patrons?q=$q")->status_is(200)
|
||||
->json_is( '/0/patron_id' => $patron->id, 'Filtering by date-time works' );
|
||||
};
|
||||
|
||||
|
|
@ -263,20 +250,16 @@ subtest 'list() tests' => sub {
|
|||
my $userid = $librarian->userid;
|
||||
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons?_order_by=patron_id&q="
|
||||
. encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
|
||||
->status_is(200)
|
||||
->json_is( '/0/patron_id' => $patron_1->id )
|
||||
->json_is( '/1/patron_id' => $patron_2->id )
|
||||
. encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )->status_is(200)
|
||||
->json_is( '/0/patron_id' => $patron_1->id )->json_is( '/1/patron_id' => $patron_2->id )
|
||||
->json_is( '/2/patron_id' => $patron_3->id );
|
||||
|
||||
@libraries_where_can_see_patrons = ( $library_2->id );
|
||||
|
||||
my $res =
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons?_order_by=patron_id&q="
|
||||
. encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
|
||||
->status_is(200)
|
||||
->json_is( '/0/patron_id' => $patron_3->id, 'Returns the only allowed patron' )
|
||||
->tx->res->json;
|
||||
. encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )->status_is(200)
|
||||
->json_is( '/0/patron_id' => $patron_3->id, 'Returns the only allowed patron' )->tx->res->json;
|
||||
|
||||
is( scalar @{$res}, 1, 'Only one patron returned' );
|
||||
|
||||
|
|
@ -339,10 +322,8 @@ subtest 'get() tests' => sub {
|
|||
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron->id )
|
||||
->status_is( 200, 'list_borrowers permission makes patron visible' )
|
||||
->json_is( '/patron_id' => $patron->id )
|
||||
->json_is( '/category_id' => $patron->categorycode )
|
||||
->json_is( '/surname' => $patron->surname )
|
||||
->json_is( '/patron_card_lost' => Mojo::JSON->false );
|
||||
->json_is( '/patron_id' => $patron->id )->json_is( '/category_id' => $patron->categorycode )
|
||||
->json_is( '/surname' => $patron->surname )->json_is( '/patron_card_lost' => Mojo::JSON->false );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
|
@ -384,22 +365,18 @@ subtest 'get() tests' => sub {
|
|||
$librarian->set_password( { password => $password, skip_validation => 1 } );
|
||||
my $userid = $librarian->userid;
|
||||
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_1->id )
|
||||
->status_is(200)
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_1->id )->status_is(200)
|
||||
->json_is( '/patron_id' => $patron_1->id );
|
||||
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id )
|
||||
->status_is(200)
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id )->status_is(200)
|
||||
->json_is( '/patron_id' => $patron_2->id );
|
||||
|
||||
@libraries_where_can_see_patrons = ( $library_1->id );
|
||||
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_1->id )
|
||||
->status_is(200)
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_1->id )->status_is(200)
|
||||
->json_is( '/patron_id' => $patron_1->id );
|
||||
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id )
|
||||
->status_is(404)
|
||||
$t->get_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->id )->status_is(404)
|
||||
->json_is( '/error' => 'Patron not found' );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
|
|
@ -482,14 +459,14 @@ subtest 'add() tests' => sub {
|
|||
delete $newpatron->{restricted};
|
||||
delete $newpatron->{expired};
|
||||
delete $newpatron->{anonymized};
|
||||
delete $newpatron->{self_renewal_available};
|
||||
|
||||
my $password = 'thePassword123';
|
||||
$librarian->set_password( { password => $password, skip_validation => 1 } );
|
||||
my $userid = $librarian->userid;
|
||||
t::lib::Mocks::mock_preference( 'PatronDuplicateMatchingAddFields', 'firstname|surname|dateofbirth' );
|
||||
|
||||
$t->post_ok( "//$userid:$password@/api/v1/patrons" => json => $newpatron )
|
||||
->status_is(409)
|
||||
$t->post_ok( "//$userid:$password@/api/v1/patrons" => json => $newpatron )->status_is(409)
|
||||
->json_is( '/error' => "A patron record matching these details already exists" );
|
||||
|
||||
# Create a library just to make sure its ID doesn't exist on the DB
|
||||
|
|
@ -503,8 +480,7 @@ subtest 'add() tests' => sub {
|
|||
|
||||
# Test duplicate userid constraint
|
||||
$t->post_ok( "//$userid:$password@/api/v1/patrons" => { 'x-confirm-not-duplicate' => 1 } => json => $newpatron )
|
||||
->status_is(400)
|
||||
->json_is( '/error' => "Problem with " . $newpatron->{userid} );
|
||||
->status_is(400)->json_is( '/error' => "Problem with " . $newpatron->{userid} );
|
||||
|
||||
$newpatron->{library_id} = $patron->branchcode;
|
||||
|
||||
|
|
@ -513,8 +489,7 @@ subtest 'add() tests' => sub {
|
|||
warning_like {
|
||||
$t->post_ok(
|
||||
"//$userid:$password@/api/v1/patrons" => { 'x-confirm-not-duplicate' => 1 } => json => $newpatron )
|
||||
->status_is(409)
|
||||
->json_has( '/error', 'Fails when trying to POST duplicate cardnumber' )
|
||||
->status_is(409)->json_has( '/error', 'Fails when trying to POST duplicate cardnumber' )
|
||||
->json_like( '/conflict' => qr/(borrowers\.)?cardnumber/ );
|
||||
}
|
||||
qr/DBD::mysql::st execute failed: Duplicate entry '(.*?)' for key '(borrowers\.)?cardnumber'/;
|
||||
|
|
@ -529,8 +504,7 @@ subtest 'add() tests' => sub {
|
|||
$newpatron->{category_id} = $deleted_category_id; # Test invalid patron category
|
||||
|
||||
$t->post_ok( "//$userid:$password@/api/v1/patrons" => { 'x-confirm-not-duplicate' => 1 } => json => $newpatron )
|
||||
->status_is(400)
|
||||
->json_is( '/error' => "Given category_id does not exist" );
|
||||
->status_is(400)->json_is( '/error' => "Given category_id does not exist" );
|
||||
$newpatron->{category_id} = $patron->categorycode;
|
||||
|
||||
$newpatron->{falseproperty} = "Non existent property";
|
||||
|
|
@ -547,6 +521,7 @@ subtest 'add() tests' => sub {
|
|||
delete $newpatron->{restricted};
|
||||
delete $newpatron->{expired};
|
||||
delete $newpatron->{anonymized};
|
||||
delete $newpatron->{self_renewal_available};
|
||||
$patron_to_delete->delete;
|
||||
|
||||
# Set a date field
|
||||
|
|
@ -560,15 +535,11 @@ subtest 'add() tests' => sub {
|
|||
$letter_enqueued = 0;
|
||||
$t->post_ok(
|
||||
"//$userid:$password@/api/v1/patrons" => { 'x-koha-override' => 'welcome_yes' } => json => $newpatron )
|
||||
->status_is( 201, 'Patron created successfully' )
|
||||
->header_like(
|
||||
->status_is( 201, 'Patron created successfully' )->header_like(
|
||||
Location => qr|^\/api\/v1\/patrons/\d*|,
|
||||
'REST3.4.1'
|
||||
)
|
||||
->json_has( '/patron_id', 'got a patron_id' )
|
||||
->json_is( '/cardnumber' => $newpatron->{cardnumber} )
|
||||
->json_is( '/surname' => $newpatron->{surname} )
|
||||
->json_is( '/firstname' => $newpatron->{firstname} )
|
||||
)->json_has( '/patron_id', 'got a patron_id' )->json_is( '/cardnumber' => $newpatron->{cardnumber} )
|
||||
->json_is( '/surname' => $newpatron->{surname} )->json_is( '/firstname' => $newpatron->{firstname} )
|
||||
->json_is( '/date_of_birth' => $newpatron->{date_of_birth}, 'Date field set (Bug 28585)' )
|
||||
->json_is( '/last_seen' => $newpatron->{last_seen}, 'Date-time field set (Bug 28585)' );
|
||||
|
||||
|
|
@ -800,8 +771,7 @@ subtest 'add() tests' => sub {
|
|||
"city" => "Konstanz",
|
||||
"library_id" => "MPL"
|
||||
}
|
||||
)
|
||||
->status_is(400)
|
||||
)->status_is(400)
|
||||
->json_is( '/error' => "Tried to add more than one non-repeatable attributes. type=$code value=$attr" );
|
||||
|
||||
is( Koha::Patrons->search->count, $patrons_count, 'No patron added' );
|
||||
|
|
@ -816,8 +786,7 @@ subtest 'add() tests' => sub {
|
|||
"city" => "Konstanz",
|
||||
"library_id" => "MPL"
|
||||
}
|
||||
)
|
||||
->status_is(400)
|
||||
)->status_is(400)
|
||||
->json_is(
|
||||
'/error' => "Your action breaks a unique constraint on the attribute. type=$code value=$attr" );
|
||||
|
||||
|
|
@ -978,8 +947,7 @@ subtest 'add() tests' => sub {
|
|||
"city" => "Bigtown",
|
||||
"library_id" => "MPL",
|
||||
}
|
||||
)
|
||||
->status_is( 201, 'Patron added with EnhancedMessagingPreferences disabled' )
|
||||
)->status_is( 201, 'Patron added with EnhancedMessagingPreferences disabled' )
|
||||
->tx->res->json->{patron_id};
|
||||
|
||||
# No messaging preferences should be set
|
||||
|
|
@ -1037,9 +1005,9 @@ subtest 'update() tests' => sub {
|
|||
delete $newpatron->{restricted};
|
||||
delete $newpatron->{expired};
|
||||
delete $newpatron->{anonymized};
|
||||
delete $newpatron->{self_renewal_available};
|
||||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/patrons/-1" => json => $newpatron )
|
||||
->status_is(404)
|
||||
$t->put_ok( "//$userid:$password@/api/v1/patrons/-1" => json => $newpatron )->status_is(404)
|
||||
->json_has( '/error', 'Fails when trying to PUT nonexistent patron' );
|
||||
|
||||
# Create a library just to make sure its ID doesn't exist on the DB
|
||||
|
|
@ -1053,8 +1021,7 @@ subtest 'update() tests' => sub {
|
|||
$newpatron->{category_id} = $deleted_category_id;
|
||||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
|
||||
->status_is(400)
|
||||
->json_is( '/error' => "Given category_id does not exist" );
|
||||
->status_is(400)->json_is( '/error' => "Given category_id does not exist" );
|
||||
|
||||
# Restore the valid category
|
||||
$newpatron->{category_id} = $patron_2->categorycode;
|
||||
|
|
@ -1071,8 +1038,7 @@ subtest 'update() tests' => sub {
|
|||
|
||||
warning_like {
|
||||
$t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
|
||||
->status_is(400)
|
||||
->json_is( '/error' => "Given library_id does not exist" );
|
||||
->status_is(400)->json_is( '/error' => "Given library_id does not exist" );
|
||||
}
|
||||
qr/DBD::mysql::st execute failed: Cannot add or update a child row: a foreign key constraint fails/;
|
||||
|
||||
|
|
@ -1083,8 +1049,7 @@ subtest 'update() tests' => sub {
|
|||
$newpatron->{falseproperty} = "Non existent property";
|
||||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
|
||||
->status_is(400)
|
||||
->json_is( '/errors/0/message' => 'Properties not allowed: falseproperty.' );
|
||||
->status_is(400)->json_is( '/errors/0/message' => 'Properties not allowed: falseproperty.' );
|
||||
|
||||
# Get rid of the invalid attribute
|
||||
delete $newpatron->{falseproperty};
|
||||
|
|
@ -1094,8 +1059,7 @@ subtest 'update() tests' => sub {
|
|||
$newpatron->{userid} = $patron_1->userid;
|
||||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/patrons/" . $patron_2->borrowernumber => json => $newpatron )
|
||||
->status_is(400)
|
||||
->json_has( '/error', "Problem with userid " . $patron_1->userid );
|
||||
->status_is(400)->json_has( '/error', "Problem with userid " . $patron_1->userid );
|
||||
|
||||
$newpatron->{cardnumber} = $patron_1->id . $patron_2->id;
|
||||
$newpatron->{userid} = "user" . $patron_1->id . $patron_2->id;
|
||||
|
|
@ -1117,6 +1081,8 @@ subtest 'update() tests' => sub {
|
|||
$newpatron->{restricted} = $unauthorized_patron->to_api( { user => $authorized_patron } )->{restricted};
|
||||
$newpatron->{expired} = $unauthorized_patron->to_api( { user => $authorized_patron } )->{expired};
|
||||
$newpatron->{anonymized} = $unauthorized_patron->to_api( { user => $authorized_patron } )->{anonymized};
|
||||
$newpatron->{self_renewal_available} =
|
||||
$unauthorized_patron->to_api( { user => $authorized_patron } )->{self_renewal_available};
|
||||
|
||||
my $got = $result->tx->res->json;
|
||||
my $updated_on_got = delete $got->{updated_on};
|
||||
|
|
@ -1152,6 +1118,7 @@ subtest 'update() tests' => sub {
|
|||
delete $newpatron->{restricted};
|
||||
delete $newpatron->{expired};
|
||||
delete $newpatron->{anonymized};
|
||||
delete $newpatron->{self_renewal_available};
|
||||
|
||||
# attempt to update
|
||||
$authorized_patron->flags( 2**4 )->store; # borrowers flag = 4
|
||||
|
|
@ -1179,7 +1146,7 @@ subtest 'update() tests' => sub {
|
|||
->status_is(
|
||||
403,
|
||||
"Non-superlibrarian user change of superlibrarian secondary_email to undefined forbidden"
|
||||
)->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
|
||||
)->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
|
||||
|
||||
$newpatron->{secondary_email} = $superlibrarian->emailpro;
|
||||
$newpatron->{altaddress_email} = 'nonsense@no.no';
|
||||
|
|
@ -1195,7 +1162,7 @@ subtest 'update() tests' => sub {
|
|||
->status_is(
|
||||
403,
|
||||
"Non-superlibrarian user change of superlibrarian altaddress_email to undefined forbidden"
|
||||
)->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
|
||||
)->json_is( { error => "Not enough privileges to change a superlibrarian's email" } );
|
||||
|
||||
# update patron without sending email
|
||||
delete $newpatron->{email};
|
||||
|
|
@ -1266,15 +1233,13 @@ subtest 'update() tests' => sub {
|
|||
"city" => "Konstanz",
|
||||
"library_id" => "MPL"
|
||||
}
|
||||
)
|
||||
->status_is(400)
|
||||
)->status_is(400)
|
||||
->json_is(
|
||||
'/error' => "Missing mandatory extended attribute (type=" . $attr_type_mandatory->code . ")" );
|
||||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/patrons/"
|
||||
. $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
|
||||
$newpatron )
|
||||
->status_is(400)
|
||||
$newpatron )->status_is(400)
|
||||
->json_is( '/error' => 'Tried to use an invalid attribute type. type=' . $deleted_attr_code )
|
||||
->json_is( '/error_code' => 'invalid_attribute_type' );
|
||||
|
||||
|
|
@ -1291,13 +1256,11 @@ subtest 'update() tests' => sub {
|
|||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/patrons/"
|
||||
. $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
|
||||
$newpatron )
|
||||
->status_is(400)
|
||||
$newpatron )->status_is(400)
|
||||
->json_is( '/error' => 'Your action breaks a unique constraint on the attribute. type='
|
||||
. $attr_type_unique->code
|
||||
. ' value='
|
||||
. $unique_attr->attribute )
|
||||
->json_is( '/error_code' => 'attribute_not_unique' );
|
||||
. $unique_attr->attribute )->json_is( '/error_code' => 'attribute_not_unique' );
|
||||
|
||||
$newpatron->{extended_attributes} = [
|
||||
{ type => $attr_type_repeatable->code, value => 'a' },
|
||||
|
|
@ -1308,13 +1271,11 @@ subtest 'update() tests' => sub {
|
|||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/patrons/"
|
||||
. $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
|
||||
$newpatron )
|
||||
->status_is(400)
|
||||
$newpatron )->status_is(400)
|
||||
->json_is( '/error' => 'Your action breaks a unique constraint on the attribute. type='
|
||||
. $attr_type_unique->code
|
||||
. ' value='
|
||||
. $unique_attr->attribute )
|
||||
->json_is( '/error_code' => 'attribute_not_unique' );
|
||||
. $unique_attr->attribute )->json_is( '/error_code' => 'attribute_not_unique' );
|
||||
|
||||
$newpatron->{extended_attributes} = [
|
||||
{ type => $attr_type_repeatable->code, value => 'a' },
|
||||
|
|
@ -1324,12 +1285,10 @@ subtest 'update() tests' => sub {
|
|||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/patrons/"
|
||||
. $superlibrarian->borrowernumber => { 'x-koha-embed' => 'extended_attributes' } => json =>
|
||||
$newpatron )
|
||||
->status_is(400)
|
||||
$newpatron )->status_is(400)
|
||||
->json_is( '/error' => 'Tried to add more than one non-repeatable attributes. type='
|
||||
. $attr_type_mandatory->code
|
||||
. ' value=pong' )
|
||||
->json_is( '/error_code' => 'non_repeatable_attribute' );
|
||||
. ' value=pong' )->json_is( '/error_code' => 'non_repeatable_attribute' );
|
||||
|
||||
my $unique_value = $unique_attr->attribute;
|
||||
$unique_attr->delete;
|
||||
|
|
@ -1388,8 +1347,7 @@ subtest 'delete() tests' => sub {
|
|||
|
||||
t::lib::Mocks::mock_preference( 'AnonymousPatron', $patron->borrowernumber );
|
||||
$t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
|
||||
->status_is( 409, 'Anonymous patron cannot be deleted' )
|
||||
->json_is(
|
||||
->status_is( 409, 'Anonymous patron cannot be deleted' )->json_is(
|
||||
{
|
||||
error => 'Anonymous patron cannot be deleted',
|
||||
error_code => 'is_anonymous_patron'
|
||||
|
|
@ -1411,8 +1369,7 @@ subtest 'delete() tests' => sub {
|
|||
$guarantee->add_guarantor( { guarantor_id => $patron->id, relationship => 'parent' } );
|
||||
|
||||
$t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
|
||||
->status_is( 409, 'Patron with checkouts cannot be deleted' )
|
||||
->json_is(
|
||||
->status_is( 409, 'Patron with checkouts cannot be deleted' )->json_is(
|
||||
{
|
||||
error => 'Pending checkouts prevent deletion',
|
||||
error_code => 'has_checkouts'
|
||||
|
|
@ -1423,8 +1380,7 @@ subtest 'delete() tests' => sub {
|
|||
$checkout->delete;
|
||||
|
||||
$t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
|
||||
->status_is( 409, 'Patron with debt cannot be deleted' )
|
||||
->json_is(
|
||||
->status_is( 409, 'Patron with debt cannot be deleted' )->json_is(
|
||||
{
|
||||
error => 'Pending debts prevent deletion',
|
||||
error_code => 'has_debt'
|
||||
|
|
@ -1435,8 +1391,7 @@ subtest 'delete() tests' => sub {
|
|||
$patron->account->pay( { amount => 10, debits => [$debit] } );
|
||||
|
||||
$t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
|
||||
->status_is( 409, 'Patron with guarantees cannot be deleted' )
|
||||
->json_is(
|
||||
->status_is( 409, 'Patron with guarantees cannot be deleted' )->json_is(
|
||||
{
|
||||
error => 'Patron is a guarantor and it prevents deletion',
|
||||
error_code => 'has_guarantees'
|
||||
|
|
@ -1449,8 +1404,7 @@ subtest 'delete() tests' => sub {
|
|||
$patron->protected(1)->store();
|
||||
|
||||
$t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
|
||||
->status_is( 409, 'Protected patron cannot be deleted' )
|
||||
->json_is(
|
||||
->status_is( 409, 'Protected patron cannot be deleted' )->json_is(
|
||||
{
|
||||
error => 'Protected patrons cannot be deleted',
|
||||
error_code => 'is_protected'
|
||||
|
|
@ -1460,8 +1414,7 @@ subtest 'delete() tests' => sub {
|
|||
$patron->protected(0)->store();
|
||||
|
||||
$t->delete_ok( "//$userid:$password@/api/v1/patrons/" . $patron->borrowernumber )
|
||||
->status_is( 204, 'REST3.2.4' )
|
||||
->content_is( '', 'REST3.3.4' );
|
||||
->status_is( 204, 'REST3.2.4' )->content_is( '', 'REST3.3.4' );
|
||||
|
||||
my $deleted_patrons = Koha::Old::Patrons->search( { borrowernumber => $patron->borrowernumber } );
|
||||
is( $deleted_patrons->count, 1, 'The patron has been moved to the vault' );
|
||||
|
|
@ -1493,13 +1446,11 @@ subtest 'guarantors_can_see_charges() tests' => sub {
|
|||
)->status_is(401)->json_is( { error => "Authentication failure." } );
|
||||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/public/patrons/$other_patron_id/guarantors/can_see_charges" => json =>
|
||||
{ allowed => Mojo::JSON->true } )
|
||||
->status_is(403)
|
||||
{ allowed => Mojo::JSON->true } )->status_is(403)
|
||||
->json_is( { error => "Unprivileged user cannot access another user's resources" } );
|
||||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/guarantors/can_see_charges" => json =>
|
||||
{ allowed => Mojo::JSON->true } )
|
||||
->status_is(403)
|
||||
{ allowed => Mojo::JSON->true } )->status_is(403)
|
||||
->json_is( '/error', 'The current configuration doesn\'t allow the requested action.' );
|
||||
|
||||
t::lib::Mocks::mock_preference( 'AllowPatronToSetFinesVisibilityForGuarantor', 1 );
|
||||
|
|
@ -1537,15 +1488,13 @@ subtest 'guarantors_can_see_checkouts() tests' => sub {
|
|||
{ allowed => Mojo::JSON->true } )->status_is(401)->json_is( { error => "Authentication failure." } );
|
||||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/public/patrons/$other_patron_id/guarantors/can_see_checkouts" => json =>
|
||||
{ allowed => Mojo::JSON->true } )
|
||||
->status_is(403)
|
||||
{ allowed => Mojo::JSON->true } )->status_is(403)
|
||||
->json_is( { error => "Unprivileged user cannot access another user's resources" } );
|
||||
|
||||
t::lib::Mocks::mock_preference( 'AllowPatronToSetCheckoutsVisibilityForGuarantor', 0 );
|
||||
|
||||
$t->put_ok( "//$userid:$password@/api/v1/public/patrons/$patron_id/guarantors/can_see_checkouts" => json =>
|
||||
{ allowed => Mojo::JSON->true } )
|
||||
->status_is(403)
|
||||
{ allowed => Mojo::JSON->true } )->status_is(403)
|
||||
->json_is( '/error', 'The current configuration doesn\'t allow the requested action.' );
|
||||
|
||||
t::lib::Mocks::mock_preference( 'AllowPatronToSetCheckoutsVisibilityForGuarantor', 1 );
|
||||
|
|
@ -1588,8 +1537,7 @@ sub unauthorized_access_tests {
|
|||
$unauthorized_patron->set_password( { password => $password, skip_validation => 1 } );
|
||||
my $unauth_userid = $unauthorized_patron->userid;
|
||||
|
||||
$t->$verb_ok( "//$unauth_userid:$password\@$endpoint" => json => $json )
|
||||
->status_is(403)
|
||||
$t->$verb_ok( "//$unauth_userid:$password\@$endpoint" => json => $json )->status_is(403)
|
||||
->json_has('/required_permissions');
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,198 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
# This file is part of Koha.
|
||||
#
|
||||
# Koha is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Koha is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Koha; if not, see <https://www.gnu.org/licenses>.
|
||||
|
||||
use Modern::Perl;
|
||||
|
||||
use Test::NoWarnings;
|
||||
use Test::More tests => 3;
|
||||
use Test::Mojo;
|
||||
|
||||
use t::lib::TestBuilder;
|
||||
use t::lib::Mocks;
|
||||
|
||||
use Koha::Database;
|
||||
use Koha::DateUtils qw( dt_from_string );
|
||||
|
||||
my $schema = Koha::Database->new->schema;
|
||||
my $builder = t::lib::TestBuilder->new();
|
||||
|
||||
my $t = Test::Mojo->new('Koha::REST::V1');
|
||||
|
||||
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
|
||||
|
||||
subtest 'start()' => sub {
|
||||
plan tests => 9;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $category = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Patron::Categories',
|
||||
value => {
|
||||
self_renewal_enabled => 0, self_renewal_availability_start => 10, self_renewal_if_expired => 10,
|
||||
self_renewal_fines_block => 10, noissuescharge => 10,
|
||||
self_renewal_failure_message => 'This is a failure message'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
my $patron = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Patrons',
|
||||
value => { categorycode => $category->categorycode, dateexpiry => dt_from_string(), debarred => undef }
|
||||
}
|
||||
);
|
||||
|
||||
my $password = 'thePassword123';
|
||||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||||
my $userid = $patron->userid;
|
||||
|
||||
my $borrowernumber = $patron->borrowernumber;
|
||||
|
||||
$t->get_ok("//$userid:$password@/api/v1/public/patrons/$borrowernumber/self_renewal")
|
||||
->status_is( 403, 'REST3.2.2' )->json_is( { error => "You are not eligible for self-renewal" } );
|
||||
|
||||
$category->self_renewal_enabled(1)->store();
|
||||
|
||||
t::lib::Mocks::mock_preference( 'OPACPatronDetails', 1 );
|
||||
|
||||
$t->get_ok("//$userid:$password@/api/v1/public/patrons/$borrowernumber/self_renewal")
|
||||
->status_is( 200, 'REST3.2.2' )->json_is(
|
||||
{
|
||||
self_renewal_settings => {
|
||||
self_renewal_failure_message => $category->self_renewal_failure_message,
|
||||
self_renewal_information_message => $category->self_renewal_information_message,
|
||||
opac_patron_details => 1
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
my $new_category = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Patron::Categories',
|
||||
value => {
|
||||
self_renewal_enabled => 1, self_renewal_availability_start => 10, self_renewal_if_expired => 10,
|
||||
self_renewal_fines_block => 10, noissuescharge => 10,
|
||||
self_renewal_failure_message => 'This is a failure message'
|
||||
}
|
||||
}
|
||||
);
|
||||
$t->get_ok("//$userid:$password@/api/v1/public/patrons/$borrowernumber/self_renewal")
|
||||
->status_is( 200, 'REST3.2.2' )->json_is(
|
||||
{
|
||||
self_renewal_settings => {
|
||||
self_renewal_failure_message => $category->self_renewal_failure_message,
|
||||
self_renewal_information_message => $category->self_renewal_information_message,
|
||||
opac_patron_details => 1
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'submit()' => sub {
|
||||
plan tests => 11;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $category = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Patron::Categories',
|
||||
value => {
|
||||
self_renewal_enabled => 0, self_renewal_availability_start => 10, self_renewal_if_expired => 10,
|
||||
self_renewal_fines_block => 10, noissuescharge => 10,
|
||||
self_renewal_failure_message => 'This is a failure message'
|
||||
}
|
||||
}
|
||||
);
|
||||
my $branch = $builder->build_object( { class => 'Koha::Libraries' } );
|
||||
|
||||
my $patron = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Patrons',
|
||||
value => {
|
||||
branchcode => $branch->branchcode, categorycode => $category->categorycode,
|
||||
dateexpiry => dt_from_string(), debarred => undef, lang => 'default'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
my $password = 'thePassword123';
|
||||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||||
my $userid = $patron->userid;
|
||||
|
||||
my $borrowernumber = $patron->borrowernumber;
|
||||
|
||||
$t->post_ok( "//$userid:$password@/api/v1/public/patrons/$borrowernumber/self_renewal" => json => {} )
|
||||
->status_is( 403, 'REST3.2.2' )->json_is( { error => "You are not eligible for self-renewal" } );
|
||||
|
||||
t::lib::Mocks::mock_preference( 'OPACPatronDetails', 1 );
|
||||
t::lib::Mocks::mock_preference( 'AutoApprovePatronProfileSettings', 0 );
|
||||
$category->self_renewal_enabled(1)->store();
|
||||
|
||||
my $date;
|
||||
if ( C4::Context->preference('BorrowerRenewalPeriodBase') eq 'combination' ) {
|
||||
$date =
|
||||
( dt_from_string gt dt_from_string( $patron->dateexpiry ) )
|
||||
? dt_from_string
|
||||
: dt_from_string( $patron->dateexpiry );
|
||||
} else {
|
||||
$date =
|
||||
C4::Context->preference('BorrowerRenewalPeriodBase') eq 'dateexpiry'
|
||||
? dt_from_string( $patron->dateexpiry )
|
||||
: dt_from_string;
|
||||
}
|
||||
my $expiry_date = $patron->category->get_expiry_date($date);
|
||||
|
||||
my $renewal_notice = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::Notice::Templates',
|
||||
value => {
|
||||
module => 'members',
|
||||
code => 'MEMBERSHIP_RENEWED',
|
||||
branchcode => $branch->branchcode,
|
||||
message_transport_type => 'print',
|
||||
lang => 'default'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
my $counter = Koha::Notice::Messages->search( { borrowernumber => $patron->borrowernumber } )->count;
|
||||
$t->post_ok( "//$userid:$password@/api/v1/public/patrons/$borrowernumber/self_renewal" => json => {} )
|
||||
->status_is( 201, 'REST3.2.2' )
|
||||
->json_is( { expiry_date => $expiry_date->truncate( to => 'day' ), confirmation_sent => 1 } );
|
||||
is(
|
||||
Koha::Notice::Messages->search( { borrowernumber => $patron->borrowernumber } )->count, $counter + 1,
|
||||
"Notice queued"
|
||||
);
|
||||
|
||||
# Test that modifications are created correctly
|
||||
t::lib::Mocks::mock_preference( 'OPACPatronDetails', 1 );
|
||||
my $modification_data = { patron => { firstname => 'Newname' } };
|
||||
$patron->dateexpiry( dt_from_string() )->store();
|
||||
|
||||
$t->post_ok(
|
||||
"//$userid:$password@/api/v1/public/patrons/$borrowernumber/self_renewal" => json => $modification_data )
|
||||
->status_is( 201, 'REST3.2.2' )
|
||||
->json_is( { expiry_date => $expiry_date->truncate( to => 'day' ), confirmation_sent => 1 } );
|
||||
|
||||
my @modifications = Koha::Patron::Modifications->search( { borrowernumber => $patron->borrowernumber } )->as_list;
|
||||
is( scalar(@modifications), 1, "New modification has replaced any existing mods" );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
Loading…
Reference in New Issue