+ my $quantity = $self->quantity || 1;
+ my ($unitsetup, $unitrecur);
+ # calculate base fees
+ if ( $self->waive_setup eq 'Y' || $self->{'_NO_SETUP_KLUDGE'} ) {
+ $unitsetup = '0.00';
+ } else {
+ $unitsetup = $part_pkg->base_setup;
+ }
+ if ( $self->{'_NO_RECUR_KLUDGE'} ) {
+ $unitrecur = '0.00';
+ } else {
+ $unitrecur = $part_pkg->base_recur;
+ }
+
+ #XXX add-on packages
+
+ $self->set('unitsetup', $unitsetup);
+ $self->set('unitrecur', $unitrecur);
+ my $error = $self->replace;
+ return $error if $error;
+
+ # semi-duplicates calc_discount
+ my $setup_discount = 0;
+ my $recur_discount = 0;
+
+ my %setup_discounts; # quotationpkgdiscountnum => amount
+ my %recur_discounts; # quotationpkgdiscountnum => amount
+
+ # XXX the order of applying discounts is ill-defined, which matters
+ # if there are percentage and amount discounts on the same package.
+ foreach my $pkg_discount ($self->quotation_pkg_discount) {
+
+ my $discount = $pkg_discount->discount;
+ my $this_setup_discount = 0;
+ my $this_recur_discount = 0;
+
+ if ( $discount->percent > 0 ) {
+
+ if ( $discount->setup ) {
+ $this_setup_discount = ($discount->percent * $unitsetup / 100);
+ }
+ $this_recur_discount = ($discount->percent * $unitrecur / 100);
+
+ } elsif ( $discount->amount > 0 ) {
+
+ my $discount_left = $discount->amount;
+ if ( $discount->setup ) {
+ if ( $discount_left > $unitsetup - $setup_discount ) {
+ # then discount the setup to zero
+ $discount_left -= $unitsetup - $setup_discount;
+ $this_setup_discount = $unitsetup - $setup_discount;
+ } else {
+ # not enough discount to fully cover the setup
+ $this_setup_discount = $discount_left;
+ $discount_left = 0;
+ }
+ }
+ # same logic for recur
+ if ( $discount_left > $unitrecur - $recur_discount ) {
+ $this_recur_discount = $unitrecur - $recur_discount;
+ } else {
+ $this_recur_discount = $discount_left;
+ }
+
+ }
+
+ # increment the total discountage
+ $setup_discount += $this_setup_discount;
+ $recur_discount += $this_recur_discount;
+ # and update the pkg_discount object
+ $pkg_discount->set('setup_amount', sprintf('%.2f', $setup_discount));
+ $pkg_discount->set('recur_amount', sprintf('%.2f', $recur_discount));
+ my $error = $pkg_discount->replace;
+ return $error if $error;
+ }