From 319df5cdb75ca76d4f3fd57e0bbf73ac62941fc4 Mon Sep 17 00:00:00 2001
From: Lari Taskula <lari.taskula@jns.fi>
Date: Mon, 13 Feb 2017 16:42:14 +0200
Subject: [PATCH] Bug 18103: Add patronstatus operation to controller

This patch adds patronstatus operation to Koha::REST::V1::Patron.

Also adds new method Koha::Patron->status_not_ok that returns an array of
Koha::Exceptions if there are some issues with patron status.

To test:
1. prove t/db_dependent/Koha/Patrons.t
2. prove t/db_dependent/api/v1/patrons.t

https://bugs.koha-community.org/show_bug.cgi?id=18103
---
 Koha/Patron.pm                  | 29 +++++++++++++++++++++++++++++
 Koha/REST/V1/Patron.pm          | 31 +++++++++++++++++++++++++++++++
 t/db_dependent/Koha/Patrons.t   | 41 ++++++++++++++++++++++++++++++++++++++++-
 t/db_dependent/api/v1/patrons.t | 23 ++++++++++++++++++++++-
 4 files changed, 122 insertions(+), 2 deletions(-)

diff --git a/Koha/Patron.pm b/Koha/Patron.pm
index f04831d..012a14f 100644
--- a/Koha/Patron.pm
+++ b/Koha/Patron.pm
@@ -24,6 +24,7 @@ use Carp;
 
 use C4::Context;
 use C4::Log;
+use Koha::Availability::Checks::Patron;
 use Koha::Checkouts;
 use Koha::Database;
 use Koha::DateUtils;
@@ -583,6 +584,34 @@ sub holds {
     return Koha::Holds->_new_from_dbic($holds_rs);
 }
 
+=head3 status_not_ok
+
+my $status = $patron->status_not_ok
+
+Checks patron's status for checkouts and holds.
+
+Returns an array of Koha::Exception::Patron::* if any restrictions are found.
+
+=cut
+
+sub status_not_ok {
+    my ($self) = @_;
+
+    my $patron_checks = Koha::Availability::Checks::Patron->new($self);
+
+    my @problems;
+    my $ex;
+    push @problems, $ex if $ex = $patron_checks->debarred;
+    push @problems, $ex if $ex = $patron_checks->debt_hold;
+    push @problems, $ex if $ex = $patron_checks->debt_checkout_guarantees;
+    push @problems, $ex if $ex = $patron_checks->exceeded_maxreserves;
+    push @problems, $ex if $ex = $patron_checks->expired;
+    push @problems, $ex if $ex = $patron_checks->gonenoaddress;
+    push @problems, $ex if $ex = $patron_checks->lost;
+
+    return @problems;
+}
+
 =head3 type
 
 =cut
diff --git a/Koha/REST/V1/Patron.pm b/Koha/REST/V1/Patron.pm
index b97a154..4f64022 100644
--- a/Koha/REST/V1/Patron.pm
+++ b/Koha/REST/V1/Patron.pm
@@ -19,8 +19,11 @@ use Modern::Perl;
 
 use Mojo::Base 'Mojolicious::Controller';
 
+use Koha::Availability;
 use Koha::Patrons;
 
+use Try::Tiny;
+
 sub list {
     my ($c, $args, $cb) = @_;
 
@@ -44,4 +47,32 @@ sub get {
     return $c->$cb($patron->unblessed, 200);
 }
 
+sub getstatus {
+    my ($c, $args, $cb) = @_;
+
+    return try {
+        my $user = $c->stash('koha.user');
+
+        my $patron = Koha::Patrons->find($args->{borrowernumber});
+        unless ($patron) {
+            return $c->$cb({error => "Patron not found"}, 404);
+        }
+
+        my $ret = $patron->unblessed;
+        my %problems = map { ref($_) => $_ } $patron->status_not_ok;
+        $ret->{blocks} = Koha::Availability->_swaggerize_exception(\%problems);
+
+        return $c->$cb($ret, 200);
+    } catch {
+        if ( $_->isa('DBIx::Class::Exception') ) {
+            return $c->$cb( { error => $_->msg }, 500 );
+        }
+        else {
+            return $c->$cb(
+                { error => "Something went wrong, check the logs." }, 500 );
+        }
+    };
+    
+}
+
 1;
diff --git a/t/db_dependent/Koha/Patrons.t b/t/db_dependent/Koha/Patrons.t
index 0e6791a..47c00fc 100644
--- a/t/db_dependent/Koha/Patrons.t
+++ b/t/db_dependent/Koha/Patrons.t
@@ -19,7 +19,7 @@
 
 use Modern::Perl;
 
-use Test::More tests => 20;
+use Test::More tests => 21;
 use Test::Warn;
 use DateTime;
 
@@ -661,6 +661,45 @@ subtest 'holds' => sub {
     $patron->delete;
 };
 
+subtest 'status_not_ok' => sub {
+    plan tests => 5;
+
+    t::lib::Mocks::mock_preference('maxoutstanding', 5);
+    my $patron = $builder->build(
+        {
+            source => 'Borrower',
+            value  => { branchcode => $library->{branchcode},
+                        gonenoaddress => 0,
+                        lost => 0,
+                        debarred => undef,
+                        debarredcomment => undef,
+                        dateexpiry => '9999-12-12' }
+        }
+    );
+
+    $patron = Koha::Patrons->find($patron->{borrowernumber});
+    my $line = Koha::Account::Line->new({
+        borrowernumber => $patron->borrowernumber,
+        amountoutstanding => 9001,
+    })->store;
+    my $outstanding = $patron->account->balance;
+    my $maxoutstanding = C4::Context->preference('maxoutstanding');
+    my $expecting = 'Koha::Exceptions::Patron::Debt';
+    my @problems = $patron->status_not_ok;
+
+    ok($maxoutstanding, 'When I look at system preferences, I see that maximum '
+       .'allowed outstanding fines is set.');
+    ok($maxoutstanding < $outstanding, 'When I check patron\'s balance, I found '
+       .'out they have more outstanding fines than allowed.');
+    is(scalar(@problems), 1, 'There is an issue with patron\'s current status');
+    my $debt = $problems[0];
+    is($debt->max_outstanding, 0+$maxoutstanding, 'Then I can see the status '
+       .'showing me how much outstanding total can be at maximum.');
+    is($debt->current_outstanding, 0+$outstanding, 'Then I can see the status '
+       .'showing me how much outstanding fines patron has right now.');
+    $patron->delete;
+};
+
 $retrieved_patron_1->delete;
 is( Koha::Patrons->search->count, $nb_of_patrons + 1, 'Delete should have deleted the patron' );
 
diff --git a/t/db_dependent/api/v1/patrons.t b/t/db_dependent/api/v1/patrons.t
index f4b9410..d6924b6 100644
--- a/t/db_dependent/api/v1/patrons.t
+++ b/t/db_dependent/api/v1/patrons.t
@@ -17,8 +17,9 @@
 
 use Modern::Perl;
 
-use Test::More tests => 20;
+use Test::More tests => 25;
 use Test::Mojo;
+use t::lib::Mocks;
 use t::lib::TestBuilder;
 
 use C4::Auth;
@@ -129,4 +130,24 @@ $t->request_ok($tx)
   ->json_is('/borrowernumber' => $borrower->{ borrowernumber })
   ->json_is('/surname' => $borrower->{ surname });
 
+# patronstatus
+my $debt = {
+    current_outstanding => 9001,
+    max_outstanding => 5,
+};
+t::lib::Mocks::mock_preference('maxoutstanding', $debt->{max_outstanding});
+my $patron = Koha::Patrons->find($borrower->{borrowernumber});
+my $line = Koha::Account::Line->new({
+    borrowernumber => $patron->borrowernumber,
+    amountoutstanding => $debt->{current_outstanding},
+})->store;
+$tx = $t->ua->build_tx(GET => "/api/v1/patrons/".$borrower->{ borrowernumber }
+                             ."/status");
+$tx->req->cookies({name => 'CGISESSID', value => $session->id});
+$t->request_ok($tx)
+  ->status_is(200)
+  ->json_is('/borrowernumber' => $borrower->{ borrowernumber })
+  ->json_is('/surname' => $borrower->{ surname })
+  ->json_is('/blocks/Patron::Debt' => $debt);
+
 $dbh->rollback;
-- 
1.9.1