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

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

Return to bug 23091