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

(-)a/C4/Circulation.pm (-127 / +10 lines)
Lines 1446-1467 sub AddIssue { Link Here
1446
                UpdateTotalIssues( $item_object->biblionumber, 1 );
1446
                UpdateTotalIssues( $item_object->biblionumber, 1 );
1447
            }
1447
            }
1448
1448
1449
            ## If item was lost, it has now been found, reverse any list item charges if necessary.
1450
            if ( $item_object->itemlost ) {
1451
                if (
1452
                    Koha::CirculationRules->get_lostreturn_policy(
1453
                        {
1454
                            return_branch => C4::Context->userenv->{branch},
1455
                            item          => $item_object
1456
                        }
1457
                    )
1458
                  )
1459
                {
1460
                    _FixAccountForLostAndFound( $item_object->itemnumber, undef,
1461
                        $item_object->barcode );
1462
                }
1463
            }
1464
1465
            $item_object->issues( ( $item_object->issues || 0 ) + 1);
1449
            $item_object->issues( ( $item_object->issues || 0 ) + 1);
1466
            $item_object->holdingbranch(C4::Context->userenv->{'branch'});
1450
            $item_object->holdingbranch(C4::Context->userenv->{'branch'});
1467
            $item_object->itemlost(0);
1451
            $item_object->itemlost(0);
Lines 1999-2011 sub AddReturn { Link Here
1999
1983
2000
    # the holdingbranch is updated if the document is returned to another location.
1984
    # the holdingbranch is updated if the document is returned to another location.
2001
    # this is always done regardless of whether the item was on loan or not
1985
    # this is always done regardless of whether the item was on loan or not
2002
    my $item_holding_branch = $item->holdingbranch;
2003
    if ($item->holdingbranch ne $branch) {
1986
    if ($item->holdingbranch ne $branch) {
2004
        $item->holdingbranch($branch)->store;
1987
        $item->holdingbranch($branch)->store;
2005
    }
1988
    }
2006
1989
1990
    my $item_was_lost = $item->itemlost;
2007
    my $leave_item_lost = C4::Context->preference("BlockReturnOfLostItems") ? 1 : 0;
1991
    my $leave_item_lost = C4::Context->preference("BlockReturnOfLostItems") ? 1 : 0;
2008
    ModDateLastSeen( $item->itemnumber, $leave_item_lost );
1992
    my $updated_item = ModDateLastSeen( $item->itemnumber, $leave_item_lost ); # will unset itemlost if needed
1993
1994
    # fix up the accounts.....
1995
    if ( $item_was_lost ) {
1996
        $messages->{'WasLost'} = 1;
1997
        unless ( C4::Context->preference("BlockReturnOfLostItems") ) {
1998
            $messages->{'LostItemFeeRefunded'} = $updated_item->{_refunded};
1999
        }
2000
    }
2009
2001
2010
    # check if we have a transfer for this document
2002
    # check if we have a transfer for this document
2011
    my ($datesent,$frombranch,$tobranch) = GetTransfers( $item->itemnumber );
2003
    my ($datesent,$frombranch,$tobranch) = GetTransfers( $item->itemnumber );
Lines 2027-2052 sub AddReturn { Link Here
2027
        }
2019
        }
2028
    }
2020
    }
2029
2021
2030
    # fix up the accounts.....
2031
    if ( $item->itemlost ) {
2032
        $messages->{'WasLost'} = 1;
2033
        unless ( C4::Context->preference("BlockReturnOfLostItems") ) {
2034
            if (
2035
                Koha::CirculationRules->get_lostreturn_policy(
2036
                    {
2037
                        return_branch => C4::Context->userenv->{branch},
2038
                        item          => $item,
2039
                    }
2040
                  )
2041
              )
2042
            {
2043
                _FixAccountForLostAndFound( $item->itemnumber,
2044
                    $borrowernumber, $barcode );
2045
                $messages->{'LostItemFeeRefunded'} = 1;
2046
            }
2047
        }
2048
    }
2049
2050
    # fix up the overdues in accounts...
2022
    # fix up the overdues in accounts...
2051
    if ($borrowernumber) {
2023
    if ($borrowernumber) {
2052
        my $fix = _FixOverduesOnReturn( $borrowernumber, $item->itemnumber, $exemptfine, 'RETURNED' );
2024
        my $fix = _FixOverduesOnReturn( $borrowernumber, $item->itemnumber, $exemptfine, 'RETURNED' );
Lines 2467-2561 sub _FixOverduesOnReturn { Link Here
2467
    return $result;
2439
    return $result;
2468
}
2440
}
2469
2441
2470
=head2 _FixAccountForLostAndFound
2471
2472
  &_FixAccountForLostAndFound($itemnumber, [$borrowernumber, $barcode]);
2473
2474
Finds the most recent lost item charge for this item and refunds the borrower
2475
appropriatly, taking into account any payments or writeoffs already applied
2476
against the charge.
2477
2478
Internal function, not exported, called only by AddReturn.
2479
2480
=cut
2481
2482
sub _FixAccountForLostAndFound {
2483
    my $itemnumber     = shift or return;
2484
    my $borrowernumber = @_ ? shift : undef;
2485
    my $item_id        = @_ ? shift : $itemnumber;  # Send the barcode if you want that logged in the description
2486
2487
    my $credit;
2488
2489
    # check for charge made for lost book
2490
    my $accountlines = Koha::Account::Lines->search(
2491
        {
2492
            itemnumber      => $itemnumber,
2493
            debit_type_code => 'LOST',
2494
            status          => [ undef, { '<>' => 'FOUND' } ]
2495
        },
2496
        {
2497
            order_by => { -desc => [ 'date', 'accountlines_id' ] }
2498
        }
2499
    );
2500
2501
    return unless $accountlines->count > 0;
2502
    my $accountline     = $accountlines->next;
2503
    my $total_to_refund = 0;
2504
2505
    return unless $accountline->borrowernumber;
2506
    my $patron = Koha::Patrons->find( $accountline->borrowernumber );
2507
    return unless $patron; # Patron has been deleted, nobody to credit the return to
2508
2509
    my $account = $patron->account;
2510
2511
    # Use cases
2512
    if ( $accountline->amount > $accountline->amountoutstanding ) {
2513
        # some amount has been cancelled. collect the offsets that are not writeoffs
2514
        # this works because the only way to subtract from this kind of a debt is
2515
        # using the UI buttons 'Pay' and 'Write off'
2516
        my $credits_offsets = Koha::Account::Offsets->search({
2517
            debit_id  => $accountline->id,
2518
            credit_id => { '!=' => undef }, # it is not the debit itself
2519
            type      => { '!=' => 'Writeoff' },
2520
            amount    => { '<'  => 0 } # credits are negative on the DB
2521
        });
2522
2523
        $total_to_refund = ( $credits_offsets->count > 0 )
2524
                            ? $credits_offsets->total * -1 # credits are negative on the DB
2525
                            : 0;
2526
    }
2527
2528
    my $credit_total = $accountline->amountoutstanding + $total_to_refund;
2529
2530
    if ( $credit_total > 0 ) {
2531
        my $branchcode = C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
2532
        $credit = $account->add_credit(
2533
            {
2534
                amount      => $credit_total,
2535
                description => 'Item found ' . $item_id,
2536
                type        => 'LOST_FOUND',
2537
                interface   => C4::Context->interface,
2538
                library_id  => $branchcode,
2539
                item_id     => $itemnumber
2540
            }
2541
        );
2542
2543
        $credit->apply( { debits => [ $accountline ] } );
2544
    }
2545
2546
    # Update the account status
2547
    $accountline->discard_changes->status('FOUND');
2548
    $accountline->store;
2549
2550
    $accountline->item->paidfor('')->store({ log_action => 0 });
2551
2552
    if ( defined $account and C4::Context->preference('AccountAutoReconcile') ) {
2553
        $account->reconcile_balance;
2554
    }
2555
2556
    return ($credit) ? $credit->id : undef;
2557
}
2558
2559
=head2 _GetCircControlBranch
2442
=head2 _GetCircControlBranch
2560
2443
2561
   my $circ_control_branch = _GetCircControlBranch($iteminfos, $borrower);
2444
   my $circ_control_branch = _GetCircControlBranch($iteminfos, $borrower);
(-)a/Koha/CirculationRules.pm (-2 / +2 lines)
Lines 436-443 sub get_lostreturn_policy { Link Here
436
436
437
    my $behaviour = C4::Context->preference( 'RefundLostOnReturnControl' ) // 'CheckinLibrary';
437
    my $behaviour = C4::Context->preference( 'RefundLostOnReturnControl' ) // 'CheckinLibrary';
438
    my $behaviour_mapping = {
438
    my $behaviour_mapping = {
439
           CheckinLibrary => $params->{'return_branch'},
439
        CheckinLibrary    => $params->{'return_branch'} // $item->homebranch,
440
           ItemHomeBranch => $item->homebranch,
440
        ItemHomeBranch    => $item->homebranch,
441
        ItemHoldingBranch => $item->holdingbranch
441
        ItemHoldingBranch => $item->holdingbranch
442
    };
442
    };
443
443
(-)a/Koha/Item.pm (-28 / +162 lines)
Lines 117-154 sub store { Link Here
117
117
118
    } else { # ModItem
118
    } else { # ModItem
119
119
120
        { # Update *_on  fields if needed
120
        my %updated_columns = $self->_result->get_dirty_columns;
121
          # Why not for AddItem as well?
121
        return $self->SUPER::store unless %updated_columns;
122
            my @fields = qw( itemlost withdrawn damaged );
123
124
            # Only retrieve the item if we need to set an "on" date field
125
            if ( $self->itemlost || $self->withdrawn || $self->damaged ) {
126
                my $pre_mod_item = $self->get_from_storage;
127
                for my $field (@fields) {
128
                    if (    $self->$field
129
                        and not $pre_mod_item->$field )
130
                    {
131
                        my $field_on = "${field}_on";
132
                        $self->$field_on(
133
                          DateTime::Format::MySQL->format_datetime( dt_from_string() )
134
                        );
135
                    }
136
                }
137
            }
138
122
139
            # If the field is defined but empty, we are removing and,
123
        # Retrieve the item for comparison if we need to
140
            # and thus need to clear out the 'on' field as well
124
        my $pre_mod_item = (
141
            for my $field (@fields) {
125
                 exists $updated_columns{itemlost}
142
                if ( defined( $self->$field ) && !$self->$field ) {
126
              or exists $updated_columns{withdrawn}
143
                    my $field_on = "${field}_on";
127
              or exists $updated_columns{damaged}
144
                    $self->$field_on(undef);
128
        ) ? $self->get_from_storage : undef;
145
                }
129
130
        # Update *_on  fields if needed
131
        # FIXME: Why not for AddItem as well?
132
        my @fields = qw( itemlost withdrawn damaged );
133
        for my $field (@fields) {
134
135
            # If the field is defined but empty or 0, we are
136
            # removing/unsetting and thus need to clear out
137
            # the 'on' field
138
            if (   exists $updated_columns{$field}
139
                && defined( $self->$field )
140
                && !$self->$field )
141
            {
142
                my $field_on = "${field}_on";
143
                $self->$field_on(undef);
144
            }
145
            # If the field has changed otherwise, we much update
146
            # the 'on' field
147
            elsif (exists $updated_columns{$field}
148
                && $updated_columns{$field}
149
                && !$pre_mod_item->$field )
150
            {
151
                my $field_on = "${field}_on";
152
                $self->$field_on(
153
                    DateTime::Format::MySQL->format_datetime(
154
                        dt_from_string()
155
                    )
156
                );
146
            }
157
            }
147
        }
158
        }
148
159
149
        my %updated_columns = $self->_result->get_dirty_columns;
150
        return $self->SUPER::store unless %updated_columns;
151
152
        if (   exists $updated_columns{itemcallnumber}
160
        if (   exists $updated_columns{itemcallnumber}
153
            or exists $updated_columns{cn_source} )
161
            or exists $updated_columns{cn_source} )
154
        {
162
        {
Lines 165-170 sub store { Link Here
165
            $self->permanent_location( $self->location );
173
            $self->permanent_location( $self->location );
166
        }
174
        }
167
175
176
        # If item was lost and has now been found,
177
        # reverse any list item charges if necessary.
178
        if (    exists $updated_columns{itemlost}
179
            and $updated_columns{itemlost} <= 0
180
            and $pre_mod_item->itemlost > 0 )
181
        {
182
            $self->_set_found_trigger($pre_mod_item);
183
            $self->paidfor('');
184
        }
185
168
        $self->_after_item_action_hooks({ action => 'modify' });
186
        $self->_after_item_action_hooks({ action => 'modify' });
169
187
170
        logaction( "CATALOGUING", "MODIFY", $self->itemnumber, "item " . Dumper($self->unblessed) )
188
        logaction( "CATALOGUING", "MODIFY", $self->itemnumber, "item " . Dumper($self->unblessed) )
Lines 760-765 sub renewal_branchcode { Link Here
760
    return $branchcode;
778
    return $branchcode;
761
}
779
}
762
780
781
=head3 _set_found_trigger
782
783
    $self->_set_found_trigger
784
785
Finds the most recent lost item charge for this item and refunds the patron
786
appropriately, taking into account any payments or writeoffs already applied
787
against the charge.
788
789
Internal function, not exported, called only by Koha::Item->store.
790
791
=cut
792
793
sub _set_found_trigger {
794
    my ( $self, $pre_mod_item ) = @_;
795
796
    ## If item was lost, it has now been found, reverse any list item charges if necessary.
797
    my $no_refund_after_days =
798
      C4::Context->preference('NoRefundOnLostReturnedItemsAge');
799
    if ($no_refund_after_days) {
800
        my $today = dt_from_string();
801
        my $lost_age_in_days =
802
          dt_from_string( $pre_mod_item->itemlost_on )->delta_days($today)
803
          ->in_units('days');
804
805
        return $self unless $lost_age_in_days < $no_refund_after_days;
806
    }
807
808
    return $self
809
      unless Koha::CirculationRules->get_lostreturn_policy(
810
        {
811
            item          => $self,
812
            return_branch => C4::Context->userenv
813
            ? C4::Context->userenv->{'branch'}
814
            : undef,
815
        }
816
      );
817
818
    # check for charge made for lost book
819
    my $accountlines = Koha::Account::Lines->search(
820
        {
821
            itemnumber      => $self->itemnumber,
822
            debit_type_code => 'LOST',
823
            status          => [ undef, { '<>' => 'FOUND' } ]
824
        },
825
        {
826
            order_by => { -desc => [ 'date', 'accountlines_id' ] }
827
        }
828
    );
829
830
    return $self unless $accountlines->count > 0;
831
832
    my $accountline     = $accountlines->next;
833
    my $total_to_refund = 0;
834
835
    return $self unless $accountline->borrowernumber;
836
837
    my $patron = Koha::Patrons->find( $accountline->borrowernumber );
838
    return $self
839
      unless $patron;  # Patron has been deleted, nobody to credit the return to
840
                       # FIXME Should not we notify this somewhere
841
842
    my $account = $patron->account;
843
844
    # Use cases
845
    if ( $accountline->amount > $accountline->amountoutstanding ) {
846
847
    # some amount has been cancelled. collect the offsets that are not writeoffs
848
    # this works because the only way to subtract from this kind of a debt is
849
    # using the UI buttons 'Pay' and 'Write off'
850
        my $credits_offsets = Koha::Account::Offsets->search(
851
            {
852
                debit_id  => $accountline->id,
853
                credit_id => { '!=' => undef },     # it is not the debit itself
854
                type      => { '!=' => 'Writeoff' },
855
                amount => { '<' => 0 }    # credits are negative on the DB
856
            }
857
        );
858
859
        $total_to_refund = ( $credits_offsets->count > 0 )
860
          ? $credits_offsets->total * -1    # credits are negative on the DB
861
          : 0;
862
    }
863
864
    my $credit_total = $accountline->amountoutstanding + $total_to_refund;
865
866
    my $credit;
867
    if ( $credit_total > 0 ) {
868
        my $branchcode =
869
          C4::Context->userenv ? C4::Context->userenv->{'branch'} : undef;
870
        $credit = $account->add_credit(
871
            {
872
                amount      => $credit_total,
873
                description => 'Item found ' . $self->itemnumber,
874
                type        => 'LOST_FOUND',
875
                interface   => C4::Context->interface,
876
                library_id  => $branchcode,
877
                item_id     => $self->itemnumber,
878
                issue_id    => $accountline->issue_id
879
            }
880
        );
881
882
        $credit->apply( { debits => [$accountline] } );
883
        $self->{_refunded} = 1;
884
    }
885
886
    # Update the account status
887
    $accountline->status('FOUND');
888
    $accountline->store();
889
890
    if ( defined $account and C4::Context->preference('AccountAutoReconcile') ) {
891
        $account->reconcile_balance;
892
    }
893
894
    return $self;
895
}
896
763
=head3 to_api_mapping
897
=head3 to_api_mapping
764
898
765
This method returns the mapping for representing a Koha::Item object
899
This method returns the mapping for representing a Koha::Item object
(-)a/cataloguing/additem.pl (-2 / +3 lines)
Lines 732-739 if ($op eq "additem") { Link Here
732
        $itemnumber = q{};
732
        $itemnumber = q{};
733
        my $olditemlost = $item->itemlost;
733
        my $olditemlost = $item->itemlost;
734
        my $newitemlost = $newitem->{itemlost};
734
        my $newitemlost = $newitem->{itemlost};
735
        LostItem( $item->itemnumber, 'additem' )
735
        if ( $newitemlost && $newitemlost ge '1' && !$olditemlost ) {
736
            if $newitemlost && $newitemlost ge '1' && !$olditemlost;
736
            LostItem( $item->itemnumber, 'additem' )
737
        }
737
    }
738
    }
738
    $nextop="additem";
739
    $nextop="additem";
739
} elsif ($op eq "delinkitem"){
740
} elsif ($op eq "delinkitem"){
(-)a/t/db_dependent/Circulation.t (-434 / +1 lines)
Lines 18-24 Link Here
18
use Modern::Perl;
18
use Modern::Perl;
19
use utf8;
19
use utf8;
20
20
21
use Test::More tests => 47;
21
use Test::More tests => 45;
22
use Test::MockModule;
22
use Test::MockModule;
23
use Test::Deep qw( cmp_deeply );
23
use Test::Deep qw( cmp_deeply );
24
24
Lines 2668-3064 subtest 'AddReturn | is_overdue' => sub { Link Here
2668
    };
2668
    };
2669
};
2669
};
2670
2670
2671
subtest '_FixAccountForLostAndFound' => sub {
2672
2673
    plan tests => 5;
2674
2675
    t::lib::Mocks::mock_preference( 'WhenLostChargeReplacementFee', 1 );
2676
    t::lib::Mocks::mock_preference( 'WhenLostForgiveFine',          0 );
2677
2678
    my $processfee_amount  = 20;
2679
    my $replacement_amount = 99.00;
2680
    my $item_type          = $builder->build_object(
2681
        {   class => 'Koha::ItemTypes',
2682
            value => {
2683
                notforloan         => undef,
2684
                rentalcharge       => 0,
2685
                defaultreplacecost => undef,
2686
                processfee         => $processfee_amount,
2687
                rentalcharge_daily => 0,
2688
            }
2689
        }
2690
    );
2691
    my $library = $builder->build_object( { class => 'Koha::Libraries' } );
2692
2693
    my $biblio = $builder->build_sample_biblio({ author => 'Hall, Daria' });
2694
2695
    subtest 'Full write-off tests' => sub {
2696
2697
        plan tests => 12;
2698
2699
        my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
2700
        my $manager = $builder->build_object({ class => "Koha::Patrons" });
2701
        t::lib::Mocks::mock_userenv({ patron => $manager,branchcode => $manager->branchcode });
2702
2703
        my $item = $builder->build_sample_item(
2704
            {
2705
                biblionumber     => $biblio->biblionumber,
2706
                library          => $library->branchcode,
2707
                replacementprice => $replacement_amount,
2708
                itype            => $item_type->itemtype,
2709
            }
2710
        );
2711
2712
        AddIssue( $patron->unblessed, $item->barcode );
2713
2714
        # Simulate item marked as lost
2715
        $item->itemlost(3)->store;
2716
        LostItem( $item->itemnumber, 1 );
2717
2718
        my $processing_fee_lines = Koha::Account::Lines->search(
2719
            { borrowernumber => $patron->id, itemnumber => $item->itemnumber, debit_type_code => 'PROCESSING' } );
2720
        is( $processing_fee_lines->count, 1, 'Only one processing fee produced' );
2721
        my $processing_fee_line = $processing_fee_lines->next;
2722
        is( $processing_fee_line->amount + 0,
2723
            $processfee_amount, 'The right PROCESSING amount is generated' );
2724
        is( $processing_fee_line->amountoutstanding + 0,
2725
            $processfee_amount, 'The right PROCESSING amountoutstanding is generated' );
2726
2727
        my $lost_fee_lines = Koha::Account::Lines->search(
2728
            { borrowernumber => $patron->id, itemnumber => $item->itemnumber, debit_type_code => 'LOST' } );
2729
        is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
2730
        my $lost_fee_line = $lost_fee_lines->next;
2731
        is( $lost_fee_line->amount + 0, $replacement_amount, 'The right LOST amount is generated' );
2732
        is( $lost_fee_line->amountoutstanding + 0,
2733
            $replacement_amount, 'The right LOST amountoutstanding is generated' );
2734
        is( $lost_fee_line->status,
2735
            undef, 'The LOST status was not set' );
2736
2737
        my $account = $patron->account;
2738
        my $debts   = $account->outstanding_debits;
2739
2740
        # Write off the debt
2741
        my $credit = $account->add_credit(
2742
            {   amount => $account->balance,
2743
                type   => 'WRITEOFF',
2744
                interface => 'test',
2745
            }
2746
        );
2747
        $credit->apply( { debits => [ $debts->as_list ], offset_type => 'Writeoff' } );
2748
2749
        my $credit_return_id = C4::Circulation::_FixAccountForLostAndFound( $item->itemnumber, $patron->id );
2750
        is( $credit_return_id, undef, 'No LOST_FOUND account line added' );
2751
2752
        $lost_fee_line->discard_changes; # reload from DB
2753
        is( $lost_fee_line->amountoutstanding + 0, 0, 'Lost fee has no outstanding amount' );
2754
        is( $lost_fee_line->debit_type_code,
2755
            'LOST', 'Lost fee now still has account type of LOST' );
2756
        is( $lost_fee_line->status, 'FOUND', "Lost fee now has account status of FOUND");
2757
2758
        is( $patron->account->balance, -0, 'The patron balance is 0, everything was written off' );
2759
    };
2760
2761
    subtest 'Full payment tests' => sub {
2762
2763
        plan tests => 13;
2764
2765
        my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
2766
2767
        my $item = $builder->build_sample_item(
2768
            {
2769
                biblionumber     => $biblio->biblionumber,
2770
                library          => $library->branchcode,
2771
                replacementprice => $replacement_amount,
2772
                itype            => $item_type->itemtype
2773
            }
2774
        );
2775
2776
        AddIssue( $patron->unblessed, $item->barcode );
2777
2778
        # Simulate item marked as lost
2779
        $item->itemlost(1)->store;
2780
        LostItem( $item->itemnumber, 1 );
2781
2782
        my $processing_fee_lines = Koha::Account::Lines->search(
2783
            { borrowernumber => $patron->id, itemnumber => $item->itemnumber, debit_type_code => 'PROCESSING' } );
2784
        is( $processing_fee_lines->count, 1, 'Only one processing fee produced' );
2785
        my $processing_fee_line = $processing_fee_lines->next;
2786
        is( $processing_fee_line->amount + 0,
2787
            $processfee_amount, 'The right PROCESSING amount is generated' );
2788
        is( $processing_fee_line->amountoutstanding + 0,
2789
            $processfee_amount, 'The right PROCESSING amountoutstanding is generated' );
2790
2791
        my $lost_fee_lines = Koha::Account::Lines->search(
2792
            { borrowernumber => $patron->id, itemnumber => $item->itemnumber, debit_type_code => 'LOST' } );
2793
        is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
2794
        my $lost_fee_line = $lost_fee_lines->next;
2795
        is( $lost_fee_line->amount + 0, $replacement_amount, 'The right LOST amount is generated' );
2796
        is( $lost_fee_line->amountoutstanding + 0,
2797
            $replacement_amount, 'The right LOST amountountstanding is generated' );
2798
2799
        my $account = $patron->account;
2800
        my $debts   = $account->outstanding_debits;
2801
2802
        # Write off the debt
2803
        my $credit = $account->add_credit(
2804
            {   amount => $account->balance,
2805
                type   => 'PAYMENT',
2806
                interface => 'test',
2807
            }
2808
        );
2809
        $credit->apply( { debits => [ $debts->as_list ], offset_type => 'Payment' } );
2810
2811
        my $credit_return_id = C4::Circulation::_FixAccountForLostAndFound( $item->itemnumber, $patron->id );
2812
        my $credit_return = Koha::Account::Lines->find($credit_return_id);
2813
2814
        is( $credit_return->credit_type_code, 'LOST_FOUND', 'An account line of type LOST_FOUND is added' );
2815
        is( $credit_return->amount + 0,
2816
            -99.00, 'The account line of type LOST_FOUND has an amount of -99' );
2817
        is( $credit_return->amountoutstanding + 0,
2818
            -99.00, 'The account line of type LOST_FOUND has an amountoutstanding of -99' );
2819
2820
        $lost_fee_line->discard_changes;
2821
        is( $lost_fee_line->amountoutstanding + 0, 0, 'Lost fee has no outstanding amount' );
2822
        is( $lost_fee_line->debit_type_code,
2823
            'LOST', 'Lost fee now still has account type of LOST' );
2824
        is( $lost_fee_line->status, 'FOUND', "Lost fee now has account status of FOUND");
2825
2826
        is( $patron->account->balance,
2827
            -99, 'The patron balance is -99, a credit that equals the lost fee payment' );
2828
    };
2829
2830
    subtest 'Test without payment or write off' => sub {
2831
2832
        plan tests => 13;
2833
2834
        my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
2835
2836
        my $item = $builder->build_sample_item(
2837
            {
2838
                biblionumber     => $biblio->biblionumber,
2839
                library          => $library->branchcode,
2840
                replacementprice => 23.00,
2841
                replacementprice => $replacement_amount,
2842
                itype            => $item_type->itemtype
2843
            }
2844
        );
2845
2846
        AddIssue( $patron->unblessed, $item->barcode );
2847
2848
        # Simulate item marked as lost
2849
        $item->itemlost(3)->store;
2850
        LostItem( $item->itemnumber, 1 );
2851
2852
        my $processing_fee_lines = Koha::Account::Lines->search(
2853
            { borrowernumber => $patron->id, itemnumber => $item->itemnumber, debit_type_code => 'PROCESSING' } );
2854
        is( $processing_fee_lines->count, 1, 'Only one processing fee produced' );
2855
        my $processing_fee_line = $processing_fee_lines->next;
2856
        is( $processing_fee_line->amount + 0,
2857
            $processfee_amount, 'The right PROCESSING amount is generated' );
2858
        is( $processing_fee_line->amountoutstanding + 0,
2859
            $processfee_amount, 'The right PROCESSING amountoutstanding is generated' );
2860
2861
        my $lost_fee_lines = Koha::Account::Lines->search(
2862
            { borrowernumber => $patron->id, itemnumber => $item->itemnumber, debit_type_code => 'LOST' } );
2863
        is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
2864
        my $lost_fee_line = $lost_fee_lines->next;
2865
        is( $lost_fee_line->amount + 0, $replacement_amount, 'The right LOST amount is generated' );
2866
        is( $lost_fee_line->amountoutstanding + 0,
2867
            $replacement_amount, 'The right LOST amountountstanding is generated' );
2868
2869
        my $credit_return_id = C4::Circulation::_FixAccountForLostAndFound( $item->itemnumber, $patron->id );
2870
        my $credit_return = Koha::Account::Lines->find($credit_return_id);
2871
2872
        is( $credit_return->credit_type_code, 'LOST_FOUND', 'An account line of type LOST_FOUND is added' );
2873
        is( $credit_return->amount + 0, -99.00, 'The account line of type LOST_FOUND has an amount of -99' );
2874
        is( $credit_return->amountoutstanding + 0, 0, 'The account line of type LOST_FOUND has an amountoutstanding of 0' );
2875
2876
        $lost_fee_line->discard_changes;
2877
        is( $lost_fee_line->amountoutstanding + 0, 0, 'Lost fee has no outstanding amount' );
2878
        is( $lost_fee_line->debit_type_code,
2879
            'LOST', 'Lost fee now still has account type of LOST' );
2880
        is( $lost_fee_line->status, 'FOUND', "Lost fee now has account status of FOUND");
2881
2882
        is( $patron->account->balance, 20, 'The patron balance is 20, still owes the processing fee' );
2883
    };
2884
2885
    subtest 'Test with partial payement and write off, and remaining debt' => sub {
2886
2887
        plan tests => 16;
2888
2889
        my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
2890
        my $item = $builder->build_sample_item(
2891
            {
2892
                biblionumber     => $biblio->biblionumber,
2893
                library          => $library->branchcode,
2894
                replacementprice => $replacement_amount,
2895
                itype            => $item_type->itemtype
2896
            }
2897
        );
2898
2899
        AddIssue( $patron->unblessed, $item->barcode );
2900
2901
        # Simulate item marked as lost
2902
        $item->itemlost(1)->store;
2903
        LostItem( $item->itemnumber, 1 );
2904
2905
        my $processing_fee_lines = Koha::Account::Lines->search(
2906
            { borrowernumber => $patron->id, itemnumber => $item->itemnumber, debit_type_code => 'PROCESSING' } );
2907
        is( $processing_fee_lines->count, 1, 'Only one processing fee produced' );
2908
        my $processing_fee_line = $processing_fee_lines->next;
2909
        is( $processing_fee_line->amount + 0,
2910
            $processfee_amount, 'The right PROCESSING amount is generated' );
2911
        is( $processing_fee_line->amountoutstanding + 0,
2912
            $processfee_amount, 'The right PROCESSING amountoutstanding is generated' );
2913
2914
        my $lost_fee_lines = Koha::Account::Lines->search(
2915
            { borrowernumber => $patron->id, itemnumber => $item->itemnumber, debit_type_code => 'LOST' } );
2916
        is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
2917
        my $lost_fee_line = $lost_fee_lines->next;
2918
        is( $lost_fee_line->amount + 0, $replacement_amount, 'The right LOST amount is generated' );
2919
        is( $lost_fee_line->amountoutstanding + 0,
2920
            $replacement_amount, 'The right LOST amountountstanding is generated' );
2921
2922
        my $account = $patron->account;
2923
        is( $account->balance, $processfee_amount + $replacement_amount, 'Balance is PROCESSING + L' );
2924
2925
        # Partially pay fee
2926
        my $payment_amount = 27;
2927
        my $payment        = $account->add_credit(
2928
            {   amount => $payment_amount,
2929
                type   => 'PAYMENT',
2930
                interface => 'test',
2931
            }
2932
        );
2933
2934
        $payment->apply( { debits => [ $lost_fee_line ], offset_type => 'Payment' } );
2935
2936
        # Partially write off fee
2937
        my $write_off_amount = 25;
2938
        my $write_off        = $account->add_credit(
2939
            {   amount => $write_off_amount,
2940
                type   => 'WRITEOFF',
2941
                interface => 'test',
2942
            }
2943
        );
2944
        $write_off->apply( { debits => [ $lost_fee_line ], offset_type => 'Writeoff' } );
2945
2946
        is( $account->balance,
2947
            $processfee_amount + $replacement_amount - $payment_amount - $write_off_amount,
2948
            'Payment and write off applied'
2949
        );
2950
2951
        # Store the amountoutstanding value
2952
        $lost_fee_line->discard_changes;
2953
        my $outstanding = $lost_fee_line->amountoutstanding;
2954
2955
        my $credit_return_id = C4::Circulation::_FixAccountForLostAndFound( $item->itemnumber, $patron->id );
2956
        my $credit_return = Koha::Account::Lines->find($credit_return_id);
2957
2958
        is( $account->balance, $processfee_amount - $payment_amount, 'Balance is PROCESSING - PAYMENT (LOST_FOUND)' );
2959
2960
        $lost_fee_line->discard_changes;
2961
        is( $lost_fee_line->amountoutstanding + 0, 0, 'Lost fee has no outstanding amount' );
2962
        is( $lost_fee_line->debit_type_code,
2963
            'LOST', 'Lost fee now still has account type of LOST' );
2964
        is( $lost_fee_line->status, 'FOUND', "Lost fee now has account status of FOUND");
2965
2966
        is( $credit_return->credit_type_code, 'LOST_FOUND', 'An account line of type LOST_FOUND is added' );
2967
        is( $credit_return->amount + 0,
2968
            ($payment_amount + $outstanding ) * -1,
2969
            'The account line of type LOST_FOUND has an amount equal to the payment + outstanding'
2970
        );
2971
        is( $credit_return->amountoutstanding + 0,
2972
            $payment_amount * -1,
2973
            'The account line of type LOST_FOUND has an amountoutstanding equal to the payment'
2974
        );
2975
2976
        is( $account->balance,
2977
            $processfee_amount - $payment_amount,
2978
            'The patron balance is the difference between the PROCESSING and the credit'
2979
        );
2980
    };
2981
2982
    subtest 'Partial payement, existing debits and AccountAutoReconcile' => sub {
2983
2984
        plan tests => 8;
2985
2986
        my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
2987
        my $barcode = 'KD123456793';
2988
        my $replacement_amount = 100;
2989
        my $processfee_amount  = 20;
2990
2991
        my $item_type          = $builder->build_object(
2992
            {   class => 'Koha::ItemTypes',
2993
                value => {
2994
                    notforloan         => undef,
2995
                    rentalcharge       => 0,
2996
                    defaultreplacecost => undef,
2997
                    processfee         => 0,
2998
                    rentalcharge_daily => 0,
2999
                }
3000
            }
3001
        );
3002
        my $item = Koha::Item->new(
3003
            {
3004
                biblionumber     => $biblio->biblionumber,
3005
                homebranch       => $library->branchcode,
3006
                holdingbranch    => $library->branchcode,
3007
                barcode          => $barcode,
3008
                replacementprice => $replacement_amount,
3009
                itype            => $item_type->itemtype
3010
            },
3011
        )->store;
3012
3013
        AddIssue( $patron->unblessed, $barcode );
3014
3015
        # Simulate item marked as lost
3016
        $item->itemlost(1)->store;
3017
        LostItem( $item->itemnumber, 1 );
3018
3019
        my $lost_fee_lines = Koha::Account::Lines->search(
3020
            { borrowernumber => $patron->id, itemnumber => $item->itemnumber, debit_type_code => 'LOST' } );
3021
        is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
3022
        my $lost_fee_line = $lost_fee_lines->next;
3023
        is( $lost_fee_line->amount + 0, $replacement_amount, 'The right LOST amount is generated' );
3024
        is( $lost_fee_line->amountoutstanding + 0,
3025
            $replacement_amount, 'The right LOST amountountstanding is generated' );
3026
3027
        my $account = $patron->account;
3028
        is( $account->balance, $replacement_amount, 'Balance is L' );
3029
3030
        # Partially pay fee
3031
        my $payment_amount = 27;
3032
        my $payment        = $account->add_credit(
3033
            {   amount => $payment_amount,
3034
                type   => 'PAYMENT',
3035
                interface => 'test',
3036
            }
3037
        );
3038
        $payment->apply({ debits => [ $lost_fee_line ], offset_type => 'Payment' });
3039
3040
        is( $account->balance,
3041
            $replacement_amount - $payment_amount,
3042
            'Payment applied'
3043
        );
3044
3045
        my $manual_debit_amount = 80;
3046
        $account->add_debit( { amount => $manual_debit_amount, type => 'OVERDUE', interface =>'test' } );
3047
3048
        is( $account->balance, $manual_debit_amount + $replacement_amount - $payment_amount, 'Manual debit applied' );
3049
3050
        t::lib::Mocks::mock_preference( 'AccountAutoReconcile', 1 );
3051
3052
        my $credit_return_id = C4::Circulation::_FixAccountForLostAndFound( $item->itemnumber, $patron->id );
3053
        my $credit_return = Koha::Account::Lines->find($credit_return_id);
3054
3055
        is( $account->balance, $manual_debit_amount - $payment_amount, 'Balance is PROCESSING - payment (LOST_FOUND)' );
3056
3057
        my $manual_debit = Koha::Account::Lines->search({ borrowernumber => $patron->id, debit_type_code => 'OVERDUE', status => 'UNRETURNED' })->next;
3058
        is( $manual_debit->amountoutstanding + 0, $manual_debit_amount - $payment_amount, 'reconcile_balance was called' );
3059
    };
3060
};
3061
3062
subtest '_FixOverduesOnReturn' => sub {
2671
subtest '_FixOverduesOnReturn' => sub {
3063
    plan tests => 14;
2672
    plan tests => 14;
3064
2673
Lines 3144-3191 subtest '_FixOverduesOnReturn' => sub { Link Here
3144
    is( $accountline->status, 'RETURNED', 'Passed status has been used to set as RETURNED )');
2753
    is( $accountline->status, 'RETURNED', 'Passed status has been used to set as RETURNED )');
3145
};
2754
};
3146
2755
3147
subtest '_FixAccountForLostAndFound returns undef if patron is deleted' => sub {
3148
    plan tests => 1;
3149
3150
    my $manager = $builder->build_object({ class => "Koha::Patrons" });
3151
    t::lib::Mocks::mock_userenv({ patron => $manager, branchcode => $manager->branchcode });
3152
3153
    my $biblio = $builder->build_sample_biblio({ author => 'Hall, Kylie' });
3154
3155
    my $branchcode  = $library2->{branchcode};
3156
3157
    my $item = $builder->build_sample_item(
3158
        {
3159
            biblionumber     => $biblio->biblionumber,
3160
            library          => $branchcode,
3161
            replacementprice => 99.00,
3162
            itype            => $itemtype,
3163
        }
3164
    );
3165
3166
    my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
3167
3168
    ## Start with basic call, should just close out the open fine
3169
    my $accountline = Koha::Account::Line->new(
3170
        {
3171
            borrowernumber => $patron->id,
3172
            debit_type_code    => 'LOST',
3173
            status         => undef,
3174
            itemnumber     => $item->itemnumber,
3175
            amount => 99.00,
3176
            amountoutstanding => 99.00,
3177
            interface => 'test',
3178
        }
3179
    )->store();
3180
3181
    $patron->delete();
3182
3183
    my $return_value = C4::Circulation::_FixAccountForLostAndFound( $patron->id, $item->itemnumber );
3184
3185
    is( $return_value, undef, "_FixAccountForLostAndFound returns undef if patron is deleted" );
3186
3187
};
3188
3189
subtest 'Set waiting flag' => sub {
2756
subtest 'Set waiting flag' => sub {
3190
    plan tests => 11;
2757
    plan tests => 11;
3191
2758
(-)a/t/db_dependent/Items.t (-29 / +4 lines)
Lines 33-39 use Koha::AuthorisedValues; Link Here
33
use t::lib::Mocks;
33
use t::lib::Mocks;
34
use t::lib::TestBuilder;
34
use t::lib::TestBuilder;
35
35
36
use Test::More tests => 15;
36
use Test::More tests => 14;
37
37
38
use Test::Warn;
38
use Test::Warn;
39
39
Lines 126-156 subtest 'General Add, Get and Del tests' => sub { Link Here
126
    $schema->storage->txn_rollback;
126
    $schema->storage->txn_rollback;
127
};
127
};
128
128
129
subtest 'ModItem tests' => sub {
130
    plan tests => 6;
131
132
    $schema->storage->txn_begin;
133
134
    my $builder = t::lib::TestBuilder->new;
135
    my $item    = $builder->build_sample_item();
136
137
    my @fields = qw( itemlost withdrawn damaged );
138
    for my $field (@fields) {
139
        my $field_on = $field."_on";
140
141
        $item->$field(1)->store;
142
        $item->discard_changes;
143
        is( output_pref({ str => $item->$field_on, dateonly => 1 }), output_pref({ dt => dt_from_string(), dateonly => 1 }), "When updating $field, $field_on is updated" );
144
145
        $item->$field(0)->store;
146
        $item->discard_changes;
147
        is( $item->$field_on, undef, "When clearing $field, $field_on is cleared" );
148
    }
149
150
    $schema->storage->txn_rollback;
151
152
};
153
154
subtest 'ModItemTransfer tests' => sub {
129
subtest 'ModItemTransfer tests' => sub {
155
    plan tests => 8;
130
    plan tests => 8;
156
131
Lines 1009-1015 subtest 'ModItemFromMarc' => sub { Link Here
1009
    my $item = Koha::Items->find($itemnumber);
984
    my $item = Koha::Items->find($itemnumber);
1010
    is( $item->itemlost, 1, 'itemlost picked from the item marc');
985
    is( $item->itemlost, 1, 'itemlost picked from the item marc');
1011
986
1012
    $item->paidfor("this is something")->store;
987
    $item->new_status("this is something")->store;
1013
988
1014
    my $updated_item_record = new MARC::Record;
989
    my $updated_item_record = new MARC::Record;
1015
    $updated_item_record->append_fields(
990
    $updated_item_record->append_fields(
Lines 1021-1028 subtest 'ModItemFromMarc' => sub { Link Here
1021
996
1022
    my $updated_item = ModItemFromMarc($updated_item_record, $biblio->biblionumber, $itemnumber);
997
    my $updated_item = ModItemFromMarc($updated_item_record, $biblio->biblionumber, $itemnumber);
1023
    is( $updated_item->{itemlost}, 0, 'itemlost should have been reset to the default value in DB' );
998
    is( $updated_item->{itemlost}, 0, 'itemlost should have been reset to the default value in DB' );
1024
    is( $updated_item->{paidfor}, "this is something", "Non mapped field has not been reset" );
999
    is( $updated_item->{new_status}, "this is something", "Non mapped field has not been reset" );
1025
    is( Koha::Items->find($itemnumber)->paidfor, "this is something" );
1000
    is( Koha::Items->find($itemnumber)->new_status, "this is something" );
1026
1001
1027
    $schema->storage->txn_rollback;
1002
    $schema->storage->txn_rollback;
1028
};
1003
};
(-)a/t/db_dependent/Koha/CirculationRules.t (-5 / +10 lines)
Lines 285-291 subtest 'get_onshelfholds_policy() tests' => sub { Link Here
285
};
285
};
286
286
287
subtest 'get_lostreturn_policy() tests' => sub {
287
subtest 'get_lostreturn_policy() tests' => sub {
288
    plan tests => 6;
288
    plan tests => 7;
289
289
290
    $schema->storage->txn_begin;
290
    $schema->storage->txn_begin;
291
291
Lines 357-364 subtest 'get_lostreturn_policy() tests' => sub { Link Here
357
357
358
    my $item = $builder->build_sample_item(
358
    my $item = $builder->build_sample_item(
359
        {
359
        {
360
            homebranch    => $specific_rule_true->{branchcode},
360
            homebranch    => $specific_rule_false->{branchcode},
361
            holdingbranch => $specific_rule_false->{branchcode}
361
            holdingbranch => $specific_rule_true->{branchcode}
362
        }
362
        }
363
    );
363
    );
364
    my $params = {
364
    my $params = {
Lines 373-383 subtest 'get_lostreturn_policy() tests' => sub { Link Here
373
373
374
    t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'ItemHomeBranch' );
374
    t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'ItemHomeBranch' );
375
    is( Koha::CirculationRules->get_lostreturn_policy( $params ),
375
    is( Koha::CirculationRules->get_lostreturn_policy( $params ),
376
         1,'Specific rule for home branch is applied (true)');
376
         0,'Specific rule for home branch is applied (false)');
377
377
378
    t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'ItemHoldingBranch' );
378
    t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'ItemHoldingBranch' );
379
    is( Koha::CirculationRules->get_lostreturn_policy( $params ),
379
    is( Koha::CirculationRules->get_lostreturn_policy( $params ),
380
         0,'Specific rule for holoding branch is applied (false)');
380
         1,'Specific rule for holding branch is applied (true)');
381
381
382
    # Default rule check
382
    # Default rule check
383
    t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'CheckinLibrary' );
383
    t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl', 'CheckinLibrary' );
Lines 405-409 subtest 'get_lostreturn_policy() tests' => sub { Link Here
405
    is( Koha::CirculationRules->get_lostreturn_policy( $params ),
405
    is( Koha::CirculationRules->get_lostreturn_policy( $params ),
406
         1,'No rule for branch, no default rule, fallback default (true)');
406
         1,'No rule for branch, no default rule, fallback default (true)');
407
407
408
    # Fallback to ItemHoldBranch if CheckinLibrary is undefined
409
    $params->{return_branch} = undef;
410
    is( Koha::CirculationRules->get_lostreturn_policy( $params ),
411
         0,'return_branch undefined, fallback to ItemHomeBranch rule (false)');
412
408
    $schema->storage->txn_rollback;
413
    $schema->storage->txn_rollback;
409
};
414
};
(-)a/t/db_dependent/Koha/Items.t (-14 / +743 lines)
Lines 21-26 use Modern::Perl; Link Here
21
21
22
use Test::More tests => 11;
22
use Test::More tests => 11;
23
use Test::Exception;
23
use Test::Exception;
24
use Time::Fake;
24
25
25
use C4::Circulation;
26
use C4::Circulation;
26
use C4::Context;
27
use C4::Context;
Lines 64-87 my $retrieved_item_1 = Koha::Items->find( $new_item_1->itemnumber ); Link Here
64
is( $retrieved_item_1->barcode, $new_item_1->barcode, 'Find a item by id should return the correct item' );
65
is( $retrieved_item_1->barcode, $new_item_1->barcode, 'Find a item by id should return the correct item' );
65
66
66
subtest 'store' => sub {
67
subtest 'store' => sub {
67
    plan tests => 4;
68
    plan tests => 6;
69
68
    my $biblio = $builder->build_sample_biblio;
70
    my $biblio = $builder->build_sample_biblio;
69
    my $today = dt_from_string->set( hour => 0, minute => 0, second => 0 );
71
    my $today  = dt_from_string->set( hour => 0, minute => 0, second => 0 );
70
    my $item = Koha::Item->new(
72
    my $item   = Koha::Item->new(
71
        {
73
        {
72
            homebranch    => $library->{branchcode},
74
            homebranch    => $library->{branchcode},
73
            holdingbranch => $library->{branchcode},
75
            holdingbranch => $library->{branchcode},
74
            biblionumber  => $biblio->biblionumber,
76
            biblionumber  => $biblio->biblionumber,
75
            location      => 'my_loc',
77
            location      => 'my_loc',
76
        }
78
        }
77
    )->store
79
    )->store->get_from_storage;
78
    ->get_from_storage;
80
79
81
    is( t::lib::Dates::compare( $item->replacementpricedate, $today ),
80
    is( t::lib::Dates::compare($item->replacementpricedate, $today), 0, 'replacementpricedate must have been set to today if not given');
82
        0, 'replacementpricedate must have been set to today if not given' );
81
    is( t::lib::Dates::compare($item->datelastseen,         $today), 0, 'datelastseen must have been set to today if not given');
83
    is( t::lib::Dates::compare( $item->datelastseen, $today ),
82
    is( $item->itype, $biblio->biblioitem->itemtype, 'items.itype must have been set to biblioitem.itemtype is not given');
84
        0, 'datelastseen must have been set to today if not given' );
83
    is( $item->permanent_location, $item->location, 'permanent_location must have been set to location if not given' );
85
    is(
86
        $item->itype,
87
        $biblio->biblioitem->itemtype,
88
        'items.itype must have been set to biblioitem.itemtype is not given'
89
    );
90
    is( $item->permanent_location, $item->location,
91
        'permanent_location must have been set to location if not given' );
84
    $item->delete;
92
    $item->delete;
93
94
    subtest '*_on updates' => sub {
95
        plan tests => 9;
96
97
        # Once the '_on' value is set (triggered by the related field turning from false to true)
98
        # it should not be re-set for any changes outside of the related field being 'unset'.
99
100
        my @fields = qw( itemlost withdrawn damaged );
101
        my $today = dt_from_string();
102
        my $yesterday = $today->clone()->subtract( days => 1 );
103
104
        for my $field ( @fields ) {
105
            my $item = $builder->build_sample_item(
106
                {
107
                    itemlost     => 0,
108
                    itemlost_on  => undef,
109
                    withdrawn    => 0,
110
                    withdrawn_on => undef,
111
                    damaged      => 0,
112
                    damaged_on   => undef
113
                }
114
            );
115
            my $field_on = $field . '_on';
116
117
            # Set field for the first time
118
            Time::Fake->offset( $yesterday->epoch );
119
            $item->$field(1)->store;
120
            $item->get_from_storage;
121
            is( t::lib::Dates::compare( $item->$field_on, $yesterday ),
122
                0, $field_on . " was set upon first truthy setting" );
123
124
            # Update the field to a new 'true' value
125
            Time::Fake->offset( $today->epoch );
126
            $item->$field(2)->store;
127
            $item->get_from_storage;
128
            is( t::lib::Dates::compare( $item->$field_on, $yesterday ),
129
                0, $field_on . " was not updated upon second truthy setting" );
130
131
            # Update the field to a new 'false' value
132
            $item->$field(0)->store;
133
            $item->get_from_storage;
134
            is($item->$field_on, undef, $field_on . " was unset upon untruthy setting");
135
136
            Time::Fake->reset;
137
        }
138
    };
139
140
    subtest '_lost_found_trigger' => sub {
141
        plan tests => 7;
142
143
        t::lib::Mocks::mock_preference( 'WhenLostChargeReplacementFee', 1 );
144
        t::lib::Mocks::mock_preference( 'WhenLostForgiveFine',          0 );
145
146
        my $processfee_amount  = 20;
147
        my $replacement_amount = 99.00;
148
        my $item_type          = $builder->build_object(
149
            {
150
                class => 'Koha::ItemTypes',
151
                value => {
152
                    notforloan         => undef,
153
                    rentalcharge       => 0,
154
                    defaultreplacecost => undef,
155
                    processfee         => $processfee_amount,
156
                    rentalcharge_daily => 0,
157
                }
158
            }
159
        );
160
        my $library = $builder->build_object( { class => 'Koha::Libraries' } );
161
162
        $biblio = $builder->build_sample_biblio( { author => 'Hall, Daria' } );
163
164
        subtest 'Full write-off tests' => sub {
165
166
            plan tests => 12;
167
168
            my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
169
            my $manager =
170
              $builder->build_object( { class => "Koha::Patrons" } );
171
            t::lib::Mocks::mock_userenv(
172
                { patron => $manager, branchcode => $manager->branchcode } );
173
174
            my $item = $builder->build_sample_item(
175
                {
176
                    biblionumber     => $biblio->biblionumber,
177
                    library          => $library->branchcode,
178
                    replacementprice => $replacement_amount,
179
                    itype            => $item_type->itemtype,
180
                }
181
            );
182
183
            C4::Circulation::AddIssue( $patron->unblessed, $item->barcode );
184
185
            # Simulate item marked as lost
186
            $item->itemlost(3)->store;
187
            C4::Circulation::LostItem( $item->itemnumber, 1 );
188
189
            my $processing_fee_lines = Koha::Account::Lines->search(
190
                {
191
                    borrowernumber  => $patron->id,
192
                    itemnumber      => $item->itemnumber,
193
                    debit_type_code => 'PROCESSING'
194
                }
195
            );
196
            is( $processing_fee_lines->count,
197
                1, 'Only one processing fee produced' );
198
            my $processing_fee_line = $processing_fee_lines->next;
199
            is( $processing_fee_line->amount + 0,
200
                $processfee_amount,
201
                'The right PROCESSING amount is generated' );
202
            is( $processing_fee_line->amountoutstanding + 0,
203
                $processfee_amount,
204
                'The right PROCESSING amountoutstanding is generated' );
205
206
            my $lost_fee_lines = Koha::Account::Lines->search(
207
                {
208
                    borrowernumber  => $patron->id,
209
                    itemnumber      => $item->itemnumber,
210
                    debit_type_code => 'LOST'
211
                }
212
            );
213
            is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
214
            my $lost_fee_line = $lost_fee_lines->next;
215
            is( $lost_fee_line->amount + 0,
216
                $replacement_amount, 'The right LOST amount is generated' );
217
            is( $lost_fee_line->amountoutstanding + 0,
218
                $replacement_amount,
219
                'The right LOST amountoutstanding is generated' );
220
            is( $lost_fee_line->status, undef, 'The LOST status was not set' );
221
222
            my $account = $patron->account;
223
            my $debts   = $account->outstanding_debits;
224
225
            # Write off the debt
226
            my $credit = $account->add_credit(
227
                {
228
                    amount    => $account->balance,
229
                    type      => 'WRITEOFF',
230
                    interface => 'test',
231
                }
232
            );
233
            $credit->apply(
234
                { debits => [ $debts->as_list ], offset_type => 'Writeoff' } );
235
236
            # Simulate item marked as found
237
            $item->itemlost(0)->store;
238
            is( $item->{_refunded}, undef, 'No LOST_FOUND account line added' );
239
240
            $lost_fee_line->discard_changes;    # reload from DB
241
            is( $lost_fee_line->amountoutstanding + 0,
242
                0, 'Lost fee has no outstanding amount' );
243
            is( $lost_fee_line->debit_type_code,
244
                'LOST', 'Lost fee now still has account type of LOST' );
245
            is( $lost_fee_line->status, 'FOUND',
246
                "Lost fee now has account status of FOUND - No Refund" );
247
248
            is( $patron->account->balance,
249
                -0, 'The patron balance is 0, everything was written off' );
250
        };
251
252
        subtest 'Full payment tests' => sub {
253
254
            plan tests => 14;
255
256
            my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
257
258
            my $item = $builder->build_sample_item(
259
                {
260
                    biblionumber     => $biblio->biblionumber,
261
                    library          => $library->branchcode,
262
                    replacementprice => $replacement_amount,
263
                    itype            => $item_type->itemtype
264
                }
265
            );
266
267
            my $issue =
268
              C4::Circulation::AddIssue( $patron->unblessed, $item->barcode );
269
270
            # Simulate item marked as lost
271
            $item->itemlost(1)->store;
272
            C4::Circulation::LostItem( $item->itemnumber, 1 );
273
274
            my $processing_fee_lines = Koha::Account::Lines->search(
275
                {
276
                    borrowernumber  => $patron->id,
277
                    itemnumber      => $item->itemnumber,
278
                    debit_type_code => 'PROCESSING'
279
                }
280
            );
281
            is( $processing_fee_lines->count,
282
                1, 'Only one processing fee produced' );
283
            my $processing_fee_line = $processing_fee_lines->next;
284
            is( $processing_fee_line->amount + 0,
285
                $processfee_amount,
286
                'The right PROCESSING amount is generated' );
287
            is( $processing_fee_line->amountoutstanding + 0,
288
                $processfee_amount,
289
                'The right PROCESSING amountoutstanding is generated' );
290
291
            my $lost_fee_lines = Koha::Account::Lines->search(
292
                {
293
                    borrowernumber  => $patron->id,
294
                    itemnumber      => $item->itemnumber,
295
                    debit_type_code => 'LOST'
296
                }
297
            );
298
            is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
299
            my $lost_fee_line = $lost_fee_lines->next;
300
            is( $lost_fee_line->amount + 0,
301
                $replacement_amount, 'The right LOST amount is generated' );
302
            is( $lost_fee_line->amountoutstanding + 0,
303
                $replacement_amount,
304
                'The right LOST amountountstanding is generated' );
305
306
            my $account = $patron->account;
307
            my $debts   = $account->outstanding_debits;
308
309
            # Pay off the debt
310
            my $credit = $account->add_credit(
311
                {
312
                    amount    => $account->balance,
313
                    type      => 'PAYMENT',
314
                    interface => 'test',
315
                }
316
            );
317
            $credit->apply(
318
                { debits => [ $debts->as_list ], offset_type => 'Payment' } );
319
320
            # Simulate item marked as found
321
            $item->itemlost(0)->store;
322
            is( $item->{_refunded}, 1, 'Refund triggered' );
323
324
            my $credit_return = Koha::Account::Lines->search(
325
                {
326
                    itemnumber       => $item->itemnumber,
327
                    credit_type_code => 'LOST_FOUND'
328
                },
329
                { rows => 1 }
330
            )->single;
331
332
            ok( $credit_return, 'An account line of type LOST_FOUND is added' );
333
            is( $credit_return->amount + 0,
334
                -99.00,
335
                'The account line of type LOST_FOUND has an amount of -99' );
336
            is(
337
                $credit_return->amountoutstanding + 0,
338
                -99.00,
339
'The account line of type LOST_FOUND has an amountoutstanding of -99'
340
            );
341
342
            $lost_fee_line->discard_changes;
343
            is( $lost_fee_line->amountoutstanding + 0,
344
                0, 'Lost fee has no outstanding amount' );
345
            is( $lost_fee_line->debit_type_code,
346
                'LOST', 'Lost fee now still has account type of LOST' );
347
            is( $lost_fee_line->status, 'FOUND',
348
                "Lost fee now has account status of FOUND" );
349
350
            is( $patron->account->balance, -99,
351
'The patron balance is -99, a credit that equals the lost fee payment'
352
            );
353
        };
354
355
        subtest 'Test without payment or write off' => sub {
356
357
            plan tests => 14;
358
359
            my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
360
361
            my $item = $builder->build_sample_item(
362
                {
363
                    biblionumber     => $biblio->biblionumber,
364
                    library          => $library->branchcode,
365
                    replacementprice => 23.00,
366
                    replacementprice => $replacement_amount,
367
                    itype            => $item_type->itemtype
368
                }
369
            );
370
371
            my $issue =
372
              C4::Circulation::AddIssue( $patron->unblessed, $item->barcode );
373
374
            # Simulate item marked as lost
375
            $item->itemlost(3)->store;
376
            C4::Circulation::LostItem( $item->itemnumber, 1 );
377
378
            my $processing_fee_lines = Koha::Account::Lines->search(
379
                {
380
                    borrowernumber  => $patron->id,
381
                    itemnumber      => $item->itemnumber,
382
                    debit_type_code => 'PROCESSING'
383
                }
384
            );
385
            is( $processing_fee_lines->count,
386
                1, 'Only one processing fee produced' );
387
            my $processing_fee_line = $processing_fee_lines->next;
388
            is( $processing_fee_line->amount + 0,
389
                $processfee_amount,
390
                'The right PROCESSING amount is generated' );
391
            is( $processing_fee_line->amountoutstanding + 0,
392
                $processfee_amount,
393
                'The right PROCESSING amountoutstanding is generated' );
394
395
            my $lost_fee_lines = Koha::Account::Lines->search(
396
                {
397
                    borrowernumber  => $patron->id,
398
                    itemnumber      => $item->itemnumber,
399
                    debit_type_code => 'LOST'
400
                }
401
            );
402
            is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
403
            my $lost_fee_line = $lost_fee_lines->next;
404
            is( $lost_fee_line->amount + 0,
405
                $replacement_amount, 'The right LOST amount is generated' );
406
            is( $lost_fee_line->amountoutstanding + 0,
407
                $replacement_amount,
408
                'The right LOST amountountstanding is generated' );
409
410
            # Simulate item marked as found
411
            $item->itemlost(0)->store;
412
            is( $item->{_refunded}, 1, 'Refund triggered' );
413
414
            my $credit_return = Koha::Account::Lines->search(
415
                {
416
                    itemnumber       => $item->itemnumber,
417
                    credit_type_code => 'LOST_FOUND'
418
                },
419
                { rows => 1 }
420
            )->single;
421
422
            ok( $credit_return, 'An account line of type LOST_FOUND is added' );
423
            is( $credit_return->amount + 0,
424
                -99.00,
425
                'The account line of type LOST_FOUND has an amount of -99' );
426
            is(
427
                $credit_return->amountoutstanding + 0,
428
                0,
429
'The account line of type LOST_FOUND has an amountoutstanding of 0'
430
            );
431
432
            $lost_fee_line->discard_changes;
433
            is( $lost_fee_line->amountoutstanding + 0,
434
                0, 'Lost fee has no outstanding amount' );
435
            is( $lost_fee_line->debit_type_code,
436
                'LOST', 'Lost fee now still has account type of LOST' );
437
            is( $lost_fee_line->status, 'FOUND',
438
                "Lost fee now has account status of FOUND" );
439
440
            is( $patron->account->balance,
441
                20, 'The patron balance is 20, still owes the processing fee' );
442
        };
443
444
        subtest
445
          'Test with partial payement and write off, and remaining debt' =>
446
          sub {
447
448
            plan tests => 17;
449
450
            my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
451
            my $item = $builder->build_sample_item(
452
                {
453
                    biblionumber     => $biblio->biblionumber,
454
                    library          => $library->branchcode,
455
                    replacementprice => $replacement_amount,
456
                    itype            => $item_type->itemtype
457
                }
458
            );
459
460
            my $issue =
461
              C4::Circulation::AddIssue( $patron->unblessed, $item->barcode );
462
463
            # Simulate item marked as lost
464
            $item->itemlost(1)->store;
465
            C4::Circulation::LostItem( $item->itemnumber, 1 );
466
467
            my $processing_fee_lines = Koha::Account::Lines->search(
468
                {
469
                    borrowernumber  => $patron->id,
470
                    itemnumber      => $item->itemnumber,
471
                    debit_type_code => 'PROCESSING'
472
                }
473
            );
474
            is( $processing_fee_lines->count,
475
                1, 'Only one processing fee produced' );
476
            my $processing_fee_line = $processing_fee_lines->next;
477
            is( $processing_fee_line->amount + 0,
478
                $processfee_amount,
479
                'The right PROCESSING amount is generated' );
480
            is( $processing_fee_line->amountoutstanding + 0,
481
                $processfee_amount,
482
                'The right PROCESSING amountoutstanding is generated' );
483
484
            my $lost_fee_lines = Koha::Account::Lines->search(
485
                {
486
                    borrowernumber  => $patron->id,
487
                    itemnumber      => $item->itemnumber,
488
                    debit_type_code => 'LOST'
489
                }
490
            );
491
            is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
492
            my $lost_fee_line = $lost_fee_lines->next;
493
            is( $lost_fee_line->amount + 0,
494
                $replacement_amount, 'The right LOST amount is generated' );
495
            is( $lost_fee_line->amountoutstanding + 0,
496
                $replacement_amount,
497
                'The right LOST amountountstanding is generated' );
498
499
            my $account = $patron->account;
500
            is(
501
                $account->balance,
502
                $processfee_amount + $replacement_amount,
503
                'Balance is PROCESSING + L'
504
            );
505
506
            # Partially pay fee
507
            my $payment_amount = 27;
508
            my $payment        = $account->add_credit(
509
                {
510
                    amount    => $payment_amount,
511
                    type      => 'PAYMENT',
512
                    interface => 'test',
513
                }
514
            );
515
516
            $payment->apply(
517
                { debits => [$lost_fee_line], offset_type => 'Payment' } );
518
519
            # Partially write off fee
520
            my $write_off_amount = 25;
521
            my $write_off        = $account->add_credit(
522
                {
523
                    amount    => $write_off_amount,
524
                    type      => 'WRITEOFF',
525
                    interface => 'test',
526
                }
527
            );
528
            $write_off->apply(
529
                { debits => [$lost_fee_line], offset_type => 'Writeoff' } );
530
531
            is(
532
                $account->balance,
533
                $processfee_amount +
534
                  $replacement_amount -
535
                  $payment_amount -
536
                  $write_off_amount,
537
                'Payment and write off applied'
538
            );
539
540
            # Store the amountoutstanding value
541
            $lost_fee_line->discard_changes;
542
            my $outstanding = $lost_fee_line->amountoutstanding;
543
544
            # Simulate item marked as found
545
            $item->itemlost(0)->store;
546
            is( $item->{_refunded}, 1, 'Refund triggered' );
547
548
            my $credit_return = Koha::Account::Lines->search(
549
                {
550
                    itemnumber       => $item->itemnumber,
551
                    credit_type_code => 'LOST_FOUND'
552
                },
553
                { rows => 1 }
554
            )->single;
555
556
            ok( $credit_return, 'An account line of type LOST_FOUND is added' );
557
558
            is(
559
                $account->balance,
560
                $processfee_amount - $payment_amount,
561
                'Balance is PROCESSING - PAYMENT (LOST_FOUND)'
562
            );
563
564
            $lost_fee_line->discard_changes;
565
            is( $lost_fee_line->amountoutstanding + 0,
566
                0, 'Lost fee has no outstanding amount' );
567
            is( $lost_fee_line->debit_type_code,
568
                'LOST', 'Lost fee now still has account type of LOST' );
569
            is( $lost_fee_line->status, 'FOUND',
570
                "Lost fee now has account status of FOUND" );
571
572
            is(
573
                $credit_return->amount + 0,
574
                ( $payment_amount + $outstanding ) * -1,
575
'The account line of type LOST_FOUND has an amount equal to the payment + outstanding'
576
            );
577
            is(
578
                $credit_return->amountoutstanding + 0,
579
                $payment_amount * -1,
580
'The account line of type LOST_FOUND has an amountoutstanding equal to the payment'
581
            );
582
583
            is(
584
                $account->balance,
585
                $processfee_amount - $payment_amount,
586
'The patron balance is the difference between the PROCESSING and the credit'
587
            );
588
          };
589
590
        subtest 'Partial payment, existing debits and AccountAutoReconcile' =>
591
          sub {
592
593
            plan tests => 10;
594
595
            my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
596
            my $barcode            = 'KD123456793';
597
            my $replacement_amount = 100;
598
            my $processfee_amount  = 20;
599
600
            my $item_type = $builder->build_object(
601
                {
602
                    class => 'Koha::ItemTypes',
603
                    value => {
604
                        notforloan         => undef,
605
                        rentalcharge       => 0,
606
                        defaultreplacecost => undef,
607
                        processfee         => 0,
608
                        rentalcharge_daily => 0,
609
                    }
610
                }
611
            );
612
            my $item = Koha::Item->new(
613
                {
614
                    biblionumber     => $biblio->biblionumber,
615
                    homebranch       => $library->branchcode,
616
                    holdingbranch    => $library->branchcode,
617
                    barcode          => $barcode,
618
                    replacementprice => $replacement_amount,
619
                    itype            => $item_type->itemtype
620
                },
621
            )->store;
622
623
            my $issue =
624
              C4::Circulation::AddIssue( $patron->unblessed, $barcode );
625
626
            # Simulate item marked as lost
627
            $item->itemlost(1)->store;
628
            C4::Circulation::LostItem( $item->itemnumber, 1 );
629
630
            my $lost_fee_lines = Koha::Account::Lines->search(
631
                {
632
                    borrowernumber  => $patron->id,
633
                    itemnumber      => $item->itemnumber,
634
                    debit_type_code => 'LOST'
635
                }
636
            );
637
            is( $lost_fee_lines->count, 1, 'Only one lost item fee produced' );
638
            my $lost_fee_line = $lost_fee_lines->next;
639
            is( $lost_fee_line->amount + 0,
640
                $replacement_amount, 'The right LOST amount is generated' );
641
            is( $lost_fee_line->amountoutstanding + 0,
642
                $replacement_amount,
643
                'The right LOST amountountstanding is generated' );
644
645
            my $account = $patron->account;
646
            is( $account->balance, $replacement_amount, 'Balance is L' );
647
648
            # Partially pay fee
649
            my $payment_amount = 27;
650
            my $payment        = $account->add_credit(
651
                {
652
                    amount    => $payment_amount,
653
                    type      => 'PAYMENT',
654
                    interface => 'test',
655
                }
656
            );
657
            $payment->apply(
658
                { debits => [$lost_fee_line], offset_type => 'Payment' } );
659
660
            is(
661
                $account->balance,
662
                $replacement_amount - $payment_amount,
663
                'Payment applied'
664
            );
665
666
            my $manual_debit_amount = 80;
667
            $account->add_debit(
668
                {
669
                    amount    => $manual_debit_amount,
670
                    type      => 'OVERDUE',
671
                    interface => 'test'
672
                }
673
            );
674
675
            is(
676
                $account->balance,
677
                $manual_debit_amount + $replacement_amount - $payment_amount,
678
                'Manual debit applied'
679
            );
680
681
            t::lib::Mocks::mock_preference( 'AccountAutoReconcile', 1 );
682
683
            # Simulate item marked as found
684
            $item->itemlost(0)->store;
685
            is( $item->{_refunded}, 1, 'Refund triggered' );
686
687
            my $credit_return = Koha::Account::Lines->search(
688
                {
689
                    itemnumber       => $item->itemnumber,
690
                    credit_type_code => 'LOST_FOUND'
691
                },
692
                { rows => 1 }
693
            )->single;
694
695
            ok( $credit_return, 'An account line of type LOST_FOUND is added' );
696
697
            is(
698
                $account->balance,
699
                $manual_debit_amount - $payment_amount,
700
                'Balance is PROCESSING - payment (LOST_FOUND)'
701
            );
702
703
            my $manual_debit = Koha::Account::Lines->search(
704
                {
705
                    borrowernumber  => $patron->id,
706
                    debit_type_code => 'OVERDUE',
707
                    status          => 'UNRETURNED'
708
                }
709
            )->next;
710
            is(
711
                $manual_debit->amountoutstanding + 0,
712
                $manual_debit_amount - $payment_amount,
713
                'reconcile_balance was called'
714
            );
715
          };
716
717
        subtest 'Patron deleted' => sub {
718
            plan tests => 1;
719
720
            my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
721
            my $barcode            = 'KD123456794';
722
            my $replacement_amount = 100;
723
            my $processfee_amount  = 20;
724
725
            my $item_type = $builder->build_object(
726
                {
727
                    class => 'Koha::ItemTypes',
728
                    value => {
729
                        notforloan         => undef,
730
                        rentalcharge       => 0,
731
                        defaultreplacecost => undef,
732
                        processfee         => 0,
733
                        rentalcharge_daily => 0,
734
                    }
735
                }
736
            );
737
            my $item = Koha::Item->new(
738
                {
739
                    biblionumber     => $biblio->biblionumber,
740
                    homebranch       => $library->branchcode,
741
                    holdingbranch    => $library->branchcode,
742
                    barcode          => $barcode,
743
                    replacementprice => $replacement_amount,
744
                    itype            => $item_type->itemtype
745
                },
746
            )->store;
747
748
            my $issue =
749
              C4::Circulation::AddIssue( $patron->unblessed, $barcode );
750
751
            # Simulate item marked as lost
752
            $item->itemlost(1)->store;
753
            C4::Circulation::LostItem( $item->itemnumber, 1 );
754
755
            $issue->delete();
756
            $patron->delete();
757
758
            # Simulate item marked as found
759
            $item->itemlost(0)->store;
760
            is( $item->{_refunded}, undef, 'No refund triggered' );
761
762
        };
763
764
        subtest 'Continue when userenv is not set' => sub {
765
            plan tests => 1;
766
767
            my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
768
            my $barcode            = 'KD123456795';
769
            my $replacement_amount = 100;
770
            my $processfee_amount  = 20;
771
772
            my $item_type = $builder->build_object(
773
                {
774
                    class => 'Koha::ItemTypes',
775
                    value => {
776
                        notforloan         => undef,
777
                        rentalcharge       => 0,
778
                        defaultreplacecost => undef,
779
                        processfee         => 0,
780
                        rentalcharge_daily => 0,
781
                    }
782
                }
783
            );
784
            my $item = $builder->build_sample_item(
785
                {
786
                    biblionumber     => $biblio->biblionumber,
787
                    homebranch       => $library->branchcode,
788
                    holdingbranch    => $library->branchcode,
789
                    barcode          => $barcode,
790
                    replacementprice => $replacement_amount,
791
                    itype            => $item_type->itemtype
792
                }
793
            );
794
795
            my $issue =
796
              C4::Circulation::AddIssue( $patron->unblessed, $barcode );
797
798
            # Simulate item marked as lost
799
            $item->itemlost(1)->store;
800
            C4::Circulation::LostItem( $item->itemnumber, 1 );
801
802
            # Unset the userenv
803
            C4::Context->_new_userenv(undef);
804
805
            # Simluate item marked as found
806
            $item->itemlost(0)->store;
807
            is( $item->{_refunded}, 1, 'No refund triggered' );
808
809
        };
810
    };
85
};
811
};
86
812
87
subtest 'get_transfer' => sub {
813
subtest 'get_transfer' => sub {
Lines 107-113 subtest 'holds' => sub { Link Here
107
    my $item   = $builder->build_sample_item({
833
    my $item   = $builder->build_sample_item({
108
        biblionumber => $biblio->biblionumber,
834
        biblionumber => $biblio->biblionumber,
109
    });
835
    });
110
    $nb_of_items++;
111
    is($item->holds->count, 0, "Nothing returned if no holds");
836
    is($item->holds->count, 0, "Nothing returned if no holds");
112
    my $hold1 = $builder->build({ source => 'Reserve', value => { itemnumber=>$item->itemnumber, found => 'T' }});
837
    my $hold1 = $builder->build({ source => 'Reserve', value => { itemnumber=>$item->itemnumber, found => 'T' }});
113
    my $hold2 = $builder->build({ source => 'Reserve', value => { itemnumber=>$item->itemnumber, found => 'W' }});
838
    my $hold2 = $builder->build({ source => 'Reserve', value => { itemnumber=>$item->itemnumber, found => 'W' }});
Lines 135-140 subtest 'biblioitem' => sub { Link Here
135
    is( $biblioitem->biblionumber, $retrieved_item_1->biblionumber, 'Koha::Item->biblioitem should return the correct biblioitem' );
860
    is( $biblioitem->biblionumber, $retrieved_item_1->biblionumber, 'Koha::Item->biblioitem should return the correct biblioitem' );
136
};
861
};
137
862
863
# Restore userenv
864
t::lib::Mocks::mock_userenv({ branchcode => $library->{branchcode} });
138
subtest 'checkout' => sub {
865
subtest 'checkout' => sub {
139
    plan tests => 5;
866
    plan tests => 5;
140
    my $item = Koha::Items->find( $new_item_1->itemnumber );
867
    my $item = Koha::Items->find( $new_item_1->itemnumber );
Lines 172-178 subtest 'can_be_transferred' => sub { Link Here
172
        homebranch       => $library1->branchcode,
899
        homebranch       => $library1->branchcode,
173
        holdingbranch    => $library1->branchcode,
900
        holdingbranch    => $library1->branchcode,
174
    });
901
    });
175
    $nb_of_items++;
176
902
177
    is(Koha::Item::Transfer::Limits->search({
903
    is(Koha::Item::Transfer::Limits->search({
178
        fromBranch => $library1->branchcode,
904
        fromBranch => $library1->branchcode,
Lines 196-202 subtest 'can_be_transferred' => sub { Link Here
196
       'We get the same result also if we pass the from-library parameter.');
922
       'We get the same result also if we pass the from-library parameter.');
197
};
923
};
198
924
925
# Reset nb_of_items prior to testing delete
926
$nb_of_items = Koha::Items->search->count;
927
928
# Test delete
199
$retrieved_item_1->delete;
929
$retrieved_item_1->delete;
200
is( Koha::Items->search->count, $nb_of_items + 1, 'Delete should have deleted the item' );
930
is( Koha::Items->search->count, $nb_of_items - 1, 'Delete should have deleted the item' );
201
931
202
$schema->storage->txn_rollback;
932
$schema->storage->txn_rollback;
203
- 

Return to bug 18501