summaryrefslogtreecommitdiff
path: root/httemplate
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2012-12-09 10:30:54 -0800
committerIvan Kohler <ivan@freeside.biz>2012-12-09 10:30:54 -0800
commit93e3a52f23c3473207f29f36cda06adfe221353f (patch)
tree350bda2d2d5906f1f2d8756e30a59fc61bf786b5 /httemplate
parentb62f98268b17471c7b195d7d193b33c4a6915892 (diff)
create credits by selecting line items, RT#18676
Diffstat (limited to 'httemplate')
-rw-r--r--httemplate/edit/credit-cust_bill_pkg.html249
-rwxr-xr-xhttemplate/edit/cust_credit.cgi1
-rw-r--r--httemplate/edit/process/credit-cust_bill_pkg.html41
-rwxr-xr-xhttemplate/edit/process/cust_credit.cgi4
-rw-r--r--httemplate/misc/xmlhttp-cust_bill_pkg-calculate_taxes.html123
-rw-r--r--httemplate/view/cust_main/payment_history.html10
6 files changed, 426 insertions, 2 deletions
diff --git a/httemplate/edit/credit-cust_bill_pkg.html b/httemplate/edit/credit-cust_bill_pkg.html
new file mode 100644
index 000000000..e317936b3
--- /dev/null
+++ b/httemplate/edit/credit-cust_bill_pkg.html
@@ -0,0 +1,249 @@
+<& /elements/header-popup.html, 'Credit line items' &>
+
+<FORM ACTION="process/credit-cust_bill_pkg.html" METHOD="POST">
+<INPUT TYPE="hidden" NAME="crednum" VALUE="">
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum |h %>">
+<INPUT TYPE="hidden" NAME="paybatch" VALUE="">
+<INPUT TYPE="hidden" NAME="_date" VALUE="<% time %>">
+<table>
+
+% my $old_invnum = 0;
+%# foreach my $cust_bill_pkg ( @cust_bill_pkg ) {
+% foreach my $item ( @items ) {
+% my( $setuprecur, $cust_bill_pkg ) = @$item;
+
+% my $method = $setuprecur eq 'setup' ? 'setup' : 'recur';
+% my $amount = $cust_bill_pkg->$method();
+% my $credited = $cust_bill_pkg->credited('', '', 'setuprecur'=>$method);
+% $amount -= $credited;
+% $amount = sprintf('%.2f', $amount);
+% next unless $amount > 0;
+
+% if ( $cust_bill_pkg->invnum ne $old_invnum ) {
+ <TR><TD COLSPAN=3 BGCOLOR="#f8f8f8">&nbsp;</TD></TR>
+ <TR><TH COLSPAN=3 BGCOLOR="#f8f8f8" ALIGN="left">Invoice #<% $cust_bill_pkg->invnum %> - <% time2str($date_format, $cust_bill_pkg->cust_bill->_date) %></TD></TR>
+% $old_invnum = $cust_bill_pkg->invnum;
+% }
+
+ <TR>
+ <TD>
+ <INPUT TYPE = "checkbox"
+ NAME = "billpkgnum<% $cust_bill_pkg->billpkgnum.'-'. $setuprecur %>"
+ VALUE = "<% $amount %>"
+ onClick = "calc_total(this)"
+ data-amount = "<% $amount %>"
+ data-billpkgnum = "<% $cust_bill_pkg->billpkgnum %>"
+ data-setuprecur = "<% $setuprecur %>"
+ >
+ </TD>
+ <TD BGCOLOR="#ffffff"><% $cust_bill_pkg->desc |h %></TD>
+%# show one-time/setup vs recur vs usage?
+ <TD BGCOLOR="#ffffff" ALIGN="right"><% $money_char. $amount %></TD>
+ </TR>
+
+% }
+
+<TR><TD COLSPAN=3 BGCOLOR="#f8f8f8">&nbsp;</TD></TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="right">Subtotal: </TD>
+ <TD ALIGN="right" ID="subtotal_td"><% $money_char %><% sprintf('%.2f', 0) %></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="right">Taxes: </TD>
+ <TD ALIGN="right" ID="taxtotal_td"><% $money_char %><% sprintf('%.2f', 0) %></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TH ALIGN="right">Total credit amount: </TD>
+ <TH ALIGN="right" ID="total_td"><% $money_char %><% sprintf('%.2f', 0) %></TD>
+</TR>
+<INPUT TYPE="hidden" NAME="amount" ID="total_el" VALUE="0.00">
+
+</table>
+
+<table>
+
+<& /elements/tr-select-reason.html,
+ 'field' => 'reasonnum',
+ 'reason_class' => 'R',
+ #XXX reconcile both this and show_taxes wanteding to enable this
+ 'control_button' => "document.getElementById('credit_button')",
+ 'cgi' => $cgi,
+&>
+
+<TR>
+ <TD ALIGN="right"><% mt('Additional info') |h %></TD>
+ <TD>
+ <INPUT TYPE="text" NAME="addlinfo" VALUE="<% $cgi->param('addlinfo') |h %>">
+ </TD>
+</TR>
+
+</table>
+
+<BR>
+<INPUT TYPE="submit" ID="credit_button" VALUE="Credit" DISABLED>
+
+</FORM>
+
+<% include( '/elements/xmlhttp.html',
+ 'url' => $p.'misc/xmlhttp-cust_bill_pkg-calculate_taxes.html',
+ 'subs' => [ 'calculate_taxes' ],
+ )
+%>
+<SCRIPT TYPE="text/javascript">
+
+function show_taxes(arg) {
+ var argsHash = eval('(' + arg + ')');
+
+ //XXX add an 'ErrorMessage' section to the HTML and re-enable
+ //var error = argsHash['error'];
+
+ //var paragraph = document.getElementById('ErrorMessage');
+ //if (error) {
+ // paragraph.innerHTML = 'Error: ' + error;
+ // paragraph.style.color = '#ff0000';
+ //} else {
+ // paragraph.innerHTML = '';
+ //}
+
+ var taxlines = argsHash['taxlines'];
+
+//XXX display the tax lines? just a total will do for now
+//
+// var table = document.getElementById('ApplicationTable');
+//
+// var aFoundRow = 0;
+// for (i = 0; taxlines[i]; i++) {
+// var itemdesc = taxlines[i][0];
+// var locnum = taxlines[i][2];
+// if (taxlines[i][3]) {
+// locnum = taxlines[i][3];
+// }
+//
+// var found = 0;
+// for (var row = 2; table.rows[row]; row++) {
+// var inputs = table.rows[row].getElementsByTagName('input');
+// if (! inputs.length) {
+// while ( table.rows[row] ) {
+// table.deleteRow(row);
+// }
+// break;
+// }
+// if ( inputs.item(4).value == itemdesc && inputs.item(2).value == locnum )
+// {
+// inputs.item(0).value = taxlines[i][1];
+// aFoundRow = found = row;
+// break;
+// }
+// }
+// if (! found) {
+// var row = table.insertRow(table.rows.length);
+// var warning_cell = document.createElement('TD');
+// warning_cell.style.color = '#ff0000';
+// warning_cell.colSpan = 2;
+// warning_cell.innerHTML = 'Calculated Tax - ' + itemdesc + ' - ' +
+// taxlines[i][1] + ' will not be applied';
+// row.appendChild(warning_cell);
+// }
+// }
+//
+// if (aFoundRow) {
+// sub_changed(table.rows[aFoundRow].getElementsByTagName('input').item(0));
+// }
+
+ var subtotal = parseFloat( argsHash['subtotal'] );
+
+ var taxtotal = parseFloat( argsHash['taxtotal'] );
+ document.getElementById('taxtotal_td').innerHTML =
+ '<% $money_char %>' + taxtotal.toFixed(2);
+
+ var total = subtotal + taxtotal;
+ document.getElementById('total_td').innerHTML =
+ '<% $money_char %>' + total.toFixed(2);
+ document.getElementById('total_el').value = total.toFixed(2);
+
+ //XXX reconcile both this and the reason selector wanteding to enable this
+ if ( total > 0 ) {
+ document.getElementById('credit_button').disabled = false;
+ }
+
+}
+
+function calc_total(what) {
+
+ document.getElementById('credit_button').disabled = true;
+
+ var subtotal = 0;
+ // bah, a pain, just using an attribute var re = /^billpkgnum(\d+)$/;
+
+ var el = what.form.elements;
+ var billpkgnums = [];
+ var setuprecurs = [];
+ var amounts = [];
+ for (var i=0; i<el.length; i++) {
+ if ( el[i].type == 'checkbox' && el[i].checked ) {
+ subtotal += parseFloat( el[i].getAttribute('data-amount') );
+ amounts.push( el[i].getAttribute('data-amount') );
+ billpkgnums.push( el[i].getAttribute('data-billpkgnum') );
+ setuprecurs.push( el[i].getAttribute('data-setuprecur') );
+ }
+ }
+
+ document.getElementById('subtotal_td').innerHTML =
+ '<% $money_char %>' + subtotal.toFixed(2);
+
+ var args = new Array(
+ 'custnum', '<% $custnum %>',
+ 'subtotal', subtotal,
+ 'billpkgnums', billpkgnums.join(),
+ 'setuprecurs', setuprecurs.join(),
+ 'amounts', amounts.join()
+ );
+
+ calculate_taxes( args, show_taxes );
+
+}
+</SCRIPT>
+
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied" unless $curuser->access_right('Post credit');
+
+#a tiny bit of false laziness w/search/cust_bill_pkg.cgi, but we're pretty
+# specialized and a piece of UI, not a report
+#slightly more false laziness w/httemplate/edit/elements/ApplicationCommon.html
+# show_taxes & calc_total here/do_calculate_tax there
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+my $date_format = $conf->config('date_format') || '%m/%d/%Y';
+
+$cgi->param('custnum') =~ /^(\d+)$/ or die 'illegal custnum';
+my $custnum = $1;
+
+my $cust_main = qsearchs({
+ 'table' => 'cust_main',
+ 'hashref' => { 'custnum' => $custnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+}) or die 'unknown customer';
+
+my @cust_bill_pkg = qsearch({
+ 'select' => 'cust_bill_pkg.*',
+ 'table' => 'cust_bill_pkg',
+ 'addl_from' => 'LEFT JOIN cust_bill USING (invnum)',
+ 'extra_sql' => "WHERE custnum = $custnum AND pkgnum != 0",
+ 'order_by' => 'ORDER BY invnum ASC, billpkgnum ASC',
+});
+
+my @items = map { my %hash = $_->disintegrate;
+ map [ $_, $hash{$_} ],
+ keys(%hash);
+ }
+ @cust_bill_pkg;
+
+#omit line items which have been previously credited? would be nice
+
+</%init>
diff --git a/httemplate/edit/cust_credit.cgi b/httemplate/edit/cust_credit.cgi
index 6e8a9c989..4dba1e769 100755
--- a/httemplate/edit/cust_credit.cgi
+++ b/httemplate/edit/cust_credit.cgi
@@ -34,6 +34,7 @@
<TD>
<INPUT TYPE="text" NAME="addlinfo" VALUE="<% $cgi->param('addlinfo') |h %>">
</TD>
+ </TR>
% if ( $conf->exists('credits-auto-apply-disable') ) {
<INPUT TYPE="HIDDEN" NAME="apply" VALUE="no">
diff --git a/httemplate/edit/process/credit-cust_bill_pkg.html b/httemplate/edit/process/credit-cust_bill_pkg.html
new file mode 100644
index 000000000..d3323e6ed
--- /dev/null
+++ b/httemplate/edit/process/credit-cust_bill_pkg.html
@@ -0,0 +1,41 @@
+%if ($error) {
+% errorpage_popup($error); #XXX redirect back for correction...
+%} else {
+<& /elements/header-popup.html, 'Credit successful' &>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY></HTML>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Post credit');
+
+my @billpkgnum_setuprecurs =
+ map { $_ =~ /^billpkgnum(\d+\-\w*)$/ or die 'gm#23'; $1; }
+ grep { $_ =~ /^billpkgnum\d+\-\w*$/ && $cgi->param($_) } $cgi->param;
+
+my @billpkgnums = ();
+my @setuprecurs = ();
+my @amounts = ();
+foreach my $billpkgnum_setuprecur (@billpkgnum_setuprecurs) {
+ my $amount = $cgi->param("billpkgnum$billpkgnum_setuprecur");
+ my( $billpkgnum, $setuprecur ) = split('-', $billpkgnum_setuprecur);
+ push @billpkgnums, $billpkgnum;
+ push @setuprecurs, $setuprecur;
+ push @amounts, $amount;
+}
+
+my $error = FS::cust_credit->credit_lineitems(
+ 'newreasonnum' => scalar($cgi->param('newreasonnum')),
+ 'newreasonnum_type' => scalar($cgi->param('newreasonnumT')),
+ 'billpkgnums' => \@billpkgnums,
+ 'setuprecurs' => \@setuprecurs,
+ 'amounts' => \@amounts,
+ map { $_ => scalar($cgi->param($_)) }
+ #fields('cust_credit')
+ qw( custnum _date amount reason reasonnum addlinfo ), #pkgnum eventnum
+);
+
+</%init>
diff --git a/httemplate/edit/process/cust_credit.cgi b/httemplate/edit/process/cust_credit.cgi
index 776112ac0..245f31af7 100755
--- a/httemplate/edit/process/cust_credit.cgi
+++ b/httemplate/edit/process/cust_credit.cgi
@@ -15,7 +15,7 @@
%
% $dbh->commit or die $dbh->errstr if $oldAutoCommit;
%
-<% header(emt('Credit sucessful')) %>
+<% header(emt('Credit successful')) %>
<SCRIPT TYPE="text/javascript">
window.top.location.reload();
</SCRIPT>
@@ -27,7 +27,7 @@
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Post credit');
-$cgi->param('custnum') =~ /^(\d*)$/ or die "Illegal custnum!";
+$cgi->param('custnum') =~ /^(\d+)$/ or die "Illegal custnum!";
my $custnum = $1;
$cgi->param('reasonnum') =~ /^(-?\d+)$/ or die "Illegal reasonnum";
diff --git a/httemplate/misc/xmlhttp-cust_bill_pkg-calculate_taxes.html b/httemplate/misc/xmlhttp-cust_bill_pkg-calculate_taxes.html
new file mode 100644
index 000000000..993504619
--- /dev/null
+++ b/httemplate/misc/xmlhttp-cust_bill_pkg-calculate_taxes.html
@@ -0,0 +1,123 @@
+<% to_json($return) %>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied" unless $curuser->access_right('Post credit');
+
+my $DEBUG = 0;
+
+my $conf = new FS::Conf;
+
+my $sub = $cgi->param('sub');
+
+my $return = {};
+
+if ( $sub eq 'calculate_taxes' ) {
+
+ {
+
+ my %arg = $cgi->param('arg');
+ $return = \%arg;
+ warn join('', map "$_: $arg{$_}\n", keys %arg )
+ if $DEBUG;
+
+ #some false laziness w/cust_credit::credit_lineitems
+
+ my $cust_main = qsearchs({
+ 'table' => 'cust_main',
+ 'hashref' => { 'custnum' => $arg{custnum} },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+ }) or die 'unknown customer';
+
+ my @billpkgnums = split(',', $arg{billpkgnums});
+ my @setuprecurs = split(',', $arg{setuprecurs});
+ my @amounts = split(',', $arg{amounts});
+
+ my @cust_bill_pkg = ();
+ my $taxlisthash = {};
+ while ( @billpkgnums ) {
+ my $billpkgnum = shift @billpkgnums;
+ my $setuprecur = shift @setuprecurs;
+ my $amount = shift @amounts;
+
+ my $cust_bill_pkg = qsearchs({
+ 'table' => 'cust_bill_pkg',
+ 'hashref' => { 'billpkgnum' => $billpkgnum },
+ 'addl_from' => 'LEFT JOIN cust_bill USING (invnum)',
+ 'extra_sql' => 'AND custnum = '. $cust_main->custnum,
+ }) or die "unknown billpkgnum $billpkgnum";
+
+ #shouldn't be passed# next if $cust_bill_pkg->pkgnum == 0;
+
+ if ( $setuprecur eq 'setup' ) {
+ $cust_bill_pkg->setup($amount);
+ $cust_bill_pkg->recur(0);
+ $cust_bill_pkg->unitrecur(0);
+ $cust_bill_pkg->type('');
+ } else {
+ $cust_bill_pkg->recur($amount);
+ $cust_bill_pkg->setup(0);
+ $cust_bill_pkg->unitsetup(0);
+ }
+
+ push @cust_bill_pkg, $cust_bill_pkg;
+
+ my $part_pkg = $cust_bill_pkg->part_pkg;
+ $cust_main->_handle_taxes( $part_pkg,
+ $taxlisthash,
+ $cust_bill_pkg,
+ $cust_bill_pkg->cust_pkg,
+ $cust_bill_pkg->cust_bill->_date,
+ $cust_bill_pkg->cust_pkg->pkgpart,
+ );
+
+ }
+
+ if ( @cust_bill_pkg ) {
+
+ my $listref_or_error =
+ $cust_main->calculate_taxes( \@cust_bill_pkg, $taxlisthash, $cust_bill_pkg[0]->cust_bill->_date );
+
+ unless ( ref( $listref_or_error ) ) {
+ $return->{error} = $listref_or_error;
+ last;
+ }
+
+ my @taxlines = ();
+ my $taxtotal = 0;
+ $return->{taxlines} = \@taxlines;
+ foreach my $taxline ( @$listref_or_error ) {
+ my $amount = $taxline->setup;
+ my $desc = $taxline->desc;
+ foreach my $location ( @{$taxline->cust_bill_pkg_tax_location}, @{$taxline->cust_bill_pkg_tax_rate_location} ) {
+ my $taxlocnum = $location->locationnum || '';
+ my $taxratelocnum = $location->taxratelocationnum || '';
+ $location->cust_bill_pkg_desc($taxline->desc); #ugh @ that kludge
+ $taxtotal += $location->amount;
+ push @taxlines,
+ #[ $location->desc, $taxline->setup, $taxlocnum, $taxratelocnum ];
+ [ $location->desc, $location->amount, $taxlocnum, $taxratelocnum ];
+ $amount -= $location->amount;
+ }
+ if ($amount > 0) {
+ $taxtotal += $amount;
+ push @taxlines,
+ [ $taxline->itemdesc. ' (default)', sprintf('%.2f', $amount), '', '' ];
+ }
+ }
+
+ $return->{taxlines} = \@taxlines;
+ $return->{taxtotal} = sprintf('%.2f', $taxtotal);
+
+ } else {
+
+ $return->{taxlines} = [];
+ $return->{taxtotal} = '0.00';
+
+ }
+
+ }
+
+}
+
+</%init>
diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html
index 166addbf4..6630d12a5 100644
--- a/httemplate/view/cust_main/payment_history.html
+++ b/httemplate/view/cust_main/payment_history.html
@@ -70,6 +70,16 @@
'actionlabel' => emt('Enter credit'),
'width' => 616, #make room for reasons #540 default
&>
+ |
+ <& /elements/popup_link-cust_main.html,
+ 'label' => emt('Credit line items'),
+ #'action' => "${p}search/cust_bill_pkg.cgi?nottax=1;type=select",
+ 'action' => "${p}edit/credit-cust_bill_pkg.html",
+ 'cust_main' => $cust_main,
+ 'actionlabel' => emt('Credit line items'),
+ 'width' => 884, #763,
+ 'height' => 575,
+ &>
<BR>
% }