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

(-)a/Koha/REST/V1/Holds.pm (+21 lines)
Lines 27-32 use Koha::Patrons; Link Here
27
use Koha::Holds;
27
use Koha::Holds;
28
use Koha::DateUtils;
28
use Koha::DateUtils;
29
29
30
use List::MoreUtils qw(any);
30
use Try::Tiny;
31
use Try::Tiny;
31
32
32
=head1 API
33
=head1 API
Lines 232-237 sub edit { Link Here
232
        my $body = $c->req->json;
233
        my $body = $c->req->json;
233
234
234
        my $pickup_library_id = $body->{pickup_library_id} // $hold->branchcode;
235
        my $pickup_library_id = $body->{pickup_library_id} // $hold->branchcode;
236
237
        my @pickup_locations;
238
        if ( $hold->itemnumber ) { # item-level
239
            @pickup_locations = $hold->item->pickup_locations({ patron => $hold->patron });
240
        }
241
        else { # biblio-level
242
            @pickup_locations = $hold->biblio->pickup_locations({ patron => $hold->patron });
243
        }
244
245
        unless ( any { $_->branchcode eq $pickup_library_id } @pickup_locations ) {
246
            Koha::Exceptions::Hold::InvalidPickupLocation->throw;
247
        }
248
235
        my $priority          = $body->{priority} // $hold->priority;
249
        my $priority          = $body->{priority} // $hold->priority;
236
        # suspended_until can also be set to undef
250
        # suspended_until can also be set to undef
237
        my $suspended_until   = exists $body->{suspended_until} ? $body->{suspended_until} : $hold->suspend_until;
251
        my $suspended_until   = exists $body->{suspended_until} ? $body->{suspended_until} : $hold->suspend_until;
Lines 253-258 sub edit { Link Here
253
        );
267
        );
254
    }
268
    }
255
    catch {
269
    catch {
270
        if ( blessed $_ and $_->isa('Koha::Exceptions::Hold::InvalidPickupLocation')) {
271
            return $c->render(
272
                status  => 400,
273
                openapi => { error => "$_" }
274
            );
275
        }
276
256
        $c->unhandled_exception($_);
277
        $c->unhandled_exception($_);
257
    };
278
    };
258
}
279
}
(-)a/t/db_dependent/api/v1/holds.t (-30 / +118 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 10;
20
use Test::More tests => 11;
21
use Test::MockModule;
21
use Test::MockModule;
22
use Test::Mojo;
22
use Test::Mojo;
23
use t::lib::TestBuilder;
23
use t::lib::TestBuilder;
Lines 200-206 subtest "Test endpoints without permission" => sub { Link Here
200
200
201
subtest "Test endpoints with permission" => sub {
201
subtest "Test endpoints with permission" => sub {
202
202
203
    plan tests => 62;
203
    plan tests => 44;
204
204
205
    $t->get_ok( "//$userid_1:$password@/api/v1/holds" )
205
    $t->get_ok( "//$userid_1:$password@/api/v1/holds" )
206
      ->status_is(200)
206
      ->status_is(200)
Lines 213-245 subtest "Test endpoints with permission" => sub { Link Here
213
      ->json_is('/0/patron_id', $patron_2->borrowernumber)
213
      ->json_is('/0/patron_id', $patron_2->borrowernumber)
214
      ->json_hasnt('/1');
214
      ->json_hasnt('/1');
215
215
216
    # While suspended_until is date-time, it's always set to midnight.
217
    my $expected_suspended_until = $suspended_until->strftime('%FT00:00:00%z');
218
    substr($expected_suspended_until, -2, 0, ':');
219
220
    $t->put_ok( "//$userid_1:$password@/api/v1/holds/$reserve_id" => json => $put_data )
221
      ->status_is(200)
222
      ->json_is( '/hold_id', $reserve_id )
223
      ->json_is( '/suspended_until', $expected_suspended_until )
224
      ->json_is( '/priority', 2 )
225
      ->json_is( '/pickup_library_id', $branchcode );
226
227
    # Change only pickup library, everything else should remain
228
    $t->put_ok( "//$userid_1:$password@/api/v1/holds/$reserve_id" => json => { pickup_library_id => $branchcode2 } )
229
      ->status_is(200)
230
      ->json_is( '/hold_id', $reserve_id )
231
      ->json_is( '/suspended_until', $expected_suspended_until )
232
      ->json_is( '/priority', 2 )
233
      ->json_is( '/pickup_library_id', $branchcode2 );
234
235
    # Reset suspended_until, everything else should remain
236
    $t->put_ok( "//$userid_1:$password@/api/v1/holds/$reserve_id" => json => { suspended_until => undef } )
237
      ->status_is(200)
238
      ->json_is( '/hold_id', $reserve_id )
239
      ->json_is( '/suspended_until', undef )
240
      ->json_is( '/priority', 2 )
241
      ->json_is( '/pickup_library_id', $branchcode2 );
242
243
    $t->delete_ok( "//$userid_3:$password@/api/v1/holds/$reserve_id" )
216
    $t->delete_ok( "//$userid_3:$password@/api/v1/holds/$reserve_id" )
244
      ->status_is(204, 'SWAGGER3.2.4')
217
      ->status_is(204, 'SWAGGER3.2.4')
245
      ->content_is('', 'SWAGGER3.3.4');
218
      ->content_is('', 'SWAGGER3.3.4');
Lines 777-779 subtest 'pickup_locations() tests' => sub { Link Here
777
750
778
    $schema->storage->txn_rollback;
751
    $schema->storage->txn_rollback;
779
};
752
};
780
- 
753
754
subtest 'edit() tests' => sub {
755
756
    plan tests => 12;
757
758
    $schema->storage->txn_begin;
759
760
    my $password = 'AbcdEFG123';
761
762
    my $library  = $builder->build_object({ class => 'Koha::Libraries' });
763
    my $patron = $builder->build_object(
764
        { class => 'Koha::Patrons', value => { flags => 1 } } );
765
    $patron->set_password( { password => $password, skip_validation => 1 } );
766
    my $userid = $patron->userid;
767
    $builder->build(
768
        {
769
            source => 'UserPermission',
770
            value  => {
771
                borrowernumber => $patron->borrowernumber,
772
                module_bit     => 6,
773
                code           => 'modify_holds_priority',
774
            },
775
        }
776
    );
777
778
    # Disable logging
779
    t::lib::Mocks::mock_preference( 'HoldsLog',      0 );
780
    t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
781
782
    my $mock_biblio = Test::MockModule->new('Koha::Biblio');
783
    my $mock_item   = Test::MockModule->new('Koha::Item');
784
785
    my $library_1 = $builder->build_object({ class => 'Koha::Libraries' });
786
    my $library_2 = $builder->build_object({ class => 'Koha::Libraries' });
787
    my $library_3 = $builder->build_object({ class => 'Koha::Libraries' });
788
789
    # let's control what Koha::Biblio->pickup_locations returns, for testing
790
    $mock_biblio->mock( 'pickup_locations', sub {
791
        return Koha::Libraries->search( { branchcode => [ $library_2->branchcode, $library_3->branchcode ] } );
792
    });
793
    # let's mock what Koha::Item->pickup_locations returns, for testing
794
    $mock_item->mock( 'pickup_locations', sub {
795
        return Koha::Libraries->search( { branchcode => [ $library_2->branchcode, $library_3->branchcode ] } );
796
    });
797
798
    my $biblio = $builder->build_sample_biblio;
799
    my $item   = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
800
801
    # Test biblio-level holds
802
    my $biblio_hold = $builder->build_object(
803
        {
804
            class => "Koha::Holds",
805
            value => {
806
                biblionumber => $biblio->biblionumber,
807
                branchcode   => $library_3->branchcode,
808
                itemnumber   => undef,
809
                priority     => 1,
810
            }
811
        }
812
    );
813
814
    my $biblio_hold_data = $biblio_hold->to_api;
815
    $biblio_hold_data->{pickup_library_id} = $library_1->branchcode;
816
817
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
818
          . $biblio_hold->id
819
          => json => $biblio_hold_data )
820
      ->status_is(400);
821
822
    $biblio_hold->discard_changes;
823
    is( $biblio_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
824
825
    $biblio_hold_data->{pickup_library_id} = $library_2->branchcode;
826
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
827
          . $biblio_hold->id
828
          => json => $biblio_hold_data )
829
      ->status_is(200);
830
831
    $biblio_hold->discard_changes;
832
    is( $biblio_hold->branchcode, $library_2->id, 'Pickup location changed correctly' );
833
834
    # Test item-level holds
835
    my $item_hold = $builder->build_object(
836
        {
837
            class => "Koha::Holds",
838
            value => {
839
                biblionumber => $biblio->biblionumber,
840
                branchcode   => $library_3->branchcode,
841
                itemnumber   => $item->itemnumber,
842
                priority     => 1,
843
            }
844
        }
845
    );
846
847
    my $item_hold_data = $item_hold->to_api;
848
    $item_hold_data->{pickup_library_id} = $library_1->branchcode;
849
850
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
851
          . $item_hold->id
852
          => json => $item_hold_data )
853
      ->status_is(400);
854
855
    $item_hold->discard_changes;
856
    is( $item_hold->branchcode, $library_3->branchcode, 'branchcode remains untouched' );
857
858
    $item_hold_data->{pickup_library_id} = $library_2->branchcode;
859
    $t->put_ok( "//$userid:$password@/api/v1/holds/"
860
          . $item_hold->id
861
          => json => $item_hold_data )
862
      ->status_is(200);
863
864
    $item_hold->discard_changes;
865
    is( $item_hold->branchcode, $library_2->id, 'Pickup location changed correctly' );
866
867
    $schema->storage->txn_rollback;
868
};

Return to bug 27205