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

(-)a/Koha/REST/V1/Checkouts.pm (+91 lines)
Lines 25-30 use C4::Context; Link Here
25
use C4::Circulation;
25
use C4::Circulation;
26
use Koha::Checkouts;
26
use Koha::Checkouts;
27
use Koha::IssuingRules;
27
use Koha::IssuingRules;
28
use Koha::Patrons;
29
use JSON;
28
30
29
use Try::Tiny;
31
use Try::Tiny;
30
32
Lines 172-177 sub allows_renewal { Link Here
172
    );
174
    );
173
}
175
}
174
176
177
=head3 add
178
179
Create a checkout
180
181
=cut
182
183
sub add {
184
    my $c = shift->openapi->valid_input or return;
185
186
    my $body = $c->validation->param('body');
187
188
    my $patron_id       = $body->{'patron_id'};
189
    my $barcode         = $body->{'barcode'};
190
    my $duedate         = $body->{'due_date'};
191
    my $inprocess       = $body->{'inprocess'};
192
    my $ignore_reserves = $body->{'ignore_reserves'};
193
    my $cancel_reserve  = $body->{'cancel_reserve'};
194
    my $issuedate       = $body->{'issue_date'};
195
    my $sipmode         = $body->{'sipmode'};
196
    my $params          = $body->{'params'};
197
198
    my $patron = Koha::Patrons->find({ borrowernumber => $patron_id });
199
    my $item = Koha::Items->find({ barcode => $barcode });
200
201
    $c->res->headers->location( $c->req->url->to_string );
202
    unless ($patron) {
203
        return $c->render(
204
            status => 404,
205
            openapi => { error => "Patron doesn't exist" }
206
        );
207
    }
208
209
    unless ($item) {
210
        return $c->render(
211
            status => 404,
212
            openapi => { error => "Item doesn't exist" }
213
        );
214
    }
215
216
    my ( $error, $confirm, $alerts, $messages ) =
217
        C4::Circulation::CanBookBeIssued(
218
            $patron,
219
            $barcode,
220
            $duedate,
221
            $inprocess,
222
            $ignore_reserves,
223
            $params
224
        );
225
226
    my $problems = {};
227
    $problems->{error} = $error if %{$error};
228
    $problems->{confirm} = $confirm if %{$confirm};
229
    $problems->{alerts} = $alerts if %{$alerts};
230
    $problems->{messages} = $messages if %{$messages};
231
232
    if (%{$problems}) {
233
        return $c->render(
234
            status => 403,
235
            openapi => {
236
                error  => encode_json $problems
237
            }
238
        );
239
    }
240
241
    my $issue = C4::Circulation::AddIssue(
242
        $patron->unblessed,
243
        $barcode,
244
        $duedate,
245
        $cancel_reserve,
246
        $issuedate,
247
        $sipmode,
248
        $params
249
    );
250
251
    if ($issue && %{$issue}) {
252
        return $c->render(
253
            status => 201,
254
            openapi => _to_api( $issue->TO_JSON )
255
        );
256
    } else {
257
        return $c->render(
258
            status => 500,
259
            openapi => { error => 'Unknown error during checkout' }
260
        );
261
    }
262
263
264
}
265
175
=head3 _to_api
266
=head3 _to_api
176
267
177
Helper function that maps a hashref of Koha::Checkout attributes into REST api
268
Helper function that maps a hashref of Koha::Checkout attributes into REST api
(-)a/api/v1/swagger/paths/checkouts.json (+117 lines)
Lines 35-40 Link Here
35
          "circulate": "circulate_remaining_permissions"
35
          "circulate": "circulate_remaining_permissions"
36
        }
36
        }
37
      }
37
      }
38
    },
39
    "post": {
40
      "x-mojo-to": "Checkouts#add",
41
      "operationId": "addCheckout",
42
      "tags": ["patrons", "checkouts"],
43
      "parameters": [{
44
          "name": "body",
45
          "in": "body",
46
          "description": "A JSON object containing information about the new checkout",
47
          "required": true,
48
          "schema": {
49
            "type": "object",
50
            "properties": {
51
              "patron_id": {
52
                "description": "Internal patron identifier",
53
                "type": "string"
54
              },
55
              "barcode": {
56
                "description": "Internal item barcode",
57
                "type": "string"
58
              },
59
              "due_date": {
60
                "description": "Checkout due date",
61
                "type": ["string", "null"],
62
                "format": "date"
63
              },
64
              "inprocess": {
65
                "description": "In process",
66
                "type": ["boolean", "null"]
67
              },
68
              "ignore_reserves": {
69
                "description": "Should reserves on this item be ignored",
70
                "type": [ "boolean", "null" ]
71
              },
72
              "cancel_reserve": {
73
                "description": "Should reserves on this item be cancelled",
74
                "type": [ "string", "null" ],
75
                "enum": [
76
                    "revert",
77
                    "cancel"
78
                ]
79
              },
80
              "issue_date": {
81
                "description": "Checkout issue date",
82
                "type": ["string", "null"],
83
                "format": "date"
84
              },
85
              "sipmode": {
86
                "description": "Flag indicating sipmode",
87
                "type": ["boolean", "null"]
88
              },
89
              "params": {
90
                "description": "Object holding other arbitrary paramters",
91
                "type": ["object", "null"]
92
              }
93
            },
94
            "required": [ "patron_id", "barcode" ]
95
          }
96
        }
97
      ],
98
      "consumes": ["application/json"],
99
      "produces": ["application/json"],
100
      "responses": {
101
        "201": {
102
          "description": "Created checkout",
103
          "schema": {
104
            "$ref": "../definitions.json#/checkout"
105
          }
106
        },
107
        "400": {
108
          "description": "Missing or wrong parameters",
109
          "schema": {
110
            "$ref": "../definitions.json#/error"
111
          }
112
        },
113
        "401": {
114
          "description": "Authentication required",
115
          "schema": {
116
            "$ref": "../definitions.json#/error"
117
          }
118
        },
119
        "403": {
120
          "description": "Checkout not allowed",
121
          "schema": {
122
            "$ref": "../definitions.json#/error"
123
          }
124
        },
125
        "404": {
126
          "description": "Item not found",
127
          "schema": {
128
            "$ref": "../definitions.json#/error"
129
          }
130
        },
131
        "404": {
132
          "description": "Borrower not found",
133
          "schema": {
134
            "$ref": "../definitions.json#/error"
135
          }
136
        },
137
        "500": {
138
          "description": "Internal server error",
139
          "schema": {
140
            "$ref": "../definitions.json#/error"
141
          }
142
        },
143
        "503": {
144
          "description": "Under maintenance",
145
          "schema": {
146
            "$ref": "../definitions.json#/error"
147
          }
148
        }
149
      },
150
      "x-koha-authorization": {
151
        "permissions": {
152
          "circulate": "circulate_remaining_permissions"
153
        }
154
      }
38
    }
155
    }
39
  },
156
  },
40
  "/checkouts/{checkout_id}": {
157
  "/checkouts/{checkout_id}": {
(-)a/t/db_dependent/api/v1/checkouts.t (-2 / +35 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 79;
20
use Test::More tests => 95;
21
use Test::MockModule;
21
use Test::MockModule;
22
use Test::Mojo;
22
use Test::Mojo;
23
use t::lib::Mocks;
23
use t::lib::Mocks;
Lines 196-198 $t->get_ok( "//$userid:$password@/api/v1/checkouts/" . $issue2->issue_id . "/all Link Here
196
        current_renewals => 1,
196
        current_renewals => 1,
197
        error            => 'too_many'
197
        error            => 'too_many'
198
    });
198
    });
199
- 
199
200
# Test create checkout POST route
201
$dbh->do(q{
202
    UPDATE issuingrules SET issuelength=?
203
}, {}, 7);
204
my $itemtype = $builder->build({
205
    source => 'Itemtype',
206
    value  => { notforloan => 0 }
207
})->{itemtype};
208
my $item4 = $builder->build_sample_item({ itype => $itemtype });
209
my $expected_issue_datedue = DateTime->now
210
    ->set_time_zone('local')
211
    ->add(days => 7)
212
    ->set(hour => 23, minute => 59, second => 0);
213
214
$t->post_ok( "//$userid:$password@/api/v1/checkouts/" => json => { patron_id => $patron_id, barcode => 'not_here' })
215
  ->status_is(404)
216
  ->json_is({ error => "Item doesn't exist" })
217
  ->header_is(Location => "/api/v1/checkouts/");
218
219
$t->post_ok( "//$userid:$password@/api/v1/checkouts/" => json => { patron_id => 'not_here', barcode => $item4->barcode })
220
  ->status_is(404)
221
  ->json_is({ error => "Patron doesn't exist" })
222
  ->header_is(Location => "/api/v1/checkouts/");
223
224
$t->post_ok( "//$userid:$password@/api/v1/checkouts/" => json => { patron_id => $patron_id, barcode => $item4->barcode })
225
  ->status_is(201)
226
  ->json_is('/due_date' => output_pref( { dateformat => "rfc3339", dt => $expected_issue_datedue }) )
227
  ->header_is(Location => "/api/v1/checkouts/");
228
229
$t->post_ok( "//$userid:$password@/api/v1/checkouts/" => json => { patron_id => $patron_id, barcode => $item4->barcode })
230
  ->status_is(403)
231
  ->json_is({ error => '{"confirm":{"RENEW_ISSUE":1}}' })
232
  ->header_is(Location => "/api/v1/checkouts/");

Return to bug 23336