From: Mark Wells Date: Tue, 27 Oct 2015 23:20:31 +0000 (-0700) Subject: separate setup/recur quotation discounts, #14092 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=a7692509e282a27c81b134c77c3441c732669642 separate setup/recur quotation discounts, #14092 --- diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 7dc54f7c4..447302b36 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -1985,8 +1985,8 @@ sub tables_hashref { 'quotationpkgdiscountnum', 'serial', '', '', '', '', 'quotationpkgnum', 'int', '', '', '', '', 'discountnum', 'int', '', '', '', '', - 'setup_amount', @money_typen, '', '', - 'recur_amount', @money_typen, '', '', + 'setuprecur', 'varchar', 'NULL', $char_d, '', '', + 'amount', @money_typen, '', '', #'end_date', @date_type, '', '', ], 'primary_key' => 'quotationpkgdiscountnum', diff --git a/FS/FS/quotation.pm b/FS/FS/quotation.pm index d66b1b8e4..c4004934a 100644 --- a/FS/FS/quotation.pm +++ b/FS/FS/quotation.pm @@ -260,6 +260,7 @@ sub _items_sections { my %opt = @_; my $escape = $opt{escape}; # the only one we care about + my %show; # package frequency => 1 if there's anything to display my %subtotals = (); # package frequency => subtotal my $disable_total = 0; foreach my $pkg ($self->quotation_pkg) { @@ -267,6 +268,8 @@ sub _items_sections { my $part_pkg = $pkg->part_pkg; my $recur_freq = $part_pkg->freq; + $show{$recur_freq} = 1 if $pkg->unitrecur > 0; + $show{0} = 1 if $pkg->unitsetup > 0; ($subtotals{0} ||= 0) += $pkg->setup + $pkg->setup_tax; ($subtotals{$recur_freq} ||= 0) += $pkg->recur + $pkg->recur_tax; @@ -288,7 +291,8 @@ sub _items_sections { my $no_recurring = 0; foreach my $freq (keys %subtotals) { - next if $subtotals{$freq} == 0; + #next if $subtotals{$freq} == 0; + next if !$show{$freq}; my $weight = List::MoreUtils::first_index { $_ eq $freq } @pkg_freq_order; @@ -405,10 +409,10 @@ sub order { $cust_pkg->set( $_, $quotation_pkg->get($_) ); } - # currently only one discount each - my ($pkg_discount) = $quotation_pkg->quotation_pkg_discount; - if ( $pkg_discount ) { - $cust_pkg->set('discountnum', $pkg_discount->discountnum); + # can now have two discounts each (setup and recur) + foreach my $pkg_discount ($quotation_pkg->quotation_pkg_discount) { + my $field = $pkg_discount->setuprecur . '_discountnum'; + $cust_pkg->set($field, $pkg_discount->discountnum); } $all_cust_pkg{$cust_pkg} = []; # no services @@ -685,7 +689,7 @@ sub estimate { } my %quotation_pkg_tax; # quotationpkgnum => tax name => quotation_pkg_tax obj - my %quotation_pkg_discount; # quotationpkgnum => quotation_pkg_discount obj + my %quotation_pkg_discount; # quotationpkgnum => setuprecur => quotation_pkg_discount obj for (my $i = 0; $i < scalar(@return_bill); $i++) { my $this_bill = $return_bill[$i]->[0]; @@ -725,25 +729,25 @@ sub estimate { # discounts if ( $cust_bill_pkg->get('discounts') ) { + # discount records are generated as (setup, recur). + # well, not always, sometimes it's just (recur), but fixing this + # is horribly invasive. my $discount = $cust_bill_pkg->get('discounts')->[0]; + if ( $discount ) { - # discount records are generated as (setup, recur). - # well, not always, sometimes it's just (recur), but fixing this - # is horribly invasive. - my $qpd = $quotation_pkg_discount{$quotationpkgnum} + # find the quotation_pkg_discount record for this billing pass... + my $setuprecur = $i ? 'recur' : 'setup'; + my $qpd = $quotation_pkg_discount{$quotationpkgnum}{$setuprecur} ||= qsearchs('quotation_pkg_discount', { - 'quotationpkgnum' => $quotationpkgnum + 'quotationpkgnum' => $quotationpkgnum, + 'setuprecur' => $setuprecur, }); if (!$qpd) { #can't happen - warn "$me simulated bill returned a discount but no discount is in effect.\n"; + warn "$me simulated bill returned a $setuprecur discount but no discount is in effect.\n"; } - if ($discount and $qpd) { - if ( $i == 0 ) { - $qpd->set('setup_amount', $discount->amount); - } else { - $qpd->set('recur_amount', $discount->amount); - } + if ($qpd) { + $qpd->set('amount', $discount->amount); } } } # end of discount stuff @@ -812,10 +816,13 @@ sub estimate { return "$error (recording estimate for ".$quotation_pkg->part_pkg->pkg.")" if $error; } - foreach my $quotation_pkg_discount (values %quotation_pkg_discount) { - $error = $quotation_pkg_discount->replace; - return "$error (recording estimated discount)" - if $error; + foreach (values %quotation_pkg_discount) { + # { setup => one, recur => another } + foreach my $quotation_pkg_discount (values %$_) { + $error = $quotation_pkg_discount->replace; + return "$error (recording estimated discount)" + if $error; + } } foreach my $quotation_pkg_tax (map { values %$_ } values %quotation_pkg_tax) { $error = $quotation_pkg_tax->insert; diff --git a/FS/FS/quotation_pkg.pm b/FS/FS/quotation_pkg.pm index 10bdc2efe..49d0d9a5c 100644 --- a/FS/FS/quotation_pkg.pm +++ b/FS/FS/quotation_pkg.pm @@ -132,8 +132,8 @@ sub insert { my $error = $self->SUPER::insert; - if ( !$error and $self->discountnum ) { - warn "inserting discount #".$self->discountnum."\n"; + if ( !$error and ($self->setup_discountnum || $self->recur_discountnum) ) { + #warn "inserting discount\n"; $error = $self->insert_discount; $error .= ' (setting discount)' if $error; } @@ -262,28 +262,37 @@ sub insert_discount { #my ($self, %options) = @_; my $self = shift; - my $quotation_pkg_discount = FS::quotation_pkg_discount->new( { - 'quotationpkgnum' => $self->quotationpkgnum, - 'discountnum' => $self->discountnum, - #for the create a new discount case - '_type' => $self->discountnum__type, - 'amount' => $self->discountnum_amount, - 'percent' => $self->discountnum_percent, - 'months' => $self->discountnum_months, - 'setup' => $self->discountnum_setup, - } ); - - $quotation_pkg_discount->insert; + foreach my $x (qw(setup recur)) { + if ( my $discountnum = $self->get("${x}_discountnum") ) { + my $cust_pkg_discount = FS::quotation_pkg_discount->new( { + 'quotationpkgnum' => $self->quotationpkgnum, + 'discountnum' => $discountnum, + 'setuprecur' => $x, + #for the create a new discount case + 'amount' => $self->get("${x}_discountnum_amount"), + 'percent' => $self->get("${x}_discountnum_percent"), + 'months' => $self->get("${x}_discountnum_months"), + } ); + if ( $x eq 'setup' ) { + $cust_pkg_discount->setup('Y'); + $cust_pkg_discount->months(''); + } + my $error = $cust_pkg_discount->insert; + return $error if $error; + } + } } sub _item_discount { my $self = shift; my %options = @_; my $setuprecur = $options{'setuprecur'}; + # a little different from cust_bill_pkg::_item_discount, in that this one + # is asked specifically whether to show setup or recur discounts (because + # on the quotation they're separate sections entirely) - # kind of silly treating this as multiple records, but it works, and will - # work if we allow multiple discounts at some point - my @pkg_discounts = $self->pkg_discount; + my @pkg_discounts = grep { $_->setuprecur eq $setuprecur } + $self->pkg_discount; return if @pkg_discounts == 0; my @ext; @@ -296,7 +305,7 @@ sub _item_discount { }; foreach my $pkg_discount (@pkg_discounts) { push @ext, $pkg_discount->description; - my $amount = $pkg_discount->get($setuprecur.'_amount'); + my $amount = $pkg_discount->get('amount'); $d->{amount} -= $amount; } $d->{amount} = sprintf('%.2f', $d->{amount} * $self->quantity); @@ -306,8 +315,12 @@ sub _item_discount { sub setup { my $self = shift; - ($self->unitsetup - sum(0, map { $_->setup_amount } $self->pkg_discount)) - * ($self->quantity || 1); + return '0.00' if $self->waive_setup eq 'Y';; + my $discount_amount = sum(0, map { $_->amount } + grep { $_->setuprecur eq 'setup' } + $self->pkg_discount + ); + ($self->unitsetup - $discount_amount) * ($self->quantity || 1); } @@ -318,8 +331,12 @@ sub setup_tax { sub recur { my $self = shift; - ($self->unitrecur - sum(0, map { $_->recur_amount } $self->pkg_discount)) - * ($self->quantity || 1) + my $discount_amount = sum(0, map { $_->amount } + grep { $_->setuprecur eq 'recur' } + $self->pkg_discount + ); + ($self->unitrecur - $discount_amount) * ($self->quantity || 1); + } sub recur_tax { diff --git a/FS/FS/quotation_pkg_discount.pm b/FS/FS/quotation_pkg_discount.pm index 4389db243..1815294ef 100644 --- a/FS/FS/quotation_pkg_discount.pm +++ b/FS/FS/quotation_pkg_discount.pm @@ -45,14 +45,14 @@ for. discountnum (L) -=item setup_amount +=item setuprecur -Amount that will be discounted from setup fees, per package quantity. +Whether this is a setup or recur discount. -=item recur_amount +=item amount -Amount that will be discounted from recurring fees in the first billing -cycle, per package quantity. +Amount that will be discounted from either setup or recur fees, per package +quantity. =back @@ -106,8 +106,8 @@ sub check { $self->ut_numbern('quotationpkgdiscountnum') || $self->ut_foreign_key('quotationpkgnum', 'quotation_pkg', 'quotationpkgnum' ) || $self->ut_foreign_key('discountnum', 'discount', 'discountnum' ) - || $self->ut_moneyn('setup_amount') - || $self->ut_moneyn('recur_amount') + || $self->ut_enum('setuprecur', ['setup', 'recur']) + || $self->ut_moneyn('amount') ; return $error if $error;