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

(-)a/Koha/REST/V1/Checkout.pm (+94 lines)
Line 0 Link Here
1
package Koha::REST::V1::Checkout;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it under the
6
# terms of the GNU General Public License as published by the Free Software
7
# Foundation; either version 3 of the License, or (at your option) any later
8
# version.
9
#
10
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License along
15
# with Koha; if not, write to the Free Software Foundation, Inc.,
16
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18
use Modern::Perl;
19
20
use Mojo::Base 'Mojolicious::Controller';
21
22
use C4::Auth qw( haspermission );
23
use C4::Circulation;
24
use Koha::Issues;
25
26
sub list {
27
    my ($c, $args, $cb) = @_;
28
29
    my $user = $c->stash('koha.user');
30
    unless ($user && haspermission($user->userid, { circulate => "circulate_remaining_permissions" })) {
31
        return $c->$cb({error => "You don't have the required permission"}, 403);
32
    }
33
34
    my $borrowernumber = $c->param('borrowernumber');
35
    my $checkouts = C4::Circulation::GetIssues({
36
        borrowernumber => $borrowernumber
37
    });
38
39
    $c->$cb($checkouts, 200);
40
}
41
42
sub get {
43
    my ($c, $args, $cb) = @_;
44
45
    my $user = $c->stash('koha.user');
46
    unless ($user && haspermission($user->userid, { circulate => "circulate_remaining_permissions" })) {
47
        return $c->$cb({error => "You don't have the required permission"}, 403);
48
    }
49
50
    my $checkout_id = $args->{checkout_id};
51
    my $checkout = Koha::Issues->find($checkout_id);
52
53
    if (!$checkout) {
54
        return $c->$cb({
55
            error => "Checkout doesn't exist"
56
        }, 404);
57
    }
58
59
    return $c->$cb($checkout->unblessed, 200);
60
}
61
62
sub renew {
63
    my ($c, $args, $cb) = @_;
64
65
    my $user = $c->stash('koha.user');
66
    unless ($user && haspermission($user->userid, { circulate => "circulate_remaining_permissions" })) {
67
        return $c->$cb({error => "You don't have the required permission"}, 403);
68
    }
69
70
    my $checkout_id = $args->{checkout_id};
71
    my $checkout = Koha::Issues->find($checkout_id);
72
73
    if (!$checkout) {
74
        return $c->$cb({
75
            error => "Checkout doesn't exists"
76
        }, 404);
77
    }
78
79
    $checkout = $checkout->unblessed;
80
    my ($borrowernumber, $itemnumber) = @$checkout{qw(borrowernumber itemnumber)};
81
    my ($can_renew, $error) = C4::Circulation::CanBookBeRenewed(
82
        $borrowernumber, $itemnumber);
83
84
    if (!$can_renew) {
85
        return $c->$cb({error => "Renewal not authorized ($error)"}, 403);
86
    }
87
88
    AddRenewal($borrowernumber, $itemnumber, $checkout->{branchcode});
89
    $checkout = Koha::Issues->find($checkout_id);
90
91
    return $c->$cb($checkout->unblessed, 200);
92
}
93
94
1;
(-)a/api/v1/definitions/checkout.json (+51 lines)
Line 0 Link Here
1
{
2
    "type": "object",
3
    "properties": {
4
        "issue_id": {
5
          "type": "string",
6
          "description": "internally assigned checkout identifier"
7
        },
8
        "borrowernumber": {
9
            "type": "string",
10
            "description": "internally assigned user identifier"
11
        },
12
        "itemnumber": {
13
            "type": "string",
14
            "description": "internally assigned item identifier"
15
        },
16
        "date_due": {
17
            "description": "Due date"
18
        },
19
        "branchcode": {
20
            "type": ["string", "null"],
21
            "description": "code of patron's home branch"
22
        },
23
        "issuingbranch": {
24
            "description": "Code of the branch where issue was made"
25
        },
26
        "returndate": {
27
            "description": "Date the item was returned"
28
        },
29
        "lastreneweddate": {
30
            "description": "Date the item was last renewed"
31
        },
32
        "return": {
33
            "description": "?"
34
        },
35
        "renewals": {
36
            "description": "Number of renewals"
37
        },
38
        "auto_renew": {
39
            "description": "Auto renewal"
40
        },
41
        "timestamp": {
42
            "description": "Last update time"
43
        },
44
        "issuedate": {
45
            "description": "Date the item was issued"
46
        },
47
        "onsite_checkout": {
48
            "description": "On site checkout"
49
        }
50
    }
51
}
(-)a/api/v1/definitions/checkouts.json (+6 lines)
Line 0 Link Here
1
{
2
    "type": "array",
3
    "items": {
4
        "$ref": "./checkout.json"
5
    }
6
}
(-)a/api/v1/definitions/index.json (+2 lines)
Lines 1-4 Link Here
1
{
1
{
2
    "patron": { "$ref": "patron.json" },
2
    "patron": { "$ref": "patron.json" },
3
    "checkouts": { "$ref": "checkouts.json" },
4
    "checkout": { "$ref": "checkout.json" },
3
    "error": { "$ref": "error.json" }
5
    "error": { "$ref": "error.json" }
4
}
6
}
(-)a/api/v1/swagger.json (+94 lines)
Lines 73-78 Link Here
73
          }
73
          }
74
        }
74
        }
75
      }
75
      }
76
    },
77
    "/checkouts": {
78
      "get": {
79
        "operationId": "listCheckouts",
80
        "tags": ["borrowers", "checkouts"],
81
        "parameters": [
82
          {
83
            "name": "borrowernumber",
84
            "in": "query",
85
            "description": "Internal patron identifier",
86
            "required": false,
87
            "type": "integer"
88
          }
89
        ],
90
        "produces": [
91
          "application/json"
92
        ],
93
        "responses": {
94
          "200": {
95
            "description": "A list of checkouts",
96
            "schema": {
97
              "$ref": "#/definitions/checkouts"
98
            }
99
          },
100
          "403": {
101
            "description": "Access forbidden",
102
            "schema": { "$ref": "#/definitions/error" }
103
          },
104
          "404": {
105
            "description": "Borrower not found",
106
            "schema": {
107
              "$ref": "#/definitions/error"
108
            }
109
          }
110
        }
111
      }
112
    },
113
    "/checkouts/{checkout_id}": {
114
      "get": {
115
        "operationId": "getCheckout",
116
        "tags": ["borrowers", "checkouts"],
117
        "parameters": [
118
          {
119
            "name": "checkout_id",
120
            "in": "path",
121
            "description": "Internal checkout identifier",
122
            "required": true,
123
            "type": "integer"
124
          }
125
        ],
126
        "produces": ["application/json"],
127
        "responses": {
128
          "200": {
129
            "description": "Updated borrower's checkout",
130
            "schema": { "$ref": "#/definitions/checkout" }
131
          },
132
          "403": {
133
            "description": "Access forbidden",
134
            "schema": { "$ref": "#/definitions/error" }
135
          },
136
          "404": {
137
            "description": "Checkout not found",
138
            "schema": { "$ref": "#/definitions/error" }
139
          }
140
        }
141
      },
142
      "put": {
143
        "operationId": "renewCheckout",
144
        "tags": ["borrowers", "checkouts"],
145
        "parameters": [
146
          {
147
            "name": "checkout_id",
148
            "in": "path",
149
            "description": "Internal checkout identifier",
150
            "required": true,
151
            "type": "integer"
152
          }
153
        ],
154
        "produces": ["application/json"],
155
        "responses": {
156
          "200": {
157
            "description": "Updated borrower's checkout",
158
            "schema": { "$ref": "#/definitions/checkout" }
159
          },
160
          "403": {
161
            "description": "Cannot renew checkout",
162
            "schema": { "$ref": "#/definitions/error" }
163
          },
164
          "404": {
165
            "description": "Checkout not found",
166
            "schema": { "$ref": "#/definitions/error" }
167
          }
168
        }
169
      }
76
    }
170
    }
77
  },
171
  },
78
  "definitions": {
172
  "definitions": {
(-)a/t/db_dependent/api/v1/checkouts.t (-1 / +154 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it under the
6
# terms of the GNU General Public License as published by the Free Software
7
# Foundation; either version 3 of the License, or (at your option) any later
8
# version.
9
#
10
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License along
15
# with Koha; if not, write to the Free Software Foundation, Inc.,
16
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18
use Modern::Perl;
19
20
use Test::More tests => 27;
21
use Test::MockModule;
22
use Test::Mojo;
23
use t::lib::TestBuilder;
24
25
use DateTime;
26
use MARC::Record;
27
28
use C4::Context;
29
use C4::Biblio;
30
use C4::Circulation;
31
use C4::Items;
32
33
use Koha::Database;
34
use Koha::Patron;
35
36
my $dbh = C4::Context->dbh;
37
$dbh->{AutoCommit} = 0;
38
$dbh->{RaiseError} = 1;
39
40
$ENV{REMOTE_ADDR} = '127.0.0.1';
41
my $t = Test::Mojo->new('Koha::REST::V1');
42
43
my $builder = t::lib::TestBuilder->new();
44
45
my $loggedinuser = $builder->build({ source => 'Borrower' });
46
47
$dbh->do(q{
48
    INSERT INTO user_permissions (borrowernumber, module_bit, code)
49
    VALUES (?, 1, 'circulate_remaining_permissions')
50
}, undef, $loggedinuser->{borrowernumber});
51
52
my $session = C4::Auth::get_session('');
53
$session->param('number', $loggedinuser->{ borrowernumber });
54
$session->param('id', $loggedinuser->{ userid });
55
$session->param('ip', '127.0.0.1');
56
$session->param('lasttime', time());
57
$session->flush;
58
59
my $borrower = $builder->build({ source => 'Borrower' });
60
my $borrowernumber = $borrower->{borrowernumber};
61
62
my $tx = $t->ua->build_tx(GET => "/api/v1/checkouts?borrowernumber=$borrowernumber");
63
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
64
$t->request_ok($tx)
65
  ->status_is(200)
66
  ->json_is([]);
67
68
my $notexisting_borrowernumber = $borrowernumber + 1;
69
$tx = $t->ua->build_tx(GET => "/api/v1/checkouts?borrowernumber=$notexisting_borrowernumber");
70
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
71
$t->request_ok($tx)
72
  ->status_is(200)
73
  ->json_is([]);
74
75
my $biblionumber = create_biblio('RESTful Web APIs');
76
my $itemnumber1 = create_item($biblionumber, 'TEST000001');
77
my $itemnumber2 = create_item($biblionumber, 'TEST000002');
78
79
my $date_due = DateTime->now->add(weeks => 2);
80
my $issue1 = C4::Circulation::AddIssue($borrower, 'TEST000001', $date_due);
81
my $date_due1 = Koha::DateUtils::dt_from_string( $issue1->date_due );
82
my $issue2 = C4::Circulation::AddIssue($borrower, 'TEST000002', $date_due);
83
my $date_due2 = Koha::DateUtils::dt_from_string( $issue2->date_due );
84
85
$tx = $t->ua->build_tx(GET => "/api/v1/checkouts?borrowernumber=$borrowernumber");
86
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
87
$t->request_ok($tx)
88
  ->status_is(200)
89
  ->json_is('/0/borrowernumber' => $borrowernumber)
90
  ->json_is('/0/itemnumber' => $itemnumber1)
91
  ->json_is('/0/date_due' => $date_due1->ymd . ' ' . $date_due1->hms)
92
  ->json_is('/1/borrowernumber' => $borrowernumber)
93
  ->json_is('/1/itemnumber' => $itemnumber2)
94
  ->json_is('/1/date_due' => $date_due2->ymd . ' ' . $date_due2->hms)
95
  ->json_hasnt('/2');
96
97
$tx = $t->ua->build_tx(GET => "/api/v1/checkouts/" . $issue1->issue_id);
98
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
99
$t->request_ok($tx)
100
  ->status_is(200)
101
  ->json_is('/date_due' => $date_due1->ymd . ' ' . $date_due1->hms);
102
103
$tx = $t->ua->build_tx(GET => "/api/v1/checkouts/" . $issue2->issue_id);
104
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
105
$t->request_ok($tx)
106
  ->status_is(200)
107
  ->json_is('/date_due' => $date_due2->ymd . ' ' . $date_due2->hms);
108
109
110
$dbh->do('DELETE FROM issuingrules');
111
$dbh->do(q{
112
    INSERT INTO issuingrules (categorycode, branchcode, itemtype, issuelength, renewalsallowed)
113
    VALUES (?, ?, ?, ?, ?)
114
}, {}, '*', '*', '*', 7, 1);
115
116
my $expected_datedue = DateTime->now->add(days => 7)->set(hour => 23, minute => 59, second => 0);
117
$tx = $t->ua->build_tx(PUT => "/api/v1/checkouts/" . $issue1->issue_id);
118
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
119
$t->request_ok($tx)
120
  ->status_is(200)
121
  ->json_is('/date_due' => $expected_datedue->ymd . ' ' . $expected_datedue->hms);
122
123
$tx = $t->ua->build_tx(PUT => "/api/v1/checkouts/" . $issue1->issue_id);
124
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
125
$t->request_ok($tx)
126
  ->status_is(403)
127
  ->json_is({ error => 'Renewal not authorized (too_many)' });
128
129
$dbh->rollback;
130
131
sub create_biblio {
132
    my ($title) = @_;
133
134
    my $record = new MARC::Record;
135
    $record->append_fields(
136
        new MARC::Field('200', ' ', ' ', a => $title),
137
    );
138
139
    my ($biblionumber) = C4::Biblio::AddBiblio($record, '');
140
141
    return $biblionumber;
142
}
143
144
sub create_item {
145
    my ($biblionumber, $barcode) = @_;
146
147
    my $item = {
148
        barcode => $barcode,
149
    };
150
151
    my $itemnumber = C4::Items::AddItem($item, $biblionumber);
152
153
    return $itemnumber;
154
}

Return to bug 13895