- my %total;
- my $pkgnums = 0;
- my $pkgnums_times_discounts = 0;
- # tricky, because packages may not all be eligible for the same discounts
- foreach my $cust_bill_pkg ( $self->cust_bill_pkg ) {
- my $cust_pkg = $cust_bill_pkg->cust_pkg or next;
- my $part_pkg = $cust_pkg->part_pkg or next;
- # for simplicity, skip all this if the customer already has a term discount
- return () if $cust_pkg->cust_pkg_discount_active;
-
- $pkgnums++;
- next if $part_pkg->freq ne '1';
-
- foreach my $discount (
- map { $_->discount } $part_pkg->part_pkg_discount
- ) {
-
- $total{$discount->discountnum} ||=
- {
- discount => $discount,
- pkgnums => [],
- base_current => 0,
- base_permonth => 0,
- setup_include => 0,
- setup_exclude => 0,
- };
- my $hash = $total{$discount->discountnum};
- $hash->{discount} = $discount;
- $hash->{thismonth} += $cust_bill_pkg->recur || 0;
- $hash->{setup} += $cust_bill_pkg->setup || 0;
- $hash->{base_permonth} += $part_pkg->base_recur_permonth;
-
- # and make a list of pkgnums
- push @{ $hash->{pkgnums} }, $cust_pkg->pkgnum;
- $pkgnums_times_discounts++;
- }
- }
-
- # Test for the simple case where all packages on the invoice
- # are eligible for the same set of discounts. If not, we need
- # to list eligibility in the ext_description.
- my $list_pkgnums = ( $pkgnums_times_discounts != $pkgnums * keys(%total) );
-
- foreach my $hash (values %total) {
- my $discount = $hash->{discount};
- my ($amount, $term_total, $percent, $permonth);
- my $months = $discount->months;
- $hash->{months} = $months;
-
- if ( $discount->percent ) {
-
- # per discount_Mixin, percent discounts are calculated on the base
- # recurring fee, not the prorated fee.
- $percent = $discount->percent;
- $amount = sprintf('%.2f', 0.01 * $percent * $hash->{base_permonth});
- # percent discounts apply to setup fee
- if ( $discount->setup ) {
- $hash->{setup} *= (1 - 0.01*$percent);
- }
-
- }
- elsif ( $discount->amount > 0 ) {
-
- # amount discounts are amount * number of packages
- $amount = $discount->amount * scalar(@{ $hash->{pkgnums} });
- $percent = sprintf('%.0f', 100 * $amount / $hash->{base_permonth});
-
- # flat discounts are applied to setup and recur together
- if ( $discount->setup ) {
- $hash->{thismonth} += $hash->{setup};
- $hash->{setup} = 0;
- }
-
- }
-
- $permonth = max( $hash->{base_permonth} - $amount, 0);
- $term_total = max( $hash->{thismonth} - $amount , 0 ) # this month
- + $permonth * ($months - 1) # rest of the term
- + $hash->{setup}; # setup fee
-
- $hash->{description} = $self->mt('Save [_1]% by paying for [_2] months',
- $percent, $months,
- );
- $hash->{amount} = $self->mt('[_1] ([_2] per month)',
- sprintf('%.2f',$term_total), #no money_char to accommodate template quirk
- $money_char.sprintf('%.2f',$permonth) );
-
- my @detail;
- if ( $list_pkgnums ) {
- push @detail, $self->mt('for item'). ' '.
- join(', ', map { "#$_" } @{ $hash->{pkgnums} });
- }
- if ( !$discount->setup and $hash->{setup} ) {
- push @detail, $self->mt('excluding setup fees');
+ my $list_pkgnums = 0; # if any packages are not eligible for all discounts
+
+ my %plans = $self->discount_plans;
+
+ $list_pkgnums = grep { $_->list_pkgnums } values %plans;
+
+ map {
+ my $months = $_;
+ my $plan = $plans{$months};
+
+ my $term_total = sprintf('%.2f', $plan->discounted_total);
+ my $percent = sprintf('%.0f',
+ 100 * (1 - $term_total / $plan->base_total) );
+ my $permonth = sprintf('%.2f', $term_total / $months);
+ my $detail = $self->mt('discount on item'). ' '.
+ join(', ', map { "#$_" } $plan->pkgnums)
+ if $list_pkgnums;
+
+ +{
+ description => $self->mt('Save [_1]% by paying for [_2] months',
+ $percent, $months),
+ amount => $self->mt('[_1] ([_2] per month)',
+ $term_total, $money_char.$permonth),
+ ext_description => ($detail || ''),