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

(-)a/C4/Circulation.pm (-1 / +3 lines)
Lines 683-688 data is keyed in lower case! Link Here
683
Available keys:
683
Available keys:
684
    override_high_holds - Ignore high holds
684
    override_high_holds - Ignore high holds
685
    onsite_checkout     - Checkout is an onsite checkout that will not leave the library
685
    onsite_checkout     - Checkout is an onsite checkout that will not leave the library
686
    item                - Optionally pass the object for the item we are checking out to save a lookup
686
687
687
=back
688
=back
688
689
Lines 776-782 sub CanBookBeIssued { Link Here
776
    my $onsite_checkout     = $params->{onsite_checkout}     || 0;
777
    my $onsite_checkout     = $params->{onsite_checkout}     || 0;
777
    my $override_high_holds = $params->{override_high_holds} || 0;
778
    my $override_high_holds = $params->{override_high_holds} || 0;
778
779
779
    my $item_object = Koha::Items->find({barcode => $barcode });
780
    my $item_object = $params->{item}
781
      // Koha::Items->find( { barcode => $barcode } );
780
782
781
    # MANDATORY CHECKS - unless item exists, nothing else matters
783
    # MANDATORY CHECKS - unless item exists, nothing else matters
782
    unless ( $item_object ) {
784
    unless ( $item_object ) {
(-)a/Koha/Item.pm (-1 lines)
Lines 336-342 sub move_to_deleted { Link Here
336
    return Koha::Database->new->schema->resultset('Deleteditem')->create($item_infos);
336
    return Koha::Database->new->schema->resultset('Deleteditem')->create($item_infos);
337
}
337
}
338
338
339
340
=head3 effective_itemtype
339
=head3 effective_itemtype
341
340
342
Returns the itemtype for the item based on whether item level itemtypes are set or not.
341
Returns the itemtype for the item based on whether item level itemtypes are set or not.
(-)a/Koha/REST/V1/Checkouts.pm (-1 / +161 lines)
Lines 19-28 use Modern::Perl; Link Here
19
19
20
use Mojo::Base 'Mojolicious::Controller';
20
use Mojo::Base 'Mojolicious::Controller';
21
use Mojo::JSON;
21
use Mojo::JSON;
22
use Mojo::JWT;
23
use Digest::MD5 qw( md5_base64 );
24
use Encode;
22
25
23
use C4::Auth qw( haspermission );
26
use C4::Auth qw( haspermission );
24
use C4::Context;
27
use C4::Context;
25
use C4::Circulation qw( AddRenewal CanBookBeRenewed );
28
use C4::Circulation qw( AddIssue AddRenewal CanBookBeRenewed );
26
use Koha::Checkouts;
29
use Koha::Checkouts;
27
use Koha::Old::Checkouts;
30
use Koha::Old::Checkouts;
28
31
Lines 99-104 sub get { Link Here
99
    };
102
    };
100
}
103
}
101
104
105
=head3 get_availablity
106
107
Controller function that handles retrieval of Checkout availability
108
109
=cut
110
111
sub get_availability {
112
    my $c = shift->openapi->valid_input or return;
113
114
    my $patron = Koha::Patrons->find( $c->validation->param('patron_id') );
115
    my $inprocess = 0; # What does this do?
116
    my $ignore_reserves = 0; # Don't ignore reserves
117
    my $item   = Koha::Items->find( $c->validation->param('item_id') );
118
    my $params = {
119
        item => $item
120
    };
121
122
    my ( $impossible, $confirmation, $alerts, $messages ) =
123
      C4::Circulation::CanBookBeIssued( $patron, undef, undef, $inprocess, $ignore_reserves,
124
        $params );
125
126
    my $token;
127
    if (keys %{$confirmation}) {
128
        my $claims = { map { $_ => 1 } keys %{$confirmation} };
129
        my $secret =
130
          md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) );
131
        $token = Mojo::JWT->new( claims => $claims, secret => $secret )->encode;
132
    }
133
134
    my $response = {
135
        blockers           => $impossible,
136
        confirms           => $confirmation,
137
        warnings           => { %{$alerts}, %{$messages} },
138
        confirmation_token => $token
139
    };
140
141
    return $c->render( status => 200, openapi => $response );
142
}
143
144
=head3 add
145
146
Add a new checkout
147
148
=cut
149
150
sub add {
151
    my $c = shift->openapi->valid_input or return;
152
153
    my $body      = $c->validation->param('body');
154
    my $item_id   = $body->{item_id};
155
    my $patron_id = $body->{patron_id};
156
    my $onsite    = $body->{onsite_checkout};
157
158
    return try {
159
        my $item = Koha::Items->find($item_id);
160
        unless ($item) {
161
            return $c->render(
162
                status  => 409,
163
                openapi => {
164
                    error      => 'Item not found',
165
                    error_code => 'ITEM_NOT_FOUND',
166
                }
167
            );
168
        }
169
170
        my $patron = Koha::Patrons->find($patron_id);
171
        unless ($patron) {
172
            return $c->render(
173
                status  => 409,
174
                openapi => {
175
                    error      => 'Patron not found',
176
                    error_code => 'PATRON_NOT_FOUND',
177
                }
178
            );
179
        }
180
181
        my $inprocess       = 0;                   # What does this do?
182
        my $ignore_reserves = 0;                   # Don't ignore reserves
183
        my $params          = { item => $item };
184
185
        # Call 'CanBookBeIssued'
186
        my ( $impossible, $confirmation, $alerts, $messages ) =
187
          C4::Circulation::CanBookBeIssued(
188
             $patron,
189
             undef,
190
             undef,
191
             $inprocess,
192
             $ignore_reserves,
193
             $params
194
        );
195
196
        # * Fail for blockers - render 403
197
        if ( keys %{$impossible} ) {
198
            my @errors = keys %{$impossible};
199
            return $c->render(
200
                status  => 403,
201
                openapi => { error => "Checkout not authorized (@errors)" }
202
            );
203
        }
204
205
        # * If confirmation required, check variable set above
206
        #   and render 412 if variable is false
207
        if ( keys %{$confirmation} ) {
208
            my $confirmed = 0;
209
210
            # Check for existance of confirmation token
211
            # and if exists check validity
212
            if ( my $token = $c->validation->param('confirmation') ) {
213
                my $secret =
214
                  md5_base64(
215
                    Encode::encode( 'UTF-8', C4::Context->config('pass') ) );
216
                my $claims = try {
217
                    Mojo::JWT->new( secret => $secret )->decode($token);
218
                }
219
                catch {
220
                    return $c->render(
221
                        status  => 403,
222
                        openapi => { error => "Confirmation required" }
223
                    );
224
                };
225
226
                # check claims match
227
                my $token_claims = join( / /, sort keys %{$claims} );
228
                my $confirm_keys = join( / /, sort keys %{$confirmation} );
229
                $confirmed = 1 if ( $token_claims eq $confirm_keys );
230
            }
231
232
            unless ($confirmed) {
233
                return $c->render(
234
                    status  => 412,
235
                    openapi => { error => "Confirmation error" }
236
                );
237
            }
238
        }
239
240
        # Call 'AddIssue'
241
        my $checkout = AddIssue( $patron->unblessed, $item->barcode );
242
        if ($checkout) {
243
            $c->res->headers->location(
244
                $c->req->url->to_string . '/' . $checkout->id );
245
            return $c->render(
246
                status  => 201,
247
                openapi => $checkout->to_api
248
            );
249
        }
250
        else {
251
            return $c->render(
252
                status  => 500,
253
                openapi => { error => 'Unknown error during checkout' }
254
            );
255
        }
256
    }
257
    catch {
258
        $c->unhandled_exception($_);
259
    };
260
}
261
102
=head3 get_renewals
262
=head3 get_renewals
103
263
104
List Koha::Checkout::Renewals
264
List Koha::Checkout::Renewals
(-)a/api/v1/swagger/paths/checkouts.yaml (+97 lines)
Lines 61-66 Link Here
61
    x-koha-authorization:
61
    x-koha-authorization:
62
      permissions:
62
      permissions:
63
        circulate: circulate_remaining_permissions
63
        circulate: circulate_remaining_permissions
64
  post:
65
    x-mojo-to: Checkouts#add
66
    operationId: addCheckout
67
    tags:
68
      - checkouts
69
      - patrons
70
    summary: Add a new checkout
71
    parameters:
72
      - name: body
73
        in: body
74
        description: A JSON object containing information about the new checkout
75
        required: true
76
        schema:
77
          $ref: "../swagger.yaml#/definitions/checkout"
78
      - name: confirmation
79
        in: query
80
        description: A JWT confirmation token
81
        required: false
82
        type: string
83
    consumes:
84
      - application/json
85
    produces:
86
      - application/json
87
    responses:
88
      "201":
89
        description: Created checkout
90
        schema:
91
          $ref: "../swagger.yaml#/definitions/checkout"
92
      "400":
93
        description: Missing or wrong parameters
94
        schema:
95
          $ref: "../swagger.yaml#/definitions/error"
96
      "401":
97
        description: Authentication required
98
        schema:
99
          $ref: "../swagger.yaml#/definitions/error"
100
      "403":
101
        description: Cannot create checkout
102
        schema:
103
          $ref: "../swagger.yaml#/definitions/error"
104
      "409":
105
        description: Conflict in creating checkout
106
        schema:
107
          $ref: "../swagger.yaml#/definitions/error"
108
      "412":
109
        description: Precondition failed
110
        schema:
111
          $ref: "../swagger.yaml#/definitions/error"
112
      "500":
113
        description: |
114
          Internal server error. Possible `error_code` attribute values:
115
116
          * `internal_server_error`
117
        schema:
118
          $ref: "../swagger.yaml#/definitions/error"
119
      "503":
120
        description: Under maintenance
121
        schema:
122
          $ref: "../swagger.yaml#/definitions/error"
123
    x-koha-authorization:
124
      permissions:
125
        circulate: circulate_remaining_permissions
64
"/checkouts/{checkout_id}":
126
"/checkouts/{checkout_id}":
65
  get:
127
  get:
66
    x-mojo-to: Checkouts#get
128
    x-mojo-to: Checkouts#get
Lines 273-275 Link Here
273
    x-koha-authorization:
335
    x-koha-authorization:
274
      permissions:
336
      permissions:
275
        circulate: circulate_remaining_permissions
337
        circulate: circulate_remaining_permissions
338
"/checkouts/availability":
339
  get:
340
    x-mojo-to: Checkouts#get_availability
341
    operationId: availabilityCheckouts
342
    tags:
343
      - checkouts
344
    summary: Get checkout availability
345
    parameters:
346
      - $ref: "../swagger.yaml#/parameters/patron_id_qp"
347
      - $ref: "../swagger.yaml#/parameters/item_id_qp"
348
    produces:
349
      - application/json
350
    responses:
351
      "200":
352
        description: Availability
353
        schema:
354
          type: "object"
355
      "403":
356
        description: Access forbidden
357
        schema:
358
          $ref: "../swagger.yaml#/definitions/error"
359
      "500":
360
        description: |
361
          Internal server error. Possible `error_code` attribute values:
362
363
          * `internal_server_error`
364
        schema:
365
          $ref: "../swagger.yaml#/definitions/error"
366
      "503":
367
        description: Under maintenance
368
        schema:
369
          $ref: "../swagger.yaml#/definitions/error"
370
    x-koha-authorization:
371
      permissions:
372
        circulate: circulate_remaining_permissions
(-)a/api/v1/swagger/swagger.yaml (-1 / +7 lines)
Lines 197-202 paths: Link Here
197
    $ref: "./paths/checkouts.yaml#/~1checkouts~1{checkout_id}~1renewals"
197
    $ref: "./paths/checkouts.yaml#/~1checkouts~1{checkout_id}~1renewals"
198
  "/checkouts/{checkout_id}/renewal":
198
  "/checkouts/{checkout_id}/renewal":
199
    $ref: "./paths/checkouts.yaml#/~1checkouts~1{checkout_id}~1renewal"
199
    $ref: "./paths/checkouts.yaml#/~1checkouts~1{checkout_id}~1renewal"
200
  "/checkouts/availability":
201
    $ref: "./paths/checkouts.yaml#/~1checkouts~1availability"
200
  /circulation-rules/kinds:
202
  /circulation-rules/kinds:
201
    $ref: ./paths/circulation-rules.yaml#/~1circulation-rules~1kinds
203
    $ref: ./paths/circulation-rules.yaml#/~1circulation-rules~1kinds
202
  /cities:
204
  /cities:
Lines 519-524 parameters: Link Here
519
    name: item_id
521
    name: item_id
520
    required: true
522
    required: true
521
    type: integer
523
    type: integer
524
  item_id_qp:
525
    description: Internal item identifier
526
    in: query
527
    name: item_id
528
    type: integer
522
  job_id_pp:
529
  job_id_pp:
523
    description: Job internal identifier
530
    description: Job internal identifier
524
    in: path
531
    in: path
525
- 

Return to bug 23336