be more selective when unapplying payments for a line item credit, #42729
[freeside.git] / FS / t / suite / 09-sales_tax_credit_change.t
1 #!/usr/bin/perl
2
3 =head2 DESCRIPTION
4
5 Tests crediting a package for unused time when it has sales tax. See
6 RT#42729.
7
8 The package will be billed for $30.00 with 10% tax, then credited for 1/3
9 of the billing period.
10
11 Correct: The credit amount will be $11.00.
12
13 =cut
14
15 use strict;
16 use Test::More tests => 3;
17 use FS::Test;
18 use Date::Parse 'str2time';
19 use Date::Format 'time2str';
20 use Test::MockTime qw(set_fixed_time);
21 use FS::cust_main;
22 use FS::cust_pkg;
23 use FS::part_pkg;
24 use FS::Conf;
25 my $FS= FS::Test->new;
26
27 # Create a package def
28 my $error;
29 my $part_pkg = FS::part_pkg->new({
30   pkg     => 'Tax credit test',
31   plan    => 'flat',
32   freq    => '1',
33   agentnum => 1,
34 });
35 my %options = (
36   'setup_fee' => 0,
37   'recur_fee' => 30.00,
38   'recur_temporality' => 'upcoming',
39   'unused_credit_cancel' => '1',
40 );
41 $error = $part_pkg->insert(options => \%options);
42 BAIL_OUT("can't create package def: $error") if $error;
43
44 # Create the customer and order a package
45 my $cust = $FS->new_customer('Credit unused with taxes');
46 $cust->bill_location->state('AK');
47 $error = $cust->insert;
48 BAIL_OUT("can't create test customer: $error") if $error;
49
50 my $pkg = FS::cust_pkg->new({ pkgpart => $part_pkg->pkgpart });
51 $error = $cust->order_pkg({ cust_pkg => $pkg });
52 BAIL_OUT("can't create test charges: $error") if $error;
53
54 # Create tax def
55 my $cust_main_county = FS::cust_main_county->new({
56   'country'       => 'US',
57   'state'         => 'AK',
58   'exempt_amount' => 0.00,
59   'taxname'       => 'Test tax',
60   'tax'           => '10',
61 });
62 $error = $cust_main_county->insert;
63 BAIL_OUT("can't create tax definitions: $error") if $error;
64
65 # Bill the customer on Apr 1
66 # (April because it's 30 days, and also doesn't have DST)
67 set_fixed_time(str2time('2016-04-01 00:00'));
68 my @return;
69 $error = $cust->bill( return_bill => \@return );
70 BAIL_OUT("can't bill charges: $error") if $error;
71 my $cust_bill = $return[0] or BAIL_OUT("no invoice generated");
72
73 # Check amount
74 my ($tax_item) = grep { $_->itemdesc eq $cust_main_county->taxname }
75                 $cust_bill->cust_bill_pkg;
76 ok ( $tax_item && $tax_item->setup == 3.00, "Tax charged = 3.00" );
77
78 # sync
79 $pkg = $pkg->replace_old;
80
81 # Pay the bill in two parts
82 set_fixed_time(str2time('2016-04-02 00:00'));
83 foreach my $paid (10.00, 23.00) {
84   my $cust_pay = FS::cust_pay->new({
85     custnum => $cust->custnum,
86     invnum  => $cust_bill->invnum,
87     _date   => time,
88     paid    => $paid,
89     payby   => 'CASH',
90   });
91   $error = $cust_pay->insert;
92   BAIL_OUT("can't record payment: $error") if $error;
93 }
94 # Now cancel with 1/3 of the period left
95 set_fixed_time(str2time('2016-04-21 00:00'));
96 $error = $pkg->cancel();
97 BAIL_OUT("can't cancel package: $error") if $error;
98
99 # and find the credit
100 my ($credit) = $cust->cust_credit
101   or BAIL_OUT("no credit was created");
102 ok ( $credit->amount == 11.00, "Credited 1/3 of package charge with tax" )
103   or diag("is ". $credit->amount );
104
105 # the invoice should also be fully paid after that
106 ok ( $cust_bill->owed == 0, "Invoice balance is zero" )
107   or diag("is ". $cust_bill->owed);
108