test: scheduled package change on suspended package, #38564
[freeside.git] / FS / t / suite / 04-pkg_change_status.t
1 #!/usr/bin/perl
2
3 =head2 DESCRIPTION
4
5 Tests the effect of a scheduled change on the status of an active or
6 suspended package. Ref RT#38564.
7
8 Correct: A scheduled package change should result in a package with the same
9 status as before.
10
11 =cut
12
13 use strict;
14 use Test::More tests => 20;
15 use FS::Test;
16 use Date::Parse 'str2time';
17 use Test::MockTime qw(set_fixed_time);
18 use FS::cust_main;
19 use FS::cust_pkg;
20 my $FS = FS::Test->new;
21
22 # Create two package defs with the suspend_bill flag, and one with
23 # the unused_credit_change flag.
24 my $part_pkg = $FS->qsearchs('part_pkg', { pkgpart => 2 });
25 my $error;
26 my @part_pkgs;
27 foreach my $i (0, 1) {
28   $part_pkgs[$i] = $part_pkg->clone;
29   $part_pkgs[$i]->insert(options => { $part_pkg->options,
30                                       'suspend_bill' => 1,
31                                       'unused_credit_change' => $i } );
32   BAIL_OUT("can't configure package: $error") if $error;
33 }
34
35 # For customer #3, order four packages. 0-1 will be suspended, 2-3 will not.
36 # 1 and 3 will use $part_pkgs[1], the one with unused_credit_change.
37
38 my $cust = $FS->qsearchs('cust_main', { custnum => 3 });
39 my @pkgs;
40 foreach my $i (0..3) {
41   $pkgs[$i] = FS::cust_pkg->new({ pkgpart => $part_pkgs[$i % 2]->pkgpart });
42   $error = $cust->order_pkg({ cust_pkg => $pkgs[$i] });
43   BAIL_OUT("can't order package: $error") if $error;
44 }
45
46 # On Mar 25, bill the customer.
47
48 set_fixed_time(str2time('2016-03-25'));
49 $error = $cust->bill_and_collect;
50 ok( $error eq '', 'initially bill customer' );
51 # update our @pkgs to match
52 @pkgs = map { $_->replace_old } @pkgs;
53
54 # On Mar 26, suspend packages 0-1.
55
56 set_fixed_time(str2time('2016-03-25'));
57 my $reason_type = $FS->qsearchs('reason_type', { type => 'Suspend Reason' });
58 foreach my $i (0,1) {
59   $error = $pkgs[$i]->suspend(reason => {
60     typenum => $reason_type->typenum,
61     reason  => 'Test suspension + future package change',
62   });
63   ok( $error eq '', "suspended package $i" ) or diag($error);
64   $pkgs[$i] = $pkgs[$i]->replace_old;
65 }
66
67 # For each of these packages, clone the package def, then schedule a future
68 # change (on Mar 26) to that package.
69 my $change_date = str2time('2016-03-26');
70 my @new_pkgs;
71 foreach my $i (0..3) {
72   my $pkg = $pkgs[$i];
73   my $new_part_pkg = $pkg->part_pkg->clone;
74   $error = $new_part_pkg->insert( options => { $pkg->part_pkg->options } );
75   ok( $error eq '', 'created new package def' ) or diag($error);
76   $error = $pkg->change_later(
77     pkgpart     => $new_part_pkg->pkgpart,
78     start_date  => $change_date,
79   );
80   ok( $error eq '', 'scheduled package change' ) or diag($error);
81   $new_pkgs[$i] = $FS->qsearchs('cust_pkg', {
82       pkgnum    => $pkg->change_to_pkgnum
83   });
84   ok( $new_pkgs[$i], 'future package was created' );
85 }
86
87 # Then bill the customer on that date.
88 set_fixed_time($change_date);
89 $error = $cust->bill_and_collect;
90 ok( $error eq '', 'billed customer on change date' ) or diag($error);
91
92 foreach my $i (0,1) {
93   $new_pkgs[$i] = $new_pkgs[$i]->replace_old;
94   ok( $new_pkgs[$i]->status eq 'suspended', "new package $i is suspended" )
95     or diag($new_pkgs[$i]->status);
96 }
97 foreach my $i (2,3) {
98   $new_pkgs[$i] = $new_pkgs[$i]->replace_old;
99   ok( $new_pkgs[$i]->status eq 'active', "new package $i is active" )
100     or diag($new_pkgs[$i]->status);
101 }
102
103 1;