From 12e160e55d18ac823bbc6f2b328d244fc2cceb42 Mon Sep 17 00:00:00 2001
From: Olli-Antti Kivilahti <olli-antti.kivilahti@jns.fi>
Date: Fri, 17 Oct 2014 17:23:21 +0300
Subject: [PATCH] Bug 13106 - Encapsulate Circulation::GetAgeRestriction() and
 modify it to check borrowers age as well.

This patch moves the logic of deciding whether or not a borrower is old enough to access this material
to its own function GetAgeRestriction.

This makes it easier to use AgeRestriction elsewhere, like with placing holds.

Unit tests included.
---
 C4/Circulation.pm                     |   68 +++++++++++++++++++++------------
 t/Circulation/AgeRestrictionMarkers.t |   22 ++++++++++-
 2 files changed, 64 insertions(+), 26 deletions(-)

diff --git a/C4/Circulation.pm b/C4/Circulation.pm
index 8c0b208..ec10251 100644
--- a/C4/Circulation.pm
+++ b/C4/Circulation.pm
@@ -981,29 +981,14 @@ sub CanBookBeIssued {
     }
 
     ## CHECK AGE RESTRICTION
-    # get $marker from preferences. Could be something like "FSK|PEGI|Alter|Age:"
-    my $markers         = C4::Context->preference('AgeRestrictionMarker');
-    my $bibvalues       = $biblioitem->{'agerestriction'};
-    my $restriction_age = GetAgeRestriction( $bibvalues );
-
-    if ( $restriction_age > 0 ) {
-        if ( $borrower->{'dateofbirth'} ) {
-            my @alloweddate = split /-/, $borrower->{'dateofbirth'};
-            $alloweddate[0] += $restriction_age;
-
-            #Prevent runime eror on leap year (invalid date)
-            if ( ( $alloweddate[1] == 2 ) && ( $alloweddate[2] == 29 ) ) {
-                $alloweddate[2] = 28;
-            }
-
-            if ( Date_to_Days(Today) < Date_to_Days(@alloweddate) - 1 ) {
-                if ( C4::Context->preference('AgeRestrictionOverride') ) {
-                    $needsconfirmation{AGE_RESTRICTION} = "$bibvalues";
-                }
-                else {
-                    $issuingimpossible{AGE_RESTRICTION} = "$bibvalues";
-                }
-            }
+    my $agerestriction  = $biblioitem->{'agerestriction'};
+    my ($restriction_age, $daysToAgeRestriction) = GetAgeRestriction( $agerestriction, $borrower );
+    if ( $daysToAgeRestriction ) {
+        if ( C4::Context->preference('AgeRestrictionOverride') ) {
+            $needsconfirmation{AGE_RESTRICTION} = "$agerestriction";
+        }
+        else {
+            $issuingimpossible{AGE_RESTRICTION} = "$agerestriction";
         }
     }
 
@@ -3737,8 +3722,23 @@ sub IsItemIssued {
     return $sth->fetchrow;
 }
 
+=head2 GetAgeRestriction
+
+  my ($ageRestriction, $daysToAgeRestriction) = GetAgeRestriction($record_restrictions, $borrower);
+  my ($ageRestriction, $daysToAgeRestriction) = GetAgeRestriction($record_restrictions);
+  
+  if($daysToAgeRestriction <= 0) { #Borrower is allowed to access this material, as he is older or as old as the agerestriction }
+  if($daysToAgeRestriction > 0) { #Borrower is this many days from meeting the agerestriction }
+
+@PARAM1 the koha.biblioitems.agerestriction value, like K18, PEGI 13, ...
+@PARAM2 a borrower-object with koha.borrowers.dateofbirth. (OPTIONAL)
+@RETURNS The age restriction age in years and the days to fulfill the age restriction for the given borrower.
+         Negative days mean the borrower has gone past the age restriction age.
+
+=cut
+
 sub GetAgeRestriction {
-    my ($record_restrictions) = @_;
+    my ($record_restrictions, $borrower) = @_;
     my $markers = C4::Context->preference('AgeRestrictionMarker');
 
     # Split $record_restrictions to something like FSK 16 or PEGI 6
@@ -3772,7 +3772,25 @@ sub GetAgeRestriction {
         last if ( $restriction_year > 0 );
     }
 
-    return $restriction_year;
+    #Check if the borrower is age restricted for this material and for how long.
+    if ($restriction_year && $borrower) {
+        if ( $borrower->{'dateofbirth'} ) {
+            my @alloweddate = split /-/, $borrower->{'dateofbirth'};
+            $alloweddate[0] += $restriction_year;
+
+            #Prevent runime eror on leap year (invalid date)
+            if ( ( $alloweddate[1] == 2 ) && ( $alloweddate[2] == 29 ) ) {
+                $alloweddate[2] = 28;
+            }
+
+            #Get how many days the borrower has to reach the age restriction
+            my $daysToAgeRestriction = Date_to_Days(@alloweddate) - Date_to_Days(Today);
+            #Negative days means the borrower went past the age restriction age
+            return ($restriction_year, $daysToAgeRestriction);
+        }
+    }
+
+    return ($restriction_year);
 }
 
 1;
diff --git a/t/Circulation/AgeRestrictionMarkers.t b/t/Circulation/AgeRestrictionMarkers.t
index 619e4ea..2eb9cdc 100644
--- a/t/Circulation/AgeRestrictionMarkers.t
+++ b/t/Circulation/AgeRestrictionMarkers.t
@@ -1,5 +1,8 @@
+#!/usr/bin/perl
+
 use Modern::Perl;
-use Test::More tests => 5;
+use DateTime;
+use Test::More tests => 10;
 
 use t::lib::Mocks;
 
@@ -13,3 +16,20 @@ is ( C4::Circulation::GetAgeRestriction('PEGI16'), '16', 'PEGI16 returns 16' );
 is ( C4::Circulation::GetAgeRestriction('Age 16'), '16', 'Age 16 returns 16' );
 is ( C4::Circulation::GetAgeRestriction('K16'), '16', 'K16 returns 16' );
 
+
+##Testing age restriction for a borrower.
+my $now = DateTime->now();
+my $duration_15years = DateTime::Duration->new(years => 15);
+my $past15yearsAgo = DateTime->now()->subtract_duration($duration_15years);
+my $borrower = {dateofbirth => $past15yearsAgo->ymd()};
+
+my ($restriction_age, $daysToAgeRestriction) = C4::Circulation::GetAgeRestriction('FSK 16', $borrower);
+is ( ($daysToAgeRestriction > 0), 1, 'FSK 16 blocked for a 15 year old' );
+($restriction_age, $daysToAgeRestriction) = C4::Circulation::GetAgeRestriction('PEGI 15', $borrower);
+is ( ($daysToAgeRestriction <= 0), 1, 'PEGI 15 allowed for a 15 year old' );
+($restriction_age, $daysToAgeRestriction) = C4::Circulation::GetAgeRestriction('PEGI14', $borrower);
+is ( ($daysToAgeRestriction <= 0), 1, 'PEGI14 allowed for a 15 year old' );
+($restriction_age, $daysToAgeRestriction) = C4::Circulation::GetAgeRestriction('Age 10', $borrower);
+is ( ($daysToAgeRestriction <= 0), 1, 'Age 10 allowed for a 15 year old' );
+($restriction_age, $daysToAgeRestriction) = C4::Circulation::GetAgeRestriction('K18', $borrower);
+is ( ($daysToAgeRestriction > 0), 1, 'K18 blocked for a 15 year old' );
\ No newline at end of file
-- 
1.7.9.5