summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormark <mark>2010-08-19 19:11:45 +0000
committermark <mark>2010-08-19 19:11:45 +0000
commit4117c20f85ce085d7dd42b8970ce9c65b95d7e27 (patch)
tree8654b1cb481095ce4a1daf2d9c3ea1c9dceba7b7
parentbb617fa9977d6886ac930d7a97e9221b33899474 (diff)
part_pkg prorate mixin and sync_bill_date option, RT#9554
-rw-r--r--FS/FS/Conf.pm7
-rw-r--r--FS/FS/part_pkg/flat.pm23
-rw-r--r--FS/FS/part_pkg/prorate.pm30
-rw-r--r--FS/FS/part_pkg/prorate_Mixin.pm96
-rw-r--r--FS/FS/part_pkg/recur_Common.pm23
-rw-r--r--httemplate/misc/order_pkg.html8
6 files changed, 138 insertions, 49 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index fe010f77b..ce2c01d46 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -3294,6 +3294,13 @@ and customer address. Include units.',
},
{
+ 'key' => 'order_pkg-no_start_date',
+ 'section' => 'UI',
+ 'description' => 'Don\'t set a default start date for new packages.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'mcp_svcpart',
'section' => '',
'description' => 'Master Control Program svcpart. Leave this blank.',
diff --git a/FS/FS/part_pkg/flat.pm b/FS/FS/part_pkg/flat.pm
index 648a83ddc..a04f44ae4 100644
--- a/FS/FS/part_pkg/flat.pm
+++ b/FS/FS/part_pkg/flat.pm
@@ -13,7 +13,7 @@ use FS::Conf;
use FS::part_pkg;
use FS::cust_bill_pkg_discount;
-@ISA = qw(FS::part_pkg);
+@ISA = qw(FS::part_pkg FS::part_pkg::prorate_Mixin);
tie my %temporalities, 'Tie::IxHash',
'upcoming' => "Upcoming (future)",
@@ -119,6 +119,10 @@ tie my %temporalities, 'Tie::IxHash',
'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 @@ tie my %temporalities, 'Tie::IxHash',
},
'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 unit_setup {
}
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 @@ sub calc_recur {
return 0
if $self->option('recur_temporality', 1) eq 'preceding' && $last_bill == 0;
- my $br = $self->base_recur($cust_pkg);
-
- my $discount = $self->calc_discount($cust_pkg, $sdate, $details, $param);
+ 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 {
diff --git a/FS/FS/part_pkg/prorate.pm b/FS/FS/part_pkg/prorate.pm
index 09561cf51..918b910be 100644
--- a/FS/FS/part_pkg/prorate.pm
+++ b/FS/FS/part_pkg/prorate.pm
@@ -95,34 +95,8 @@ use FS::part_pkg::flat;
);
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;
diff --git a/FS/FS/part_pkg/prorate_Mixin.pm b/FS/FS/part_pkg/prorate_Mixin.pm
new file mode 100644
index 000000000..a60858b37
--- /dev/null
+++ b/FS/FS/part_pkg/prorate_Mixin.pm
@@ -0,0 +1,96 @@
+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;
diff --git a/FS/FS/part_pkg/recur_Common.pm b/FS/FS/part_pkg/recur_Common.pm
index 8ed9eb6af..9a6774579 100644
--- a/FS/FS/part_pkg/recur_Common.pm
+++ b/FS/FS/part_pkg/recur_Common.pm
@@ -4,9 +4,9 @@ use strict;
use vars qw( @ISA %info %recur_method );
use Tie::IxHash;
use Time::Local;
-use FS::part_pkg::prorate;
+use FS::part_pkg::prorate_Mixin;
-@ISA = qw(FS::part_pkg::prorate);
+@ISA = qw(FS::part_pkg::prorate_Mixin);
%info = ( 'disabled' => 1 ); #recur_Common not a usable price plan directly
@@ -26,11 +26,12 @@ sub calc_recur_Common {
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 @@ sub calc_recur_Common {
$$sdate = timelocal(0, 0, 0, $cutoff_day, $mon, $year);
}#$recur_method eq 'subscription'
+ $charges -= $self->calc_discount( $cust_pkg, $sdate, $details, $param );
- $charges -= $self->calc_discount( $cust_pkg, $sdate, $details, $param );
-
- }#$recur_method eq 'prorate'
-
+ }#$recur_method eq 'prorate' or ...
}#increment_next_bill
- $charges;
+ return $charges;
}
diff --git a/httemplate/misc/order_pkg.html b/httemplate/misc/order_pkg.html
index 33b2bb390..2511a3deb 100644
--- a/httemplate/misc/order_pkg.html
+++ b/httemplate/misc/order_pkg.html
@@ -128,7 +128,11 @@ my $cust_main = qsearchs({
my $pkgpart = scalar($cgi->param('pkgpart'));
my $format = $date_format. ' %T %z (%Z)'; #false laziness w/REAL_cust_pkg.cgi?
-my $start_date = $cust_main->next_bill_date;
-$start_date = $start_date ? time2str($format, $start_date) : '';
+my $start_date = '';
+if(! $conf->exists('order_pkg-no_start_date') ) {
+ warn "foo";
+ $cust_main->next_bill_date;
+ $start_date = $start_date ? time2str($format, $start_date) : '';
+}
</%init>