[freeside-commits] branch master updated. f92a083465019a7224d912cd78b6881f8aef1b52

Ivan ivan at 420.am
Sun Jan 18 19:43:57 PST 2015


The branch, master has been updated
       via  f92a083465019a7224d912cd78b6881f8aef1b52 (commit)
      from  03c12b4dabfcaabc218f39ee13557edebc13931d (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit f92a083465019a7224d912cd78b6881f8aef1b52
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Sun Jan 18 19:43:48 2015 -0800

    one-time charges on quotations, RT#25561

diff --git a/FS/FS/quotation.pm b/FS/FS/quotation.pm
index 44b72f4..75a592d 100644
--- a/FS/FS/quotation.pm
+++ b/FS/FS/quotation.pm
@@ -7,8 +7,11 @@ use Tie::RefHash;
 use FS::CurrentUser;
 use FS::UID qw( dbh );
 use FS::Maketext qw( emt );
+use FS::Record qw( qsearchs );
 use FS::cust_main;
 use FS::cust_pkg;
+use FS::quotation_pkg;
+use FS::type_pkgs;
 
 =head1 NAME
 
@@ -351,6 +354,133 @@ sub order {
 
 }
 
+=item charge
+
+One-time charges, like FS::cust_main::charge()
+
+=cut
+
+#super false laziness w/cust_main::charge
+sub charge {
+  my $self = shift;
+  my ( $amount, $setup_cost, $quantity, $start_date, $classnum );
+  my ( $pkg, $comment, $additional );
+  my ( $setuptax, $taxclass );   #internal taxes
+  my ( $taxproduct, $override ); #vendor (CCH) taxes
+  my $no_auto = '';
+  my $cust_pkg_ref = '';
+  my ( $bill_now, $invoice_terms ) = ( 0, '' );
+  my $locationnum;
+  if ( ref( $_[0] ) ) {
+    $amount     = $_[0]->{amount};
+    $setup_cost = $_[0]->{setup_cost};
+    $quantity   = exists($_[0]->{quantity}) ? $_[0]->{quantity} : 1;
+    $start_date = exists($_[0]->{start_date}) ? $_[0]->{start_date} : '';
+    $no_auto    = exists($_[0]->{no_auto}) ? $_[0]->{no_auto} : '';
+    $pkg        = exists($_[0]->{pkg}) ? $_[0]->{pkg} : 'One-time charge';
+    $comment    = exists($_[0]->{comment}) ? $_[0]->{comment}
+                                           : '$'. sprintf("%.2f",$amount);
+    $setuptax   = exists($_[0]->{setuptax}) ? $_[0]->{setuptax} : '';
+    $taxclass   = exists($_[0]->{taxclass}) ? $_[0]->{taxclass} : '';
+    $classnum   = exists($_[0]->{classnum}) ? $_[0]->{classnum} : '';
+    $additional = $_[0]->{additional} || [];
+    $taxproduct = $_[0]->{taxproductnum};
+    $override   = { '' => $_[0]->{tax_override} };
+    $cust_pkg_ref = exists($_[0]->{cust_pkg_ref}) ? $_[0]->{cust_pkg_ref} : '';
+    $bill_now = exists($_[0]->{bill_now}) ? $_[0]->{bill_now} : '';
+    $invoice_terms = exists($_[0]->{invoice_terms}) ? $_[0]->{invoice_terms} : '';
+    $locationnum = $_[0]->{locationnum} || $self->ship_locationnum;
+  } else {
+    $amount     = shift;
+    $setup_cost = '';
+    $quantity   = 1;
+    $start_date = '';
+    $pkg        = @_ ? shift : 'One-time charge';
+    $comment    = @_ ? shift : '$'. sprintf("%.2f",$amount);
+    $setuptax   = '';
+    $taxclass   = @_ ? shift : '';
+    $additional = [];
+  }
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  my $part_pkg = new FS::part_pkg ( {
+    'pkg'           => $pkg,
+    'comment'       => $comment,
+    'plan'          => 'flat',
+    'freq'          => 0,
+    'disabled'      => 'Y',
+    'classnum'      => ( $classnum ? $classnum : '' ),
+    'setuptax'      => $setuptax,
+    'taxclass'      => $taxclass,
+    'taxproductnum' => $taxproduct,
+    'setup_cost'    => $setup_cost,
+  } );
+
+  my %options = ( ( map { ("additional_info$_" => $additional->[$_] ) }
+                        ( 0 .. @$additional - 1 )
+                  ),
+                  'additional_count' => scalar(@$additional),
+                  'setup_fee' => $amount,
+                );
+
+  my $error = $part_pkg->insert( options       => \%options,
+                                 tax_overrides => $override,
+                               );
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  my $pkgpart = $part_pkg->pkgpart;
+
+  #DIFF
+  my %type_pkgs = ( 'typenum' => $self->cust_or_prospect->agent->typenum, 'pkgpart' => $pkgpart );
+
+  unless ( qsearchs('type_pkgs', \%type_pkgs ) ) {
+    my $type_pkgs = new FS::type_pkgs \%type_pkgs;
+    $error = $type_pkgs->insert;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
+  #except for DIFF, eveything above is idential to cust_main version
+  #but below is our own thing pretty much (adding a quotation package instead
+  # of ordering a customer package, no "bill now")
+
+  my $quotation_pkg = new FS::quotation_pkg ( {
+    'quotationnum'  => $self->quotationnum,
+    'pkgpart'       => $pkgpart,
+    'quantity'      => $quantity,
+    #'start_date' => $start_date,
+    #'no_auto'    => $no_auto,
+    'locationnum'=> $locationnum,
+  } );
+
+  $error = $quotation_pkg->insert;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  #} elsif ( $cust_pkg_ref ) {
+  #  ${$cust_pkg_ref} = $cust_pkg;
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+  return '';
+
+}
+
 =item disable
 
 Disables this quotation (sets disabled to Y, which hides the quotation on
diff --git a/httemplate/edit/process/quick-charge.cgi b/httemplate/edit/process/quick-charge.cgi
index 6de746e..c130a55 100644
--- a/httemplate/edit/process/quick-charge.cgi
+++ b/httemplate/edit/process/quick-charge.cgi
@@ -24,15 +24,20 @@ for ( my $row = 0; exists($param->{"description$row"}); $row++ ) {
     if ($param->{"description$row"} =~ /\S/);
 }
 
-$param->{"custnum"} =~ /^(\d+)$/
-  or $error .= "Illegal customer number " . $param->{"custnum"} . "  ";
-my $custnum = $1;
-
-my $cust_main = FS::cust_main->by_key($custnum)
-  or die "custnum $custnum not found";
-
-exists($curuser->agentnums_href->{$cust_main->agentnum})
-  or die "access denied";
+my( $cust_main, $prospect_main, $quotation ) = ( '', '', '' );
+if ( $cgi->param('quotationnum') =~ /^(\d+)$/ ) {
+  $quotation = FS::quotation->by_key($1) or die "quotationnum $1 not found";
+}
+if ( $param->{"custnum"} =~ /^(\d+)$/ ) {
+  $cust_main = FS::cust_main->by_key($1) or die "custnum $1 not found";
+  exists($curuser->agentnums_href->{$cust_main->agentnum})
+    or die "access denied";
+}
+if ( $param->{"prospectnum"} =~ /^(\d+)$/ ) {
+  $prospect_main = FS::prospect_main->by_key($1) or die "prospectnum $1 not found";
+  exists($curuser->agentnums_href->{$prospect_main->agentnum})
+    or die "access denied";
+}
 
 my $message;
 
@@ -106,30 +111,32 @@ if ( $param->{'pkgnum'} =~ /^(\d+)$/ ) { #modifying an existing one-time charge
     $cgi->param('taxclass', '');
   }
 
-  unless ( $error ) {
-    my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
-      or $error .= "Unknown customer number $custnum.  ";
-
-    $error ||= $cust_main->charge( {
-      'amount'        => $amount,
-      'setup_cost'    => $setup_cost,
-      'quantity'      => $quantity,
-      'bill_now'      => scalar($cgi->param('bill_now')),
-      'invoice_terms' => scalar($cgi->param('invoice_terms')),
-      'start_date'    => ( scalar($cgi->param('start_date'))
-                             ? parse_datetime($cgi->param('start_date'))
-                             : ''
-                         ),
-      'no_auto'       => scalar($cgi->param('no_auto')),
-      'pkg'           => scalar($cgi->param('pkg')),
-      'setuptax'      => scalar($cgi->param('setuptax')),
-      'taxclass'      => scalar($cgi->param('taxclass')),
-      'taxproductnum' => scalar($cgi->param('taxproductnum')),
-      'tax_override'  => $override,
-      'classnum'      => scalar($cgi->param('classnum')),
-      'additional'    => \@description,
-    } );
+  my %charge = (
+    'amount'        => $amount,
+    'setup_cost'    => $setup_cost,
+    'quantity'      => $quantity,
+    'bill_now'      => scalar($cgi->param('bill_now')),
+    'invoice_terms' => scalar($cgi->param('invoice_terms')),
+    'start_date'    => ( scalar($cgi->param('start_date'))
+                           ? parse_datetime($cgi->param('start_date'))
+                           : ''
+                       ),
+    'no_auto'       => scalar($cgi->param('no_auto')),
+    'pkg'           => scalar($cgi->param('pkg')),
+    'setuptax'      => scalar($cgi->param('setuptax')),
+    'taxclass'      => scalar($cgi->param('taxclass')),
+    'taxproductnum' => scalar($cgi->param('taxproductnum')),
+    'tax_override'  => $override,
+    'classnum'      => scalar($cgi->param('classnum')),
+    'additional'    => \@description,
+  );
+
+  if ( $quotation ) {
+    $error ||= $quotation->charge( \%charge );
+  } else {
+    $error ||= $cust_main->charge( \%charge );
   }
+
 }
 
 </%init>
diff --git a/httemplate/edit/quick-charge.html b/httemplate/edit/quick-charge.html
index ec1a580..dfaf404 100644
--- a/httemplate/edit/quick-charge.html
+++ b/httemplate/edit/quick-charge.html
@@ -100,7 +100,9 @@ function bill_now_changed (what) {
       onSubmit = "document.QuickChargeForm.submit.disabled=true; return validate_quick_charge();"
 >
 
-<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
+<INPUT TYPE="hidden" NAME="custnum"     VALUE="<% $cust_main ? $cust_main->custnum : '' %>">
+<INPUT TYPE="hidden" NAME="prospectnum" VALUE="<% $prospect_main ? $prospect_main->prospectnum : '' %>">
+<INPUT TYPE="hidden" NAME="quotationnum" VALUE="<% $quotationnum %>">
 
 <TABLE ID="QuickChargeTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 STYLE="background-color: #cccccc">
 
@@ -209,63 +211,67 @@ function bill_now_changed (what) {
 
 <& /elements/tr-select-pkg_class.html, 'curr_value' => $classnum  &>
 
-<TR>
-  <TD ALIGN="right"><% mt('Invoice now') |h %></TD>
-  <TD>
-    <INPUT TYPE  = "checkbox"
-           NAME  = "bill_now"
-           VALUE = "1"
-           <% $cgi->param('bill_now') ? 'CHECKED' : '' %>
-           onClick  = "bill_now_changed(this);"
-           onChange = "bill_now_changed(this);"
-    >
-    <% mt('with terms') |h %> 
-    <& /elements/select-terms.html,
-         'curr_value' => scalar($cgi->param('invoice_terms')),
-         'disabled'   => ( $cgi->param('bill_now') ? 0 : 1 ),
-         'agentnum'   => $cust_main->agentnum,
-    &>
-  </TD>
-</TR>
+% unless ( $quotationnum ) {
 
-%# false laziness w/misc/order_pkg.html
-<TR>
-  <TD ALIGN="right"><% mt('Charge date') |h %> </TD>
-  <TD>
-    <INPUT TYPE  = "text"
-           NAME  = "start_date"
-           SIZE  = 32
-           ID    = "start_date_text"
-           VALUE = "<% $start_date %>"
-           onKeyPress="return enable_quick_charge(event)"
-           <% $cgi->param('bill_now')
-                ? 'STYLE = "background-color:#dddddd" DISABLED'
-                : ''
-           %>
-    >
-    <IMG SRC   = "<%$fsurl%>images/calendar.png"
-         ID    = "start_date_button"
-         TITLE = "<% mt('Select date') |h %>"
-         STYLE = "cursor:pointer<% $cgi->param('bill_now') ? ';display:none' : '' %>"
-    >
-    <IMG SRC   = "<%$fsurl%>images/calendar-disabled.png"
-         ID    = "start_date_button_disabled"
-         <% $cgi->param('bill_now') ? '' : 'STYLE="display:none"' %>
-    >
-    <FONT SIZE=-1>(<% mt('leave blank to charge immediately') |h %>)</FONT>
-  </TD>
-</TR>
+    <TR>
+      <TD ALIGN="right"><% mt('Invoice now') |h %></TD>
+      <TD>
+        <INPUT TYPE  = "checkbox"
+               NAME  = "bill_now"
+               VALUE = "1"
+               <% $cgi->param('bill_now') ? 'CHECKED' : '' %>
+               onClick  = "bill_now_changed(this);"
+               onChange = "bill_now_changed(this);"
+        >
+        <% mt('with terms') |h %> 
+        <& /elements/select-terms.html,
+             'curr_value' => scalar($cgi->param('invoice_terms')),
+             'disabled'   => ( $cgi->param('bill_now') ? 0 : 1 ),
+             'agentnum'   => $cust_or_prospect->agentnum,
+        &>
+      </TD>
+    </TR>
 
-<SCRIPT TYPE="text/javascript">
-  Calendar.setup({
-    inputField: "start_date_text",
-    ifFormat:   "<% $date_format %>",
-    button:     "start_date_button",
-    align:      "BR"
-  });
-</SCRIPT>
+%   # false laziness w/misc/order_pkg.html
+    <TR>
+      <TD ALIGN="right"><% mt('Charge date') |h %> </TD>
+      <TD>
+        <INPUT TYPE  = "text"
+               NAME  = "start_date"
+               SIZE  = 32
+               ID    = "start_date_text"
+               VALUE = "<% $start_date %>"
+               onKeyPress="return enable_quick_charge(event)"
+               <% $cgi->param('bill_now')
+                    ? 'STYLE = "background-color:#dddddd" DISABLED'
+                    : ''
+               %>
+        >
+        <IMG SRC   = "<%$fsurl%>images/calendar.png"
+             ID    = "start_date_button"
+             TITLE = "<% mt('Select date') |h %>"
+             STYLE = "cursor:pointer<% $cgi->param('bill_now') ? ';display:none' : '' %>"
+        >
+        <IMG SRC   = "<%$fsurl%>images/calendar-disabled.png"
+             ID    = "start_date_button_disabled"
+             <% $cgi->param('bill_now') ? '' : 'STYLE="display:none"' %>
+        >
+        <FONT SIZE=-1>(<% mt('leave blank to charge immediately') |h %>)</FONT>
+      </TD>
+    </TR>
+
+    <SCRIPT TYPE="text/javascript">
+      Calendar.setup({
+        inputField: "start_date_text",
+        ifFormat:   "<% $date_format %>",
+        button:     "start_date_button",
+        align:      "BR"
+      });
+    </SCRIPT>
 
-% if ( $cust_main->payby =~ /^(CARD|CHEK)$/ ) {
+% }
+
+% if ( ! $quotationnum && $cust_main->payby =~ /^(CARD|CHEK)$/ ) {
 %   my $what = lc(FS::payby->shortname($cust_main->payby));
     <TR>
       <TD ALIGN="right"><% mt("Disable automatic $what charge") |h %> </TD>
@@ -409,7 +415,7 @@ my $conf = new FS::Conf;
 my $date_format = $conf->config('date_format') || '%m/%d/%Y';
 my $money_char = $conf->config('money_char') || '$';
 
-my ($cust_main, $cust_pkg);
+my( $cust_main, $cust_pkg, $prospect_main, $quotationnum ) = ( '', '', '', '' );
 if ( $cgi->param('change_pkgnum') ) {
   # change an existing one-time charge
   die "access denied"
@@ -419,18 +425,37 @@ if ( $cgi->param('change_pkgnum') ) {
   $cust_pkg = FS::cust_pkg->by_key($1) or die "pkgnum $1 not found";
   $cust_main = $cust_pkg->cust_main;
 } else {
-  $cgi->param('custnum') =~ /^(\d+)$/ or die 'illegal custnum';
-  $cust_main = FS::cust_main->by_key($1) or die "custnum $1 not found";
+  if ( $cgi->param('quotationnum') =~ /^(\d+)$/ ) {
+    $quotationnum = $1;
+  }
+  if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+    $cust_main = FS::cust_main->by_key($1) or die "custnum $1 not found";
+  }
+  if ( $cgi->param('prospectnum') =~ /^(\d+)$/ ) {
+    $prospect_main = FS::prospect_main->by_key($1) or die "prospectnum $1 not found";
+  }
+  die "custnum or prospectnum must be specified"
+    unless $cust_main || $prospect_main;
 }
 
-my $custnum = $cust_main->custnum;
-# agent-virt
-if (!exists($curuser->agentnums_href->{$cust_main->agentnum})) {
-  die "custnum $custnum not found";
+my $cust_or_prospect = $cust_main || $prospect_main;
+
+if ( $cust_main ) {
+  my $custnum = $cust_main->custnum;
+  # agent-virt
+  if (!exists($curuser->agentnums_href->{$cust_main->agentnum})) {
+    die "custnum $custnum not found";
+  }
+} elsif ( $prospect_main ) {
+  my $prospectnum = $prospect_main->prospectnum;
+  # agent-virt
+  if (!exists($curuser->agentnums_href->{$prospect_main->agentnum})) {
+    die "prospectnum $prospectnum not found";
+  }
 }
 
 my $format = "%m/%d/%Y %T %z (%Z)"; #false laziness w/REAL_cust_pkg.cgi?
-my $start_date = $cust_main->next_bill_date;
+my $start_date = $cust_main ? $cust_main->next_bill_date : '';
 $start_date = $start_date ? time2str($format, $start_date) : '';
 
 my $amount = '';
@@ -453,12 +478,12 @@ $cgi->param('pkg') =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]]*)$/
 my $pkg = $1;
 
 my $default_terms;
-if ( $cust_main->invoice_terms ) {
+if ( $cust_main && $cust_main->invoice_terms ) {
   $default_terms = emt("Customer default ([_1])", $cust_main->invoice_terms);
 } else {
   $default_terms =
     emt( "Default ([_1])",
-         ( $conf->config('invoice_default_terms', $cust_main->agentnum)
+         ( $conf->config('invoice_default_terms', $cust_or_prospect->agentnum)
              || emt('Payable upon receipt')
          )
        );
diff --git a/httemplate/view/cust_main/one_time_charge_link.html b/httemplate/elements/one_time_charge_link.html
similarity index 84%
rename from httemplate/view/cust_main/one_time_charge_link.html
rename to httemplate/elements/one_time_charge_link.html
index 1efd2d0..4ef5ede 100644
--- a/httemplate/view/cust_main/one_time_charge_link.html
+++ b/httemplate/elements/one_time_charge_link.html
@@ -1,3 +1,16 @@
+<%doc>
+
+Example:
+
+  <& /elements/one_time_charge_link.html,
+
+     #one of these is required
+     'custnum'     => $custnum,
+     'prospectnum' => $prospectnum,
+
+  &>
+
+</%doc>
 <SCRIPT TYPE="text/javascript">
 
 function taxproductmagic(which) {
@@ -72,10 +85,16 @@ function taxoverridequickchargemagic() {
 
 </SCRIPT>
 
-<FORM NAME='quickcharge' STYLE="margin:0; padding:0; display:inline"><INPUT NAME="taxproductnum"  ID="taxproductnum"  TYPE="hidden"><INPUT NAME="tax_override"   ID="tax_override"   TYPE="hidden"><INPUT NAME="charge_storage" ID="charge_storage" TYPE="hidden"><INPUT NAME="taxproductnum_description" ID="taxproductnum_description" TYPE="hidden"></FORM>
+<FORM NAME='quickcharge' STYLE="margin:0; padding:0; display:inline">
+% for (qw(
+%   taxproductnum tax_override charge_storage taxproductnum_description
+% )) {
+    <INPUT NAME="<% $_ %>" ID="<% $_ %>" TYPE="hidden">
+% }
+</FORM>
 
 <% include('/elements/popup_link.html', { 
-     'action'      => $p.'edit/quick-charge.html?custnum='. $cust_main->custnum,
+     'action'      => $p. 'edit/quick-charge.html?'. $query,
      'label'       => emt('One-time charge'),
      'actionlabel' => emt('One-time charge'),
      'color'       => '#333399',
@@ -86,6 +105,10 @@ function taxoverridequickchargemagic() {
 
 <%init>
 
-my($cust_main) = @_;
+my %opt = @_;
+
+my $query = $opt{custnum} ? 'custnum='.$opt{custnum}
+                          : 'prospectnum='.$opt{prospectnum};
+$query .= ';quotationnum='.$opt{quotationnum} if $opt{quotationnum};
 
 </%init>
diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html
index 228b04e..9a2332b 100755
--- a/httemplate/view/cust_main/packages.html
+++ b/httemplate/view/cust_main/packages.html
@@ -96,7 +96,7 @@ if ( el ) el.scrollIntoView(true);
 %        && $conf->config('payby-default') ne 'HIDE'
 %      ) {
   <% $s++ ? ' | ' : '' %>
-  <& one_time_charge_link.html, $cust_main &>
+  <& /elements/one_time_charge_link.html, 'custnum'=>$cust_main->custnum &>
 % } 
 
 % if ( $curuser->access_right('Bulk move customer services') ) { 
diff --git a/httemplate/view/quotation.html b/httemplate/view/quotation.html
index 81c7cdd..bd998bb 100755
--- a/httemplate/view/quotation.html
+++ b/httemplate/view/quotation.html
@@ -17,9 +17,15 @@ function areyousure(href, message) {
            'actionlabel' => emt('Add package'),
            map { $_ => $quotation->$_ } qw( quotationnum custnum prospectnum )
       &>
-      <BR><BR>
 %   }
 
+%   if ( $curuser->access_right('One-time charge') ) {
+      | <& /elements/one_time_charge_link.html,
+             map { $_ => $quotation->$_ } qw( quotationnum custnum prospectnum )
+        &>
+%   }
+      <BR><BR>
+
 %   if ( 1 ) { #if ( $curuser->access_right('Send quotations') )
 
       <& /elements/popup_link.html,

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/quotation.pm                                 |  130 ++++++++++++++++
 httemplate/edit/process/quick-charge.cgi           |   71 +++++----
 httemplate/edit/quick-charge.html                  |  155 ++++++++++++--------
 .../one_time_charge_link.html                      |   29 +++-
 httemplate/view/cust_main/packages.html            |    2 +-
 httemplate/view/quotation.html                     |    8 +-
 6 files changed, 293 insertions(+), 102 deletions(-)
 rename httemplate/{view/cust_main => elements}/one_time_charge_link.html (84%)




More information about the freeside-commits mailing list