From e8c18a8360028897431140b0e1c3772edfd31f53 Mon Sep 17 00:00:00 2001
From: Thibaud Guillot <thibaud.guillot@biblibre.com>
Date: Fri, 17 Nov 2023 11:14:21 +0100
Subject: [PATCH] Bug 14293: Rebasing tests

--Including:--

    Bug 14293: Add more tests and improve get_chargeable_units

    Not sure at all about this change, especially because it could modify
    CalcFine

    Signed-off-by: Arthur Suzuki <arthur.suzuki@biblibre.com>

    Signed-off-by: Mark Tompsett <mtompset@hotmail.com>

    Bug 14293: Add more tests and fix floor/ceil

    Signed-off-by: Mark Tompsett <mtompset@hotmail.com>
---
 .../IssuingRules/maxsuspensiondays.t          | 133 ------------------
 .../Circulation/maxsuspensiondays.t           | 118 +++++++++++++++-
 2 files changed, 114 insertions(+), 137 deletions(-)
 delete mode 100644 t/db_dependent/Circulation/IssuingRules/maxsuspensiondays.t

diff --git a/t/db_dependent/Circulation/IssuingRules/maxsuspensiondays.t b/t/db_dependent/Circulation/IssuingRules/maxsuspensiondays.t
deleted file mode 100644
index b969baa960..0000000000
--- a/t/db_dependent/Circulation/IssuingRules/maxsuspensiondays.t
+++ /dev/null
@@ -1,133 +0,0 @@
-use Modern::Perl;
-use Test::More tests => 3;
-
-use MARC::Record;
-use MARC::Field;
-use C4::Context;
-
-use C4::Circulation qw( AddIssue AddReturn );
-use C4::Items qw( AddItem );
-use C4::Biblio qw( AddBiblio );
-use Koha::Database;
-use Koha::DateUtils;
-use Koha::Patron::Debarments qw( GetDebarments DelDebarment );
-use Koha::Patrons;
-
-use t::lib::TestBuilder;
-use t::lib::Mocks;
-
-my $schema = Koha::Database->schema;
-$schema->storage->txn_begin;
-my $builder = t::lib::TestBuilder->new;
-my $dbh = C4::Context->dbh;
-$dbh->{RaiseError} = 1;
-
-my $branchcode = $builder->build({ source => 'Branch' })->{branchcode};
-my $itemtype   = $builder->build({ source => 'Itemtype' })->{itemtype};
-my $patron_category = $builder->build({ source => 'Category' });
-
-t::lib::Mocks::mock_userenv({ branchcode => $branchcode });
-
-# Test without maxsuspensiondays set
-Koha::IssuingRules->search->delete;
-$builder->build(
-    {
-        source => 'Issuingrule',
-        value  => {
-            categorycode => '*',
-            itemtype     => '*',
-            branchcode   => '*',
-            firstremind  => 0,
-            finedays     => 2,
-            lengthunit   => 'days',
-            suspension_chargeperiod => 1,
-        }
-    }
-);
-
-my $borrowernumber = Koha::Patron->new({
-    firstname =>  'my firstname',
-    surname => 'my surname',
-    categorycode => $patron_category->{categorycode},
-    branchcode => $branchcode,
-})->store->borrowernumber;
-my $borrower = Koha::Patrons->find( $borrowernumber )->unblessed;
-
-my $record = MARC::Record->new();
-$record->append_fields(
-    MARC::Field->new('100', ' ', ' ', a => 'My author'),
-    MARC::Field->new('245', ' ', ' ', a => 'My title'),
-);
-
-my $barcode = 'bc_maxsuspensiondays';
-my ($biblionumber, $biblioitemnumber) = AddBiblio($record, '');
-my (undef, undef, $itemnumber) = AddItem({
-        homebranch => $branchcode,
-        holdingbranch => $branchcode,
-        barcode => $barcode,
-        itype => $itemtype
-    } , $biblionumber);
-
-# clear any holidays to avoid throwing off the suspension day
-# calculations
-$dbh->do('DELETE FROM special_holidays');
-$dbh->do('DELETE FROM repeatable_holidays');
-
-my $daysago20 = dt_from_string->add_duration(DateTime::Duration->new(days => -20));
-my $daysafter40 = dt_from_string->add_duration(DateTime::Duration->new(days => 40));
-
-AddIssue( $borrower, $barcode, $daysago20 );
-AddReturn( $barcode, $branchcode );
-my $debarments = GetDebarments({borrowernumber => $borrower->{borrowernumber}});
-is(
-    $debarments->[0]->{expiration},
-    output_pref({ dt => $daysafter40, dateformat => 'iso', dateonly => 1 }),
-    'calculate suspension with no maximum set'
-);
-DelDebarment( $debarments->[0]->{borrower_debarment_id} );
-
-# Test with maxsuspensiondays = 10 days
-my $issuing_rule = Koha::IssuingRules->search->next;
-$issuing_rule->maxsuspensiondays( 10 )->store;
-
-my $daysafter10 = dt_from_string->add_duration(DateTime::Duration->new(days => 10));
-AddIssue( $borrower, $barcode, $daysago20 );
-AddReturn( $barcode, $branchcode );
-$debarments = GetDebarments({borrowernumber => $borrower->{borrowernumber}});
-is(
-    $debarments->[0]->{expiration},
-    output_pref({ dt => $daysafter10, dateformat => 'iso', dateonly => 1 }),
-    'calculate suspension with a maximum set'
-);
-DelDebarment( $debarments->[0]->{borrower_debarment_id} );
-
-# Test with lengthunit => 'hours'
-Koha::IssuingRules->search->delete;
-$builder->build(
-    {
-        source => 'Issuingrule',
-        value  => {
-            categorycode => '*',
-            itemtype     => '*',
-            branchcode   => '*',
-            firstremind  => 0,
-            finedays     => 2,
-            lengthunit   => 'hours',
-            suspension_chargeperiod => 1,
-            maxsuspensiondays => 100,
-        }
-    }
-);
-
-$daysafter10 = dt_from_string->add_duration(DateTime::Duration->new(days => 10));
-AddIssue( $borrower, $barcode, $daysago20 );
-AddReturn( $barcode, $branchcode );
-$debarments = GetDebarments({borrowernumber => $borrower->{borrowernumber}});
-is(
-    $debarments->[0]->{expiration},
-    output_pref({ dt => $daysafter40, dateformat => 'iso', dateonly => 1 }),
-    'calculate suspension with lengthunit hours.'
-);
-DelDebarment( $debarments->[0]->{borrower_debarment_id} );
-
-$schema->storage->txn_rollback;
diff --git a/t/db_dependent/Circulation/maxsuspensiondays.t b/t/db_dependent/Circulation/maxsuspensiondays.t
index 614a32303a..36929a14e3 100755
--- a/t/db_dependent/Circulation/maxsuspensiondays.t
+++ b/t/db_dependent/Circulation/maxsuspensiondays.t
@@ -15,6 +15,9 @@ use Koha::Patrons;
 use t::lib::TestBuilder;
 use t::lib::Mocks;
 
+use POSIX qw( ceil );
+
+
 my $schema = Koha::Database->schema;
 $schema->storage->txn_begin;
 my $builder = t::lib::TestBuilder->new;
@@ -130,8 +133,8 @@ subtest "suspension_chargeperiod" => sub {
     my $today = dt_from_string;
     my $new_debar_dt = C4::Circulation::_calculate_new_debar_dt( $patron, $item, $last_year, $today );
     is( $new_debar_dt->truncate( to => 'day' ),
-        $today->clone->add( days => 365 / 15 * 7 )->truncate( to => 'day' ) );
-
+        $today->clone->add( days => ceil(365 / 15 * 7) )->truncate( to => 'day' )),
+        'the truncated dates are equal.'
 };
 
 subtest "maxsuspensiondays" => sub {
@@ -156,7 +159,114 @@ subtest "maxsuspensiondays" => sub {
     my $today = dt_from_string;
     my $new_debar_dt = C4::Circulation::_calculate_new_debar_dt( $patron, $item, $last_year, $today );
     is( $new_debar_dt->truncate( to => 'day' ),
-        $today->clone->add( days => 333 )->truncate( to => 'day' ) );
-};
+        $today->clone->add( days => 333 )->truncate( to => 'day' ));
+
+
+    Koha::CirculationRules->set_rules(
+        {
+            categorycode => undef,
+            itemtype     => undef,
+            branchcode   => undef,
+            rules        => {
+                firstremind  => 0,
+                finedays     => 2,
+                lengthunit   => 'hours',
+                suspension_chargeperiod => 1,
+                maxsuspensiondays => 100,
+            }
+        }
+    );
+
+    my $yesterday = dt_from_string->clone->subtract( days => 1 );
+    my $daysafter2 = dt_from_string->clone->add( days => 2 );
+    AddIssue( $patron, $barcode, $yesterday);
+    AddReturn( $barcode, $branchcode );
+    $debarments = $patron->restrictions;
+    $THE_debarment = $debarments->next;
+    is(
+        $THE_debarment->expiration,
+        output_pref({ dt => $daysafter2, dateformat => 'iso', dateonly => 1 }),
+        'calculate suspension with lengthunit hours.'
+    );
+
+    DelDebarment( $THE_debarment->borrower_debarment_id );
+
+    my $hoursago2 = dt_from_string->clone->subtract( hours => 2 );
+    AddIssue( $patron, $barcode, $hoursago2);
+    AddReturn( $barcode, $branchcode );
+    $debarments = $patron->restrictions;
+    $THE_debarment = $debarments->next;
+    is(
+        $THE_debarment->expiration,
+        output_pref({ dt => $daysafter2, dateformat => 'iso', dateonly => 1 }),
+        'calculate suspension with lengthunit hours.'
+    );
+
+    DelDebarment( $THE_debarment->borrower_debarment_id );
 
+    my $hoursafter2 = dt_from_string->clone->add( hours => 2 );
+    AddIssue( $patron, $barcode, $hoursafter2);
+    AddReturn( $barcode, $branchcode );
+    $debarments = $patron->restrictions;
+    $THE_debarment = $debarments->next;
+    is_deeply(
+        $THE_debarment,
+        undef,
+        'No debarment if in time'
+    );
+
+    # Add 1 day every 2 days
+    Koha::CirculationRules->set_rules(
+        {
+            categorycode => undef,
+            itemtype     => undef,
+            branchcode   => undef,
+            rules        => {
+                firstremind  => 0,
+                finedays     => 1,
+                lengthunit   => 'hours',
+                suspension_chargeperiod => 2,
+                maxsuspensiondays => 100,
+            }
+        }
+    );
+
+    # 20 days late => 20/2 * 1 => 10 days of suspension
+    AddIssue( $patron, $barcode, $daysago20 );
+    AddReturn( $barcode, $branchcode );
+    $debarments = $patron->restrictions;
+    $THE_debarment = $debarments->next;
+    is(
+        $THE_debarment->expiration,
+        output_pref({ dt => $daysafter10, dateformat => 'iso', dateonly => 1 }),
+        'calculate suspension with lengthunit hours.'
+    );
+
+    DelDebarment( $THE_debarment->borrower_debarment_id );
+
+    # 1 day late => ceil(1/2) * 1 => 1 day of suspension
+    my $tomorrow = dt_from_string->clone->add( days => 1 );
+    AddIssue( $patron, $barcode, $yesterday);
+    AddReturn( $barcode, $branchcode );
+    $debarments = $patron->restrictions;
+    $THE_debarment = $debarments->next;
+    is(
+        $THE_debarment->expiration,
+        output_pref({ dt => $tomorrow, dateformat => 'iso', dateonly => 1 }),
+        'calculate suspension with lengthunit hours.'
+    );
+
+    DelDebarment( $THE_debarment->borrower_debarment_id );
+
+    # 2 hours late => ceil(.x/2) * 1 => 1 day of suspension
+    AddIssue( $patron, $barcode, $hoursafter2);
+    AddReturn( $barcode, $branchcode );
+    $debarments = $patron->restrictions;
+    $THE_debarment = $debarments->next;
+    is_deeply(
+        $THE_debarment,
+        undef,
+        'No debarment if in time'
+    );
+};
 $schema->storage->txn_rollback;
-- 
2.30.2