1 package FS::part_pkg::flat_introrate;
2 use base qw( FS::part_pkg::flat );
9 # mostly false laziness with FS::part_pkg::global_Mixin::validate_moneyn,
10 # except for blank string handling...
12 my ($option, $valref) = @_;
13 if ( $$valref eq '' ) {
15 } elsif ( $$valref =~ /^\s*(\d*)(\.\d{1})\s*$/ ) {
16 #handle one decimal place without barfing out
17 $$valref = ( ($1||''). ($2.'0') ) || 0;
18 } elsif ( $$valref =~ /^\s*(\d*)(\.\d{2})?\s*$/ ) {
19 $$valref = ( ($1||''). ($2||'') ) || 0;
21 return "Illegal (money) $option: ". $$valref;
27 my ($option, $valref) = @_;
28 $$valref = 0 unless $$valref;
29 return "Invalid $option"
30 unless ($$valref) = ($$valref =~ /^\s*(\d+)\s*$/);
35 'name' => 'Introductory price for X months, then flat rate,'.
36 'relative to setup date (anniversary billing)',
37 'shortname' => 'Anniversary, with intro price',
38 'inherit_fields' => [ 'flat', 'usage_Mixin', 'global_Mixin' ],
40 'intro_fee' => { 'name' => 'Introductory recurring fee for this package',
42 'validate' => \&validate_money,
45 { 'name' => 'Duration of the introductory period, in number of months',
47 'validate' => \&validate_number,
50 { 'name' => 'Show the introductory rate on the invoice as if it\'s a discount',
54 'fieldorder' => [ qw(intro_duration intro_fee show_as_discount) ],
59 my($self, $cust_pkg) = @_;
60 my ($duration) = ($self->option('intro_duration') =~ /^\s*(\d+)\s*$/);
61 unless (length($duration)) {
62 my $log = FS::Log->new('FS::part_pkg');
63 $log->warning("Invalid intro_duration '".$self->option('intro_duration')."' on pkgpart ".$self->pkgpart
64 .", defaulting to 0, check package definition");
68 # no setup or start_date means "start billing the package ASAP", so assume
69 # it would start billing right now.
70 my $start = $cust_pkg->setup || $cust_pkg->start_date || time;
72 $self->add_freq($start, $duration);
76 my($self, $cust_pkg, $time ) = @_;
79 if (!$time) { # the "$sdate" from _make_lines
80 my $log = FS::Log->new('FS::part_pkg');
81 $log->warning("flat_introrate base_recur requires date!");
87 if ($now < $self->intro_end($cust_pkg)) {
88 return $self->option('intro_fee');
90 return $self->option('recur_fee');
96 my ($self, $cust_pkg) = @_;
97 return unless $self->option('show_as_discount',1);
98 my $intro_end = $self->intro_end($cust_pkg);
99 my $amount = sprintf('%.2f',
100 $self->option('intro_fee') - $self->option('recur_fee')
102 return unless $amount < 0;
103 # otherwise it's an "introductory surcharge"? not the intended use of
106 { '_is_discount' => 1,
107 'description' => $cust_pkg->mt('Introductory discount until') . ' ' .
108 $cust_pkg->time2str_local('short', $intro_end),
110 'recur_amount' => $amount,
111 'ext_description' => [],
112 'pkgpart' => $self->pkgpart,