+=item _items_discounts_avail
+
+Returns an array of line item hashrefs representing available term discounts
+for this invoice. This makes the same assumptions that apply to term
+discounts in general: that the package is billed monthly, at a flat rate,
+with no usage charges. A prorated first month will be handled, as will
+a setup fee if the discount is allowed to apply to setup fees.
+
+=cut
+
+sub _items_discounts_avail {
+ my $self = shift;
+ my %terms;
+ my $list_pkgnums = 0; # if any packages are not eligible for all discounts
+
+ my ($previous_balance) = $self->previous;
+
+ foreach (qsearch('discount',{ 'months' => { op => '>', value => 1} })) {
+ $terms{$_->months} = {
+ pkgnums => [],
+ base => $previous_balance || 0, # pre-discount sum of charges
+ discounted => $previous_balance || 0, # post-discount sum
+ list_pkgnums => 0, # whether any packages are not discounted
+ }
+ }
+ foreach my $months (keys %terms) {
+ my $hash = $terms{$months};
+
+ # 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;
+
+ next if $part_pkg->freq ne '1';
+ my $setup = $cust_bill_pkg->setup || 0;
+ my $recur = $cust_bill_pkg->recur || 0;
+ my $permonth = $part_pkg->base_recur_permonth || 0;
+
+ my ($discount) = grep { $_->months == $months }
+ map { $_->discount } $part_pkg->part_pkg_discount;
+
+ $hash->{base} += $setup + $recur + ($months - 1) * $permonth;
+ if ($discount) {
+
+ my $discountable;
+ if ( $discount->setup ) {
+ $discountable += $setup;
+ }
+ else {
+ $hash->{discounted} += $setup;
+ }
+
+ if ( $discount->percent ) {
+ $discountable += $months * $permonth;
+ $discountable -= ($discountable * $discount->percent / 100);
+ $discountable -= ($permonth - $recur); # correct for prorate
+ $hash->{discounted} += $discountable;
+ }
+ else {
+ $discountable += $recur;
+ $discountable -= $discount->amount * $recur/$permonth;
+
+ $discountable += ($months - 1) * max($permonth - $discount->amount,0);
+ }
+
+ $hash->{discounted} += $discountable;
+ push @{ $hash->{pkgnums} }, $cust_pkg->pkgnum;
+ }
+ else { #no discount
+ $hash->{discounted} += $setup + $recur + ($months - 1) * $permonth;
+ $hash->{list_pkgnums} = 1;
+ }
+ } #foreach $cust_bill_pkg
+
+ # don't show this line if no packages have discounts at this term
+ # or if there are no new charges to apply the discount to
+ delete $terms{$months} if $hash->{base} == $hash->{discounted}
+ or $hash->{base} == 0;
+
+ }
+
+ $list_pkgnums = grep { $_->{list_pkgnums} > 0 } values %terms;
+
+ foreach my $months (keys %terms) {
+ my $hash = $terms{$months};
+ my $term_total = sprintf('%.2f', $hash->{discounted});
+ # possibly shouldn't include previous balance in these?
+ my $percent = sprintf('%.0f', 100 * (1 - $term_total / $hash->{base}) );
+ my $permonth = sprintf('%.2f', $term_total / $months);
+
+ $hash->{description} = $self->mt('Save [_1]% by paying for [_2] months',
+ $percent, $months
+ );
+ $hash->{amount} = $self->mt('[_1] ([_2] per month)',
+ $term_total, $money_char.$permonth
+ );
+
+ my @detail;
+ if ( $list_pkgnums ) {
+ push @detail, $self->mt('discount on item'). ' '.
+ join(', ', map { "#$_" } @{ $hash->{pkgnums} });
+ }
+ $hash->{ext_description} = join ', ', @detail;
+ }
+
+ map { $terms{$_} } sort {$b <=> $a} keys %terms;
+}
+