X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fpart_pkg%2Fprorate_Mixin.pm;h=1bd4feb44c141e675c7d44aad3c40c53ed5a1a42;hb=6f30bad25fdfe6d85094f3f6caac9a3ab84b4a86;hp=9c0c2669b284ba684b59e31e72e004ca3720766d;hpb=aaf8baf3662e16e9414de236a39f8801a8c41b01;p=freeside.git diff --git a/FS/FS/part_pkg/prorate_Mixin.pm b/FS/FS/part_pkg/prorate_Mixin.pm index 9c0c2669b..1bd4feb44 100644 --- a/FS/FS/part_pkg/prorate_Mixin.pm +++ b/FS/FS/part_pkg/prorate_Mixin.pm @@ -1,10 +1,9 @@ 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, ); @@ -33,11 +32,11 @@ sub calc_recur { =item calc_prorate CUST_PKG Takes all the arguments of calc_recur, followed by a day of the month -to prorate to. Calculates a prorated charge from the $sdate to that day, -and sets the $sdate and $param->{months} accordingly. +to prorate to (which must be <= 28). Calculates a prorated charge from +the $sdate to that day, and sets the $sdate and $param->{months} accordingly. +base_recur() will be called to determine the base price per billing cycle. Options: -- recur_fee: The charge to use for a complete billing period. - add_full_period: Bill for the time up to the prorate day plus one full billing period after that. - prorate_round_day: Round the current time to the nearest full day, @@ -49,17 +48,34 @@ sub calc_prorate { my $self = shift; my ($cust_pkg, $sdate, $details, $param, $cutoff_day) = @_; - my $charge = $self->option('recur_fee',1) || 0; + my $charge = $self->base_recur($cust_pkg, $sdate) || 0; if($cutoff_day) { # only works for freq >= 1 month; probably can't be fixed my $mnow = $$sdate; 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 date. $mnow = timelocal(0,0,0,$mday,$mon,$year); } my $mend; my $mstart; + # if cutoff day > 28, force it to the 1st of next month + if ( $cutoff_day > 28 ) { + $cutoff_day = 1; + # and if we are currently after the 28th, roll the current day + # forward to that day + if ( $mday > 28 ) { + $mday = 1; + #set $mnow = $mend so the amount billed will be zero + $mnow = timelocal(0,0,0,1,$mon == 11 ? 0 : $mon + 1,$year+($mon==11)); + } + } if ( $mday >= $cutoff_day ) { $mend = timelocal(0,0,0,$cutoff_day,$mon == 11 ? 0 : $mon + 1,$year+($mon==11)); @@ -70,7 +86,7 @@ sub calc_prorate { $mend = timelocal(0,0,0,$cutoff_day,$mon,$year); $mstart = - timelocal(0,0,0,$cutoff_day,$mon == 0 ? 11 : $mon - 1,$year-($mon==11)); + timelocal(0,0,0,$cutoff_day,$mon == 0 ? 11 : $mon - 1,$year-($mon==0)); } # next bill date will be figured as $$sdate + one period @@ -79,8 +95,8 @@ sub calc_prorate { my $permonth = $charge / $self->freq; my $months = ( ( $self->freq - 1 ) + ($mend-$mnow) / ($mend-$mstart) ); - if ( $self->option('add_full_period',1) ) { - # charge a full period in addition to the partial month + # add a full period if currently billing for a partial period + if ( $self->option('add_full_period',1) and $months < $self->freq ) { $months += $self->freq; $$sdate = $self->add_freq($mstart); }