show prorate details on invoice, #16010
authormark <mark>
Tue, 7 Feb 2012 01:35:19 +0000 (01:35 +0000)
committermark <mark>
Tue, 7 Feb 2012 01:35:19 +0000 (01:35 +0000)
FS/FS/cust_main/Billing.pm
FS/FS/part_pkg/prorate.pm
FS/FS/part_pkg/prorate_Mixin.pm

index 3828eaa..0a557fc 100644 (file)
@@ -1116,7 +1116,12 @@ sub _make_lines {
         'freq'      => $part_pkg->freq,
       };
 
         'freq'      => $part_pkg->freq,
       };
 
-      if ( $part_pkg->recur_temporality eq 'preceding' ) {
+      if ( $part_pkg->option('prorate_defer_bill',1) 
+           and !$hash{last_bill} ) {
+        # both preceding and upcoming, technically
+        $cust_bill_pkg->sdate( $cust_pkg->setup );
+        $cust_bill_pkg->edate( $cust_pkg->bill );
+      } elsif ( $part_pkg->recur_temporality eq 'preceding' ) {
         $cust_bill_pkg->sdate( $hash{last_bill} );
         $cust_bill_pkg->edate( $sdate - 86399   ); #60s*60m*24h-1
         $cust_bill_pkg->edate( $time ) if $options{cancel};
         $cust_bill_pkg->sdate( $hash{last_bill} );
         $cust_bill_pkg->edate( $sdate - 86399   ); #60s*60m*24h-1
         $cust_bill_pkg->edate( $time ) if $options{cancel};
index 320fdb6..f930d41 100644 (file)
@@ -32,8 +32,12 @@ use FS::part_pkg::flat;
                         'name' => 'Defer the first bill until the billing day',
                         'type' => 'checkbox',
                         },
                         'name' => 'Defer the first bill until the billing day',
                         'type' => 'checkbox',
                         },
+    'prorate_verbose' => {
+                        'name' => 'Show prorate details on the invoice',
+                        'type' => 'checkbox',
+                        },
   },
   },
-  'fieldorder' => [ 'cutoff_day', 'prorate_defer_bill', 'add_full_period', 'prorate_round_day' ],
+  'fieldorder' => [ 'cutoff_day', 'prorate_defer_bill', 'add_full_period', 'prorate_round_day', 'prorate_verbose' ],
   'freq' => 'm',
   'weight' => 20,
 );
   'freq' => 'm',
   'weight' => 20,
 );
index 63b63d7..0f40576 100644 (file)
@@ -3,6 +3,7 @@ package FS::part_pkg::prorate_Mixin;
 use strict;
 use vars qw( %info );
 use Time::Local qw( timelocal );
 use strict;
 use vars qw( %info );
 use Time::Local qw( timelocal );
+use Date::Format qw( time2str );
 
 %info = ( 
   'disabled'  => 1,
 
 %info = ( 
   'disabled'  => 1,
@@ -22,8 +23,13 @@ use Time::Local qw( timelocal );
                           'billing day',
                 'type' => 'checkbox',
     },
                           'billing day',
                 'type' => 'checkbox',
     },
+    'prorate_verbose' => {
+                'name' => 'Show prorate details on the invoice',
+                'type' => 'checkbox',
+    },
   },
   },
-  'fieldorder' => [ qw(prorate_defer_bill prorate_round_day add_full_period) ],
+  'fieldorder' => [ qw(prorate_defer_bill prorate_round_day 
+                       add_full_period prorate_verbose) ],
 );
 
 sub fieldorder {
 );
 
 sub fieldorder {
@@ -65,6 +71,7 @@ billing period after that.
 instead of using the exact time.
 - prorate_defer_bill: Don't bill the prorate interval until the prorate 
 day arrives.
 instead of using the exact time.
 - prorate_defer_bill: Don't bill the prorate interval until the prorate 
 day arrives.
+- prorate_verbose: Generate details to explain the prorate calculations.
 
 =cut
 
 
 =cut
 
@@ -73,6 +80,8 @@ sub calc_prorate {
   die "no cutoff_day" unless $cutoff_day;
   die "can't prorate non-monthly package\n" if $self->freq =~ /\D/;
 
   die "no cutoff_day" unless $cutoff_day;
   die "can't prorate non-monthly package\n" if $self->freq =~ /\D/;
 
+  my $money_char = FS::Conf->new->config('money_char') || '$';
+
   my $charge = $self->base_recur($cust_pkg, $sdate) || 0;
 
   my $add_period = $self->option('add_full_period',1);
   my $charge = $self->base_recur($cust_pkg, $sdate) || 0;
 
   my $add_period = $self->option('add_full_period',1);
@@ -103,12 +112,28 @@ sub calc_prorate {
   my $permonth = $charge / $self->freq;
   my $months = ( ( $self->freq - 1 ) + ($mend-$mnow) / ($mend-$mstart) );
 
   my $permonth = $charge / $self->freq;
   my $months = ( ( $self->freq - 1 ) + ($mend-$mnow) / ($mend-$mstart) );
 
+  if ( $self->option('prorate_verbose',1) 
+      and $months > 0 and $months < $self->freq ) {
+    push @$details, 
+          'Prorated (' . time2str('%b %d', $mnow) .
+            ' - ' . time2str('%b %d', $mend) . '): ' . $money_char . 
+            sprintf('%.2f', $permonth * $months + 0.00000001 );
+  }
+
   # add a full period if currently billing for a partial period
   # or periods up to freq_override if billing for an override interval
   if ( ($param->{'freq_override'} || 0) > 1 ) {
     $months += $param->{'freq_override'} - 1;
   } 
   elsif ( $add_period && $months < $self->freq) {
   # add a full period if currently billing for a partial period
   # or periods up to freq_override if billing for an override interval
   if ( ($param->{'freq_override'} || 0) > 1 ) {
     $months += $param->{'freq_override'} - 1;
   } 
   elsif ( $add_period && $months < $self->freq) {
+
+    if ( $self->option('prorate_verbose',1) ) {
+      # calculate the prorated and add'l period charges
+      push @$details,
+        'First full month: ' . $money_char . 
+          sprintf('%.2f', $permonth);
+    }
+
     $months += $self->freq;
     $$sdate = $self->add_freq($mstart);
   }
     $months += $self->freq;
     $$sdate = $self->add_freq($mstart);
   }