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

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

Return to bug 23091