[freeside-commits] freeside/FS/FS/part_pkg flat.pm, 1.44, 1.45 prorate.pm, 1.19, 1.20 prorate_Mixin.pm, NONE, 1.1 recur_Common.pm, 1.3, 1.4

Mark Wells mark at wavetail.420.am
Thu Aug 19 12:11:35 PDT 2010


Update of /home/cvs/cvsroot/freeside/FS/FS/part_pkg
In directory wavetail.420.am:/tmp/cvs-serv1123/FS/FS/part_pkg

Modified Files:
	flat.pm prorate.pm recur_Common.pm 
Added Files:
	prorate_Mixin.pm 
Log Message:
part_pkg prorate mixin and sync_bill_date option, RT#9554

--- NEW FILE: prorate_Mixin.pm ---
package FS::part_pkg::prorate_Mixin;

use strict;
use vars qw(@ISA %info);
use Time::Local qw(timelocal);

@ISA = qw(FS::part_pkg);
%info = ( 'disabled' => 1 );

=head1 NAME

FS::part_pkg::prorate_Mixin - Mixin class for part_pkg:: classes that 
need to prorate partial months

=head1 SYNOPSIS

package FS::part_pkg::...;
use base qw( FS::part_pkg::prorate_Mixin );

sub calc_recur {
  ...
  if( conditions that trigger prorate ) {
    # sets $$sdate and $param->{'months'}, returns the prorated charge
    $charges = $self->calc_prorate($cust_pkg, $sdate, $param, $cutoff_day);
  } 
  ...
}

=head METHODS

=item calc_prorate

Takes all the arguments of calc_recur, and calculates a prorated charge 
in one of two ways:

- If 'sync_bill_date' is set: Charge for a number of days to synchronize 
  this package to the customer's next bill date.  If this is their only 
  package (or they're already synchronized), that will take them through 
  one billing cycle.
- If 'cutoff_day' is set: Prorate this package so that its next bill date 
  falls on that day of the month.

=cut

sub calc_prorate {
  my $self  = shift;
  my ($cust_pkg, $sdate, $details, $param) = @_;
 
  my $charge = $self->option('recur_fee') || 0;
  my $cutoff_day;
  if( $self->option('sync_bill_date') ) {
    my $next_bill = $cust_pkg->cust_main->next_bill_date;
    if( defined($next_bill) and $next_bill != $$sdate ) {
      $cutoff_day = (localtime($next_bill))[3];
    }
    else {
      # don't prorate, assume a full month
      $param->{'months'} = $self->freq;
    }
  }
  else { # no sync, use cutoff_day or day 1
    $cutoff_day = $self->option('cutoff_day') || 1;
  }

  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];
    my $mend;
    my $mstart;
    if ( $mday >= $cutoff_day ) {
      $mend = 
        timelocal(0,0,0,$cutoff_day,$mon == 11 ? 0 : $mon + 1,$year+($mon==11));
      $mstart =
        timelocal(0,0,0,$cutoff_day,$mon,$year);
    }
    else {
      $mend = 
        timelocal(0,0,0,$cutoff_day,$mon,$year);
      $mstart = 
        timelocal(0,0,0,$cutoff_day,$mon == 0 ? 11 : $mon - 1,$year-($mon==11));
    }
    
    $$sdate = $mstart;

    my $permonth = $self->option('recur_fee', 1) / $self->freq;
    my $months = ( ( $self->freq - 1 ) + ($mend-$mnow) / ($mend-$mstart) );
    
    $param->{'months'} = $months;
    $charge = sprintf('%.2f', $permonth * $months);
  }
  my $discount =  $self->calc_discount(@_);
  return ($charge - $discount);
}

1;

Index: prorate.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/part_pkg/prorate.pm,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -w -d -r1.19 -r1.20
--- prorate.pm	21 May 2010 03:42:34 -0000	1.19
+++ prorate.pm	19 Aug 2010 19:11:32 -0000	1.20
@@ -95,34 +95,8 @@
 );
 
 sub calc_recur {
-  my($self, $cust_pkg, $sdate, $details, $param ) = @_;
-  my $cutoff_day = $self->option('cutoff_day', 1) || 1;
-  my $mnow = $$sdate;
-  my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($mnow) )[0,1,2,3,4,5];
-  my $mend;
-  my $mstart;
-  
-  if ( $mday >= $cutoff_day ) {
-    $mend =
-      timelocal(0,0,0,$cutoff_day, $mon == 11 ? 0 : $mon+1, $year+($mon==11));
-    $mstart =
-      timelocal(0,0,0,$cutoff_day,$mon,$year);  
-
-  } else {
-    $mend = timelocal(0,0,0,$cutoff_day, $mon, $year);
-    if ($mon==0) {$mon=11;$year--;} else {$mon--;}
-    $mstart=  timelocal(0,0,0,$cutoff_day,$mon,$year);  
-  }
-
-  $$sdate = $mstart;
-  my $permonth = $self->option('recur_fee') / $self->freq;
-
-  my $months = ( ( $self->freq - 1 ) + ($mend-$mnow) / ($mend-$mstart) );
-
-  $param->{'months'} = $months;
-  my $discount = $self->calc_discount( $cust_pkg, $sdate, $details, $param);
-
-  sprintf('%.2f', $permonth * $months - $discount);
+  my $self = shift;
+  $self->calc_prorate(@_);
 }
 
 1;

Index: flat.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/part_pkg/flat.pm,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -w -d -r1.44 -r1.45
--- flat.pm	19 Aug 2010 10:15:21 -0000	1.44
+++ flat.pm	19 Aug 2010 19:11:32 -0000	1.45
@@ -13,7 +13,7 @@
 use FS::part_pkg;
 use FS::cust_bill_pkg_discount;
 
- at ISA = qw(FS::part_pkg);
+ at ISA = qw(FS::part_pkg FS::part_pkg::prorate_Mixin);
 
 tie my %temporalities, 'Tie::IxHash',
   'upcoming'  => "Upcoming (future)",
@@ -119,6 +119,10 @@
     'start_1st'     => { 'name' => 'Auto-add a start date to the 1st, ignoring the current month.',
                          'type' => 'checkbox',
                        },
+    'sync_bill_date' => { 'name' => 'Prorate first month to synchronize '.
+                                    'with the customer\'s other packages',
+                          'type' => 'checkbox',
+                        },
 
     %usage_fields,
     %usage_recharge_fields,
@@ -129,7 +133,7 @@
   },
   'fieldorder' => [ qw( setup_fee recur_fee
                         recur_temporality unused_credit
-                        expire_months start_1st
+                        expire_months start_1st sync_bill_date
                       ),
                     @usage_fieldorder, @usage_recharge_fieldorder,
                     qw( externalid ),
@@ -158,7 +162,8 @@
 }
 
 sub calc_recur {
-  my($self, $cust_pkg, $sdate, $details, $param ) = @_;
+  my $self = shift;
+  my($cust_pkg, $sdate, $details, $param ) = @_;
 
   #my $last_bill = $cust_pkg->last_bill;
   my $last_bill = $cust_pkg->get('last_bill'); #->last_bill falls back to setup
@@ -166,11 +171,15 @@
   return 0
     if $self->option('recur_temporality', 1) eq 'preceding' && $last_bill == 0;
 
-  my $br = $self->base_recur($cust_pkg);
-
+  if( $self->option('sync_bill_date') ) {
+    return $self->calc_prorate(@_);
+  }
+  else {
+    my $charge = $self->base_recur($cust_pkg);
   my $discount = $self->calc_discount($cust_pkg, $sdate, $details, $param);
 
-  sprintf('%.2f', $br - $discount);
+    return sprintf('%.2f', $charge - $discount);
+  }
 }
 
 sub calc_discount {

Index: recur_Common.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/part_pkg/recur_Common.pm,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -w -d -r1.3 -r1.4
--- recur_Common.pm	31 Jan 2010 02:57:14 -0000	1.3
+++ recur_Common.pm	19 Aug 2010 19:11:32 -0000	1.4
@@ -4,9 +4,9 @@
 use vars qw( @ISA %info %recur_method );
 use Tie::IxHash;
 use Time::Local;
-use FS::part_pkg::prorate;
+use FS::part_pkg::prorate_Mixin;
 
- at ISA = qw(FS::part_pkg::prorate);
+ at ISA = qw(FS::part_pkg::prorate_Mixin);
 
 %info = ( 'disabled' => 1 ); #recur_Common not a usable price plan directly
 
@@ -26,11 +26,12 @@
 
     my $recur_method = $self->option('recur_method', 1) || 'anniversary';
                   
-    if ( $recur_method eq 'prorate' ) {
-
-      $charges = $self->SUPER::calc_recur(@_);
-
-    } else {
+    if ( $recur_method eq 'prorate' 
+        or ($recur_method eq 'anniversary' and $self->option('sync_bill_date'))
+      ) {
+      $charges = $self->calc_prorate(@_);
+    } 
+    else {
 
       $charges = $self->option('recur_fee');
 
@@ -47,14 +48,12 @@
         $$sdate = timelocal(0, 0, 0, $cutoff_day, $mon, $year);
 
       }#$recur_method eq 'subscription'
-
       $charges -= $self->calc_discount( $cust_pkg, $sdate, $details, $param );
 
-    }#$recur_method eq 'prorate'
-
+    }#$recur_method eq 'prorate' or ...
   }#increment_next_bill
 
-  $charges;
+  return $charges;
 
 }
 



More information about the freeside-commits mailing list