diff options
| author | ivan <ivan> | 2010-11-05 22:58:50 +0000 | 
|---|---|---|
| committer | ivan <ivan> | 2010-11-05 22:58:50 +0000 | 
| commit | 337323718878fdfe98801193b0dbecffdc8dffc8 (patch) | |
| tree | f2dc92e872c90bb811f4b0dc6c437874192208d7 | |
| parent | 148ac21ae4677eba0e53c333ead11e74e6c8030f (diff) | |
split discount bs out into its own file before cust_main/Billing.pm becomes as bad as the old monolithic cust_main.pm, somehow RT#10462
| -rw-r--r-- | FS/FS/cust_main.pm | 1 | ||||
| -rw-r--r-- | FS/FS/cust_main/Billing.pm | 173 | ||||
| -rw-r--r-- | FS/FS/cust_main/Billing_Discount.pm | 207 | ||||
| -rw-r--r-- | FS/MANIFEST | 1 | 
4 files changed, 213 insertions, 169 deletions
| diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 796996554..03e8cc647 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -5,6 +5,7 @@ use strict;               #FS::cust_main:_Marketgear when they're ready to move to 2.1  use base qw( FS::cust_main::Packages               FS::cust_main::Billing FS::cust_main::Billing_Realtime +             FS::cust_main::Billing_Discount               FS::otaker_Mixin FS::payinfo_Mixin FS::cust_main_Mixin               FS::geocode_Mixin               FS::Record diff --git a/FS/FS/cust_main/Billing.pm b/FS/FS/cust_main/Billing.pm index e00478836..536a93860 100644 --- a/FS/FS/cust_main/Billing.pm +++ b/FS/FS/cust_main/Billing.pm @@ -12,7 +12,6 @@ use FS::cust_bill_pkg;  use FS::cust_bill_pkg_display;  use FS::cust_bill_pay;  use FS::cust_credit_bill; -use FS::cust_pkg;  use FS::cust_tax_adjustment;  use FS::tax_rate;  use FS::tax_rate_location; @@ -20,6 +19,7 @@ use FS::cust_bill_pkg_tax_location;  use FS::cust_bill_pkg_tax_rate_location;  use FS::part_event;  use FS::part_event_condition; +use FS::pkg_category;  # 1 is mostly method/subroutine entry and options  # 2 traces progress of some operations @@ -897,6 +897,7 @@ sub _make_lines {      # There may be some part_pkg for which this is wrong.  Only those      # which can_discount are supported. +    # (the UI should prevent adding discounts to these at the moment)      $recur = eval { $cust_pkg->$method( \$sdate, \@details, \%param ) };      return "$@ running $method for $cust_pkg\n" @@ -1626,174 +1627,6 @@ Explicitly pass the objects to be tested (typically used with eventtable).  Set to true to return the objects, but not actually insert them into the  database. -=item discount_terms - -Returns a list of lengths for term discounts - -=cut - -sub _discount_pkgs_and_bill { -my $self = shift; - -  my @cust_bill = $self->cust_bill; -  my $cust_bill = pop @cust_bill; -  return () unless $cust_bill && $cust_bill->owed; - -  my @where = (); -  push @where, "cust_bill_pkg.invnum = ". $cust_bill->invnum; -  push @where, "cust_bill_pkg.pkgpart_override IS NULL"; -  push @where, "part_pkg.freq = '1'"; -  push @where, "(cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0)"; -  push @where, "(cust_pkg.susp   IS NULL OR cust_pkg.susp   = 0)"; -  push @where, "0<(SELECT count(*) FROM part_pkg_discount -                  WHERE part_pkg.pkgpart = part_pkg_discount.pkgpart)"; -  push @where, -    "0=(SELECT count(*) FROM cust_bill_pkg_discount -         WHERE cust_bill_pkg.billpkgnum = cust_bill_pkg_discount.billpkgnum)"; - -  my $extra_sql = 'WHERE '. join(' AND ', @where); - -  my @cust_pkg =  -    qsearch({ -      'table' => 'cust_pkg', -      'select' => "DISTINCT cust_pkg.*", -      'addl_from' => 'JOIN cust_bill_pkg USING(pkgnum) '. -                     'JOIN part_pkg USING(pkgpart)', -      'hashref' => {}, -      'extra_sql' => $extra_sql, -    });  - -  ($cust_bill, @cust_pkg); -} - -sub _discountable_pkgs_at_term { -  my ($term, @pkgs) = @_; -  my $part_pkg = new FS::part_pkg { freq => $term - 1 }; -  grep { ( !$_->adjourn || $_->adjourn > $part_pkg->add_freq($_->bill) ) &&  -         ( !$_->expire  || $_->expire  > $part_pkg->add_freq($_->bill) ) -       } -    @pkgs; -} - -=item discount_terms - -Returns a list of lengths for term discounts - -=cut - -sub discount_terms { -my $self = shift; - -  my %terms = (); - -  my @discount_pkgs = $self->_discount_pkgs_and_bill; -  shift @discount_pkgs; #discard bill; -   -  map { $terms{$_->months} = 1 } -    grep { $_->months && $_->months > 1 } -    map { $_->discount } -    map { $_->part_pkg->part_pkg_discount } -    @discount_pkgs; - -  return sort { $a <=> $b } keys %terms; - -} - -=back - -=item discount_term_values MONTHS - -Returns a list with credit, dollar amount saved, and total bill acheived -by prepaying the most recent invoice for MONTHS. - -=cut - -sub discount_term_values { -  my $self = shift; -  my $term = shift; - -  local($DEBUG) = $FS::cust_main::DEBUG if $FS::cust_main::DEBUG > $DEBUG; - -  warn "$me discount_term_values called with $term\n" if $DEBUG; - -  my %result = (); - -  my @packages = $self->_discount_pkgs_and_bill; -  my $cust_bill = shift(@packages); -  @packages = _discountable_pkgs_at_term( $term, @packages ); -  return () unless scalar(@packages); - -  $_->bill($_->last_bill) foreach @packages; -  my @final = map { new FS::cust_pkg { $_->hash } } @packages; - -  my %options = ( -                  'recurring_only' => 1, -                  'no_usage_reset' => 1, -                  'no_commit'      => 1, -                ); - -  my %params =  ( -                  'return_bill'    => [], -                  'pkg_list'       => \@packages, -                  'time'           => $cust_bill->_date, -                ); - -  my $error = $self->bill(%options, %params); -  die $error if $error; # XXX think about this a bit more - -  my $credit = 0; -  $credit += $_->charged foreach @{$params{return_bill}}; -  $credit = sprintf('%.2f', $credit); -  warn "$me discount_term_values $term credit: $credit\n" if $DEBUG; - -  %params =  ( -               'return_bill'    => [], -               'pkg_list'       => \@packages, -               'time'           => $packages[0]->part_pkg->add_freq($cust_bill->_date) -             ); - -  $error = $self->bill(%options, %params); -  die $error if $error; # XXX think about this a bit more - -  my $next = 0; -  $next += $_->charged foreach @{$params{return_bill}}; -  warn "$me discount_term_values $term next: $next\n" if $DEBUG; -   -  %params =  (  -               'return_bill'    => [], -               'pkg_list'       => \@final, -               'time'           => $cust_bill->_date, -               'freq_override'  => $term, -             ); - -  $error = $self->bill(%options, %params); -  die $error if $error; # XXX think about this a bit more - -  my $final = $self->balance - $credit; -  $final += $_->charged foreach @{$params{return_bill}}; -  $final = sprintf('%.2f', $final); -  warn "$me discount_term_values $term final: $final\n" if $DEBUG; - -  my $savings = sprintf('%.2f', $self->balance + ($term - 1) * $next - $final); - -  ( $credit, $savings, $final ); - -} - -sub discount_terms_hash { -  my $self = shift; - -  my %result = (); -  my @terms = $self->discount_terms; -  foreach my $term (@terms) { -    my @result = $self->discount_term_values($term); -    $result{$term} = [ @result ] if scalar(@result); -  } - -  return %result; - -} -  =back  =cut @@ -2245,6 +2078,8 @@ sub apply_payments {    return $total_unapplied_payments;  } +=back +  =head1 BUGS  =head1 SEE ALSO diff --git a/FS/FS/cust_main/Billing_Discount.pm b/FS/FS/cust_main/Billing_Discount.pm new file mode 100644 index 000000000..9dda389f6 --- /dev/null +++ b/FS/FS/cust_main/Billing_Discount.pm @@ -0,0 +1,207 @@ +package FS::cust_main::Billing_Discount; + +use strict; +use vars qw( $DEBUG $me ); +use FS::Record qw( qsearch ); #qsearchs ); +use FS::cust_pkg; + +# 1 is mostly method/subroutine entry and options +# 2 traces progress of some operations +# 3 is even more information including possibly sensitive data +$DEBUG = 0; +$me = '[FS::cust_main::Billing_Discount]'; + +=head1 NAME + +FS::cust_main::Billing_Discount - Billing discount mixin for cust_main + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +These methods are available on FS::cust_main objects. + +=head1 METHODS + +=over 4 + +=item _discount_pkg_and_bill + +=cut + +sub _discount_pkgs_and_bill { +  my $self = shift; + +  my @cust_bill = $self->cust_bill; +  my $cust_bill = pop @cust_bill; +  return () unless $cust_bill && $cust_bill->owed; + +  my @where = (); +  push @where, "cust_bill_pkg.invnum = ". $cust_bill->invnum; +  push @where, "cust_bill_pkg.pkgpart_override IS NULL"; +  push @where, "part_pkg.freq = '1'"; +  push @where, "(cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0)"; +  push @where, "(cust_pkg.susp   IS NULL OR cust_pkg.susp   = 0)"; +  push @where, "0<(SELECT count(*) FROM part_pkg_discount +                  WHERE part_pkg.pkgpart = part_pkg_discount.pkgpart)"; +  push @where, +    "0=(SELECT count(*) FROM cust_bill_pkg_discount +         WHERE cust_bill_pkg.billpkgnum = cust_bill_pkg_discount.billpkgnum)"; + +  my $extra_sql = 'WHERE '. join(' AND ', @where); + +  my @cust_pkg =  +    qsearch({ +      'table' => 'cust_pkg', +      'select' => "DISTINCT cust_pkg.*", +      'addl_from' => 'JOIN cust_bill_pkg USING(pkgnum) '. +                     'JOIN part_pkg USING(pkgpart)', +      'hashref' => {}, +      'extra_sql' => $extra_sql, +    });  + +  ($cust_bill, @cust_pkg); +} + +=item _discountable_pkgs_at_term + +=cut + +#this isn't even a method +sub _discountable_pkgs_at_term { +  my ($term, @pkgs) = @_; +  my $part_pkg = new FS::part_pkg { freq => $term - 1 }; +  grep { ( !$_->adjourn || $_->adjourn > $part_pkg->add_freq($_->bill) ) &&  +         ( !$_->expire  || $_->expire  > $part_pkg->add_freq($_->bill) ) +       } +    @pkgs; +} + +=item discount_terms + +Returns a list of lengths for term discounts + +=cut + +sub discount_terms { +  my $self = shift; + +  my %terms = (); + +  my @discount_pkgs = $self->_discount_pkgs_and_bill; +  shift @discount_pkgs; #discard bill; +   +  map { $terms{$_->months} = 1 } +    grep { $_->months && $_->months > 1 } +    map { $_->discount } +    map { $_->part_pkg->part_pkg_discount } +    @discount_pkgs; + +  return sort { $a <=> $b } keys %terms; + +} + +=item discount_term_values MONTHS + +Returns a list with credit, dollar amount saved, and total bill acheived +by prepaying the most recent invoice for MONTHS. + +=cut + +sub discount_term_values { +  my $self = shift; +  my $term = shift; + +  local($DEBUG) = $FS::cust_main::DEBUG if $FS::cust_main::DEBUG > $DEBUG; + +  warn "$me discount_term_values called with $term\n" if $DEBUG; + +  my %result = (); + +  my @packages = $self->_discount_pkgs_and_bill; +  my $cust_bill = shift(@packages); +  @packages = _discountable_pkgs_at_term( $term, @packages ); +  return () unless scalar(@packages); + +  $_->bill($_->last_bill) foreach @packages; +  my @final = map { new FS::cust_pkg { $_->hash } } @packages; + +  my %options = ( +                  'recurring_only' => 1, +                  'no_usage_reset' => 1, +                  'no_commit'      => 1, +                ); + +  my %params =  ( +                  'return_bill'    => [], +                  'pkg_list'       => \@packages, +                  'time'           => $cust_bill->_date, +                ); + +  my $error = $self->bill(%options, %params); +  die $error if $error; # XXX think about this a bit more + +  my $credit = 0; +  $credit += $_->charged foreach @{$params{return_bill}}; +  $credit = sprintf('%.2f', $credit); +  warn "$me discount_term_values $term credit: $credit\n" if $DEBUG; + +  %params =  ( +               'return_bill'    => [], +               'pkg_list'       => \@packages, +               'time'           => $packages[0]->part_pkg->add_freq($cust_bill->_date) +             ); + +  $error = $self->bill(%options, %params); +  die $error if $error; # XXX think about this a bit more + +  my $next = 0; +  $next += $_->charged foreach @{$params{return_bill}}; +  warn "$me discount_term_values $term next: $next\n" if $DEBUG; +   +  %params =  (  +               'return_bill'    => [], +               'pkg_list'       => \@final, +               'time'           => $cust_bill->_date, +               'freq_override'  => $term, +             ); + +  $error = $self->bill(%options, %params); +  die $error if $error; # XXX think about this a bit more + +  my $final = $self->balance - $credit; +  $final += $_->charged foreach @{$params{return_bill}}; +  $final = sprintf('%.2f', $final); +  warn "$me discount_term_values $term final: $final\n" if $DEBUG; + +  my $savings = sprintf('%.2f', $self->balance + ($term - 1) * $next - $final); + +  ( $credit, $savings, $final ); + +} + +sub discount_terms_hash { +  my $self = shift; + +  my %result = (); +  my @terms = $self->discount_terms; +  foreach my $term (@terms) { +    my @result = $self->discount_term_values($term); +    $result{$term} = [ @result ] if scalar(@result); +  } + +  return %result; + +} + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L<FS::cust_main>, L<FS::cust_main::Billing> + +=cut + +1; diff --git a/FS/MANIFEST b/FS/MANIFEST index 56f7af0c6..b4bce287d 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -69,6 +69,7 @@ FS/cust_credit.pm  FS/cust_credit_bill.pm  FS/cust_main.pm  FS/cust_main/Billing.pm +FS/cust_main/Billing_Discount.pm  FS/cust_main/Billing_Realtime.pm  FS/cust_main/Import.pm  FS/cust_main/Packages.pm | 
