From 71231d6bd803d2a3977c3ce2fa1f3c0ed4746b2d Mon Sep 17 00:00:00 2001 From: Mitch Jackson Date: Wed, 28 Feb 2018 08:27:16 +0000 Subject: [PATCH] RT# 79284 Option to set discount at Change Package --- FS/FS/cust_pkg.pm | 154 ++++++++++++++++++++++++++- httemplate/edit/process/change-cust_pkg.html | 11 +- httemplate/elements/select-discount.html | 36 ++++++- httemplate/misc/change_pkg.cgi | 32 ++++++ 4 files changed, 230 insertions(+), 3 deletions(-) diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index b2cc874a4..fea05683d 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -2765,6 +2765,10 @@ The date for the package change. Required, and must be in the future. =item quantity +=item discount + +Optional hashref that will be passed to $new_pkg->change_discount() + =item contract_end The pkgpart, locationnum, quantity and optional contract_end of the new @@ -2782,6 +2786,9 @@ sub change_later { my $error = $self->_check_change($opt); return $error if $error; + my %discount; + %discount = %{$opt->{discount}} if ref $opt->{discount}; + my $oldAutoCommit = $FS::UID::AutoCommit; local $FS::UID::AutoCommit = 0; my $dbh = dbh; @@ -2834,6 +2841,10 @@ sub change_later { (($err_or_pkg->pkgnum == $change_to->pkgnum) ? '' : $change_to->cancel('no_delay_cancel' => 1) || $change_to->delete); + + # Apply user-specified discount to new cust_pkg + $error = $err_or_pkg->change_discount(\%discount) + if !$error && %discount && %discount{discountnum} =~ /^-?\d+$/; } else { $error = $err_or_pkg; } @@ -2841,6 +2852,10 @@ sub change_later { $self->set('expire', $date); $change_to->set('start_date', $date); $error = $self->replace || $change_to->replace; + + # Apply user-specified discount to new cust_pkg + $error = $change_to->change_discount(\%discount) + if !$error && %discount && %discount{discountnum} =~ /^-?\d+$/; } if ( $error ) { $dbh->rollback if $oldAutoCommit; @@ -2880,6 +2895,11 @@ sub change_later { $self->set('expire', $date); $error = $self->replace; } + + # Apply user-specified discount to new cust_pkg + $new->change_discount(\%discount) + if !$error && %discount && %discount{discountnum} =~ /^-?\d+$/; + if ( $error ) { $dbh->rollback if $oldAutoCommit; } else { @@ -4704,6 +4724,139 @@ sub insert_discount { $cust_pkg_discount->insert; } + +=item change_discount %opt + +Method checks if the given values represent a change in either setup or +discount level. If so, the existing discounts are revoked, the new +discounts are recorded. + +Usage: + +$error = change_discount( + { + # -1: Indicates a "custom discount" + # 0: Indicates to remove any discount + # >0: discountnum to apply + discountnum => [-1, 0, discountnum], + + # When discountnum is "-1" to indicate custom discount, include + # the additional fields: + amount => AMOUNT_DISCOUNT + percent => PERCENTAGE_DISCOUNT + months => 12, + setup => 1, # APPLY TO SETUP + _type => amount/percentage + }, +); + + +=cut + +sub change_discount { + my ($self, $opt) = @_; + return "change_discount() called with bad \%opt hashref" + unless ref $opt; + + my %opt = %{$opt}; + + my @old_discount = + qsearch('cust_pkg_discount',{ + pkgnum => $self->pkgnum, + disabled => '', + }); + + if ($DEBUG) { + warn "change_discount() pkgnum: ".$self->pkgnum." \n"; + warn "change_discount() \%opt: \n"; + warn Dumper(\%opt); + } + + my @to_be_disabled; + my %change = %opt; + + return "change_discount() called with bad discountnum" + unless $change{discountnum} =~ /^-?\d+$/; + + if ($change{discountnum} eq 0) { + # Removing old discount + + %change = (); + + push @to_be_disabled, @old_discount; + + } else { + + if ( grep { $_->discountnum eq $change{discountnum} } @old_discount ){ + # Duplicate, disregard this entry + %change = (); + } else { + # Mark any discounts we're replacing + push @to_be_disabled, @old_discount; + } + } + + # If we still have changes queued, create data structures for + # insert_discount(). + my @discount_insert; + if (%change) { + push @discount_insert, { + discountnum => $change{discountnum}, + discountnum__type => $change{_type}, + discountnum_amount => $change{amount}, + discountnum_percent => $change{percent} ? $change{percent} : '0', + discountnum_months => $change{months}, + discountnum_setup => $change{setup} ? 'Y' : '', + } + } + + if ($DEBUG) { + warn "change_discount() \% opt before insert \n"; + warn Dumper \%opt; + warn "\@to_be_disabled \n"; + warn Dumper \@to_be_disabled; + } + + # Roll these updates into a transaction + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + my $error; + + # The "waive setup fee" flag has traditionally been handled by setting + # $cust_pkg->waive_setup = Y. This has been appropriately, and separately + # handled, and it operates on a different table than cust_pkg_discount, + # so the "-2 for waive setup fee" option is not being reimplemented + # here. Perhaps this may change later. + + # Create new discounts + for my $insert_discount (@discount_insert) { + + # Set parameters for insert_discount into object, and insert + for my $k (keys %{$insert_discount}) { + $self->set($k, $insert_discount->{$k}); + } + $error ||= $self->insert_discount(); + } + + # Disabling old discounts + for my $tbd (@to_be_disabled) { + unless ($error) { + $tbd->set(disabled => 'Y'); + $error = $tbd->replace(); + } + } + + if ($error) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + $dbh->commit if $oldAutoCommit; + return undef; +} + =item set_usage USAGE_VALUE_HASHREF USAGE_VALUE_HASHREF is a hashref of svc_acct usage columns and the amounts @@ -6328,4 +6481,3 @@ L, schema.html from the base documentation =cut 1; - diff --git a/httemplate/edit/process/change-cust_pkg.html b/httemplate/edit/process/change-cust_pkg.html index e1b220e51..0b36e9053 100644 --- a/httemplate/edit/process/change-cust_pkg.html +++ b/httemplate/edit/process/change-cust_pkg.html @@ -40,6 +40,12 @@ if ( $cgi->param('locationnum') == -1 ) { $change{'cust_location'} = $cust_location; } +my %discount = (discountnum => $cgi->param('discountnum')); +if (%discount) { + $discount{$_} = $cgi->param("discountnum_$_") + for qw(_type amount months percent setup); +} + my $error; my $now = time; if (defined($cgi->param('contract_end'))) { @@ -56,6 +62,7 @@ unless ($error) { } else { # schedule the change $change{'start_date'} = $date; + $change{discount} = \%discount if %discount; $error = $cust_pkg->change_later(\%change); } } else { @@ -74,9 +81,11 @@ unless ($error) { %change = ( 'cust_pkg' => $change_to ); } } - + # do a package change right now my $pkg_or_error = $cust_pkg->change( \%change ); + $pkg_or_error->change_discount(\%discount) + if ref $pkg_or_error && $discount{discountnum} =~ /$-?\d+$/; $error = ref($pkg_or_error) ? '' : $pkg_or_error; } } diff --git a/httemplate/elements/select-discount.html b/httemplate/elements/select-discount.html index 3a267ed08..4bbdc661a 100644 --- a/httemplate/elements/select-discount.html +++ b/httemplate/elements/select-discount.html @@ -6,6 +6,7 @@ 'empty_label' => '(none)', 'hashref' => $hashref, 'post_options' => $post_options, + 'label_callback' => $label_callback, %opt, ) %> @@ -22,9 +23,42 @@ my $curuser = $FS::CurrentUser::CurrentUser; my $hashref = $opt{hashref} || { 'disabled' => '' }; my $post_options = []; + +# If a 'custom' discount is applied to existing cust_pkg, +# also add that option to the selectbox +my $pkgnum = $cgi ? $cgi->param('pkgnum') : undef; +if ($pkgnum) { + + # Does pkgnum have a custom discount? + my $cust_pkg_discount = qsearchs(cust_pkg_discount => { + disabled => '', + pkgnum => $pkgnum, + }); + + if ($cust_pkg_discount) { + my $discount = qsearchs(discount => { + discountnum => $cust_pkg_discount->discountnum, + disabled => 'Y', + }); + if ($discount) { + my $descr = $opt{carry_value} eq $discount->discountnum + ? $discount->description.' [Continue existing discount]' + : $discount->description; + push @$post_options, $discount->discountnum, $descr; + } + } +} + push @$post_options, -1 => 'Custom discount' if $curuser->access_right('Custom discount customer package') && ! $opt{disable_custom_discount}; - +my $label_callback = sub { + my $rec = shift; + if ( $opt{carry_value} eq $rec->discountnum ) { + return $rec->description.' [Continue existing discount]'; + } + return $rec->description; +}; + diff --git a/httemplate/misc/change_pkg.cgi b/httemplate/misc/change_pkg.cgi index 94f32e699..f5b807566 100755 --- a/httemplate/misc/change_pkg.cgi +++ b/httemplate/misc/change_pkg.cgi @@ -1,5 +1,17 @@ <& /elements/header-popup.html, mt($title) &> + + <& /elements/error.html &> @@ -86,6 +98,16 @@ % } +% if ( $discount_cust_pkg ) { +<% include('/elements/tr-select-discount.html', + 'empty_label' => 'Select discount', + #'onchange' => 'enable_discount_pkg()', + 'cgi' => $cgi, + 'carry_value' => $carry_value, + 'td_width' => '125', + #'setup_only' => $setup_only, + ) %> +% }
% } @@ -151,6 +173,16 @@ my $title = "Change Package"; my $use_contract_end = $cust_pkg->get('contract_end') ? 1 : 0; +# Pass previous discountnum to change screen +my $cust_pkg_discount = qsearchs(cust_pkg_discount => { + disabled => '', + pkgnum => $cust_pkg->pkgnum, +}); +my $carry_value = + $cust_pkg_discount + ? $cust_pkg_discount->discountnum + : undef; + # if there's already a package change ordered, preload it if ( $cust_pkg->change_to_pkgnum ) { my $change_to = FS::cust_pkg->by_key($cust_pkg->change_to_pkgnum); -- 2.11.0