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

(-)a/Koha/REST/V1/Accountline.pm (+37 lines)
Lines 19-26 use Modern::Perl; Link Here
19
19
20
use Mojo::Base 'Mojolicious::Controller';
20
use Mojo::Base 'Mojolicious::Controller';
21
21
22
use Scalar::Util qw( looks_like_number );
23
22
use C4::Auth qw( haspermission );
24
use C4::Auth qw( haspermission );
23
use Koha::Account::Lines;
25
use Koha::Account::Lines;
26
use Koha::Account;
24
27
25
sub list {
28
sub list {
26
    my ($c, $args, $cb) = @_;
29
    my ($c, $args, $cb) = @_;
Lines 48-51 sub edit { Link Here
48
    return $c->$cb($accountline->unblessed(), 200);
51
    return $c->$cb($accountline->unblessed(), 200);
49
}
52
}
50
53
54
55
sub pay {
56
    my ($c, $args, $cb) = @_;
57
58
    my $accountline = Koha::Account::Lines->find($args->{accountlines_id});
59
    unless ($accountline) {
60
        return $c->$cb({error => "Accountline not found"}, 404);
61
    }
62
63
    my $body = $c->req->json;
64
    my $amount = defined $body->{amount};
65
    my $note = $body->{note} || '';
66
67
    if ($amount && !looks_like_number($amount)) {
68
        return $c->$cb({error => "Invalid amount"}, 400);
69
    }
70
71
    Koha::Account->new(
72
        {
73
            patron_id => $accountline->borrowernumber,
74
        }
75
      )->pay(
76
        {
77
            lines  => [$accountline],
78
            amount => $amount,
79
            note => $note,
80
        }
81
      );
82
83
    $accountline = Koha::Account::Lines->find($args->{accountlines_id});
84
    return $c->$cb($accountline->unblessed(), 200);
85
}
86
87
51
1;
88
1;
(-)a/Koha/REST/V1/Patron.pm (+34 lines)
Lines 19-25 use Modern::Perl; Link Here
19
19
20
use Mojo::Base 'Mojolicious::Controller';
20
use Mojo::Base 'Mojolicious::Controller';
21
21
22
use Scalar::Util qw( looks_like_number );
23
24
use C4::Auth qw( haspermission );
22
use Koha::Patrons;
25
use Koha::Patrons;
26
use Koha::Account;
23
27
24
sub list {
28
sub list {
25
    my ($c, $args, $cb) = @_;
29
    my ($c, $args, $cb) = @_;
Lines 44-47 sub get { Link Here
44
    return $c->$cb($patron, 200);
48
    return $c->$cb($patron, 200);
45
}
49
}
46
50
51
sub pay {
52
    my ($c, $args, $cb) = @_;
53
54
    my $patron = Koha::Patrons->find($args->{borrowernumber});
55
    unless ($patron) {
56
        return $c->$cb({error => "Patron not found"}, 404);
57
    }
58
59
    my $body = $c->req->json;
60
    my $amount = $body->{amount};
61
    my $note = $body->{note} || '';
62
63
    unless ($amount && looks_like_number($amount)) {
64
        return $c->$cb({error => "Invalid amount"}, 400);
65
    }
66
67
    Koha::Account->new(
68
        {
69
            patron_id => $args->{borrowernumber},
70
        }
71
      )->pay(
72
        {
73
            amount => $amount,
74
            note => $note,
75
        }
76
      );
77
78
    return $c->$cb('', 204);
79
}
80
47
1;
81
1;
(-)a/api/v1/swagger/paths.json (+6 lines)
Lines 11-16 Link Here
11
  "/accountlines/{accountlines_id}": {
11
  "/accountlines/{accountlines_id}": {
12
    "$ref": "paths/accountlines.json#/~1accountlines~1{accountlines_id}"
12
    "$ref": "paths/accountlines.json#/~1accountlines~1{accountlines_id}"
13
  },
13
  },
14
  "/accountlines/{accountlines_id}/payment": {
15
    "$ref": "paths/accountlines.json#/~1accountlines~1{accountlines_id}~1payment"
16
  },
14
  "/holds": {
17
  "/holds": {
15
    "$ref": "paths/holds.json#/~1holds"
18
    "$ref": "paths/holds.json#/~1holds"
16
  },
19
  },
Lines 22-26 Link Here
22
  },
25
  },
23
  "/patrons/{borrowernumber}": {
26
  "/patrons/{borrowernumber}": {
24
    "$ref": "paths/patrons.json#/~1patrons~1{borrowernumber}"
27
    "$ref": "paths/patrons.json#/~1patrons~1{borrowernumber}"
28
  },
29
  "/patrons/{borrowernumber}/payment": {
30
    "$ref": "paths/patrons.json#/~1patrons~1{borrowernumber}~1payment"
25
  }
31
  }
26
}
32
}
(-)a/api/v1/swagger/paths/accountlines.json (+55 lines)
Lines 93-97 Link Here
93
        }
93
        }
94
      }
94
      }
95
    }
95
    }
96
  },
97
  "/accountlines/{accountlines_id}/payment": {
98
    "post": {
99
      "operationId": "payAccountlines",
100
      "tags": ["accountlines"],
101
      "produces": [
102
        "application/json"
103
      ],
104
      "parameters": [
105
        { "$ref": "../parameters.json#/accountlinesIdPathParam" },
106
        {
107
          "name": "body",
108
          "in": "body",
109
          "description": "A JSON object containing fields to modify",
110
          "schema": {
111
            "type": "object",
112
            "properties": {
113
              "amount": {
114
                "description": "Amount to pay"
115
              },
116
              "note": {
117
                "description": "Payment note"
118
              }
119
            }
120
          }
121
        }
122
      ],
123
      "consumes": ["application/json"],
124
      "produces": ["application/json"],
125
      "responses": {
126
        "200": {
127
          "description": "Paid accountline",
128
          "schema": { "$ref": "../definitions.json#/accountline" }
129
        },
130
        "400": {
131
          "description": "Missing or wrong parameters",
132
          "schema": { "$ref": "../definitions.json#/error" }
133
        },
134
        "403": {
135
          "description": "Access forbidden",
136
          "schema": {
137
            "$ref": "../definitions.json#/error"
138
          }
139
        },
140
        "404": {
141
          "description": "Accountline not found",
142
          "schema": { "$ref": "../definitions.json#/error" }
143
        }
144
      },
145
      "x-koha-authorization": {
146
        "permissions": {
147
          "updatecharges": "1"
148
        }
149
      }
150
    }
96
  }
151
  }
97
}
152
}
(-)a/api/v1/swagger/paths/patrons.json (+55 lines)
Lines 69-73 Link Here
69
        }
69
        }
70
      }
70
      }
71
    }
71
    }
72
  },
73
  "/patrons/{borrowernumber}/payment": {
74
    "post": {
75
      "operationId": "payForPatron",
76
      "tags": ["accountlines"],
77
      "produces": [
78
        "application/json"
79
      ],
80
      "parameters": [
81
        { "$ref": "../parameters.json#/borrowernumberPathParam" },
82
        {
83
          "name": "body",
84
          "in": "body",
85
          "description": "A JSON object containing fields to modify",
86
          "required": true,
87
          "schema": {
88
            "type": "object",
89
            "properties": {
90
              "amount": {
91
                "description": "Amount to pay"
92
              },
93
              "note": {
94
                "description": "Payment note"
95
              }
96
            }
97
          }
98
        }
99
      ],
100
      "consumes": ["application/json"],
101
      "produces": ["application/json"],
102
      "responses": {
103
        "204": {
104
          "description": "Success"
105
        },
106
        "400": {
107
          "description": "Missing or wrong parameters",
108
          "schema": { "$ref": "../definitions.json#/error" }
109
        },
110
        "403": {
111
          "description": "Access forbidden",
112
          "schema": {
113
            "$ref": "../definitions.json#/error"
114
          }
115
        },
116
        "404": {
117
          "description": "Borrower not found",
118
          "schema": { "$ref": "../definitions.json#/error" }
119
        }
120
      },
121
      "x-koha-authorization": {
122
        "permissions": {
123
          "updatecharges": "1"
124
        }
125
      }
126
    }
72
  }
127
  }
73
}
128
}
(-)a/t/db_dependent/api/v1/accountlines.t (-5 / +57 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 22;
20
21
use Test::More tests => 37;
21
use Test::Mojo;
22
use Test::Mojo;
22
use t::lib::TestBuilder;
23
use t::lib::TestBuilder;
23
24
Lines 45-50 $t->get_ok('/api/v1/accountlines') Link Here
45
$t->put_ok("/api/v1/accountlines/11224409" => json => {'amount' => -5})
46
$t->put_ok("/api/v1/accountlines/11224409" => json => {'amount' => -5})
46
    ->status_is(401);
47
    ->status_is(401);
47
48
49
$t->post_ok("/api/v1/accountlines/11224408/payment")
50
    ->status_is(401);
51
48
my $loggedinuser = $builder->build({
52
my $loggedinuser = $builder->build({
49
    source => 'Borrower',
53
    source => 'Borrower',
50
    value => {
54
    value => {
Lines 75-82 my $borrowernumber2 = $borrower2->{borrowernumber}; Link Here
75
79
76
$dbh->do(q| DELETE FROM accountlines |);
80
$dbh->do(q| DELETE FROM accountlines |);
77
$dbh->do(q|
81
$dbh->do(q|
78
    INSERT INTO accountlines (borrowernumber, amount, accounttype)
82
    INSERT INTO accountlines (borrowernumber, amount, accounttype, amountoutstanding)
79
    VALUES (?, 20, 'A'), (?, 40, 'F'), (?, 80, 'F'), (?, 10, 'F')
83
    VALUES (?, 20, 'A', 20), (?, 40, 'F', 40), (?, 80, 'F', 80), (?, 10, 'F', 10)
80
    |, undef, $borrowernumber, $borrowernumber, $borrowernumber, $borrowernumber2);
84
    |, undef, $borrowernumber, $borrowernumber, $borrowernumber, $borrowernumber2);
81
85
82
my $session = C4::Auth::get_session('');
86
my $session = C4::Auth::get_session('');
Lines 127-133 my $put_data = { Link Here
127
131
128
$tx = $t->ua->build_tx(
132
$tx = $t->ua->build_tx(
129
    PUT => "/api/v1/accountlines/11224409"
133
    PUT => "/api/v1/accountlines/11224409"
130
        => {Accept => '*/*'}
131
        => json => $put_data);
134
        => json => $put_data);
132
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
135
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
133
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
136
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
Lines 144-150 $t->request_ok($tx) Link Here
144
147
145
$tx = $t->ua->build_tx(
148
$tx = $t->ua->build_tx(
146
    PUT => "/api/v1/accountlines/$accountline_to_edit->{accountlines_id}"
149
    PUT => "/api/v1/accountlines/$accountline_to_edit->{accountlines_id}"
147
        => {Accept => '*/*'}
148
        => json => $put_data);
150
        => json => $put_data);
149
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
151
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
150
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
152
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
Lines 158-162 is($accountline_edited->{amountoutstanding}, '-19.000000'); Link Here
158
160
159
161
160
# Payment tests
162
# Payment tests
163
$tx = $t->ua->build_tx(POST => "/api/v1/accountlines/4562765765/payment");
164
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
165
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
166
$t->request_ok($tx)
167
  ->status_is(404);
168
169
my $accountline_to_pay = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber, 'amount' => 20})->unblessed()->[0];
170
$tx = $t->ua->build_tx(POST => "/api/v1/accountlines/$accountline_to_pay->{accountlines_id}/payment");
171
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
172
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
173
$t->request_ok($tx)
174
  ->status_is(200);
175
#$t->content_is('toto');
176
177
my $accountline_paid = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber, 'amount' => -20})->unblessed()->[0];
178
ok($accountline_paid);
179
180
# Partial payment tests
181
my $post_data = {
182
    'amount' => 17,
183
    'note' => 'Partial payment'
184
};
185
186
$tx = $t->ua->build_tx(
187
    POST => "/api/v1/accountlines/11224419/payment"
188
        => json => $post_data);
189
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
190
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
191
$t->request_ok($tx)
192
    ->status_is(404);
193
194
my $accountline_to_partiallypay = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber, 'amount' => 80})->unblessed()->[0];
195
196
$tx = $t->ua->build_tx(POST => "/api/v1/accountlines/$accountline_to_partiallypay->{accountlines_id}/payment" => json => {amount => 'foo'});
197
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
198
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
199
$t->request_ok($tx)
200
  ->status_is(400);
201
202
$tx = $t->ua->build_tx(POST => "/api/v1/accountlines/$accountline_to_partiallypay->{accountlines_id}/payment" => json => $post_data);
203
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
204
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
205
$t->request_ok($tx)
206
  ->status_is(200);
207
208
$accountline_to_partiallypay = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber, 'amount' => 80})->unblessed()->[0];
209
is($accountline_to_partiallypay->{amountoutstanding}, '63.000000');
210
211
my $accountline_partiallypaid = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber, 'amount' => -17})->unblessed()->[0];
212
ok($accountline_partiallypaid);
161
213
162
$dbh->rollback;
214
$dbh->rollback;
(-)a/t/db_dependent/api/v1/patrons.t (-3 / +55 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 21;
20
use Test::More tests => 32;
21
use Test::Mojo;
21
use Test::Mojo;
22
use t::lib::TestBuilder;
22
use t::lib::TestBuilder;
23
23
Lines 26-31 use C4::Context; Link Here
26
26
27
use Koha::Database;
27
use Koha::Database;
28
use Koha::Patron;
28
use Koha::Patron;
29
use Koha::Account::Lines;
29
30
30
my $builder = t::lib::TestBuilder->new();
31
my $builder = t::lib::TestBuilder->new();
31
32
Lines 106-112 my $loggedinuser = $builder->build({ Link Here
106
    value => {
107
    value => {
107
        branchcode   => $branchcode,
108
        branchcode   => $branchcode,
108
        categorycode => $categorycode,
109
        categorycode => $categorycode,
109
        flags        => 16 # borrowers flag
110
        flags        => 1040 # borrowers and updatecharges (2^4 | 2^10)
110
    }
111
    }
111
});
112
});
112
113
Lines 131-134 $t->request_ok($tx) Link Here
131
  ->json_is('/surname' => $borrower->{ surname })
132
  ->json_is('/surname' => $borrower->{ surname })
132
  ->json_is('/lost' => 1 );
133
  ->json_is('/lost' => 1 );
133
134
135
136
# Payment tests
137
my $borrower2 = $builder->build({
138
    source => 'Borrower',
139
    value => {
140
        branchcode   => $branchcode,
141
        categorycode => $categorycode,
142
    }
143
});
144
my $borrowernumber2 = $borrower2->{borrowernumber};
145
146
$dbh->do(q|
147
    INSERT INTO accountlines (borrowernumber, amount, accounttype, amountoutstanding)
148
    VALUES (?, 26, 'A', 26)
149
    |, undef, $borrowernumber2);
150
151
$t->post_ok("/api/v1/patrons/$borrowernumber2/payment" => json => {'amount' => 8})
152
    ->status_is(401);
153
154
my $post_data2 = {
155
    'amount' => 24,
156
    'note' => 'Partial payment'
157
};
158
159
$tx = $t->ua->build_tx(POST => "/api/v1/patrons/8789798797/payment" => json => $post_data2);
160
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
161
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
162
$t->request_ok($tx)
163
  ->status_is(404);
164
165
$tx = $t->ua->build_tx(POST => "/api/v1/patrons/$borrowernumber2/payment" => json => {amount => 0});
166
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
167
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
168
$t->request_ok($tx)
169
  ->status_is(400);
170
171
$tx = $t->ua->build_tx(POST => "/api/v1/patrons/$borrowernumber2/payment" => json => {amount => 'foo'});
172
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
173
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
174
$t->request_ok($tx)
175
  ->status_is(400);
176
177
$tx = $t->ua->build_tx(POST => "/api/v1/patrons/$borrowernumber2/payment" => json => $post_data2);
178
$tx->req->cookies({name => 'CGISESSID', value => $session->id});
179
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
180
$t->request_ok($tx)
181
  ->status_is(204);
182
183
my $accountline_partiallypaid = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber2, 'amount' => 26})->unblessed()->[0];
184
185
is($accountline_partiallypaid->{amountoutstanding}, '2.000000');
186
134
$dbh->rollback;
187
$dbh->rollback;
135
- 

Return to bug 15165