5 Tests the effect of ordering and activating two sync_bill_date packages on
6 the same day. Ref RT#42108.
8 Correct: If the packages have prorate_round_day = 1 (round nearest), or 3
9 (round down) then the second package should be prorated one day short. If
10 they have prorate_round_day = 2 (round up), they should be billed
11 for the same amount. In both cases they should have the same next bill date.
16 use Test::More tests => 9;
18 use Date::Parse 'str2time';
19 use Date::Format 'time2str';
20 use Test::MockTime qw(set_fixed_time);
24 my $FS= FS::Test->new;
26 foreach my $prorate_mode (1, 2, 3) {
27 diag("prorate_round_day = $prorate_mode");
28 # Create a package def with the sync_bill_date option.
30 my $old_part_pkg = $FS->qsearchs('part_pkg', { pkgpart => 5 });
31 my $part_pkg = $old_part_pkg->clone;
32 BAIL_OUT("existing pkgpart 5 is not a flat monthly package")
33 unless $part_pkg->freq eq '1' and $part_pkg->plan eq 'flat';
34 $error = $part_pkg->insert(
35 options => { $old_part_pkg->options,
36 'sync_bill_date' => 1,
37 'prorate_round_day' => $prorate_mode, }
40 BAIL_OUT("can't configure package: $error") if $error;
42 my $pkgpart = $part_pkg->pkgpart;
43 # Create a clean customer with no other packages.
44 my $location = FS::cust_location->new({
45 address1 => '123 Example Street',
51 my $cust = FS::cust_main->new({
55 first => 'Sync bill date',
56 invoice_email => 'newcustomer@fake.freeside.biz',
58 bill_location => $location,
59 ship_location => $location,
61 $error = $cust->insert;
62 BAIL_OUT("can't create test customer: $error") if $error;
65 # Create and bill the first package.
66 set_fixed_time(str2time('2016-03-10 08:00'));
67 $pkgs[0] = FS::cust_pkg->new({ pkgpart => $pkgpart });
68 $error = $cust->order_pkg({ 'cust_pkg' => $pkgs[0] });
69 BAIL_OUT("can't order package: $error") if $error;
70 $error = $cust->bill_and_collect;
71 # Check the amount billed.
72 my ($cust_bill_pkg) = $pkgs[0]->cust_bill_pkg;
73 my $recur = $part_pkg->base_recur;
74 ok( $cust_bill_pkg->recur == $recur, "first package recur is $recur" )
75 or diag("first package recur is ".$cust_bill_pkg->recur);
77 # Create and bill the second package.
78 set_fixed_time(str2time('2016-03-10 16:00'));
79 $pkgs[1] = FS::cust_pkg->new({ pkgpart => $pkgpart });
80 $error = $cust->order_pkg({ 'cust_pkg' => $pkgs[1] });
81 BAIL_OUT("can't order package: $error") if $error;
82 $error = $cust->bill_and_collect;
84 # Check the amount billed.
85 if ( $prorate_mode == 1 or $prorate_mode == 3 ) {
86 # it should be one day short, in March
87 $recur = sprintf('%.2f', $recur * 30/31);
89 ($cust_bill_pkg) = $pkgs[1]->cust_bill_pkg;
90 ok( $cust_bill_pkg->recur == $recur, "second package recur is $recur" )
91 or diag("second package recur is ".$cust_bill_pkg->recur);
93 my @next_bill = map { time2str('%Y-%m-%d', $_->replace_old->get('bill')) } @pkgs;
95 ok( $next_bill[0] eq $next_bill[1],
96 "both packages will bill again on $next_bill[0]" )
97 or diag("first package bill date is $next_bill[0], second package is $next_bill[1]");