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

(-)a/t/db_dependent/Circulation.t (-2 / +452 lines)
Lines 2345-2351 subtest 'CanBookBeIssued + AutoReturnCheckedOutItems' => sub { Link Here
2345
2345
2346
2346
2347
subtest 'AddReturn | is_overdue' => sub {
2347
subtest 'AddReturn | is_overdue' => sub {
2348
    plan tests => 8;
2348
    plan tests => 9;
2349
2349
2350
    t::lib::Mocks::mock_preference('MarkLostItemsAsReturned', 'batchmod|moredetail|cronjob|additem|pendingreserves|onpayment');
2350
    t::lib::Mocks::mock_preference('MarkLostItemsAsReturned', 'batchmod|moredetail|cronjob|additem|pendingreserves|onpayment');
2351
    t::lib::Mocks::mock_preference('CalculateFinesOnReturn', 1);
2351
    t::lib::Mocks::mock_preference('CalculateFinesOnReturn', 1);
Lines 2658-2663 subtest 'AddReturn | is_overdue' => sub { Link Here
2658
        Koha::Account::Lines->search(
2658
        Koha::Account::Lines->search(
2659
            { borrowernumber => $patron->borrowernumber } )->delete;
2659
            { borrowernumber => $patron->borrowernumber } )->delete;
2660
    };
2660
    };
2661
2662
    subtest 'enh 23091 | Lost item return policies' => sub {
2663
        plan tests => 4;
2664
2665
        my $manager = $builder->build_object({ class => "Koha::Patrons" });
2666
2667
        my $branchcode_false =
2668
          $builder->build( { source => 'Branch' } )->{branchcode};
2669
        my $specific_rule_false = $builder->build(
2670
            {
2671
                source => 'CirculationRule',
2672
                value  => {
2673
                    branchcode   => $branchcode_false,
2674
                    categorycode => undef,
2675
                    itemtype     => undef,
2676
                    rule_name    => 'lostreturn',
2677
                    rule_value   => 0
2678
                }
2679
            }
2680
        );
2681
        my $branchcode_refund =
2682
          $builder->build( { source => 'Branch' } )->{branchcode};
2683
        my $specific_rule_refund = $builder->build(
2684
            {
2685
                source => 'CirculationRule',
2686
                value  => {
2687
                    branchcode   => $branchcode_refund,
2688
                    categorycode => undef,
2689
                    itemtype     => undef,
2690
                    rule_name    => 'lostreturn',
2691
                    rule_value   => 'refund'
2692
                }
2693
            }
2694
        );
2695
        my $branchcode_restore =
2696
          $builder->build( { source => 'Branch' } )->{branchcode};
2697
        my $specific_rule_restore = $builder->build(
2698
            {
2699
                source => 'CirculationRule',
2700
                value  => {
2701
                    branchcode   => $branchcode_restore,
2702
                    categorycode => undef,
2703
                    itemtype     => undef,
2704
                    rule_name    => 'lostreturn',
2705
                    rule_value   => 'restore'
2706
                }
2707
            }
2708
        );
2709
        my $branchcode_charge =
2710
          $builder->build( { source => 'Branch' } )->{branchcode};
2711
        my $specific_rule_charge = $builder->build(
2712
            {
2713
                source => 'CirculationRule',
2714
                value  => {
2715
                    branchcode   => $branchcode_charge,
2716
                    categorycode => undef,
2717
                    itemtype     => undef,
2718
                    rule_name    => 'lostreturn',
2719
                    rule_value   => 'charge'
2720
                }
2721
            }
2722
        );
2723
2724
        my $replacement_amount = 99.00;
2725
        t::lib::Mocks::mock_preference( 'AllowReturnToBranch', 'anywhere' );
2726
        t::lib::Mocks::mock_preference( 'WhenLostChargeReplacementFee', 1 );
2727
        t::lib::Mocks::mock_preference( 'WhenLostForgiveFine',          0 );
2728
        t::lib::Mocks::mock_preference( 'BlockReturnOfLostItems',       0 );
2729
        t::lib::Mocks::mock_preference( 'RefundLostOnReturnControl',
2730
            'CheckinLibrary' );
2731
        t::lib::Mocks::mock_preference( 'NoRefundOnLostReturnedItemsAge',
2732
            undef );
2733
2734
        subtest 'lostreturn | false' => sub {
2735
            plan tests => 12;
2736
2737
            t::lib::Mocks::mock_userenv({ patron => $manager, branchcode => $branchcode_false });
2738
            
2739
            my $item = $builder->build_sample_item(
2740
                {
2741
                    replacementprice => $replacement_amount
2742
                }
2743
            );
2744
2745
            # Issue the item
2746
            my $issue = C4::Circulation::AddIssue( $patron->unblessed, $item->barcode, $ten_days_ago );
2747
2748
            # Fake fines cronjob on this checkout
2749
            my ($fine) =
2750
              CalcFine( $item, $patron->categorycode, $library->{branchcode},
2751
                $ten_days_ago, $now );
2752
            UpdateFine(
2753
                {
2754
                    issue_id       => $issue->issue_id,
2755
                    itemnumber     => $item->itemnumber,
2756
                    borrowernumber => $patron->borrowernumber,
2757
                    amount         => $fine,
2758
                    due            => output_pref($ten_days_ago)
2759
                }
2760
            );
2761
            my $overdue_fees = Koha::Account::Lines->search(
2762
                {
2763
                    borrowernumber  => $patron->id,
2764
                    itemnumber      => $item->itemnumber,
2765
                    debit_type_code => 'OVERDUE'
2766
                }
2767
            );
2768
            is( $overdue_fees->count, 1, 'Overdue item fee produced' );
2769
            my $overdue_fee = $overdue_fees->next;
2770
            is( $overdue_fee->amount + 0,
2771
                10, 'The right OVERDUE amount is generated' );
2772
            is( $overdue_fee->amountoutstanding + 0,
2773
                10,
2774
                'The right OVERDUE amountoutstanding is generated' );
2775
2776
            # Simulate item marked as lost
2777
            $item->itemlost(3)->store;
2778
            C4::Circulation::LostItem( $item->itemnumber, 1 );
2779
2780
            my $lost_fee_lines = Koha::Account::Lines->search(
2781
                {
2782
                    borrowernumber  => $patron->id,
2783
                    itemnumber      => $item->itemnumber,
2784
                    debit_type_code => 'LOST'
2785
                }
2786
            );
2787
            is( $lost_fee_lines->count, 1, 'Lost item fee produced' );
2788
            my $lost_fee_line = $lost_fee_lines->next;
2789
            is( $lost_fee_line->amount + 0,
2790
                $replacement_amount, 'The right LOST amount is generated' );
2791
            is( $lost_fee_line->amountoutstanding + 0,
2792
                $replacement_amount,
2793
                'The right LOST amountoutstanding is generated' );
2794
            is( $lost_fee_line->status, undef, 'The LOST status was not set' );
2795
2796
            # Return lost item
2797
            my ( $returned, $message ) =
2798
              AddReturn( $item->barcode, $branchcode_false, undef, $five_days_ago );
2799
            
2800
            $overdue_fee->discard_changes;
2801
            is( $overdue_fee->amount + 0,
2802
                10, 'The OVERDUE amount is left intact' );
2803
            is( $overdue_fee->amountoutstanding + 0,
2804
                10,
2805
                'The OVERDUE amountoutstanding is left intact' );
2806
2807
            $lost_fee_line->discard_changes;
2808
            is( $lost_fee_line->amount + 0,
2809
                $replacement_amount, 'The LOST amount is left intact' );
2810
            is( $lost_fee_line->amountoutstanding + 0,
2811
                $replacement_amount,
2812
                'The LOST amountoutstanding is left intact' );
2813
            # FIXME: Should we set the LOST fee status to 'FOUND' regardless of whether we're refunding or not?
2814
            is( $lost_fee_line->status, undef, 'The LOST status was not set' );
2815
        };
2816
2817
        subtest 'lostreturn | refund' => sub {
2818
            plan tests => 12;
2819
2820
            t::lib::Mocks::mock_userenv({ patron => $manager, branchcode => $branchcode_refund });
2821
 
2822
            my $item = $builder->build_sample_item(
2823
                {
2824
                    replacementprice => $replacement_amount
2825
                }
2826
            );
2827
2828
            # Issue the item
2829
            my $issue = C4::Circulation::AddIssue( $patron->unblessed, $item->barcode, $ten_days_ago );
2830
2831
            # Fake fines cronjob on this checkout
2832
            my ($fine) =
2833
              CalcFine( $item, $patron->categorycode, $library->{branchcode},
2834
                $ten_days_ago, $now );
2835
            UpdateFine(
2836
                {
2837
                    issue_id       => $issue->issue_id,
2838
                    itemnumber     => $item->itemnumber,
2839
                    borrowernumber => $patron->borrowernumber,
2840
                    amount         => $fine,
2841
                    due            => output_pref($ten_days_ago)
2842
                }
2843
            );
2844
            my $overdue_fees = Koha::Account::Lines->search(
2845
                {
2846
                    borrowernumber  => $patron->id,
2847
                    itemnumber      => $item->itemnumber,
2848
                    debit_type_code => 'OVERDUE'
2849
                }
2850
            );
2851
            is( $overdue_fees->count, 1, 'Overdue item fee produced' );
2852
            my $overdue_fee = $overdue_fees->next;
2853
            is( $overdue_fee->amount + 0,
2854
                10, 'The right OVERDUE amount is generated' );
2855
            is( $overdue_fee->amountoutstanding + 0,
2856
                10,
2857
                'The right OVERDUE amountoutstanding is generated' );
2858
2859
            # Simulate item marked as lost
2860
            $item->itemlost(3)->store;
2861
            C4::Circulation::LostItem( $item->itemnumber, 1 );
2862
2863
            my $lost_fee_lines = Koha::Account::Lines->search(
2864
                {
2865
                    borrowernumber  => $patron->id,
2866
                    itemnumber      => $item->itemnumber,
2867
                    debit_type_code => 'LOST'
2868
                }
2869
            );
2870
            is( $lost_fee_lines->count, 1, 'Lost item fee produced' );
2871
            my $lost_fee_line = $lost_fee_lines->next;
2872
            is( $lost_fee_line->amount + 0,
2873
                $replacement_amount, 'The right LOST amount is generated' );
2874
            is( $lost_fee_line->amountoutstanding + 0,
2875
                $replacement_amount,
2876
                'The right LOST amountoutstanding is generated' );
2877
            is( $lost_fee_line->status, undef, 'The LOST status was not set' );
2878
2879
            # Return the lost item
2880
            my ( undef, $message ) =
2881
              AddReturn( $item->barcode, $branchcode_refund, undef, $five_days_ago );
2882
2883
            $overdue_fee->discard_changes;
2884
            is( $overdue_fee->amount + 0,
2885
                10, 'The OVERDUE amount is left intact' );
2886
            is( $overdue_fee->amountoutstanding + 0,
2887
                10,
2888
                'The OVERDUE amountoutstanding is left intact' );
2889
2890
            $lost_fee_line->discard_changes;
2891
            is( $lost_fee_line->amount + 0,
2892
                $replacement_amount, 'The LOST amount is left intact' );
2893
            is( $lost_fee_line->amountoutstanding + 0,
2894
                0,
2895
                'The LOST amountoutstanding is refunded' );
2896
            is( $lost_fee_line->status, 'FOUND', 'The LOST status was set to FOUND' );
2897
        };
2898
2899
        subtest 'lostreturn | restore' => sub {
2900
            plan tests => 13;
2901
2902
            t::lib::Mocks::mock_userenv({ patron => $manager, branchcode => $branchcode_restore });
2903
2904
            my $item = $builder->build_sample_item(
2905
                {
2906
                    replacementprice => $replacement_amount
2907
                }
2908
            );
2909
2910
            # Issue the item
2911
            my $issue = C4::Circulation::AddIssue( $patron->unblessed, $item->barcode , $ten_days_ago);
2912
2913
            # Fake fines cronjob on this checkout
2914
            my ($fine) =
2915
              CalcFine( $item, $patron->categorycode, $library->{branchcode},
2916
                $ten_days_ago, $now );
2917
            UpdateFine(
2918
                {
2919
                    issue_id       => $issue->issue_id,
2920
                    itemnumber     => $item->itemnumber,
2921
                    borrowernumber => $patron->borrowernumber,
2922
                    amount         => $fine,
2923
                    due            => output_pref($ten_days_ago)
2924
                }
2925
            );
2926
            my $overdue_fees = Koha::Account::Lines->search(
2927
                {
2928
                    borrowernumber  => $patron->id,
2929
                    itemnumber      => $item->itemnumber,
2930
                    debit_type_code => 'OVERDUE'
2931
                }
2932
            );
2933
            is( $overdue_fees->count, 1, 'Overdue item fee produced' );
2934
            my $overdue_fee = $overdue_fees->next;
2935
            is( $overdue_fee->amount + 0,
2936
                10, 'The right OVERDUE amount is generated' );
2937
            is( $overdue_fee->amountoutstanding + 0,
2938
                10,
2939
                'The right OVERDUE amountoutstanding is generated' );
2940
2941
            # Simulate item marked as lost
2942
            $item->itemlost(3)->store;
2943
            C4::Circulation::LostItem( $item->itemnumber, 1 );
2944
2945
            my $lost_fee_lines = Koha::Account::Lines->search(
2946
                {
2947
                    borrowernumber  => $patron->id,
2948
                    itemnumber      => $item->itemnumber,
2949
                    debit_type_code => 'LOST'
2950
                }
2951
            );
2952
            is( $lost_fee_lines->count, 1, 'Lost item fee produced' );
2953
            my $lost_fee_line = $lost_fee_lines->next;
2954
            is( $lost_fee_line->amount + 0,
2955
                $replacement_amount, 'The right LOST amount is generated' );
2956
            is( $lost_fee_line->amountoutstanding + 0,
2957
                $replacement_amount,
2958
                'The right LOST amountoutstanding is generated' );
2959
            is( $lost_fee_line->status, undef, 'The LOST status was not set' );
2960
2961
            # Simulate refunding overdue fees upon marking item as lost
2962
            my $overdue_forgive = $patron->account->add_credit(
2963
                {
2964
                    amount     => 10.00,
2965
                    user_id    => $manager->borrowernumber,
2966
                    library_id => $branchcode_restore,
2967
                    interface  => 'test',
2968
                    type       => 'FORGIVEN',
2969
                    item_id    => $item->itemnumber
2970
                }
2971
            );
2972
            $overdue_forgive->apply(
2973
                { debits => [$overdue_fee], offset_type => 'Forgiven' } );
2974
            $overdue_fee->discard_changes;
2975
            is($overdue_fee->amountoutstanding + 0, 0, 'Overdue fee forgiven');
2976
2977
            # Do nothing
2978
            my ( undef, $message ) =
2979
              AddReturn( $item->barcode, $branchcode_restore, undef, $five_days_ago );
2980
              
2981
            $overdue_fee->discard_changes;
2982
            is( $overdue_fee->amount + 0,
2983
                10, 'The OVERDUE amount is left intact' );
2984
            is( $overdue_fee->amountoutstanding + 0,
2985
                10,
2986
                'The OVERDUE amountoutstanding is restored' );
2987
2988
            $lost_fee_line->discard_changes;
2989
            is( $lost_fee_line->amount + 0,
2990
                $replacement_amount, 'The LOST amount is left intact' );
2991
            is( $lost_fee_line->amountoutstanding + 0,
2992
                0,
2993
                'The LOST amountoutstanding is refunded' );
2994
            is( $lost_fee_line->status, 'FOUND', 'The LOST status was set to FOUND' );
2995
        };
2996
2997
        subtest 'lostreturn | charge' => sub {
2998
            plan tests => 16;
2999
3000
            t::lib::Mocks::mock_userenv({ patron => $manager, branchcode => $branchcode_charge });
3001
3002
            my $item = $builder->build_sample_item(
3003
                {
3004
                    replacementprice => $replacement_amount
3005
                }
3006
            );
3007
3008
            # Issue the item
3009
            my $issue = C4::Circulation::AddIssue( $patron->unblessed, $item->barcode, $ten_days_ago );
3010
3011
            # Fake fines cronjob on this checkout
3012
            my ($fine) =
3013
              CalcFine( $item, $patron->categorycode, $library->{branchcode},
3014
                $ten_days_ago, $now );
3015
            UpdateFine(
3016
                {
3017
                    issue_id       => $issue->issue_id,
3018
                    itemnumber     => $item->itemnumber,
3019
                    borrowernumber => $patron->borrowernumber,
3020
                    amount         => $fine,
3021
                    due            => output_pref($ten_days_ago)
3022
                }
3023
            );
3024
            my $overdue_fees = Koha::Account::Lines->search(
3025
                {
3026
                    borrowernumber  => $patron->id,
3027
                    itemnumber      => $item->itemnumber,
3028
                    debit_type_code => 'OVERDUE'
3029
                }
3030
            );
3031
            is( $overdue_fees->count, 1, 'Overdue item fee produced' );
3032
            my $overdue_fee = $overdue_fees->next;
3033
            is( $overdue_fee->amount + 0,
3034
                10, 'The right OVERDUE amount is generated' );
3035
            is( $overdue_fee->amountoutstanding + 0,
3036
                10,
3037
                'The right OVERDUE amountoutstanding is generated' );
3038
3039
            # Simulate item marked as lost
3040
            $item->itemlost(3)->store;
3041
            C4::Circulation::LostItem( $item->itemnumber, 1 );
3042
3043
            my $lost_fee_lines = Koha::Account::Lines->search(
3044
                {
3045
                    borrowernumber  => $patron->id,
3046
                    itemnumber      => $item->itemnumber,
3047
                    debit_type_code => 'LOST'
3048
                }
3049
            );
3050
            is( $lost_fee_lines->count, 1, 'Lost item fee produced' );
3051
            my $lost_fee_line = $lost_fee_lines->next;
3052
            is( $lost_fee_line->amount + 0,
3053
                $replacement_amount, 'The right LOST amount is generated' );
3054
            is( $lost_fee_line->amountoutstanding + 0,
3055
                $replacement_amount,
3056
                'The right LOST amountoutstanding is generated' );
3057
            is( $lost_fee_line->status, undef, 'The LOST status was not set' );
3058
3059
            # Simulate refunding overdue fees upon marking item as lost
3060
            my $overdue_forgive = $patron->account->add_credit(
3061
                {
3062
                    amount     => 10.00,
3063
                    user_id    => $manager->borrowernumber,
3064
                    library_id => $branchcode_charge,
3065
                    interface  => 'test',
3066
                    type       => 'FORGIVEN',
3067
                    item_id    => $item->itemnumber
3068
                }
3069
            );
3070
            $overdue_forgive->apply(
3071
                { debits => [$overdue_fee], offset_type => 'Forgiven' } );
3072
            $overdue_fee->discard_changes;
3073
            is($overdue_fee->amountoutstanding + 0, 0, 'Overdue fee forgiven');
3074
3075
            # Do nothing
3076
            my ( undef, $message ) =
3077
              AddReturn( $item->barcode, $branchcode_charge, undef, $five_days_ago );
3078
3079
            $lost_fee_line->discard_changes;
3080
            is( $lost_fee_line->amount + 0,
3081
                $replacement_amount, 'The LOST amount is left intact' );
3082
            is( $lost_fee_line->amountoutstanding + 0,
3083
                0,
3084
                'The LOST amountoutstanding is refunded' );
3085
            is( $lost_fee_line->status, 'FOUND', 'The LOST status was set to FOUND' );
3086
3087
            $overdue_fees = Koha::Account::Lines->search(
3088
                {
3089
                    borrowernumber  => $patron->id,
3090
                    itemnumber      => $item->itemnumber,
3091
                    debit_type_code => 'OVERDUE'
3092
                },
3093
                {
3094
                    order_by => { '-asc' => 'accountlines_id'}
3095
                }
3096
            );
3097
            is( $overdue_fees->count, 2, 'A second OVERDUE fee has been added' );
3098
            $overdue_fee = $overdue_fees->next;
3099
            is( $overdue_fee->amount + 0,
3100
                10, 'The original OVERDUE amount is left intact' );
3101
            is( $overdue_fee->amountoutstanding + 0,
3102
                0,
3103
                'The original OVERDUE amountoutstanding is left as forgiven' );
3104
            $overdue_fee = $overdue_fees->next;
3105
            is( $overdue_fee->amount + 0,
3106
                5, 'The new OVERDUE amount is correct for the backdated return' );
3107
            is( $overdue_fee->amountoutstanding + 0,
3108
                5,
3109
                'The new OVERDUE amountoutstanding is correct for the backdated return' );
3110
        };
3111
    };
2661
};
3112
};
2662
3113
2663
subtest '_FixOverduesOnReturn' => sub {
3114
subtest '_FixOverduesOnReturn' => sub {
2664
- 

Return to bug 23091