1 package FS::part_pkg::prorate_Mixin;
4 use vars qw(@ISA %info);
5 use Time::Local qw(timelocal);
7 @ISA = qw(FS::part_pkg);
8 %info = ( 'disabled' => 1 );
12 FS::part_pkg::prorate_Mixin - Mixin class for part_pkg:: classes that
13 need to prorate partial months
17 package FS::part_pkg::...;
18 use base qw( FS::part_pkg::prorate_Mixin );
22 if( conditions that trigger prorate ) {
23 # sets $$sdate and $param->{'months'}, returns the prorated charge
24 $charges = $self->calc_prorate($cust_pkg, $sdate, $param, $cutoff_day);
33 Takes all the arguments of calc_recur, and calculates a prorated charge
36 - If 'sync_bill_date' is set: Charge for a number of days to synchronize
37 this package to the customer's next bill date. If this is their only
38 package (or they're already synchronized), that will take them through
40 - If 'cutoff_day' is set: Prorate this package so that its next bill date
41 falls on that day of the month.
47 my ($cust_pkg, $sdate, $details, $param) = @_;
49 my $charge = $self->option('recur_fee') || 0;
51 if( $self->option('sync_bill_date',1) ) {
52 my $next_bill = $cust_pkg->cust_main->next_bill_date;
53 if( defined($next_bill) and $next_bill != $$sdate ) {
54 $cutoff_day = (localtime($next_bill))[3];
57 # don't prorate, assume a full month
58 $param->{'months'} = $self->freq;
61 else { # no sync, use cutoff_day or day 1
62 $cutoff_day = $self->option('cutoff_day') || 1;
66 # only works for freq >= 1 month; probably can't be fixed
68 my ($sec, $min, $hour, $mday, $mon, $year) = (localtime($mnow))[0..5];
69 if ( $self->option('prorate_round_day',1) ) {
70 $mday++ if $hour >= 12;
71 $mnow = timelocal(0,0,0,$mday,$mon,$year);
75 if ( $mday >= $cutoff_day ) {
77 timelocal(0,0,0,$cutoff_day,$mon == 11 ? 0 : $mon + 1,$year+($mon==11));
79 timelocal(0,0,0,$cutoff_day,$mon,$year);
83 timelocal(0,0,0,$cutoff_day,$mon,$year);
85 timelocal(0,0,0,$cutoff_day,$mon == 0 ? 11 : $mon - 1,$year-($mon==11));
88 # next bill date will be figured as $$sdate + one period
91 my $permonth = $self->option('recur_fee', 1) / $self->freq;
92 my $months = ( ( $self->freq - 1 ) + ($mend-$mnow) / ($mend-$mstart) );
94 if ( $self->option('add_full_period',1) ) {
95 # charge a full period in addition to the partial month
96 $months += $self->freq;
97 $$sdate = $self->add_freq($mstart);
100 $param->{'months'} = $months;
101 $charge = sprintf('%.2f', $permonth * $months);
103 my $discount = $self->calc_discount(@_);
104 return ($charge - $discount);