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

(-)a/Koha/REST/V1/Items.pm (-20 / +51 lines)
Lines 27-45 use List::MoreUtils qw( any ); Link Here
27
use Try::Tiny qw( catch try );
27
use Try::Tiny qw( catch try );
28
28
29
=head1 NAME
29
=head1 NAME
30
31
Koha::REST::V1::Items - Koha REST API for handling items (V1)
30
Koha::REST::V1::Items - Koha REST API for handling items (V1)
32
33
=head1 API
31
=head1 API
34
35
=head2 Methods
32
=head2 Methods
36
37
=cut
33
=cut
38
34
39
=head3 list
35
=head3 list
40
41
Controller function that handles listing Koha::Item objects
36
Controller function that handles listing Koha::Item objects
42
43
=cut
37
=cut
44
38
45
sub list {
39
sub list {
Lines 59-67 sub list { Link Here
59
}
53
}
60
54
61
=head3 list_public
55
=head3 list_public
62
63
Controller function that handles listing Koha::Item objects available to the opac
56
Controller function that handles listing Koha::Item objects available to the opac
64
65
=cut
57
=cut
66
58
67
sub list_public {
59
sub list_public {
Lines 85-93 sub list_public { Link Here
85
}
77
}
86
78
87
=head3 get
79
=head3 get
88
89
Controller function that handles retrieving a single Koha::Item
80
Controller function that handles retrieving a single Koha::Item
90
91
=cut
81
=cut
92
82
93
sub get {
83
sub get {
Lines 110-118 sub get { Link Here
110
}
100
}
111
101
112
=head3 delete
102
=head3 delete
113
114
Controller function that handles deleting a single Koha::Item
103
Controller function that handles deleting a single Koha::Item
115
116
=cut
104
=cut
117
105
118
sub delete {
106
sub delete {
Lines 173-184 sub delete { Link Here
173
        $c->unhandled_exception($_);
161
        $c->unhandled_exception($_);
174
    };
162
    };
175
}
163
}
164
=head3 checkout
165
 
166
Check out an item
167
 
168
=cut
169
 
170
sub checkout {
171
    my $c = shift->openapi->valid_input or return;
172
    my $item_id = $c->validation->param('item_id');
173
    my $item = Koha::Items->find( $item_id );
174
    unless ( $item ) {
175
        return $c->render(
176
            status  => 404,
177
            openapi => { error => "Item not found" }
178
        );
179
    }
180
    my $patron_id = $c->validation->param('patron_id');
181
    my $patron    = Koha::Patrons->find( $patron_id );
182
    unless ( $patron ) {
183
        return $c->render(
184
            status  => 400,
185
            openapi => { error => "Patron not found" }
186
        );
187
    }
188
    try {
189
        my $barcode = $item->barcode;
190
        my ( $issuing_impossible, $needs_confirmation ) = C4::Circulation::CanBookBeIssued( $patron, $barcode );
191
        if ( keys %$issuing_impossible or keys %$needs_confirmation ) {
192
            return $c->render(
193
                status => 403,
194
                openapi => { error => "Checkout not allowed" }
195
            );
196
        }
197
        my $borrower = $patron->unblessed;
198
        my $checkout = C4::Circulation::AddIssue(
199
           $borrower,
200
           $barcode
201
        );
202
 
203
        $c->res->headers->location( $c->req->url->to_string );
204
        return $c->render(
205
            status  => 201,
206
            openapi => $checkout->to_api
207
        );
208
    }
209
    catch {
210
        $c->unhandled_exception($_);
211
    };
212
}
176
213
177
=head3 pickup_locations
214
=head3 pickup_locations
178
179
Method that returns the possible pickup_locations for a given item
215
Method that returns the possible pickup_locations for a given item
180
used for building the dropdown selector
216
used for building the dropdown selector
181
182
=cut
217
=cut
183
218
184
sub pickup_locations {
219
sub pickup_locations {
Lines 242-250 sub pickup_locations { Link Here
242
}
277
}
243
278
244
=head3 bundled_items
279
=head3 bundled_items
245
246
Controller function that handles bundled_items Koha::Item objects
280
Controller function that handles bundled_items Koha::Item objects
247
248
=cut
281
=cut
249
282
250
sub bundled_items {
283
sub bundled_items {
Lines 274-282 sub bundled_items { Link Here
274
}
307
}
275
308
276
=head3 add_to_bundle
309
=head3 add_to_bundle
277
278
Controller function that handles adding items to this bundle
310
Controller function that handles adding items to this bundle
279
280
=cut
311
=cut
281
312
282
sub add_to_bundle {
313
sub add_to_bundle {
Lines 371-379 sub add_to_bundle { Link Here
371
}
402
}
372
403
373
=head3 remove_from_bundle
404
=head3 remove_from_bundle
374
375
Controller function that handles removing items from this bundle
405
Controller function that handles removing items from this bundle
376
377
=cut
406
=cut
378
407
379
sub remove_from_bundle {
408
sub remove_from_bundle {
Lines 408-410 sub remove_from_bundle { Link Here
408
}
437
}
409
438
410
1;
439
1;
440
441
(-)a/api/v1/swagger/paths/items.yaml (+35 lines)
Lines 396-401 Link Here
396
    x-koha-authorization:
396
    x-koha-authorization:
397
      permissions:
397
      permissions:
398
        reserveforothers: place_holds
398
        reserveforothers: place_holds
399
"/items/{item_id}/checkout/{patron_id}":
400
  post:
401
    x-mojo-to: Items#checkout
402
    operationId: addCheckout
403
    tags:
404
      - items
405
      - checkouts
406
    summary: Add a checkout
407
    parameters:
408
      - $ref: "../swagger.yaml#/parameters/item_id_pp"
409
      - $ref: "../swagger.yaml#/parameters/patron_id_pp"
410
    consumes:
411
      - application/json
412
    produces:
413
      - application/json
414
    responses:
415
      "201":
416
        description: Added checkout
417
        schema:
418
          $ref: "../swagger.yaml#/definitions/checkout"
419
      "400":
420
        description: Patron not found
421
        schema:
422
          $ref: "../swagger.yaml#/definitions/error"
423
      "403":
424
        description: Cannot add checkout
425
        schema:
426
          $ref: "../swagger.yaml#/definitions/error"
427
      "404":
428
        description: Item not found
429
        schema:
430
          $ref: "../swagger.yaml#/definitions/error"
431
    x-koha-authorization:
432
      permissions:
433
        circulate: circulate_remaining_permissions
399
"/public/items":
434
"/public/items":
400
  get:
435
  get:
401
    x-mojo-to: Items#list_public
436
    x-mojo-to: Items#list_public
(-)a/api/v1/swagger/swagger.yaml (+2 lines)
Lines 273-278 paths: Link Here
273
    $ref: ./paths/items.yaml#/~1items~1{item_id}~1bundled_items~1{bundled_item_id}
273
    $ref: ./paths/items.yaml#/~1items~1{item_id}~1bundled_items~1{bundled_item_id}
274
  "/items/{item_id}/pickup_locations":
274
  "/items/{item_id}/pickup_locations":
275
    $ref: "./paths/items.yaml#/~1items~1{item_id}~1pickup_locations"
275
    $ref: "./paths/items.yaml#/~1items~1{item_id}~1pickup_locations"
276
  "/items/{item_id}/checkout/{patron_id}":
277
    $ref: "./paths/items.yaml#/~1items~1{item_id}~1checkout~1{patron_id}"
276
  /jobs:
278
  /jobs:
277
    $ref: ./paths/jobs.yaml#/~1jobs
279
    $ref: ./paths/jobs.yaml#/~1jobs
278
  "/jobs/{job_id}":
280
  "/jobs/{job_id}":
(-)a/t/db_dependent/api/v1/items.t (-1 / +69 lines)
Lines 572-574 subtest 'pickup_locations() tests' => sub { Link Here
572
572
573
    $schema->storage->txn_rollback;
573
    $schema->storage->txn_rollback;
574
};
574
};
575
- 
575
576
subtest 'checkout() tests' => sub {
577
578
    plan tests => 12;
579
580
    $schema->storage->txn_begin;
581
582
    my $item   = $builder->build_sample_item;
583
    my $patron = $builder->build_object(
584
        {
585
            class => 'Koha::Patrons',
586
            value => { flags => 4 }
587
        }
588
    );
589
590
    # Make sure we have at least 10 items
591
    for ( 1..10 ) {
592
        $builder->build_sample_item;
593
    }
594
595
    my $nonprivilegedpatron = $builder->build_object(
596
        {
597
            class => 'Koha::Patrons',
598
            value => { flags => 0 }
599
        }
600
    );
601
602
    my $password = 'thePassword123';
603
604
    $nonprivilegedpatron->set_password(
605
        { password => $password, skip_validation => 1 } );
606
607
    my $userid = $nonprivilegedpatron->userid;
608
    my $itemid = $item->id;
609
    my $patronid = $patron->id;
610
    my $non_existent_code = $items->itemnumber;
611
612
    $t->get_ok( "//$userid:$password@/api/v1/items/$itemid/checkout/$patronid" )
613
      ->status_is(403)
614
      ->json_is(
615
        '/error' => 'Authorization failure. Missing required permission(s).' );
616
617
    $t->get_ok( "//$userid:$password@/api/v1/items/" . $non_existent_code )
618
      ->status_is(404)
619
      ->json_is(
620
        '/error' => 'Item not found' );
621
622
    $userid = $patron->userid;
623
624
    $t->get_ok( "//$userid:$password@/api/v1/items?_per_page=10" )
625
      ->status_is( 200, 'SWAGGER3.2.2' );
626
627
    my $response_count = scalar @{ $t->tx->res->json };
628
629
    is( $response_count, 10, 'The API returns 10 items' );
630
631
    $t->get_ok( "//$userid:$password@/api/v1/items?external_id=" . $item->barcode )
632
      ->status_is(200)
633
      ->json_is( '' => [ $item->to_api ], 'SWAGGER3.3.2');
634
635
    my $barcode = $item->barcode;
636
    $item->delete;
637
638
    $t->get_ok( "//$userid:$password@/api/v1/items?external_id=" . $item->barcode )
639
      ->status_is(200)
640
      ->json_is( '' => [] );
641
642
    $schema->storage->txn_rollback;
643
};

Return to bug 24400