+ my $escape = $options{'escape_function'};
+ my $locale = $self->cust_or_prospect->locale;
+
+ my $preref = $options{'preref_callback'};
+
+ my $section = $options{'section'};
+ my $freq = $section->{'category'};
+ my @pkgs = $self->quotation_pkg;
+ my @items;
+ die "_items_pkg called without section->{'category'}"
+ unless defined $freq;
+
+ my %tax_item; # taxname => hashref, will be aggregated AT DISPLAY TIME
+ # like we should have done in the first place
+
+ foreach my $quotation_pkg (@pkgs) {
+ my $part_pkg = $quotation_pkg->part_pkg;
+ my @details = $quotation_pkg->details;
+ my $setuprecur;
+ my $this_item = {
+ 'pkgnum' => $quotation_pkg->quotationpkgnum,
+ 'description' => $quotation_pkg->desc($locale),
+ 'ext_description' => \@details,
+ 'quantity' => $quotation_pkg->quantity,
+ };
+ if ($freq eq '0') {
+ # setup/one-time
+ $setuprecur = 'setup';
+ if ($part_pkg->freq ne '0') {
+ # indicate that it's a setup fee on a recur package (cust_bill does
+ # this too)
+ $this_item->{'description'} .= ' Setup';
+ }
+ } else {
+ # recur for this frequency
+ next if $freq ne $part_pkg->freq;
+ $setuprecur = 'recur';
+ }
+
+ $this_item->{'unit_amount'} = sprintf('%.2f',
+ $quotation_pkg->get('unit'.$setuprecur));
+ $this_item->{'amount'} = sprintf('%.2f', $this_item->{'unit_amount'}
+ * $quotation_pkg->quantity);
+ next if $this_item->{'amount'} == 0 and !(
+ $setuprecur eq 'setup'
+ ? $quotation_pkg->setup_show_zero
+ : $quotation_pkg->recur_show_zero
+ );
+
+ if ( $preref ) {
+ $this_item->{'preref_html'} = &$preref($quotation_pkg);
+ }
+
+ push @items, $this_item;
+ my $discount = $quotation_pkg->_item_discount(setuprecur => $setuprecur);
+ if ($discount) {
+ $_ = &{$escape}($_) foreach @{ $discount->{ext_description} };
+ push @items, $discount;
+ }
+
+ # each quotation_pkg_tax has two amounts: the amount charged on the
+ # setup invoice, and the amount on the recurring invoice.
+ foreach my $qpt ($quotation_pkg->quotation_pkg_tax) {
+ my $this_tax = $tax_item{$qpt->itemdesc} ||= {
+ 'pkgnum' => 0,
+ 'description' => $qpt->itemdesc,
+ 'ext_description' => [],
+ 'amount' => 0,
+ };
+ $this_tax->{'amount'} += $qpt->get($setuprecur.'_amount');
+ }
+ } # foreach $quotation_pkg
+
+ foreach my $taxname ( sort { $a cmp $b } keys (%tax_item) ) {
+ my $this_tax = $tax_item{$taxname};
+ $this_tax->{'amount'} = sprintf('%.2f', $this_tax->{'amount'});
+ next if $this_tax->{'amount'} == 0;
+ push @items, $this_tax;
+ }
+
+ return @items;
+}
+
+sub _items_tax {
+ ();