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

(-)a/Koha/REST/V1/Borrowers/Issues.pm (+60 lines)
Line 0 Link Here
1
package Koha::REST::V1::Borrowers::Issues;
2
3
use Modern::Perl;
4
5
use Mojo::Base 'Mojolicious::Controller';
6
7
use C4::Circulation;
8
9
sub list_borrower_issues {
10
    my ($c, $args, $cb) = @_;
11
12
    my $issues = C4::Circulation::GetIssues({
13
        borrowernumber => $args->{borrowernumber}
14
    });
15
16
    $c->$cb($issues, 200);
17
}
18
19
sub get_borrower_issue {
20
    my ($c, $args, $cb) = @_;
21
22
    my $borrowernumber = $args->{borrowernumber};
23
    my $itemnumber = $args->{itemnumber};
24
25
    my ($issue) = @{ C4::Circulation::GetIssues({ itemnumber => $itemnumber }) };
26
    if (!$issue or $borrowernumber != $issue->{borrowernumber}) {
27
        return $c->$cb({
28
            error => "Item $itemnumber is not issued to borrower $borrowernumber"
29
        }, 404);
30
    }
31
32
    return $c->$cb($issue, 200);
33
}
34
35
sub renew_borrower_issue {
36
    my ($c, $args, $cb) = @_;
37
38
    my $borrowernumber = $args->{borrowernumber};
39
    my $itemnumber = $args->{itemnumber};
40
41
    my ($issue) = @{ C4::Circulation::GetIssues({ itemnumber => $itemnumber }) };
42
    if (!$issue or $borrowernumber != $issue->{borrowernumber}) {
43
        return $c->$cb({
44
            error => "Item $itemnumber is not issued to borrower $borrowernumber"
45
        }, 404);
46
    }
47
48
    my ($can_renew, $error) = C4::Circulation::CanBookBeRenewed($borrowernumber,
49
        $itemnumber);
50
    if (!$can_renew) {
51
        return $c->$cb({error => "Renewal not authorized ($error)"}, 403);
52
    }
53
54
    AddRenewal($borrowernumber, $itemnumber, $issue->{branchcode});
55
    ($issue) = @{ C4::Circulation::GetIssues({ itemnumber => $itemnumber }) };
56
57
    return $c->$cb($issue, 200);
58
}
59
60
1;
(-)a/api/v1/swagger.json (+138 lines)
Lines 63-68 Link Here
63
          }
63
          }
64
        }
64
        }
65
      }
65
      }
66
    },
67
    "/borrowers/{borrowernumber}/issues": {
68
      "get": {
69
        "x-mojo-controller": "Koha::REST::V1::Borrowers::Issues",
70
        "operationId": "listBorrowerIssues",
71
        "tags": ["borrowers", "issues"],
72
        "parameters": [
73
          {
74
            "$ref": "#/parameters/borrowernumberPathParam"
75
          }
76
        ],
77
        "produces": [
78
          "application/json"
79
        ],
80
        "responses": {
81
          "200": {
82
            "description": "A list of issues",
83
            "schema": {
84
              "$ref": "#/definitions/issues"
85
            }
86
          },
87
          "404": {
88
            "description": "Borrower not found",
89
            "schema": {
90
              "$ref": "#/definitions/error"
91
            }
92
          }
93
        }
94
      }
95
    },
96
    "/borrowers/{borrowernumber}/issues/{itemnumber}": {
97
      "get": {
98
        "x-mojo-controller": "Koha::REST::V1::Borrowers::Issues",
99
        "operationId": "getBorrowerIssue",
100
        "tags": ["borrowers", "issues"],
101
        "parameters": [
102
          { "$ref": "#/parameters/borrowernumberPathParam" },
103
          { "$ref": "#/parameters/itemnumberPathParam" }
104
        ],
105
        "produces": ["application/json"],
106
        "responses": {
107
          "200": {
108
            "description": "Updated borrower's issue",
109
            "schema": { "$ref": "#/definitions/issue" }
110
          },
111
          "404": {
112
            "description": "Issue not found",
113
            "schema": { "$ref": "#/definitions/error" }
114
          }
115
        }
116
      },
117
      "put": {
118
        "x-mojo-controller": "Koha::REST::V1::Borrowers::Issues",
119
        "operationId": "renewBorrowerIssue",
120
        "tags": ["borrowers", "issues"],
121
        "parameters": [
122
          { "$ref": "#/parameters/borrowernumberPathParam" },
123
          { "$ref": "#/parameters/itemnumberPathParam" }
124
        ],
125
        "produces": ["application/json"],
126
        "responses": {
127
          "200": {
128
            "description": "Updated borrower's issue",
129
            "schema": { "$ref": "#/definitions/issue" }
130
          },
131
          "403": {
132
            "description": "Cannot renew issue",
133
            "schema": { "$ref": "#/definitions/error" }
134
          },
135
          "404": {
136
            "description": "Issue not found",
137
            "schema": { "$ref": "#/definitions/error" }
138
          }
139
        }
140
      }
66
    }
141
    }
67
  },
142
  },
68
  "definitions": {
143
  "definitions": {
Lines 83-91 Link Here
83
        }
158
        }
84
      }
159
      }
85
    },
160
    },
161
    "issues": {
162
      "type": "array",
163
      "items": {
164
        "$ref": "#/definitions/issue"
165
      }
166
    },
167
    "issue": {
168
      "type": "object",
169
      "properties": {
170
        "borrowernumber": {
171
          "$ref": "#/definitions/borrowernumber"
172
        },
173
        "itemnumber": {
174
          "$ref": "#/definitions/itemnumber"
175
        },
176
        "date_due": {
177
          "description": "Due date"
178
        },
179
        "branchcode": {
180
          "$ref": "#/definitions/branchcode"
181
        },
182
        "issuingbranch": {
183
          "description": "Code of the branch where issue was made"
184
        },
185
        "returndate": {
186
          "description": "Date the item was returned"
187
        },
188
        "lastreneweddate": {
189
          "description": "Date the item was last renewed"
190
        },
191
        "return": {
192
          "description": "?"
193
        },
194
        "renewals": {
195
          "description": "Number of renewals"
196
        },
197
        "auto_renew": {
198
          "description": "Auto renewal"
199
        },
200
        "timestamp": {
201
          "description": "Last update time"
202
        },
203
        "issuedate": {
204
          "description": "Date the item was issued"
205
        },
206
        "onsite_checkout": {
207
          "description": "On site checkout"
208
        }
209
      }
210
    },
86
    "borrowernumber": {
211
    "borrowernumber": {
87
      "description": "Borrower internal identifier"
212
      "description": "Borrower internal identifier"
88
    },
213
    },
214
    "branchcode": {
215
      "description": "Branch code"
216
    },
217
    "itemnumber": {
218
      "description": "Item internal identifier"
219
    },
89
    "error": {
220
    "error": {
90
      "type": "object",
221
      "type": "object",
91
      "properties": {
222
      "properties": {
Lines 103-108 Link Here
103
      "description": "Internal borrower identifier",
234
      "description": "Internal borrower identifier",
104
      "required": "true",
235
      "required": "true",
105
      "type": "integer"
236
      "type": "integer"
237
    },
238
    "itemnumberPathParam": {
239
      "name": "itemnumber",
240
      "in": "path",
241
      "description": "Internal item identifier",
242
      "required": "true",
243
      "type": "integer"
106
    }
244
    }
107
  }
245
  }
108
}
246
}
(-)a/t/db_dependent/api/v1/borrowers/issues.t (-1 / +129 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
use Modern::Perl;
4
5
use Test::More tests => 33;
6
use Test::MockModule;
7
use Test::Mojo;
8
9
use DateTime;
10
use MARC::Record;
11
12
use C4::Context;
13
use C4::Biblio;
14
use C4::Circulation;
15
use C4::Items;
16
17
use Koha::Database;
18
use Koha::Borrower;
19
20
my $dbh = C4::Context->dbh;
21
$dbh->{AutoCommit} = 0;
22
$dbh->{RaiseError} = 1;
23
24
my $c4_context = new Test::MockModule('C4::Context');
25
$c4_context->mock('userenv', \&Mock_userenv);
26
27
my $t = Test::Mojo->new('Koha::REST::V1');
28
29
my $schema = Koha::Database->new->schema;
30
my $categorycode = $schema->resultset('Category')->first->categorycode;
31
my $branchcode = $schema->resultset('Branch')->first->branchcode;
32
33
my $borrower = Koha::Borrower->new;
34
$borrower->categorycode( $categorycode );
35
$borrower->branchcode( $branchcode );
36
$borrower->surname("Test Surname");
37
$borrower->store;
38
my $borrowernumber = $borrower->borrowernumber;
39
40
$t->get_ok("/v1/borrowers/$borrowernumber/issues")
41
  ->status_is(200)
42
  ->json_is([]);
43
44
my $notexisting_borrowernumber = $borrowernumber + 1;
45
$t->get_ok("/v1/borrowers/$notexisting_borrowernumber/issues")
46
  ->status_is(200)
47
  ->json_is([]);
48
49
my $biblionumber = create_biblio('RESTful Web APIs');
50
my $itemnumber1 = create_item($biblionumber, 'TEST000001');
51
my $itemnumber2 = create_item($biblionumber, 'TEST000002');
52
53
my $date_due = DateTime->now->add(weeks => 2);
54
my $date_due1 = C4::Circulation::AddIssue($borrower->unblessed, 'TEST000001', $date_due);
55
my $date_due2 = C4::Circulation::AddIssue($borrower->unblessed, 'TEST000002', $date_due);
56
57
$t->get_ok("/v1/borrowers/$borrowernumber/issues")
58
  ->status_is(200)
59
  ->json_is('/0/borrowernumber' => $borrowernumber)
60
  ->json_is('/0/itemnumber' => $itemnumber1)
61
  ->json_is('/0/date_due' => $date_due1->ymd . ' ' . $date_due1->hms)
62
  ->json_is('/1/borrowernumber' => $borrowernumber)
63
  ->json_is('/1/itemnumber' => $itemnumber2)
64
  ->json_is('/1/date_due' => $date_due2->ymd . ' ' . $date_due2->hms)
65
  ->json_hasnt('/2');
66
67
$t->get_ok("/v1/borrowers/$borrowernumber/issues/$itemnumber1")
68
  ->status_is(200)
69
  ->json_is('/date_due' => $date_due1->ymd . ' ' . $date_due1->hms);
70
71
$t->get_ok("/v1/borrowers/$borrowernumber/issues/$itemnumber2")
72
  ->status_is(200)
73
  ->json_is('/date_due' => $date_due2->ymd . ' ' . $date_due2->hms);
74
75
76
$dbh->do('DELETE FROM issuingrules');
77
$dbh->do(q{
78
    INSERT INTO issuingrules (categorycode, branchcode, itemtype, issuelength, renewalsallowed)
79
    VALUES (?, ?, ?, ?, ?)
80
}, {}, '*', '*', '*', 7, 1);
81
82
my $expected_datedue = DateTime->now->add(days => 7)->set(hour => 23, minute => 59, second => 0);
83
$t->put_ok("/v1/borrowers/$borrowernumber/issues/$itemnumber1")
84
  ->status_is(200)
85
  ->json_is('/date_due' => $expected_datedue->ymd . ' ' . $expected_datedue->hms);
86
87
$t->put_ok("/v1/borrowers/$borrowernumber/issues/$itemnumber1")
88
  ->status_is(403)
89
  ->json_is({ error => 'Renewal not authorized (too_many)' });
90
91
$t->put_ok("/v1/borrowers/$notexisting_borrowernumber/issues/$itemnumber1")
92
  ->status_is(404)
93
  ->json_is({ error => "Item $itemnumber1 is not issued to borrower $notexisting_borrowernumber" });
94
95
my $notexisting_itemnumber = $itemnumber2 + 1;
96
$t->put_ok("/v1/borrowers/$borrowernumber/issues/$notexisting_itemnumber")
97
  ->status_is(404)
98
  ->json_is({ error => "Item $notexisting_itemnumber is not issued to borrower $borrowernumber" });
99
100
$dbh->rollback;
101
102
sub create_biblio {
103
    my ($title) = @_;
104
105
    my $record = new MARC::Record;
106
    $record->append_fields(
107
        new MARC::Field('200', ' ', ' ', a => $title),
108
    );
109
110
    my ($biblionumber) = C4::Biblio::AddBiblio($record, '');
111
112
    return $biblionumber;
113
}
114
115
sub create_item {
116
    my ($biblionumber, $barcode) = @_;
117
118
    my $item = {
119
        barcode => $barcode,
120
    };
121
122
    my $itemnumber = C4::Items::AddItem($item, $biblionumber);
123
124
    return $itemnumber;
125
}
126
127
sub Mock_userenv {
128
    return { branch => $branchcode };
129
}

Return to bug 13895