X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fpart_pkg%2Fprorate_Mixin.pm;h=78a089313ecd574dbb68a972b4acc7c8aa60e4e9;hb=7f5e32275a5a2674fd1d220cd651b222b9831476;hp=3e4ec06e92f5a0525b41dba695ab5f4c7ff14b5c;hpb=707906baea6674cefaebe19db2ee9912054dbcde;p=freeside.git diff --git a/FS/FS/part_pkg/prorate_Mixin.pm b/FS/FS/part_pkg/prorate_Mixin.pm index 3e4ec06e9..78a089313 100644 --- a/FS/FS/part_pkg/prorate_Mixin.pm +++ b/FS/FS/part_pkg/prorate_Mixin.pm @@ -1,14 +1,35 @@ package FS::part_pkg::prorate_Mixin; use strict; -use vars qw(@ISA %info); -use Time::Local qw(timelocal); +use vars qw( %info ); +use Time::Local qw( timelocal ); -@ISA = qw(FS::part_pkg); %info = ( 'disabled' => 1, + # define all fields that are referenced in this code + 'fields' => { + 'add_full_period' => { + 'name' => 'When prorating first month, also bill for one full '. + 'period after that', + 'type' => 'checkbox', + }, + 'prorate_round_day' => { + 'name' => 'When prorating, round to the nearest full day', + 'type' => 'checkbox', + }, + 'prorate_defer_bill' => { + 'name' => 'When prorating, defer the first bill until the '. + 'billing day', + 'type' => 'checkbox', + }, + }, + 'fieldorder' => [ qw(prorate_defer_bill prorate_round_day add_full_period) ], ); +sub fieldorder { + @{ $info{'fieldorder'} } +} + =head1 NAME FS::part_pkg::prorate_Mixin - Mixin class for part_pkg:: classes that @@ -50,19 +71,19 @@ day arrives. sub calc_prorate { my ($self, $cust_pkg, $sdate, $details, $param, $cutoff_day) = @_; die "no cutoff_day" unless $cutoff_day; + die "can't prorate non-monthly package\n" if $self->freq =~ /\D/; my $charge = $self->base_recur($cust_pkg, $sdate) || 0; - #if ( $cutoff_day ) { my $mnow = $$sdate; # if this is the first bill but the bill date has been set # (by prorate_defer_bill), calculate from the setup date, # and append the setup fee to @$details. - if ( $self->option('prorate_defer_bill') + if ( $self->option('prorate_defer_bill',1) and ! $cust_pkg->getfield('last_bill') and $cust_pkg->setup ) { - warn "[calc_prorate] #".$cust_pkg->pkgnum.": running deferred setup\n"; + #warn "[calc_prorate] #".$cust_pkg->pkgnum.": running deferred setup\n"; $param->{'setup_fee'} = $self->calc_setup($cust_pkg, $$sdate, $details); $mnow = $cust_pkg->setup; } @@ -77,8 +98,12 @@ sub calc_prorate { my $months = ( ( $self->freq - 1 ) + ($mend-$mnow) / ($mend-$mstart) ); # add a full period if currently billing for a partial period - if ( ( $self->option('add_full_period',1) - or $self->option('prorate_defer_bill',1) ) # necessary + # or periods up to freq_override if billing for an override interval + if ( ($param->{'freq_override'} || 0) > 1 ) { + $months += $param->{'freq_override'} - 1; + } + elsif ( ( $self->option('add_full_period',1) + or $self->option('prorate_defer_bill',1) ) and $months < $self->freq ) { $months += $self->freq; $$sdate = $self->add_freq($mstart); @@ -86,7 +111,6 @@ sub calc_prorate { $param->{'months'} = $months; $charge = sprintf('%.2f', $permonth * $months); - #} return $charge; } @@ -107,10 +131,12 @@ sub prorate_setup { and $cutoff_day ) { my ($mnow, $mend, $mstart) = $self->_endpoints($sdate, $cutoff_day); - # if today is the cutoff day, set the next bill to right now instead - # of waiting a month. + # If today is the cutoff day, set the next bill and setup both to + # midnight today, so that the customer will be billed normally for a + # month starting today. if ( $mnow - $mstart < 86400 ) { - $cust_pkg->bill($mnow); + $cust_pkg->setup($mstart); + $cust_pkg->bill($mstart); } else { $cust_pkg->bill($mend); @@ -135,7 +161,13 @@ sub _endpoints { # only works for freq >= 1 month; probably can't be fixed my ($sec, $min, $hour, $mday, $mon, $year) = (localtime($mnow))[0..5]; if( $self->option('prorate_round_day',1) ) { - $mday++ if $hour >= 12; + # If the time is 12:00-23:59, move to the next day by adding 18 + # hours to $mnow. Because of DST this can end up from 05:00 to 18:59 + # but it's always within the next day. + $mnow += 64800 if $hour >= 12; + # Get the new day, month, and year. + ($mday,$mon,$year) = (localtime($mnow))[3..5]; + # Then set $mnow to midnight on that day. $mnow = timelocal(0,0,0,$mday,$mon,$year); } my $mend;