Bugzilla – Attachment 59241 Details for
Bug 15165
REST API routes to list, edit and pay borrower's accountlines
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 15165 - Add API routes to pay accountlines
Bug-15165---Add-API-routes-to-pay-accountlines.patch (text/plain), 15.55 KB, created by
Josef Moravec
on 2017-01-19 13:15:00 UTC
(
hide
)
Description:
Bug 15165 - Add API routes to pay accountlines
Filename:
MIME Type:
Creator:
Josef Moravec
Created:
2017-01-19 13:15:00 UTC
Size:
15.55 KB
patch
obsolete
>From 2de805ee5dea96f4e223f68b4b4ad53c93d3b9d7 Mon Sep 17 00:00:00 2001 >From: Alex Arnaud <alex.arnaud@biblibre.com> >Date: Thu, 12 Nov 2015 14:44:47 +0100 >Subject: [PATCH] Bug 15165 - Add API routes to pay accountlines > >POST /accountlines/(:accountlines_id)/payment (pay towards accountline) >POST /patrons/(:borrowernumber)/payment (pay towards borrower) > >Test plan: >1. Open a browser tab on Koha staff and log in (to create CGISESSID > cookie). You must have permission updatecharges. >2. Create a fine to any patron and get the accountlines_id. >3. Send POST request to http://yourlibrary/api/v1/accountlines/YYY/payment > without body where YYY is the accountlines_id you created in step 2. >4. Check that the accountline that you created in step 2 is paid. >5. Create two payments with amount 5.00 (with no other outstanding payments) >6. Send POST request to > http://yourlibrary/api/v1/patrons/ZZZ/payment with body > {"amount": 10} > Replace ZZZ with the borrowernumber for which you have created two > fines >7. Check that the two accountlines are paid. >8. Repeat step 2. >9. Send POST request to > http://yourlibrary/api/v1/accountlines/YYY/payment with body > {"amount": XXX} > Replace YYY with the accountlines_id you created in step 8. > Set amount (XXX) to the half of the amount of the fine you created in > step 8. >10. Check that the fine is still outstanding with half of the original > amount. >11. Run unit tests at t/db_dependent/api/v1/accountlines.t and > t/db_dependent/api/v1/patrons.t >--- > Koha/REST/V1/Accountline.pm | 37 ++++++++++++++++++++ > Koha/REST/V1/Patron.pm | 34 +++++++++++++++++++ > api/v1/swagger/paths.json | 6 ++++ > api/v1/swagger/paths/accountlines.json | 55 ++++++++++++++++++++++++++++++ > api/v1/swagger/paths/patrons.json | 55 ++++++++++++++++++++++++++++++ > t/db_dependent/api/v1/accountlines.t | 62 +++++++++++++++++++++++++++++++--- > t/db_dependent/api/v1/patrons.t | 58 +++++++++++++++++++++++++++++-- > 7 files changed, 300 insertions(+), 7 deletions(-) > >diff --git a/Koha/REST/V1/Accountline.pm b/Koha/REST/V1/Accountline.pm >index 23c2491..9ee8aa8 100644 >--- a/Koha/REST/V1/Accountline.pm >+++ b/Koha/REST/V1/Accountline.pm >@@ -19,8 +19,11 @@ use Modern::Perl; > > use Mojo::Base 'Mojolicious::Controller'; > >+use Scalar::Util qw( looks_like_number ); >+ > use C4::Auth qw( haspermission ); > use Koha::Account::Lines; >+use Koha::Account; > > sub list { > my ($c, $args, $cb) = @_; >@@ -48,4 +51,38 @@ sub edit { > return $c->$cb($accountline->unblessed(), 200); > } > >+ >+sub pay { >+ my ($c, $args, $cb) = @_; >+ >+ my $accountline = Koha::Account::Lines->find($args->{accountlines_id}); >+ unless ($accountline) { >+ return $c->$cb({error => "Accountline not found"}, 404); >+ } >+ >+ my $body = $c->req->json; >+ my $amount = defined $body->{amount}; >+ my $note = $body->{note} || ''; >+ >+ if ($amount && !looks_like_number($amount)) { >+ return $c->$cb({error => "Invalid amount"}, 400); >+ } >+ >+ Koha::Account->new( >+ { >+ patron_id => $accountline->borrowernumber, >+ } >+ )->pay( >+ { >+ lines => [$accountline], >+ amount => $amount, >+ note => $note, >+ } >+ ); >+ >+ $accountline = Koha::Account::Lines->find($args->{accountlines_id}); >+ return $c->$cb($accountline->unblessed(), 200); >+} >+ >+ > 1; >diff --git a/Koha/REST/V1/Patron.pm b/Koha/REST/V1/Patron.pm >index b97a154..73259c5 100644 >--- a/Koha/REST/V1/Patron.pm >+++ b/Koha/REST/V1/Patron.pm >@@ -19,7 +19,11 @@ use Modern::Perl; > > use Mojo::Base 'Mojolicious::Controller'; > >+use Scalar::Util qw( looks_like_number ); >+ >+use C4::Auth qw( haspermission ); > use Koha::Patrons; >+use Koha::Account; > > sub list { > my ($c, $args, $cb) = @_; >@@ -44,4 +48,34 @@ sub get { > return $c->$cb($patron->unblessed, 200); > } > >+sub pay { >+ my ($c, $args, $cb) = @_; >+ >+ my $patron = Koha::Patrons->find($args->{borrowernumber}); >+ unless ($patron) { >+ return $c->$cb({error => "Patron not found"}, 404); >+ } >+ >+ my $body = $c->req->json; >+ my $amount = $body->{amount}; >+ my $note = $body->{note} || ''; >+ >+ unless ($amount && looks_like_number($amount)) { >+ return $c->$cb({error => "Invalid amount"}, 400); >+ } >+ >+ Koha::Account->new( >+ { >+ patron_id => $args->{borrowernumber}, >+ } >+ )->pay( >+ { >+ amount => $amount, >+ note => $note, >+ } >+ ); >+ >+ return $c->$cb('', 204); >+} >+ > 1; >diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json >index 8cfcd39..6ac3307 100644 >--- a/api/v1/swagger/paths.json >+++ b/api/v1/swagger/paths.json >@@ -11,6 +11,9 @@ > "/accountlines/{accountlines_id}": { > "$ref": "paths/accountlines.json#/~1accountlines~1{accountlines_id}" > }, >+ "/accountlines/{accountlines_id}/payment": { >+ "$ref": "paths/accountlines.json#/~1accountlines~1{accountlines_id}~1payment" >+ }, > "/holds": { > "$ref": "paths/holds.json#/~1holds" > }, >@@ -22,5 +25,8 @@ > }, > "/patrons/{borrowernumber}": { > "$ref": "paths/patrons.json#/~1patrons~1{borrowernumber}" >+ }, >+ "/patrons/{borrowernumber}/payment": { >+ "$ref": "paths/patrons.json#/~1patrons~1{borrowernumber}~1payment" > } > } >diff --git a/api/v1/swagger/paths/accountlines.json b/api/v1/swagger/paths/accountlines.json >index d89056d..89ebb23 100644 >--- a/api/v1/swagger/paths/accountlines.json >+++ b/api/v1/swagger/paths/accountlines.json >@@ -93,5 +93,60 @@ > } > } > } >+ }, >+ "/accountlines/{accountlines_id}/payment": { >+ "post": { >+ "operationId": "payAccountlines", >+ "tags": ["accountlines"], >+ "produces": [ >+ "application/json" >+ ], >+ "parameters": [ >+ { "$ref": "../parameters.json#/accountlinesIdPathParam" }, >+ { >+ "name": "body", >+ "in": "body", >+ "description": "A JSON object containing fields to modify", >+ "schema": { >+ "type": "object", >+ "properties": { >+ "amount": { >+ "description": "Amount to pay" >+ }, >+ "note": { >+ "description": "Payment note" >+ } >+ } >+ } >+ } >+ ], >+ "consumes": ["application/json"], >+ "produces": ["application/json"], >+ "responses": { >+ "200": { >+ "description": "Paid accountline", >+ "schema": { "$ref": "../definitions.json#/accountline" } >+ }, >+ "400": { >+ "description": "Missing or wrong parameters", >+ "schema": { "$ref": "../definitions.json#/error" } >+ }, >+ "403": { >+ "description": "Access forbidden", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "Accountline not found", >+ "schema": { "$ref": "../definitions.json#/error" } >+ } >+ }, >+ "x-koha-authorization": { >+ "permissions": { >+ "updatecharges": "1" >+ } >+ } >+ } > } > } >diff --git a/api/v1/swagger/paths/patrons.json b/api/v1/swagger/paths/patrons.json >index 67632e1..5b3253a 100644 >--- a/api/v1/swagger/paths/patrons.json >+++ b/api/v1/swagger/paths/patrons.json >@@ -69,5 +69,60 @@ > } > } > } >+ }, >+ "/patrons/{borrowernumber}/payment": { >+ "post": { >+ "operationId": "payForPatron", >+ "tags": ["accountlines"], >+ "produces": [ >+ "application/json" >+ ], >+ "parameters": [ >+ { "$ref": "../parameters.json#/borrowernumberPathParam" }, >+ { >+ "name": "body", >+ "in": "body", >+ "description": "A JSON object containing fields to modify", >+ "required": true, >+ "schema": { >+ "type": "object", >+ "properties": { >+ "amount": { >+ "description": "Amount to pay" >+ }, >+ "note": { >+ "description": "Payment note" >+ } >+ } >+ } >+ } >+ ], >+ "consumes": ["application/json"], >+ "produces": ["application/json"], >+ "responses": { >+ "204": { >+ "description": "Success" >+ }, >+ "400": { >+ "description": "Missing or wrong parameters", >+ "schema": { "$ref": "../definitions.json#/error" } >+ }, >+ "403": { >+ "description": "Access forbidden", >+ "schema": { >+ "$ref": "../definitions.json#/error" >+ } >+ }, >+ "404": { >+ "description": "Borrower not found", >+ "schema": { "$ref": "../definitions.json#/error" } >+ } >+ }, >+ "x-koha-authorization": { >+ "permissions": { >+ "updatecharges": "1" >+ } >+ } >+ } > } > } >diff --git a/t/db_dependent/api/v1/accountlines.t b/t/db_dependent/api/v1/accountlines.t >index d395603..4d918dd 100644 >--- a/t/db_dependent/api/v1/accountlines.t >+++ b/t/db_dependent/api/v1/accountlines.t >@@ -17,7 +17,8 @@ > > use Modern::Perl; > >-use Test::More tests => 22; >+ >+use Test::More tests => 37; > use Test::Mojo; > use t::lib::TestBuilder; > >@@ -45,6 +46,9 @@ $t->get_ok('/api/v1/accountlines') > $t->put_ok("/api/v1/accountlines/11224409" => json => {'amount' => -5}) > ->status_is(401); > >+$t->post_ok("/api/v1/accountlines/11224408/payment") >+ ->status_is(401); >+ > my $loggedinuser = $builder->build({ > source => 'Borrower', > value => { >@@ -75,8 +79,8 @@ my $borrowernumber2 = $borrower2->{borrowernumber}; > > $dbh->do(q| DELETE FROM accountlines |); > $dbh->do(q| >- INSERT INTO accountlines (borrowernumber, amount, accounttype) >- VALUES (?, 20, 'A'), (?, 40, 'F'), (?, 80, 'F'), (?, 10, 'F') >+ INSERT INTO accountlines (borrowernumber, amount, accounttype, amountoutstanding) >+ VALUES (?, 20, 'A', 20), (?, 40, 'F', 40), (?, 80, 'F', 80), (?, 10, 'F', 10) > |, undef, $borrowernumber, $borrowernumber, $borrowernumber, $borrowernumber2); > > my $session = C4::Auth::get_session(''); >@@ -127,7 +131,6 @@ my $put_data = { > > $tx = $t->ua->build_tx( > PUT => "/api/v1/accountlines/11224409" >- => {Accept => '*/*'} > => json => $put_data); > $tx->req->cookies({name => 'CGISESSID', value => $session->id}); > $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >@@ -144,7 +147,6 @@ $t->request_ok($tx) > > $tx = $t->ua->build_tx( > PUT => "/api/v1/accountlines/$accountline_to_edit->{accountlines_id}" >- => {Accept => '*/*'} > => json => $put_data); > $tx->req->cookies({name => 'CGISESSID', value => $session->id}); > $tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >@@ -158,5 +160,55 @@ is($accountline_edited->{amountoutstanding}, '-19.000000'); > > > # Payment tests >+$tx = $t->ua->build_tx(POST => "/api/v1/accountlines/4562765765/payment"); >+$tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+$tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+$t->request_ok($tx) >+ ->status_is(404); >+ >+my $accountline_to_pay = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber, 'amount' => 20})->unblessed()->[0]; >+$tx = $t->ua->build_tx(POST => "/api/v1/accountlines/$accountline_to_pay->{accountlines_id}/payment"); >+$tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+$tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+$t->request_ok($tx) >+ ->status_is(200); >+#$t->content_is('toto'); >+ >+my $accountline_paid = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber, 'amount' => -20})->unblessed()->[0]; >+ok($accountline_paid); >+ >+# Partial payment tests >+my $post_data = { >+ 'amount' => 17, >+ 'note' => 'Partial payment' >+}; >+ >+$tx = $t->ua->build_tx( >+ POST => "/api/v1/accountlines/11224419/payment" >+ => json => $post_data); >+$tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+$tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+$t->request_ok($tx) >+ ->status_is(404); >+ >+my $accountline_to_partiallypay = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber, 'amount' => 80})->unblessed()->[0]; >+ >+$tx = $t->ua->build_tx(POST => "/api/v1/accountlines/$accountline_to_partiallypay->{accountlines_id}/payment" => json => {amount => 'foo'}); >+$tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+$tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+$t->request_ok($tx) >+ ->status_is(400); >+ >+$tx = $t->ua->build_tx(POST => "/api/v1/accountlines/$accountline_to_partiallypay->{accountlines_id}/payment" => json => $post_data); >+$tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+$tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+$t->request_ok($tx) >+ ->status_is(200); >+ >+$accountline_to_partiallypay = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber, 'amount' => 80})->unblessed()->[0]; >+is($accountline_to_partiallypay->{amountoutstanding}, '63.000000'); >+ >+my $accountline_partiallypaid = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber, 'amount' => -17})->unblessed()->[0]; >+ok($accountline_partiallypaid); > > $dbh->rollback; >diff --git a/t/db_dependent/api/v1/patrons.t b/t/db_dependent/api/v1/patrons.t >index f4b9410..390b198 100644 >--- a/t/db_dependent/api/v1/patrons.t >+++ b/t/db_dependent/api/v1/patrons.t >@@ -17,7 +17,8 @@ > > use Modern::Perl; > >-use Test::More tests => 20; >+ >+use Test::More tests => 31; > use Test::Mojo; > use t::lib::TestBuilder; > >@@ -26,6 +27,7 @@ use C4::Context; > > use Koha::Database; > use Koha::Patron; >+use Koha::Account::Lines; > > my $builder = t::lib::TestBuilder->new(); > >@@ -105,7 +107,7 @@ my $loggedinuser = $builder->build({ > value => { > branchcode => $branchcode, > categorycode => $categorycode, >- flags => 16 # borrowers flag >+ flags => 1040 # borrowers and updatecharges (2^4 | 2^10) > } > }); > >@@ -129,4 +131,56 @@ $t->request_ok($tx) > ->json_is('/borrowernumber' => $borrower->{ borrowernumber }) > ->json_is('/surname' => $borrower->{ surname }); > >+ >+# Payment tests >+my $borrower2 = $builder->build({ >+ source => 'Borrower', >+ value => { >+ branchcode => $branchcode, >+ categorycode => $categorycode, >+ } >+}); >+my $borrowernumber2 = $borrower2->{borrowernumber}; >+ >+$dbh->do(q| >+ INSERT INTO accountlines (borrowernumber, amount, accounttype, amountoutstanding) >+ VALUES (?, 26, 'A', 26) >+ |, undef, $borrowernumber2); >+ >+$t->post_ok("/api/v1/patrons/$borrowernumber2/payment" => json => {'amount' => 8}) >+ ->status_is(401); >+ >+my $post_data2 = { >+ 'amount' => 24, >+ 'note' => 'Partial payment' >+}; >+ >+$tx = $t->ua->build_tx(POST => "/api/v1/patrons/8789798797/payment" => json => $post_data2); >+$tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+$tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+$t->request_ok($tx) >+ ->status_is(404); >+ >+$tx = $t->ua->build_tx(POST => "/api/v1/patrons/$borrowernumber2/payment" => json => {amount => 0}); >+$tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+$tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+$t->request_ok($tx) >+ ->status_is(400); >+ >+$tx = $t->ua->build_tx(POST => "/api/v1/patrons/$borrowernumber2/payment" => json => {amount => 'foo'}); >+$tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+$tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+$t->request_ok($tx) >+ ->status_is(400); >+ >+$tx = $t->ua->build_tx(POST => "/api/v1/patrons/$borrowernumber2/payment" => json => $post_data2); >+$tx->req->cookies({name => 'CGISESSID', value => $session->id}); >+$tx->req->env({REMOTE_ADDR => '127.0.0.1'}); >+$t->request_ok($tx) >+ ->status_is(204); >+ >+my $accountline_partiallypaid = Koha::Account::Lines->search({'borrowernumber' => $borrowernumber2, 'amount' => 26})->unblessed()->[0]; >+ >+is($accountline_partiallypaid->{amountoutstanding}, '2.000000'); >+ > $dbh->rollback; >-- >2.1.4
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 15165
:
44804
|
44805
|
44806
|
45259
|
50189
|
50190
|
50191
|
50790
|
52681
|
52682
|
52683
|
55033
|
55034
|
55035
|
56694
|
56695
|
56696
|
57843
|
57844
|
57845
|
57846
|
59239
|
59240
|
59241
|
59242
|
59932
|
59933
|
59934
|
60180
|
62769
|
62770
|
62771
|
62772
|
62773
|
62774
|
62775