50a2e9316a
+ attached items, subscriptions etc via the API as an alternative to the web interface: cgi-bin/koha/cataloguing/merge.pl
This is a slightly improved version of Zenos patch: I (domm) have converted the code in Koha::Biblio to a more DBICy style and packed it into a transaction (as requested in Comment 23)
Even the QA script is happy now!
To test:
1) you need an API user with the permissions "editcatalogue"
2) two records: one to be merged into (with biblio_id, eg 262) and another one from
which to merge (with biblio_id_to_merge, eg 9) which will be deleted!
both records may/should have items, subscription, subscriptionhistory, serial, suggestions
orders and holds
3) check both records via the web
4) Apply patch
5) Write a JSON file with inside the field 'biblio_id_to_merge' and the biblionumber from wihich to merge.
As example:
{
"biblio_id_to_merge" : 9
}
6) Execute an API call with correct headers and location. For example:
curl -s -u koha:koha --header "Content-Type: application/json" --header "Accept: application/marc-in-json"
--request POST "http://127.0.0.1:8080/api/v1/biblios/262/merge" -d @file.json
You must to setup the headers and to use a json file with parameters
7) The record with the id 9 is deleted now, the record with 262 has all items, etc attached,
the return is: return code 200 and the changed record 262 in marc-in-json format
8) It is possible to override biblio data with an external bib record. You need to put external bib record
into the json file in marc-in-json format. To write use the json file uploaded as example
You need to fill the fields 'rules' and 'datarecord'. The field 'rules' must contains 'override_ext'
To do the call:
curl -s -u koha:koha --header "Content-Type: application/json" --header "Accept: application/marc-in-json"
--request POST "http://127.0.0.1:8080/api/v1/biblios/XXX/merge" -d @file_with_recod.json
9) The record in 'biblio_id_to_merge' is deleted now, in biblio XXX now there are the bibliographic data
of field 'datarecord' of json file, the return is: return code 200 and the changed record XXX in marc-in-json format
10) Go into intranet and do a search. Select two or (better) more record.
11) Merge them; merge must be a success.
12) Test with prove -v t/db_dependent/Koha/Biblio.t
13) Test with prove -v t/db_dependent/api/v1/biblios.t
To test with curl the step 8 you can customize the json file attached in bugzilla.
The marc-in-json record inside follows the MAR21 standard
Sponsored-by: Technische Hochschule Wildau
Co-authored-by: Zeno Tajoli <ztajoli@gmail.com>
Co-authored-by: Thomas Klausner <domm@plix.at>
Co-authored-by: Mark Hofstetter <<mark@hofstetter.at>>
Signed-off-by: Jan Kissig <jkissig@th-wildau.de>
Bug 33036: Update of test number.
File ../biblios.t was update with a new subutest.
So we need this update to have a 'OK' after test running.
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
(cherry picked from commit c60a6d8cd9
)
Signed-off-by: Fridolin Somers <fridolin.somers@biblibre.com>
2162 lines
66 KiB
Perl
Executable file
2162 lines
66 KiB
Perl
Executable file
#!/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 <http://www.gnu.org/licenses>.
|
||
|
||
use Modern::Perl;
|
||
|
||
use utf8;
|
||
use Encode;
|
||
|
||
use Test::More tests => 15;
|
||
use Test::MockModule;
|
||
use Test::Mojo;
|
||
use Test::Warn;
|
||
|
||
use t::lib::Mocks;
|
||
use t::lib::TestBuilder;
|
||
|
||
use Mojo::JSON qw(encode_json);
|
||
|
||
use C4::Auth;
|
||
use C4::Circulation qw( AddIssue AddReturn );
|
||
|
||
use Koha::Biblios;
|
||
use Koha::Database;
|
||
use Koha::DateUtils qw (dt_from_string);
|
||
use Koha::Checkouts;
|
||
use Koha::Old::Checkouts;
|
||
|
||
use Mojo::JSON qw(encode_json);
|
||
|
||
my $schema = Koha::Database->new->schema;
|
||
my $builder = t::lib::TestBuilder->new;
|
||
|
||
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
|
||
|
||
my $t = Test::Mojo->new('Koha::REST::V1');
|
||
|
||
subtest 'get() tests' => sub {
|
||
|
||
plan tests => 22;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 }
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
$patron->discard_changes;
|
||
my $userid = $patron->userid;
|
||
|
||
my $biblio = $builder->build_sample_biblio({
|
||
title => 'The unbearable lightness of being',
|
||
author => 'Milan Kundera'
|
||
});
|
||
$t->get_ok("//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber)
|
||
->status_is(403);
|
||
|
||
$patron->flags(4)->store;
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/weird+format' } )
|
||
->status_is(400);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/json' } )
|
||
->status_is(200)
|
||
->json_is( '/title', 'The unbearable lightness of being' )
|
||
->json_is( '/author', 'Milan Kundera' );
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marcxml+xml' } )
|
||
->status_is(200);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marc-in-json' } )
|
||
->status_is(200);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marc' } )
|
||
->status_is(200);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'text/plain' } )
|
||
->status_is(200)
|
||
->content_is($biblio->metadata->record->as_formatted);
|
||
|
||
$biblio->delete;
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marc' } )
|
||
->status_is(404)
|
||
->json_is( '/error', 'Object not found.' );
|
||
|
||
subtest 'marc-in-json encoding tests' => sub {
|
||
|
||
plan tests => 3;
|
||
|
||
my $title_with_diacritics = "L'insoutenable légèreté de l'être";
|
||
|
||
my $biblio = $builder->build_sample_biblio(
|
||
{
|
||
title => $title_with_diacritics,
|
||
author => "Milan Kundera"
|
||
}
|
||
);
|
||
|
||
my $result = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marc-in-json' } )
|
||
->status_is(200)->tx->res->body;
|
||
|
||
my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
|
||
|
||
like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
|
||
};
|
||
|
||
subtest 'marcxml encoding tests' => sub {
|
||
plan tests => 3;
|
||
|
||
my $marcflavour = C4::Context->preference('marcflavour');
|
||
t::lib::Mocks::mock_preference('marcflavour', 'UNIMARC');
|
||
|
||
|
||
my $title_with_diacritics = "L'insoutenable légèreté de l'être";
|
||
|
||
my $biblio = $builder->build_sample_biblio(
|
||
{
|
||
title => $title_with_diacritics,
|
||
author => "Milan Kundera"
|
||
}
|
||
);
|
||
|
||
my $record = $biblio->metadata->record;
|
||
$record->leader(' nam 3 4500');
|
||
$biblio->metadata->metadata($record->as_xml_record('UNIMARC'));
|
||
$biblio->metadata->store;
|
||
|
||
my $result = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marcxml+xml' } )
|
||
->status_is(200)->tx->res->body;
|
||
|
||
my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
|
||
|
||
like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
|
||
t::lib::Mocks::mock_preference('marcflavour', $marcflavour);
|
||
};
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'get_items() tests' => sub {
|
||
|
||
plan tests => 11;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 }
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
$patron->discard_changes;
|
||
my $userid = $patron->userid;
|
||
|
||
my $biblio = $builder->build_sample_biblio();
|
||
$t->get_ok("//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items")
|
||
->status_is(403);
|
||
|
||
$patron->flags(4)->store;
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items")
|
||
->status_is(200)
|
||
->json_is( '' => [], 'No items on the biblio' );
|
||
|
||
my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
|
||
my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items")
|
||
->status_is(200)
|
||
->json_is( '' => [ $item_1->to_api, $item_2->to_api ], 'The items are returned' );
|
||
|
||
$t->get_ok(
|
||
"//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items" => { "x-koha-embed" => "+strings" } )
|
||
->status_is(200)
|
||
->json_has( '/0/_strings/home_library_id/str' => $item_1->holding_branch->branchname, '_strings are embedded' );
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'delete() tests' => sub {
|
||
|
||
plan tests => 9;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 } # no permissions
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
my $userid = $patron->userid;
|
||
|
||
my $item = $builder->build_sample_item();
|
||
my $biblio_id = $item->biblionumber;
|
||
|
||
$t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
|
||
->status_is(403, 'Not enough permissions makes it return the right code');
|
||
|
||
# Add permissions
|
||
$builder->build(
|
||
{
|
||
source => 'UserPermission',
|
||
value => {
|
||
borrowernumber => $patron->borrowernumber,
|
||
module_bit => 9,
|
||
code => 'edit_catalogue'
|
||
}
|
||
}
|
||
);
|
||
|
||
|
||
# Bibs with items cannot be deleted
|
||
$t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
|
||
->status_is(409);
|
||
|
||
$item->delete();
|
||
|
||
# Bibs with no items can be deleted
|
||
$t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
|
||
->status_is(204, 'SWAGGER3.2.4')
|
||
->content_is('', 'SWAGGER3.3.4');
|
||
|
||
$t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
|
||
->status_is(404);
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'get_public() tests' => sub {
|
||
|
||
plan tests => 25;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $category = $builder->build_object({ class => 'Koha::Patron::Categories' });
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => {
|
||
flags => undef, # opac user
|
||
categorycode => $category->categorycode
|
||
}
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
$patron->discard_changes;
|
||
my $userid = $patron->userid;
|
||
|
||
my $biblio = $builder->build_sample_biblio({
|
||
title => 'The unbearable lightness of being',
|
||
author => 'Milan Kundera'
|
||
});
|
||
|
||
# Make sure author in shown in the OPAC
|
||
my $subfields = Koha::MarcSubfieldStructures->search({ tagfield => '100' });
|
||
while ( my $subfield = $subfields->next ) {
|
||
$subfield->set({ hidden => -1 })->store;
|
||
}
|
||
Koha::Caches->get_instance()->flush_all;
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/weird+format' } )
|
||
->status_is(400);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'text/plain' } )
|
||
->status_is(200)
|
||
->content_like( qr{100\s+_aMilan Kundera} )
|
||
->content_like( qr{245\s+_aThe unbearable lightness of being} );
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marcxml+xml' } )
|
||
->status_is(200);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marc-in-json' } )
|
||
->status_is(200);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marc' } )
|
||
->status_is(200);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'text/plain' } )
|
||
->status_is(200)
|
||
->content_is($biblio->metadata->record->as_formatted);
|
||
|
||
subtest 'anonymous access' => sub {
|
||
plan tests => 9;
|
||
|
||
$t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marcxml+xml' } )
|
||
->status_is(200);
|
||
|
||
$t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marc-in-json' } )
|
||
->status_is(200);
|
||
|
||
$t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marc' } )
|
||
->status_is(200);
|
||
|
||
$t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'text/plain' } )
|
||
->status_is(200)
|
||
->content_is($biblio->metadata->record->as_formatted);
|
||
};
|
||
|
||
subtest 'marc-in-json encoding tests' => sub {
|
||
|
||
plan tests => 3;
|
||
|
||
my $title_with_diacritics = "L'insoutenable légèreté de l'être";
|
||
|
||
my $biblio = $builder->build_sample_biblio(
|
||
{
|
||
title => $title_with_diacritics,
|
||
author => "Milan Kundera"
|
||
}
|
||
);
|
||
|
||
my $result = $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marc-in-json' } )
|
||
->status_is(200)->tx->res->body;
|
||
|
||
my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
|
||
|
||
like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
|
||
};
|
||
|
||
# Hide author in OPAC
|
||
$subfields = Koha::MarcSubfieldStructures->search({ tagfield => '100' });
|
||
while ( my $subfield = $subfields->next ) {
|
||
$subfield->set({ hidden => 1 })->store;
|
||
}
|
||
|
||
Koha::Caches->get_instance()->flush_all;
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'text/plain' } )
|
||
->status_is(200)
|
||
->content_unlike( qr{100\s+_aMilan Kundera} )
|
||
->content_like( qr{245\s+_aThe unbearable lightness of being} );
|
||
|
||
subtest 'hidden_in_opac tests' => sub {
|
||
|
||
plan tests => 6;
|
||
|
||
my $biblio_hidden_in_opac = 1;
|
||
|
||
my $biblio_class = Test::MockModule->new('Koha::Biblio');
|
||
# force biblio hidden in OPAC
|
||
$biblio_class->mock( 'hidden_in_opac', sub { return $biblio_hidden_in_opac; } );
|
||
|
||
$t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'text/plain' } )
|
||
->status_is(404, 'hidden_in_opac + anonymous => hidden');
|
||
|
||
my $category_override_hidden_items = 0;
|
||
my $category_class = Test::MockModule->new('Koha::Patron::Category');
|
||
$category_class->mock( 'override_hidden_items', sub { return $category_override_hidden_items; } );
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'text/plain' } )
|
||
->status_is(404, "hidden_in_opac + patron whose category doesn't override => hidden");
|
||
|
||
# Make the category override
|
||
$category_override_hidden_items = 1;
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'text/plain' } )
|
||
->status_is(200, "hidden_in_opac + patron whose category that overrides => displayed");
|
||
|
||
t::lib::Mocks::mock_preference('OpacHiddenItems');
|
||
};
|
||
|
||
$biblio->delete;
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
|
||
=> { Accept => 'application/marc' } )
|
||
->status_is(404)
|
||
->json_is( '/error', 'Object not found.' );
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'pickup_locations() tests' => sub {
|
||
|
||
plan tests => 16;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 0 );
|
||
|
||
# Small trick to ease testing
|
||
Koha::Libraries->search->update({ pickup_location => 0 });
|
||
|
||
my $library_1 = $builder->build_object({ class => 'Koha::Libraries', value => { marcorgcode => 'A', pickup_location => 1 } });
|
||
my $library_2 = $builder->build_object({ class => 'Koha::Libraries', value => { marcorgcode => 'B', pickup_location => 1 } });
|
||
my $library_3 = $builder->build_object({ class => 'Koha::Libraries', value => { marcorgcode => 'C', pickup_location => 1 } });
|
||
|
||
my $library_1_api = $library_1->to_api();
|
||
my $library_2_api = $library_2->to_api();
|
||
my $library_3_api = $library_3->to_api();
|
||
|
||
$library_1_api->{needs_override} = Mojo::JSON->false;
|
||
$library_2_api->{needs_override} = Mojo::JSON->false;
|
||
$library_3_api->{needs_override} = Mojo::JSON->true;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { userid => 'tomasito', flags => 0 }
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
my $userid = $patron->userid;
|
||
$builder->build(
|
||
{
|
||
source => 'UserPermission',
|
||
value => {
|
||
borrowernumber => $patron->borrowernumber,
|
||
module_bit => 6,
|
||
code => 'place_holds',
|
||
},
|
||
}
|
||
);
|
||
|
||
my $biblio_class = Test::MockModule->new('Koha::Biblio');
|
||
$biblio_class->mock(
|
||
'pickup_locations',
|
||
sub {
|
||
my ( $self, $params ) = @_;
|
||
my $mock_patron = $params->{patron};
|
||
is( $mock_patron->borrowernumber,
|
||
$patron->borrowernumber, 'Patron passed correctly' );
|
||
return Koha::Libraries->search(
|
||
{
|
||
branchcode => {
|
||
'-in' => [
|
||
$library_1->branchcode,
|
||
$library_2->branchcode
|
||
]
|
||
}
|
||
},
|
||
{ # we make sure no surprises in the order of the result
|
||
order_by => { '-asc' => 'marcorgcode' }
|
||
}
|
||
);
|
||
}
|
||
);
|
||
|
||
my $biblio = $builder->build_sample_biblio;
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/"
|
||
. $biblio->id
|
||
. "/pickup_locations?patron_id=" . $patron->id )
|
||
->json_is( [ $library_1_api, $library_2_api ] );
|
||
|
||
# filtering works!
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/"
|
||
. $biblio->id
|
||
. '/pickup_locations?'
|
||
. 'patron_id=' . $patron->id . '&q={"marc_org_code": { "-like": "A%" }}' )
|
||
->json_is( [ $library_1_api ] );
|
||
|
||
t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 1 );
|
||
|
||
my $library_4 = $builder->build_object({ class => 'Koha::Libraries', value => { pickup_location => 0, marcorgcode => 'X' } });
|
||
my $library_5 = $builder->build_object({ class => 'Koha::Libraries', value => { pickup_location => 1, marcorgcode => 'Y' } });
|
||
|
||
my $library_5_api = $library_5->to_api();
|
||
$library_5_api->{needs_override} = Mojo::JSON->true;
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/"
|
||
. $biblio->id
|
||
. "/pickup_locations?"
|
||
. "patron_id=" . $patron->id . "&_order_by=marc_org_code" )
|
||
->json_is( [ $library_1_api, $library_2_api, $library_3_api, $library_5_api ] );
|
||
|
||
subtest 'Pagination and AllowHoldPolicyOverride tests' => sub {
|
||
|
||
plan tests => 27;
|
||
|
||
t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 1 );
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->id . "/pickup_locations?" . "patron_id=" . $patron->id . "&_order_by=marc_org_code" . "&_per_page=1" )
|
||
->json_is( [$library_1_api] )
|
||
->header_is( 'X-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
|
||
->header_is( 'X-Base-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
|
||
->header_unlike( 'Link', qr|rel="prev"| )
|
||
->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="next"# )
|
||
->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
|
||
->header_like( 'Link', qr#(_per_page=1.*\&_page=4.*|_page=4.*\&_per_page=1).*>\; rel="last"# );
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/"
|
||
. $biblio->id
|
||
. "/pickup_locations?"
|
||
. "patron_id="
|
||
. $patron->id
|
||
. "&_order_by=marc_org_code"
|
||
. "&_per_page=1&_page=3" ) # force the needs_override=1 check
|
||
->json_is( [$library_3_api] )
|
||
->header_is( 'X-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
|
||
->header_is( 'X-Base-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
|
||
->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="prev"# )
|
||
->header_like( 'Link', qr#(_per_page=1.*\&_page=4.*|_page=4.*\&_per_page=1.*)>\; rel="next"# )
|
||
->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
|
||
->header_like( 'Link', qr#(_per_page=1.*\&_page=4.*|_page=4.*\&_per_page=1).*>\; rel="last"# );
|
||
|
||
t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 0 );
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->id . "/pickup_locations?" . "patron_id=" . $patron->id . "&_order_by=marc_org_code" . "&_per_page=1" )
|
||
->json_is( [$library_1_api] )
|
||
->header_is( 'X-Total-Count', '2' )
|
||
->header_is( 'X-Base-Total-Count', '2' )
|
||
->header_unlike( 'Link', qr|rel="prev"| )
|
||
->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="next"# )
|
||
->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
|
||
->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1).*>\; rel="last"# );
|
||
};
|
||
|
||
my $deleted_patron = $builder->build_object({ class => 'Koha::Patrons' });
|
||
my $deleted_patron_id = $deleted_patron->id;
|
||
$deleted_patron->delete;
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/"
|
||
. $biblio->id
|
||
. "/pickup_locations?"
|
||
. "patron_id=" . $deleted_patron_id )
|
||
->status_is( 400 )
|
||
->json_is( '/error' => 'Patron not found' );
|
||
|
||
$biblio->delete;
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/"
|
||
. $biblio->id
|
||
. "/pickup_locations?"
|
||
. "patron_id=" . $patron->id )
|
||
->status_is( 404 )
|
||
->json_is( '/error' => 'Biblio not found' );
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'get_items_public() tests' => sub {
|
||
|
||
plan tests => 15;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $override_hidden_items = 0;
|
||
|
||
my $mocked_category = Test::MockModule->new('Koha::Patron::Category');
|
||
$mocked_category->mock(
|
||
'override_hidden_items',
|
||
sub {
|
||
return $override_hidden_items;
|
||
}
|
||
);
|
||
|
||
my $rules = undef;
|
||
|
||
my $mocked_context = Test::MockModule->new('C4::Context');
|
||
$mocked_context->mock(
|
||
'yaml_preference',
|
||
sub {
|
||
return $rules;
|
||
}
|
||
);
|
||
|
||
my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
$patron->discard_changes;
|
||
my $userid = $patron->userid;
|
||
|
||
my $biblio = $builder->build_sample_biblio();
|
||
|
||
$t->get_ok(
|
||
"//$userid:$password@/api/v1/public/biblios/" . $biblio->id . "/items" )
|
||
->status_is(200)->json_is( '' => [], 'No items on the biblio' );
|
||
|
||
my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->id } );
|
||
my $item_2 = $builder->build_sample_item(
|
||
{ biblionumber => $biblio->id, withdrawn => 1 } );
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/"
|
||
. $biblio->biblionumber
|
||
. "/items" )->status_is(200)->json_is(
|
||
'' => [
|
||
$item_1->to_api( { public => 1 } ),
|
||
$item_2->to_api( { public => 1 } )
|
||
],
|
||
'The items are returned'
|
||
);
|
||
|
||
$rules = { withdrawn => ['1'] };
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/"
|
||
. $biblio->biblionumber
|
||
. "/items" )->status_is(200)->json_is(
|
||
'' => [ $item_1->to_api( { public => 1 } ) ],
|
||
'The items are returned, hidden one is not returned'
|
||
);
|
||
|
||
$t->get_ok( "/api/v1/public/biblios/"
|
||
. $biblio->biblionumber
|
||
. "/items" )->status_is(200)->json_is(
|
||
'' => [ $item_1->to_api( { public => 1 } ) ],
|
||
'Anonymous user, items are returned, hidden one is not returned'
|
||
);
|
||
|
||
|
||
$override_hidden_items = 1;
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/public/biblios/"
|
||
. $biblio->biblionumber
|
||
. "/items" )->status_is(200)->json_is(
|
||
'' => [
|
||
$item_1->to_api( { public => 1 } ),
|
||
$item_2->to_api( { public => 1 } )
|
||
],
|
||
'The items are returned, the patron category has an override'
|
||
);
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'get_bookings() tests' => sub {
|
||
|
||
plan tests => 8;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $librarian = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 } # no additional permissions
|
||
}
|
||
);
|
||
$builder->build(
|
||
{
|
||
source => 'UserPermission',
|
||
value => {
|
||
borrowernumber => $librarian->borrowernumber,
|
||
module_bit => 1,
|
||
code => 'manage_bookings',
|
||
},
|
||
}
|
||
);
|
||
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 $biblio = $builder->build_sample_biblio();
|
||
my $item1 = $builder->build_sample_item( { bookable => 1, biblionumber => $biblio->id } );
|
||
my $item2 = $builder->build_sample_item( { bookable => 1, biblionumber => $biblio->id } );
|
||
|
||
$t->get_ok( "//$unauth_userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )->status_is(403);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )->status_is(200)
|
||
->json_is( '' => [], 'No bookings on the biblio' );
|
||
|
||
# One booking
|
||
my $start_0 = dt_from_string->subtract( days => 2 )->truncate( to => 'day' );
|
||
my $end_0 = dt_from_string->add( days => 4 )->truncate( to => 'day' );
|
||
my $booking_0 = $builder->build_object(
|
||
{
|
||
class => 'Koha::Bookings',
|
||
value => {
|
||
biblio_id => $biblio->id,
|
||
item_id => $item1->id,
|
||
start_date => $start_0,
|
||
end_date => $end_0
|
||
}
|
||
}
|
||
);
|
||
|
||
my $ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/bookings" )->status_is(200)
|
||
->tx->res->json;
|
||
|
||
is_deeply( $ret, [ $booking_0->to_api ] );
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'get_checkouts() tests' => sub {
|
||
|
||
plan tests => 17;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 }
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
$patron->discard_changes;
|
||
my $userid = $patron->userid;
|
||
|
||
my $biblio = $builder->build_sample_biblio();
|
||
$t->get_ok("//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts")
|
||
->status_is(403);
|
||
|
||
$builder->build(
|
||
{
|
||
source => 'UserPermission',
|
||
value => {
|
||
borrowernumber => $patron->borrowernumber,
|
||
module_bit => 1,
|
||
code => 'circulate_remaining_permissions',
|
||
},
|
||
}
|
||
);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts" )
|
||
->status_is( 200, 'circulate_remaining_permissions allows checkouts access' )
|
||
->json_is( '' => [], 'No checkouts on the biblio' );
|
||
|
||
my $bookings_librarian = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 } # no additional permissions
|
||
}
|
||
);
|
||
$builder->build(
|
||
{
|
||
source => 'UserPermission',
|
||
value => {
|
||
borrowernumber => $bookings_librarian->borrowernumber,
|
||
module_bit => 1,
|
||
code => 'manage_bookings',
|
||
},
|
||
}
|
||
);
|
||
$bookings_librarian->set_password( { password => $password, skip_validation => 1 } );
|
||
my $bookings_userid = $bookings_librarian->userid;
|
||
|
||
$t->get_ok( "//$bookings_userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts" )
|
||
->status_is( 200, 'manage_bookings allows checkouts access' )
|
||
->json_is( '' => [], 'No checkouts on the biblio' );
|
||
|
||
my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
|
||
my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
|
||
|
||
AddIssue( $patron, $item_1->barcode );
|
||
AddIssue( $patron, $item_2->barcode );
|
||
|
||
my $ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts")
|
||
->status_is(200)
|
||
->tx->res->json;
|
||
|
||
my $checkout_1 = Koha::Checkouts->find({ itemnumber => $item_1->id });
|
||
my $checkout_2 = Koha::Checkouts->find({ itemnumber => $item_2->id });
|
||
|
||
is_deeply( $ret, [ $checkout_1->to_api, $checkout_2->to_api ] );
|
||
|
||
AddReturn( $item_1->barcode );
|
||
|
||
$ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts")
|
||
->status_is(200)
|
||
->tx->res->json;
|
||
|
||
is_deeply( $ret, [ $checkout_2->to_api ] );
|
||
|
||
$ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts?checked_in=1")
|
||
->status_is(200)
|
||
->tx->res->json;
|
||
|
||
my $old_checkout_1 = Koha::Old::Checkouts->find( $checkout_1->id );
|
||
|
||
is_deeply( $ret, [ $old_checkout_1->to_api ] );
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'set_rating() tests' => sub {
|
||
|
||
plan tests => 12;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 }
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
$patron->discard_changes;
|
||
my $userid = $patron->userid;
|
||
|
||
my $biblio = $builder->build_sample_biblio();
|
||
$t->post_ok("/api/v1/public/biblios/" . $biblio->biblionumber . "/ratings" => json => { rating => 3 })
|
||
->status_is(403);
|
||
|
||
$t->post_ok("//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/ratings" => json => { rating => 3 })
|
||
->status_is(200)
|
||
->json_is( '/rating', '3' )
|
||
->json_is( '/average', '3' )
|
||
->json_is( '/count', '1' );
|
||
|
||
$t->post_ok("//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/ratings" => json => { rating => undef })
|
||
->status_is(200)
|
||
->json_is( '/rating', undef )
|
||
->json_is( '/average', '0' )
|
||
->json_is( '/count', '0' );
|
||
|
||
$schema->storage->txn_rollback;
|
||
|
||
};
|
||
|
||
|
||
subtest 'post() tests' => sub {
|
||
|
||
plan tests => 13;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 } # no permissions
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
my $userid = $patron->userid;
|
||
|
||
my $frameworkcode = 'BKS';
|
||
my $marcxml = q|<?xml version="1.0" encoding="UTF-8"?>
|
||
<record
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
|
||
xmlns="http://www.loc.gov/MARC21/slim">
|
||
|
||
<leader>01102pam a2200289 a 7500</leader>
|
||
<controlfield tag="001">2504398</controlfield>
|
||
<controlfield tag="005">20200421093816.0</controlfield>
|
||
<controlfield tag="008">920610s1993 caub s001 0 eng </controlfield>
|
||
<datafield tag="010" ind1=" " ind2=" ">
|
||
<subfield code="a"> 92021731 </subfield>
|
||
</datafield>
|
||
<datafield tag="020" ind1=" " ind2=" ">
|
||
<subfield code="a">05200784381 (Test marcxml)</subfield>
|
||
</datafield>
|
||
<datafield tag="020" ind1=" " ind2=" ">
|
||
<subfield code="a">05200784461 (Test marcxml)</subfield>
|
||
</datafield>
|
||
<datafield tag="040" ind1=" " ind2=" ">
|
||
<subfield code="a">DLC</subfield>
|
||
<subfield code="c">DLC</subfield>
|
||
<subfield code="d">DLC</subfield>
|
||
</datafield>
|
||
<datafield tag="041" ind1="0" ind2=" ">
|
||
<subfield code="a">enggrc</subfield>
|
||
</datafield>
|
||
<datafield tag="050" ind1="0" ind2="0">
|
||
<subfield code="a">PA522</subfield>
|
||
<subfield code="b">.M38 1993</subfield>
|
||
</datafield>
|
||
<datafield tag="082" ind1="0" ind2="0">
|
||
<subfield code="a">480</subfield>
|
||
<subfield code="2">20</subfield>
|
||
</datafield>
|
||
<datafield tag="100" ind1="1" ind2=" ">
|
||
<subfield code="a">Mastronarde, Donald J.</subfield>
|
||
<subfield code="9">389</subfield>
|
||
</datafield>
|
||
<datafield tag="245" ind1="1" ind2="0">
|
||
<subfield code="a">Introduction to Attic Greek (Using marcxml) /</subfield>
|
||
<subfield code="c">Donald J. Mastronarde.</subfield>
|
||
</datafield>
|
||
<datafield tag="260" ind1=" " ind2=" ">
|
||
<subfield code="a">Berkeley :</subfield>
|
||
<subfield code="b">University of California Press,</subfield>
|
||
<subfield code="c">c1993.</subfield>
|
||
</datafield>
|
||
<datafield tag="300" ind1=" " ind2=" ">
|
||
<subfield code="a">ix, 425 p. :</subfield>
|
||
<subfield code="b">maps ;</subfield>
|
||
<subfield code="c">26 cm.</subfield>
|
||
</datafield>
|
||
<datafield tag="500" ind1=" " ind2=" ">
|
||
<subfield code="a">Includes index.</subfield>
|
||
</datafield>
|
||
<datafield tag="650" ind1=" " ind2="0">
|
||
<subfield code="a">Attic Greek dialect</subfield>
|
||
<subfield code="9">7</subfield>
|
||
</datafield>
|
||
<datafield tag="856" ind1="4" ind2="2">
|
||
<subfield code="3">Contributor biographical information</subfield>
|
||
<subfield code="u">http://www.loc.gov/catdir/bios/ucal051/92021731.html</subfield>
|
||
</datafield>
|
||
<datafield tag="856" ind1="4" ind2="2">
|
||
<subfield code="3">Publisher description</subfield>
|
||
<subfield code="u">http://www.loc.gov/catdir/description/ucal041/92021731.html</subfield>
|
||
</datafield>
|
||
<datafield tag="906" ind1=" " ind2=" ">
|
||
<subfield code="a">7</subfield>
|
||
<subfield code="b">cbc</subfield>
|
||
<subfield code="c">orignew</subfield>
|
||
<subfield code="d">1</subfield>
|
||
<subfield code="e">ocip</subfield>
|
||
<subfield code="f">19</subfield>
|
||
<subfield code="g">y-gencatlg</subfield>
|
||
</datafield>
|
||
<datafield tag="942" ind1=" " ind2=" ">
|
||
<subfield code="2">ddc</subfield>
|
||
<subfield code="c">BK</subfield>
|
||
</datafield>
|
||
<datafield tag="955" ind1=" " ind2=" ">
|
||
<subfield code="a">pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93</subfield>
|
||
</datafield>
|
||
<datafield tag="999" ind1=" " ind2=" ">
|
||
<subfield code="c">3</subfield>
|
||
<subfield code="d">3</subfield>
|
||
</datafield>
|
||
</record>|;
|
||
|
||
my $mij = q|{
|
||
"fields": [
|
||
{
|
||
"001": "2504398"
|
||
},
|
||
{
|
||
"005": "20200421093816.0"
|
||
},
|
||
{
|
||
"008": "920610s1993 caub s001 0 eng "
|
||
},
|
||
{
|
||
"010": {
|
||
"ind1": " ",
|
||
"subfields": [
|
||
{
|
||
"a": " 92021731 "
|
||
}
|
||
],
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"020": {
|
||
"subfields": [
|
||
{
|
||
"a": "05200784382 (Test mij)"
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"020": {
|
||
"subfields": [
|
||
{
|
||
"a": "05200784462 (Test mij)"
|
||
}
|
||
],
|
||
"ind1": " ",
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"040": {
|
||
"subfields": [
|
||
{
|
||
"a": "DLC"
|
||
},
|
||
{
|
||
"c": "DLC"
|
||
},
|
||
{
|
||
"d": "DLC"
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"041": {
|
||
"ind2": " ",
|
||
"subfields": [
|
||
{
|
||
"a": "enggrc"
|
||
}
|
||
],
|
||
"ind1": "0"
|
||
}
|
||
},
|
||
{
|
||
"050": {
|
||
"subfields": [
|
||
{
|
||
"a": "PA522"
|
||
},
|
||
{
|
||
"b": ".M38 1993"
|
||
}
|
||
],
|
||
"ind1": "0",
|
||
"ind2": "0"
|
||
}
|
||
},
|
||
{
|
||
"082": {
|
||
"subfields": [
|
||
{
|
||
"a": "480"
|
||
},
|
||
{
|
||
"2": "20"
|
||
}
|
||
],
|
||
"ind2": "0",
|
||
"ind1": "0"
|
||
}
|
||
},
|
||
{
|
||
"100": {
|
||
"ind2": " ",
|
||
"subfields": [
|
||
{
|
||
"a": "Mastronarde, Donald J."
|
||
},
|
||
{
|
||
"9": "389"
|
||
}
|
||
],
|
||
"ind1": "1"
|
||
}
|
||
},
|
||
{
|
||
"245": {
|
||
"ind1": "1",
|
||
"subfields": [
|
||
{
|
||
"a": "Introduction to Attic Greek (Using mij) /"
|
||
},
|
||
{
|
||
"c": "Donald J. Mastronarde."
|
||
}
|
||
],
|
||
"ind2": "0"
|
||
}
|
||
},
|
||
{
|
||
"260": {
|
||
"subfields": [
|
||
{
|
||
"a": "Berkeley :"
|
||
},
|
||
{
|
||
"b": "University of California Press,"
|
||
},
|
||
{
|
||
"c": "c1993."
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"300": {
|
||
"ind1": " ",
|
||
"subfields": [
|
||
{
|
||
"a": "ix, 425 p. :"
|
||
},
|
||
{
|
||
"b": "maps ;"
|
||
},
|
||
{
|
||
"c": "26 cm."
|
||
}
|
||
],
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"500": {
|
||
"subfields": [
|
||
{
|
||
"a": "Includes index."
|
||
}
|
||
],
|
||
"ind1": " ",
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"650": {
|
||
"subfields": [
|
||
{
|
||
"a": "Attic Greek dialect"
|
||
},
|
||
{
|
||
"9": "7"
|
||
}
|
||
],
|
||
"ind2": "0",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"856": {
|
||
"subfields": [
|
||
{
|
||
"3": "Contributor biographical information"
|
||
},
|
||
{
|
||
"u": "http://www.loc.gov/catdir/bios/ucal051/92021731.html"
|
||
}
|
||
],
|
||
"ind2": "2",
|
||
"ind1": "4"
|
||
}
|
||
},
|
||
{
|
||
"856": {
|
||
"ind1": "4",
|
||
"subfields": [
|
||
{
|
||
"3": "Publisher description"
|
||
},
|
||
{
|
||
"u": "http://www.loc.gov/catdir/description/ucal041/92021731.html"
|
||
}
|
||
],
|
||
"ind2": "2"
|
||
}
|
||
},
|
||
{
|
||
"906": {
|
||
"subfields": [
|
||
{
|
||
"a": "7"
|
||
},
|
||
{
|
||
"b": "cbc"
|
||
},
|
||
{
|
||
"c": "orignew"
|
||
},
|
||
{
|
||
"d": "1"
|
||
},
|
||
{
|
||
"e": "ocip"
|
||
},
|
||
{
|
||
"f": "19"
|
||
},
|
||
{
|
||
"g": "y-gencatlg"
|
||
}
|
||
],
|
||
"ind1": " ",
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"942": {
|
||
"subfields": [
|
||
{
|
||
"2": "ddc"
|
||
},
|
||
{
|
||
"c": "BK"
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"955": {
|
||
"subfields": [
|
||
{
|
||
"a": "pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93"
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"999": {
|
||
"subfields": [
|
||
{
|
||
"c": "3"
|
||
},
|
||
{
|
||
"d": "3"
|
||
}
|
||
],
|
||
"ind1": " ",
|
||
"ind2": " "
|
||
}
|
||
}
|
||
],
|
||
"leader": "01102pam a2200289 a 8500"
|
||
}|;
|
||
my $marc = q|01102pam a2200289 a 9500001000800000005001700008008004100025010001700066020002800083020003500111040001800146041001100164050002100175082001200196100003200208245005800240260005600298300003300354500002000387650002700407856009500434856008700529906004500616942001200661955013000673999000900803250439820200421093816.0920610s1993 caub s001 0 eng a 92021731 a05200784383 (Test usmarc) a05200784463 (Test usmarc) aDLCcDLCdDLC0 aenggrc00aPA522b.M38 199300a4802201 aMastronarde, Donald J.938910aIntroduction to Attic Greek (Using usmarc) /cDonald J. Mastronarde. aBerkeley :bUniversity of California Press,cc1993. aix, 425 p. :bmaps ;c26 cm. aIncludes index. 0aAttic Greek dialect97423Contributor biographical informationuhttp://www.loc.gov/catdir/bios/ucal051/92021731.html423Publisher descriptionuhttp://www.loc.gov/catdir/description/ucal041/92021731.html a7bcbccorignewd1eocipf19gy-gencatlg 2ddccBK apc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93 c3d3|;
|
||
|
||
$t->post_ok("//$userid:$password@/api/v1/biblios")
|
||
->status_is(403, 'Not enough permissions makes it return the right code');
|
||
|
||
# Add permissions
|
||
$builder->build(
|
||
{
|
||
source => 'UserPermission',
|
||
value => {
|
||
borrowernumber => $patron->borrowernumber,
|
||
module_bit => 9,
|
||
code => 'edit_catalogue'
|
||
}
|
||
}
|
||
);
|
||
|
||
$t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode, "x-record-schema" => 'INVALID'})
|
||
->status_is(400, 'Invalid header x-record-schema');
|
||
|
||
$t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode} => $marcxml)
|
||
->status_is(200)
|
||
->json_has('/id');
|
||
|
||
$t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marc-in-json', 'x-framework-id' => $frameworkcode, 'x-confirm-not-duplicate' => 1} => $mij)
|
||
->status_is(200)
|
||
->json_has('/id');
|
||
|
||
$t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode} => $marc)
|
||
->status_is(200)
|
||
->json_has('/id');
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'put() tests' => sub {
|
||
|
||
plan tests => 14;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 } # no permissions
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
my $userid = $patron->userid;
|
||
|
||
my $frameworkcode = 'BKS';
|
||
my $biblio = $builder->build_sample_biblio({frameworkcode => $frameworkcode});
|
||
|
||
my $biblionumber = $biblio->biblionumber;
|
||
|
||
my $marcxml = q|<?xml version="1.0" encoding="UTF-8"?>
|
||
<record
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
|
||
xmlns="http://www.loc.gov/MARC21/slim">
|
||
|
||
<leader>01102pam a2200289 a 6500</leader>
|
||
<controlfield tag="001">2504398</controlfield>
|
||
<controlfield tag="005">20200421093816.0</controlfield>
|
||
<controlfield tag="008">920610s1993 caub s001 0 eng </controlfield>
|
||
<datafield tag="010" ind1=" " ind2=" ">
|
||
<subfield code="a"> 92021731 </subfield>
|
||
</datafield>
|
||
<datafield tag="020" ind1=" " ind2=" ">
|
||
<subfield code="a">05200784384 (Test json)</subfield>
|
||
</datafield>
|
||
<datafield tag="020" ind1=" " ind2=" ">
|
||
<subfield code="a">05200784464 (Test json)</subfield>
|
||
</datafield>
|
||
<datafield tag="040" ind1=" " ind2=" ">
|
||
<subfield code="a">DLC</subfield>
|
||
<subfield code="c">DLC</subfield>
|
||
<subfield code="d">DLC</subfield>
|
||
</datafield>
|
||
<datafield tag="041" ind1="0" ind2=" ">
|
||
<subfield code="a">enggrc</subfield>
|
||
</datafield>
|
||
<datafield tag="050" ind1="0" ind2="0">
|
||
<subfield code="a">PA522</subfield>
|
||
<subfield code="b">.M38 1993</subfield>
|
||
</datafield>
|
||
<datafield tag="082" ind1="0" ind2="0">
|
||
<subfield code="a">480</subfield>
|
||
<subfield code="2">20</subfield>
|
||
</datafield>
|
||
<datafield tag="100" ind1="1" ind2=" ">
|
||
<subfield code="a">Mastronarde, Donald J.</subfield>
|
||
<subfield code="9">389</subfield>
|
||
</datafield>
|
||
<datafield tag="245" ind1="1" ind2="0">
|
||
<subfield code="a">Introduction to Attic Greek (Using marcxml) /</subfield>
|
||
<subfield code="c">Donald J. Mastronarde.</subfield>
|
||
</datafield>
|
||
<datafield tag="260" ind1=" " ind2=" ">
|
||
<subfield code="a">Berkeley :</subfield>
|
||
<subfield code="b">University of California Press,</subfield>
|
||
<subfield code="c">c1993.</subfield>
|
||
</datafield>
|
||
<datafield tag="300" ind1=" " ind2=" ">
|
||
<subfield code="a">ix, 425 p. :</subfield>
|
||
<subfield code="b">maps ;</subfield>
|
||
<subfield code="c">26 cm.</subfield>
|
||
</datafield>
|
||
<datafield tag="500" ind1=" " ind2=" ">
|
||
<subfield code="a">Includes index.</subfield>
|
||
</datafield>
|
||
<datafield tag="650" ind1=" " ind2="0">
|
||
<subfield code="a">Attic Greek dialect</subfield>
|
||
<subfield code="9">7</subfield>
|
||
</datafield>
|
||
<datafield tag="856" ind1="4" ind2="2">
|
||
<subfield code="3">Contributor biographical information</subfield>
|
||
<subfield code="u">http://www.loc.gov/catdir/bios/ucal051/92021731.html</subfield>
|
||
</datafield>
|
||
<datafield tag="856" ind1="4" ind2="2">
|
||
<subfield code="3">Publisher description</subfield>
|
||
<subfield code="u">http://www.loc.gov/catdir/description/ucal041/92021731.html</subfield>
|
||
</datafield>
|
||
<datafield tag="906" ind1=" " ind2=" ">
|
||
<subfield code="a">7</subfield>
|
||
<subfield code="b">cbc</subfield>
|
||
<subfield code="c">orignew</subfield>
|
||
<subfield code="d">1</subfield>
|
||
<subfield code="e">ocip</subfield>
|
||
<subfield code="f">19</subfield>
|
||
<subfield code="g">y-gencatlg</subfield>
|
||
</datafield>
|
||
<datafield tag="942" ind1=" " ind2=" ">
|
||
<subfield code="2">ddc</subfield>
|
||
<subfield code="c">BK</subfield>
|
||
</datafield>
|
||
<datafield tag="955" ind1=" " ind2=" ">
|
||
<subfield code="a">pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93</subfield>
|
||
</datafield>
|
||
<datafield tag="999" ind1=" " ind2=" ">
|
||
<subfield code="c">3</subfield>
|
||
<subfield code="d">3</subfield>
|
||
</datafield>
|
||
</record>|;
|
||
|
||
my $mij = q|{
|
||
"fields": [
|
||
{
|
||
"001": "2504398"
|
||
},
|
||
{
|
||
"005": "20200421093816.0"
|
||
},
|
||
{
|
||
"008": "920610s1993 caub s001 0 eng "
|
||
},
|
||
{
|
||
"010": {
|
||
"ind1": " ",
|
||
"subfields": [
|
||
{
|
||
"a": " 92021731 "
|
||
}
|
||
],
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"020": {
|
||
"subfields": [
|
||
{
|
||
"a": "05200784382 (Test mij)"
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"020": {
|
||
"subfields": [
|
||
{
|
||
"a": "05200784462 (Test mij)"
|
||
}
|
||
],
|
||
"ind1": " ",
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"040": {
|
||
"subfields": [
|
||
{
|
||
"a": "DLC"
|
||
},
|
||
{
|
||
"c": "DLC"
|
||
},
|
||
{
|
||
"d": "DLC"
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"041": {
|
||
"ind2": " ",
|
||
"subfields": [
|
||
{
|
||
"a": "enggrc"
|
||
}
|
||
],
|
||
"ind1": "0"
|
||
}
|
||
},
|
||
{
|
||
"050": {
|
||
"subfields": [
|
||
{
|
||
"a": "PA522"
|
||
},
|
||
{
|
||
"b": ".M38 1993"
|
||
}
|
||
],
|
||
"ind1": "0",
|
||
"ind2": "0"
|
||
}
|
||
},
|
||
{
|
||
"082": {
|
||
"subfields": [
|
||
{
|
||
"a": "480"
|
||
},
|
||
{
|
||
"2": "20"
|
||
}
|
||
],
|
||
"ind2": "0",
|
||
"ind1": "0"
|
||
}
|
||
},
|
||
{
|
||
"100": {
|
||
"ind2": " ",
|
||
"subfields": [
|
||
{
|
||
"a": "Mastronarde, Donald J."
|
||
},
|
||
{
|
||
"9": "389"
|
||
}
|
||
],
|
||
"ind1": "1"
|
||
}
|
||
},
|
||
{
|
||
"245": {
|
||
"ind1": "1",
|
||
"subfields": [
|
||
{
|
||
"a": "Introduction to Attic Greek (Using mij) /"
|
||
},
|
||
{
|
||
"c": "Donald J. Mastronarde."
|
||
}
|
||
],
|
||
"ind2": "0"
|
||
}
|
||
},
|
||
{
|
||
"260": {
|
||
"subfields": [
|
||
{
|
||
"a": "Berkeley :"
|
||
},
|
||
{
|
||
"b": "University of California Press,"
|
||
},
|
||
{
|
||
"c": "c1993."
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"300": {
|
||
"ind1": " ",
|
||
"subfields": [
|
||
{
|
||
"a": "ix, 425 p. :"
|
||
},
|
||
{
|
||
"b": "maps ;"
|
||
},
|
||
{
|
||
"c": "26 cm."
|
||
}
|
||
],
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"500": {
|
||
"subfields": [
|
||
{
|
||
"a": "Includes index."
|
||
}
|
||
],
|
||
"ind1": " ",
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"650": {
|
||
"subfields": [
|
||
{
|
||
"a": "Attic Greek dialect"
|
||
},
|
||
{
|
||
"9": "7"
|
||
}
|
||
],
|
||
"ind2": "0",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"856": {
|
||
"subfields": [
|
||
{
|
||
"3": "Contributor biographical information"
|
||
},
|
||
{
|
||
"u": "http://www.loc.gov/catdir/bios/ucal051/92021731.html"
|
||
}
|
||
],
|
||
"ind2": "2",
|
||
"ind1": "4"
|
||
}
|
||
},
|
||
{
|
||
"856": {
|
||
"ind1": "4",
|
||
"subfields": [
|
||
{
|
||
"3": "Publisher description"
|
||
},
|
||
{
|
||
"u": "http://www.loc.gov/catdir/description/ucal041/92021731.html"
|
||
}
|
||
],
|
||
"ind2": "2"
|
||
}
|
||
},
|
||
{
|
||
"906": {
|
||
"subfields": [
|
||
{
|
||
"a": "7"
|
||
},
|
||
{
|
||
"b": "cbc"
|
||
},
|
||
{
|
||
"c": "orignew"
|
||
},
|
||
{
|
||
"d": "1"
|
||
},
|
||
{
|
||
"e": "ocip"
|
||
},
|
||
{
|
||
"f": "19"
|
||
},
|
||
{
|
||
"g": "y-gencatlg"
|
||
}
|
||
],
|
||
"ind1": " ",
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"942": {
|
||
"subfields": [
|
||
{
|
||
"2": "ddc"
|
||
},
|
||
{
|
||
"c": "BK"
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"955": {
|
||
"subfields": [
|
||
{
|
||
"a": "pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93"
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"999": {
|
||
"subfields": [
|
||
{
|
||
"c": "3"
|
||
},
|
||
{
|
||
"d": "3"
|
||
}
|
||
],
|
||
"ind1": " ",
|
||
"ind2": " "
|
||
}
|
||
}
|
||
],
|
||
"leader": "01102pam a2200289 a 8500"
|
||
}|;
|
||
my $marc = q|01116pam a2200289 a 4500001000800000005001700008008004100025010001700066020002800083020002800111040001800139041001100157050002100168082001200189100003200201245007500233260005600308300003300364500002000397650002700417856009500444856008700539906004500626942001200671955013000683999001300813250439820221223213433.0920610s1993 caub s001 0 eng a 92021731 a05200784384 (Test json) a05200784464 (Test json) aDLCcDLCdDLC0 aenggrc00aPA522b.M38 199300a4802201 aMastronarde, Donald J.938910aIntroduction to Attic Greek (Using usmarc) /cDonald J. Mastronarde. aBerkeley :bUniversity of California Press,cc1993. aix, 425 p. :bmaps ;c26 cm. aIncludes index. 0aAttic Greek dialect97423Contributor biographical informationuhttp://www.loc.gov/catdir/bios/ucal051/92021731.html423Publisher descriptionuhttp://www.loc.gov/catdir/description/ucal041/92021731.html a7bcbccorignewd1eocipf19gy-gencatlg 2ddccBK apc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93 c715d715|;
|
||
|
||
$t->put_ok("//$userid:$password@/api/v1/biblios/$biblionumber")
|
||
->status_is(403, 'Not enough permissions makes it return the right code');
|
||
|
||
# Add permissions
|
||
$builder->build(
|
||
{
|
||
source => 'UserPermission',
|
||
value => {
|
||
borrowernumber => $patron->borrowernumber,
|
||
module_bit => 9,
|
||
code => 'edit_catalogue'
|
||
}
|
||
}
|
||
);
|
||
|
||
$t->put_ok("//$userid:$password@/api/v1/biblios/$biblionumber" => {'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode} => $marcxml)
|
||
->status_is(200)
|
||
->json_has('/id');
|
||
|
||
$biblio = Koha::Biblios->find($biblionumber);
|
||
|
||
is($biblio->title, 'Introduction to Attic Greek (Using marcxml) /');
|
||
|
||
$t->put_ok("//$userid:$password@/api/v1/biblios/$biblionumber" => {'Content-Type' => 'application/marc-in-json', 'x-framework-id' => $frameworkcode} => $mij)
|
||
->status_is(200)
|
||
->json_has('/id');
|
||
|
||
$biblio = Koha::Biblios->find($biblionumber);
|
||
|
||
is($biblio->title, 'Introduction to Attic Greek (Using mij) /');
|
||
|
||
$t->put_ok("//$userid:$password@/api/v1/biblios/$biblionumber" => {'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode} => $marc)
|
||
->status_is(200)
|
||
->json_has('/id');
|
||
|
||
$biblio = Koha::Biblios->find($biblionumber);
|
||
|
||
is($biblio->title, 'Introduction to Attic Greek (Using usmarc) /');
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'list() tests' => sub {
|
||
|
||
plan tests => 17;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 }
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
$patron->discard_changes;
|
||
my $userid = $patron->userid;
|
||
|
||
t::lib::Mocks::mock_preference('marcflavour', 'UNIMARC');
|
||
|
||
my $title_with_diacritics = "L'insoutenable légèreté de l'être";
|
||
my $biblio = $builder->build_sample_biblio(
|
||
{
|
||
title => $title_with_diacritics,
|
||
author => "Milan Kundera"
|
||
}
|
||
);
|
||
|
||
my $record = $biblio->metadata->record;
|
||
$record->leader(' nam 3 4500');
|
||
$biblio->metadata->metadata($record->as_xml_record('UNIMARC'))->store;
|
||
|
||
my $biblio_id_1 = $biblio->id;
|
||
|
||
t::lib::Mocks::mock_preference('marcflavour', 'MARC21');
|
||
my $biblio_id_2 = $builder->build_sample_biblio->id;
|
||
|
||
my $query = encode_json( [ { biblio_id => $biblio_id_1 }, { biblio_id => $biblio_id_2 } ] );
|
||
|
||
$t->get_ok("//$userid:$password@/api/v1/biblios?q=$query")->status_is(403);
|
||
|
||
$patron->flags(4)->store;
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/weird+format' } )
|
||
->status_is(400);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/json' } )->status_is(200);
|
||
|
||
my $result = $t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/marcxml+xml' } )
|
||
->status_is(200)->tx->res->body;
|
||
|
||
my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
|
||
like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/marc-in-json' } )
|
||
->status_is(200);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'application/marc' } )->status_is(200);
|
||
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios?q=$query" => { Accept => 'text/plain' } )->status_is(200);
|
||
|
||
# DELETE any biblio with ISBN = TOMAS
|
||
Koha::Biblios->search({ 'biblioitem.isbn' => 'TOMAS' }, { join => [ 'biblioitem' ] })
|
||
->delete;
|
||
|
||
|
||
my $isbn_query = encode_json({ isbn => 'TOMAS' });
|
||
$biblio->biblioitem->set({ isbn => 'TOMAS' })->store;
|
||
$t->get_ok( "//$userid:$password@/api/v1/biblios?q=$isbn_query" =>
|
||
{ Accept => 'text/plain' } )
|
||
->status_is(200);
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'add_item() tests' => sub {
|
||
plan tests => 7;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 }
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
my $userid = $patron->userid;
|
||
|
||
my $biblio = $builder->build_sample_biblio();
|
||
my $biblio_id = $biblio->biblionumber;
|
||
|
||
my $barcode = 'mybarcode';
|
||
my $matching_items = Koha::Items->search({ barcode => $barcode });
|
||
|
||
while (my $item = $matching_items->next) {
|
||
$item->delete;
|
||
}
|
||
|
||
$t->post_ok("//$userid:$password@/api/v1/biblios/$biblio_id/items" => json => { external_id => $barcode })
|
||
->status_is(403, 'Not enough permissions to create an item');
|
||
|
||
# Add permissions
|
||
$builder->build(
|
||
{
|
||
source => 'UserPermission',
|
||
value => {
|
||
borrowernumber => $patron->borrowernumber,
|
||
module_bit => 9,
|
||
code => 'edit_catalogue'
|
||
}
|
||
}
|
||
);
|
||
|
||
$t->post_ok("//$userid:$password@/api/v1/biblios/$biblio_id/items" => json => {
|
||
external_id => $barcode,
|
||
})
|
||
->status_is(201, 'Item created')
|
||
->json_is('/biblio_id', $biblio_id);
|
||
|
||
my $item = $builder->build_sample_item();
|
||
|
||
$t->post_ok("//$userid:$password@/api/v1/biblios/$biblio_id/items" => json => {
|
||
external_id => $item->barcode,
|
||
})
|
||
->status_is(409, 'Duplicate barcode');
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'update_item() tests' => sub {
|
||
plan tests => 7;
|
||
|
||
$schema->storage->txn_begin;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 }
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
my $userid = $patron->userid;
|
||
|
||
my $item = $builder->build_sample_item({ replacementprice => 5 });
|
||
my $biblio_id = $item->biblionumber;
|
||
my $item_id = $item->itemnumber;
|
||
|
||
my $biblio = Koha::Biblios->find($item->biblionumber);
|
||
|
||
my $matching_items = Koha::Items->search({ barcode => $item->barcode });
|
||
|
||
while (my $mbcitem = $matching_items->next) {
|
||
$mbcitem->delete if $mbcitem->biblionumber != $item->biblionumber;
|
||
}
|
||
|
||
$t->put_ok("//$userid:$password@/api/v1/biblios/$biblio_id/items/$item_id" => json => { external_id => 'something' })
|
||
->status_is(403, 'Not enough permissions to update an item');
|
||
|
||
# Add permissions
|
||
$builder->build(
|
||
{
|
||
source => 'UserPermission',
|
||
value => {
|
||
borrowernumber => $patron->borrowernumber,
|
||
module_bit => 9,
|
||
code => 'edit_catalogue'
|
||
}
|
||
}
|
||
);
|
||
|
||
my $other_item = $builder->build_sample_item();
|
||
|
||
$t->put_ok("//$userid:$password@/api/v1/biblios/$biblio_id/items/$item_id" => json => {
|
||
external_id => $other_item->barcode,
|
||
})
|
||
->status_is(409, 'Barcode not unique');
|
||
|
||
$t->put_ok("//$userid:$password@/api/v1/biblios/$biblio_id/items/$item_id" => json => {
|
||
replacement_price => 30,
|
||
})
|
||
->status_is(200, 'Item updated')
|
||
->json_is('/replacement_price', 30);
|
||
|
||
$schema->storage->txn_rollback;
|
||
};
|
||
|
||
subtest 'merge() tests' => sub {
|
||
plan tests => 12;
|
||
$schema->storage->txn_begin;
|
||
|
||
my $mij_rec = q|{
|
||
"fields": [
|
||
{
|
||
"001": "2504398"
|
||
},
|
||
{
|
||
"005": "20200421093816.0"
|
||
},
|
||
{
|
||
"008": "920610s1993 caub s001 0 eng "
|
||
},
|
||
{
|
||
"010": {
|
||
"ind1": " ",
|
||
"subfields": [
|
||
{
|
||
"a": " 92021731 "
|
||
}
|
||
],
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"020": {
|
||
"subfields": [
|
||
{
|
||
"a": "05200784462 (Test mij)"
|
||
}
|
||
],
|
||
"ind1": " ",
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"040": {
|
||
"subfields": [
|
||
{
|
||
"a": "DLC"
|
||
},
|
||
{
|
||
"c": "DLC"
|
||
},
|
||
{
|
||
"d": "DLC"
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"041": {
|
||
"ind2": " ",
|
||
"subfields": [
|
||
{
|
||
"a": "enggrc"
|
||
}
|
||
],
|
||
"ind1": "0"
|
||
}
|
||
},
|
||
{
|
||
"082": {
|
||
"subfields": [
|
||
{
|
||
"a": "480"
|
||
},
|
||
{
|
||
"2": "20"
|
||
}
|
||
],
|
||
"ind2": "0",
|
||
"ind1": "0"
|
||
}
|
||
},
|
||
{
|
||
"100": {
|
||
"ind2": " ",
|
||
"subfields": [
|
||
{
|
||
"a": "Mastronarde, Donald J."
|
||
},
|
||
{
|
||
"9": "389"
|
||
}
|
||
],
|
||
"ind1": "1"
|
||
}
|
||
},
|
||
{
|
||
"245": {
|
||
"ind1": "1",
|
||
"subfields": [
|
||
{
|
||
"a": "Introduction to Attic Greek (Using mij) /"
|
||
},
|
||
{
|
||
"c": "Donald J. Mastronarde."
|
||
}
|
||
],
|
||
"ind2": "0"
|
||
}
|
||
},
|
||
{
|
||
"260": {
|
||
"subfields": [
|
||
{
|
||
"a": "Berkeley :"
|
||
},
|
||
{
|
||
"b": "University of California Press,"
|
||
},
|
||
{
|
||
"c": "c1993."
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"300": {
|
||
"ind1": " ",
|
||
"subfields": [
|
||
{
|
||
"a": "ix, 425 p. :"
|
||
},
|
||
{
|
||
"b": "maps ;"
|
||
},
|
||
{
|
||
"c": "26 cm."
|
||
}
|
||
],
|
||
"ind2": " "
|
||
}
|
||
},
|
||
{
|
||
"650": {
|
||
"subfields": [
|
||
{
|
||
"a": "Attic Greek dialect"
|
||
},
|
||
{
|
||
"9": "7"
|
||
}
|
||
],
|
||
"ind2": "0",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"942": {
|
||
"subfields": [
|
||
{
|
||
"2": "ddc"
|
||
},
|
||
{
|
||
"c": "BK"
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"955": {
|
||
"subfields": [
|
||
{
|
||
"a": "pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93"
|
||
}
|
||
],
|
||
"ind2": " ",
|
||
"ind1": " "
|
||
}
|
||
},
|
||
{
|
||
"999": {
|
||
"subfields": [
|
||
{
|
||
"c": "3"
|
||
},
|
||
{
|
||
"d": "3"
|
||
}
|
||
],
|
||
"ind1": " ",
|
||
"ind2": " "
|
||
}
|
||
}
|
||
],
|
||
"leader": "01102pam a2200289 a 8500"
|
||
}|;
|
||
|
||
my $patron = $builder->build_object(
|
||
{
|
||
class => 'Koha::Patrons',
|
||
value => { flags => 0 }
|
||
}
|
||
);
|
||
my $password = 'thePassword123';
|
||
$patron->set_password( { password => $password, skip_validation => 1 } );
|
||
my $userid = $patron->userid;
|
||
|
||
my $title_1 = 'Title number 1';
|
||
my $title_2 = 'Title number 2';
|
||
my $biblio1 = $builder->build_sample_biblio( { title => $title_1 } );
|
||
my $biblio2 = $builder->build_sample_biblio( { title => $title_2 } );
|
||
my $biblio_id1 = $biblio1->biblionumber;
|
||
my $biblio_id2 = $biblio2->biblionumber;
|
||
my $json_input1 = '{ "biblio_id_to_merge": "' . $biblio_id2 . '" }';
|
||
|
||
$t->post_ok( "//$userid:$password@/api/v1/biblios/$biblio_id1/merge" =>
|
||
{ 'Content-Type' => 'application/json', 'Accept' => 'application/marc-in-json' } => $json_input1 )
|
||
->status_is( 403, 'Not enough permissions to merge two bib records' );
|
||
|
||
# Add permissions
|
||
$patron->flags(516)->store;
|
||
|
||
$t->post_ok(
|
||
"//$userid:$password@/api/v1/biblios/$biblio_id1/merge" => { 'Content-Type' => 'application/weird+format' } =>
|
||
$json_input1 )->status_is( 400, 'Not correct headers' );
|
||
|
||
my $result =
|
||
$t->post_ok( "//$userid:$password@/api/v1/biblios/$biblio_id1/merge" =>
|
||
{ 'Content-Type' => 'application/json', 'Accept' => 'application/marc-in-json' } => $json_input1 )
|
||
->status_is(200)->tx->res->body;
|
||
like( $result, qr/$title_1/, "Merged record has the correct title" );
|
||
unlike( $result, qr/$title_2/, "Merged record doesn't have the wrong title" );
|
||
|
||
my $biblio3 = $builder->build_sample_biblio( { title => 'Title number 3' } );
|
||
my $biblio_id3 = $biblio3->biblionumber;
|
||
my $json_input2 = '{ "biblio_id_to_merge": "' . $biblio_id3 . '",
|
||
"rules": "override_ext",
|
||
"datarecord": ' . $mij_rec . ' }';
|
||
$result =
|
||
$t->post_ok( "//$userid:$password@/api/v1/biblios/$biblio_id1/merge" =>
|
||
{ 'Content-Type' => 'application/json', 'Accept' => 'application/marc-in-json' } => $json_input2 )
|
||
->status_is(200)->tx->res->body;
|
||
like( $result, qr/Using mij/, "Update with Marc-in-json record" );
|
||
unlike( $result, qr/$title_1/, "Change all record with dat in the 'datarecord' field" );
|
||
|
||
$schema->storage->txn_rollback;
|
||
}
|