diff options
author | jeff <jeff> | 2008-04-01 00:54:44 +0000 |
---|---|---|
committer | jeff <jeff> | 2008-04-01 00:54:44 +0000 |
commit | 4104f4e3d1b387296b16b4a035b4b7f42e0c5977 (patch) | |
tree | fcb03d2c518cc91df33059675764d548fedc9e7a /httemplate | |
parent | 12eb930abf31078c68dbf7eb94865faa1c59fc9e (diff) |
checkpoint of new tax rating system
Diffstat (limited to 'httemplate')
-rwxr-xr-x | httemplate/browse/tax_rate.cgi | 205 | ||||
-rwxr-xr-x | httemplate/edit/part_pkg.cgi | 42 | ||||
-rw-r--r-- | httemplate/edit/part_pkg_taxoverride.html | 61 | ||||
-rw-r--r-- | httemplate/edit/part_pkg_taxproduct.html | 42 | ||||
-rwxr-xr-x | httemplate/edit/process/part_pkg.cgi | 13 | ||||
-rw-r--r-- | httemplate/edit/process/tax_class.html | 49 | ||||
-rw-r--r-- | httemplate/edit/process/tax_rate.html | 13 | ||||
-rw-r--r-- | httemplate/edit/tax_class.html | 36 | ||||
-rw-r--r-- | httemplate/edit/tax_rate.html | 105 | ||||
-rw-r--r-- | httemplate/elements/menu.html | 1 | ||||
-rwxr-xr-x | httemplate/misc/process/recharge_svc.new | 85 | ||||
-rw-r--r-- | httemplate/misc/process/tax-import.cgi | 58 | ||||
-rw-r--r-- | httemplate/misc/tax-import.cgi | 91 |
13 files changed, 799 insertions, 2 deletions
diff --git a/httemplate/browse/tax_rate.cgi b/httemplate/browse/tax_rate.cgi new file mode 100755 index 000000000..b401b3786 --- /dev/null +++ b/httemplate/browse/tax_rate.cgi @@ -0,0 +1,205 @@ +<% include( 'elements/browse.html', + 'title' => "Tax Rates $title", + 'name_singular' => 'tax rate', + 'menubar' => \@menubar, + 'html_init' => $html_init, + 'query' => { + 'table' => 'tax_rate', + 'hashref' => $hashref, + 'order_by' => 'ORDER BY geocode, taxclassnum', + }, + 'count_query' => $count_query, + 'header' => \@header, + 'header2' => \@header2, + 'fields' => \@fields, + 'align' => $align, + 'color' => \@color, + 'cell_style' => \@cell_style, + 'links' => \@links, + 'link_onclicks' => \@link_onclicks, + ) +%> +<%once> + +my $conf = new FS::Conf; +my $money_char = $conf->config('money_char') || '$'; + +my $exempt_sub = sub { + my $tax_rate = shift; + + my @exempt = (); + push @exempt, + sprintf("$money_char%.2f per month", $tax_rate->exempt_amount ) + if $tax_rate->exempt_amount > 0; + + push @exempt, 'Setup fee' + if $tax_rate->setuptax =~ /^Y$/i; + + push @exempt, 'Recurring fee' + if $tax_rate->recurtax =~ /^Y$/i; + + [ map [ {'data'=>$_} ], @exempt ]; +}; + +my $oldrow; +my $cell_style; +my $cell_style_sub = sub { + my $row = shift; + if ( $oldrow ne $row ) { + if ( $oldrow ) { + if ( $oldrow->country ne $row->country ) { + $cell_style = 'border-top:1px solid #000000'; + } elsif ( $oldrow->state ne $row->state ) { + $cell_style = 'border-top:1px solid #cccccc'; #default? + } elsif ( $oldrow->state eq $row->state ) { + #$cell_style = 'border-top:dashed 1px dark gray'; + $cell_style = 'border-top:1px dashed #cccccc'; + } + } + $oldrow = $row; + } + return $cell_style; +}; + +my $select_link = [ 'javascript:void(0);', sub { ''; } ]; + +my $select_onclick = sub { + my $row = shift; + my $taxnum = $row->taxnum; + my $color = '#333399'; + qq!overlib( OLiframeContent('${p}edit/tax_rate.html?$taxnum', 540, 420, 'edit_tax_rate_popup' ), CAPTION, 'Edit tax rate', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '$color', CGCOLOR, '$color' ); return false;!; +}; + +my $separate_taxclasses_link = sub { + my( $row ) = @_; + my $taxnum = $row->taxnum; + my $url = "${p}edit/process/tax_rate-expand.cgi?taxclassnum=1;taxnum=$taxnum"; + + qq!<FONT SIZE="-1"><A HREF="$url">!; +}; + +</%once> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my @menubar; + +my $html_init = + "Click on <u>geocodes</u> to specify rates for a new area."; +$html_init .= "<BR>Click on <u>separate taxclasses</u> to specify taxes per taxclass."; +$html_init .= '<BR><BR>'; + +$html_init .= qq( + <SCRIPT TYPE="text/javascript" SRC="${fsurl}elements/overlibmws.js"></SCRIPT> + <SCRIPT TYPE="text/javascript" SRC="${fsurl}elements/overlibmws_iframe.js"></SCRIPT> + <SCRIPT TYPE="text/javascript" SRC="${fsurl}elements/overlibmws_draggable.js"></SCRIPT> + <SCRIPT TYPE="text/javascript" SRC="${fsurl}elements/iframecontentmws.js"></SCRIPT> +); + +my $title = ''; +my $select_word = 'edit'; + +my $geocode = ''; +if ( $cgi->param('geocode') =~ /^(\w+)$/ ) { + $geocode = $1; + $title = "$geocode"; +} +$cgi->delete('geocode'); + +$title = " for $title" if $title; + +my $taxclassnum = ''; +if ( $cgi->param('taxclassnum') =~ /^(\d+)$/ ) { + $taxclassnum = $1; + my $tax_class = qsearchs('tax_class', {'taxclassnum' => $taxclassnum}); + if ($tax_class) { + $title .= " for ". $tax_class->taxclass. + " (". $tax_class->description. ") tax class"; + }else{ + $taxclassnum = ''; + } +} +$cgi->delete('taxclassnum'); + +if ( $geocode || $taxclassnum ) { + push @menubar, 'View all tax rates' => $p.'browse/tax_rate.cgi'; +} + +$cgi->param('dummy', 1); + +#restore this so pagination works +$cgi->param('geocode', $geocode) if $geocode; +$cgi->param('taxclassnum', $taxclassnum ) if $taxclassnum; + +my $hashref = {}; +my $count_query = 'SELECT COUNT(*) FROM tax_rate'; +if ( $geocode ) { + $hashref->{'geocode'} = $geocode; + $count_query .= ' WHERE geocode = '. dbh->quote($geocode); +} +if ( $taxclassnum ) { + $hashref->{'taxclassnum'} = $taxclassnum; + $count_query .= ( $count_query =~ /WHERE/i ? ' AND ' : ' WHERE ' ). + ' taxclassnum = '. dbh->quote($taxclassnum); +} + + +$cell_style = ''; + +my @header = ( 'Location Code', ); +my @header2 = ( '', ); +my @links = ( '', ); +my @link_onclicks = ( '', ); +my $align = 'l'; + +my @fields = ( + 'geocode', +); + +my @color = ( + '000000', +); + +push @header, qq!Tax class (<A HREF="${p}edit/tax_class.html">add new</A>)!; +push @header2, '(per-tax classification)'; +push @fields, sub { $_[0]->taxclass_description || '(all) '. + &{$separate_taxclasses_link}($_[0], 'Separate Taxclasses'). + 'separate taxclasses</A></FONT>' + }; +push @color, sub { shift->taxclass ? '000000' : '999999' }; +push @links, ''; +push @link_onclicks, ''; +$align .= 'l'; + +push @header, 'Tax name', + 'Rate', #'Tax', + 'Exemptions', + ; + +push @header2, '(printed on invoices)', + '', + '', + ; + +push @fields, + sub { shift->taxname || 'Tax' }, + sub { shift->tax. '% <FONT SIZE="-1">('. $select_word. ')</FONT>' }, + $exempt_sub, +; + +push @color, + sub { shift->taxname ? '000000' : '666666' }, + sub { shift->tax ? '000000' : '666666' }, + '000000', +; + +$align .= 'lrl'; + +my @cell_style = map $cell_style_sub, (1..scalar(@header)); + +push @links, '', $select_link, ''; +push @link_onclicks, '', $select_onclick, ''; + +</%init> diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi index b1851a7ba..84f7498e1 100755 --- a/httemplate/edit/part_pkg.cgi +++ b/httemplate/edit/part_pkg.cgi @@ -3,6 +3,11 @@ )) %> % #), ' onLoad="visualize()"'); +<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/overlibmws.js"></SCRIPT> +<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/overlibmws_iframe.js"></SCRIPT> +<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/overlibmws_draggable.js"></SCRIPT> +<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/iframecontentmws.js"></SCRIPT> + <% include('/elements/error.html') %> <FORM NAME="dummy"> @@ -81,6 +86,34 @@ Tax information % } +% if ( $conf->exists('enable_taxproducts') ) { + + <TR><TD colspan="2"> + <% ntable("#cccccc", 2) %> + <TR> + <TD align="right">Tax product</TD> + <TD> + <INPUT name="part_pkg_taxproduct_taxproductnum" id="taxproductnum" type="hidden" value="<% $hashref->{'taxproductnum'}%>"> + <INPUT name="part_pkg_taxproduct_description" id="taxproduct_description" type="text" value="<% $taxproduct_description %>" size="12" onclick="overlib( OLiframeContent('part_pkg_taxproduct.html?'+document.getElementById('taxproductnum').value, 800, 400, 'tax_product_popup'), CAPTION, 'Select product', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK); return false;"> + </TD> + </TR> + <TR> + <TD colspan="2" align="right"> + <INPUT name="tax_override" id="tax_override" type="hidden" value="<% $tax_override %>"> + <A href="javascript:void(0)" onclick="overlib( OLiframeContent('part_pkg_taxoverride.html?'+document.getElementById('tax_override').value, 800, 400, 'tax_product_popup'), CAPTION, 'Edit product tax overrides', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK); return false;"> + <% $tax_override ? 'Edit tax overrides' : 'Override taxes' %> + </A> + </TD> + </TR> + </TABLE> + </TD></TR> + +% } else { + + <INPUT TYPE="hidden" NAME="taxproductnum" VALUE="<% $hashref->{taxproductnum} %>"> + +% } + </TABLE> <BR> @@ -234,7 +267,7 @@ Line-item revenue recognition %#} else { %# push @fixups, 'taxclass'; #hidden %#} -%my @form_elements = ( 'classnum', 'taxclass', 'agent_type' ); +%my @form_elements = ( 'classnum', 'taxclass', 'agent_type', 'tax_override' ); % %my @form_radio = ( 'pkg_svc_primary' ); % @@ -252,6 +285,7 @@ Line-item revenue recognition % 'form_elements' => \@form_elements, % 'form_text' => [ qw(pkg comment promo_code clone pkgnum pkgpart), % qw(pay_weight credit_weight), #keys(%weight), +% qw(taxproductnum), % @fixups, % ], % 'form_checkbox' => [ qw(setuptax recurtax disabled) ], @@ -409,12 +443,14 @@ my ($query) = $cgi->keywords; my $conf = new FS::Conf; my $part_pkg = ''; my @agent_type = (); +my $tax_override; my @all_agent_types = map {$_->typenum} qsearch('agent_type',{}); if ( $cgi->param('error') ) { $part_pkg = new FS::part_pkg ( { map { $_, scalar($cgi->param($_)) } fields('part_pkg') } ); (@agent_type) = $cgi->param('agent_type'); + $tax_override = $cgi->param('tax_override'); } my $action = ''; @@ -430,6 +466,9 @@ if ( $cgi->param('clone') ) { } elsif ( $query && $query =~ /^(\d+)$/ ) { (@agent_type) = map {$_->typenum} qsearch('type_pkgs',{'pkgpart'=>$1}) unless $part_pkg; + $tax_override = + join (",", map {$_->taxnum} qsearch('part_pkg_taxoverride',{'pkgpart'=>$1})) + unless $part_pkg; $part_pkg ||= qsearchs('part_pkg',{'pkgpart'=>$1}); $pkgpart = $part_pkg->pkgpart; } else { @@ -447,5 +486,6 @@ unless ( $part_pkg->plan ) { #backwards-compat } $action ||= $part_pkg->pkgpart ? 'Edit' : 'Add'; my $hashref = $part_pkg->hashref; +my $taxproduct_description = $part_pkg->taxproduct_description; </%init> diff --git a/httemplate/edit/part_pkg_taxoverride.html b/httemplate/edit/part_pkg_taxoverride.html new file mode 100644 index 000000000..61cca1fbc --- /dev/null +++ b/httemplate/edit/part_pkg_taxoverride.html @@ -0,0 +1,61 @@ +<%doc> + + The crappy version + +</%doc> +<% include('/elements/header-popup.html', 'Select tax product') %> +<SCRIPT> + function saveit2() { + var num = parent.document.getElementById('tax_override'); + var sel = document.getElementById('taxoverride_popup_select'); + var value = ''; + for (i=0; i< sel.length; i++) { + if (sel.options[i].selected) { + value = value + sel.options[i].value + ","; + } + } + if (value.length > 0) { + value = value.substr(0, value.length-1); + } + + num.value = value; + parent.cClick(); + } +</SCRIPT> +<FORM="dummy" METHOD="POST" onsubmit="saveit2();return false;" > + +<% ntable("#cccccc", 2) %> +<TR> + <TD align="left">Tax override</TD> + <TD> + <% include( '/elements/select-table.html', + 'table' => 'tax_rate', + 'name_col' => 'taxname', + 'curr_value' => \@curr_value, + 'element_etc' => "id='taxoverride_popup_select'", + 'multiple' => '1', + ) + %> + </TD> +</TR> +</TABLE> +<BR><BR> +<CENTER><INPUT type="submit" value="Select"></CENTER> +</FORM> +<% include('/elements/footer.html') %> + +<%init> + +my $conf = new FS::Conf; + +my @curr_value; +my ( $query ) = $cgi->keywords; +$query =~ /^([\d,]+)$/; +push @curr_value, split ',', $1 + if $1; + +unless (scalar(@curr_value)) { + #push @curr_value, map {$_=>taxnum} $part_pkg->tax_rate; +} + +</%init> diff --git a/httemplate/edit/part_pkg_taxproduct.html b/httemplate/edit/part_pkg_taxproduct.html new file mode 100644 index 000000000..033c37f56 --- /dev/null +++ b/httemplate/edit/part_pkg_taxproduct.html @@ -0,0 +1,42 @@ +<% include('/elements/header-popup.html', 'Select tax product') %> +<SCRIPT> + function saveit() { + var num = parent.document.getElementById('taxproductnum'); + var disp = parent.document.getElementById('taxproduct_description'); + var sel = document.getElementById('taxproduct_popup_select'); + num.value = sel.options[sel.selectedIndex].value; + disp.value = sel.options[sel.selectedIndex].text; + parent.cClick(); + } +</SCRIPT> +<FORM="dummy" METHOD="POST" onsubmit="saveit();return false;" > + +<% ntable("#cccccc", 2) %> +<TR> + <TD align="left">Tax product</TD> + <TD> + <% include( '/elements/select-table.html', + 'empty_label' => '(select product)', + 'table' => 'part_pkg_taxproduct', + 'name_col' => 'description', + 'curr_value' => $curr_value, + 'element_etc' => "id='taxproduct_popup_select'", + ) + %> + </TD> +</TR> +</TABLE> +<BR><BR> +<CENTER><INPUT type="submit" value="Select"></CENTER> +</FORM> +<% include('/elements/footer.html') %> + +<%init> + +my $conf = new FS::Conf; + +my ( $query ) = $cgi->keywords; +$query =~ /^(\d+)$/; +my $curr_value = $1; + +</%init> diff --git a/httemplate/edit/process/part_pkg.cgi b/httemplate/edit/process/part_pkg.cgi index 36debfce0..eac20af57 100755 --- a/httemplate/edit/process/part_pkg.cgi +++ b/httemplate/edit/process/part_pkg.cgi @@ -53,6 +53,9 @@ $error = "At least one agent type must be specified." !$pkgpart && $conf->exists('agent-defaultpkg') ); +$cgi->param('tax_override') =~ /^([\d,]+)$/; +my (@tax_overrides) = (grep "$_", split (",", $1)); + my $new = new FS::part_pkg ( { map { $_ => scalar($cgi->param($_)); @@ -103,11 +106,19 @@ if ( $error ) { } unless ( $error || $conf->exists('agent_defaultpkg') ) { - my $error = $new->process_m2m( + $error = $new->process_m2m( 'link_table' => 'type_pkgs', 'target_table' => 'agent_type', 'params' => \@agents, ); } +unless ( $error ) { + $error = $new->process_m2m( + 'link_table' => 'part_pkg_taxoverride', + 'target_table' => 'tax_rate', + 'params' => \@tax_overrides, + ); +} + </%init> diff --git a/httemplate/edit/process/tax_class.html b/httemplate/edit/process/tax_class.html new file mode 100644 index 000000000..339c9083e --- /dev/null +++ b/httemplate/edit/process/tax_class.html @@ -0,0 +1,49 @@ +% if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "tax_class.html?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3). "browse/tax_rate.cgi?taxclassnum=". uri_escape($tax_class->taxclassnum) ) %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $tax_class = new FS::tax_class { + 'taxclass' => $cgi->param('taxclass'), + 'description' => $cgi->param('description'), +}; + +#maybe this whole thing should be in a transaction. at some point, no biggie +#none of the follow-up stuff will fail unless there's a more serious problem +#than a hanging record in tax_class... + +my $error = $tax_class->insert; + +# all of this is highly dubious at the moment + +#unless ( $error ) { +# #auto-add the new taxclass to any regions that have taxclasses already +# +# my $sth = dbh->prepare(" +# SELECT geocode FROM tax_rate +# WHERE taxclass IS NOT NULL AND taxclass != '' +# GROUP BY geocode +# ") or die dbh->errstr; +# $sth->execute or die $sth->errstr; +# +# while ( my $row = $sth->fetchrow_hashref ) { +# warn "inserting for $row"; +# my $cust_main_county = new FS::tax_rate { +# 'geocode' => $row->{geocode}, +# 'tax' => 0, +# 'taxclassnum' => $tax_class->taxclassnum, +# }; +# $error = $cust_main_county->insert; +# #last if $error; +# die $error if $error; +# } +# +#} + +</%init> diff --git a/httemplate/edit/process/tax_rate.html b/httemplate/edit/process/tax_rate.html new file mode 100644 index 000000000..933bf07d6 --- /dev/null +++ b/httemplate/edit/process/tax_rate.html @@ -0,0 +1,13 @@ +<% include( 'elements/process.html', + 'table' => 'tax_rate', + 'popup_reload' => 'Tax changed', #a popup "parent reload" for now + #someday change the individual element and go away instead + ) +%> +<%init> + +my $conf = new FS::Conf; +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/tax_class.html b/httemplate/edit/tax_class.html new file mode 100644 index 000000000..d3e2e821f --- /dev/null +++ b/httemplate/edit/tax_class.html @@ -0,0 +1,36 @@ +<% include('/elements/header.html', "$action taxclass") %> + +<% include('/elements/error.html') %> + +<FORM ACTION="<% $p1 %>process/tax_class.html" METHOD=POST> + +<INPUT TYPE="hidden" NAME="taxclassnum" VALUE=""> +<INPUT TYPE="hidden" NAME="data_vendor" VALUE=""> + +Tax class <INPUT TYPE="text" NAME="taxclass" VALUE="<% $taxclass |h %>"><BR> +Description <INPUT TYPE="text" NAME="description" VALUE="<% $description |h %>"> + +<BR><BR> +<INPUT TYPE="submit" VALUE="<% $action %> taxclass"> + +</FORM> + +<% include('/elements/footer.html') %> + +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $taxclass = ''; +my $description = ''; +if ( $cgi->param('error') ) { + $taxclass = $cgi->param('taxclass'); + $description = $cgi->param('description'); +} + +my $action = 'Add'; + +my $p1 = popurl(1); + +</%init> diff --git a/httemplate/edit/tax_rate.html b/httemplate/edit/tax_rate.html new file mode 100644 index 000000000..e1d8d4f93 --- /dev/null +++ b/httemplate/edit/tax_rate.html @@ -0,0 +1,105 @@ +<% include('elements/edit.html', + 'popup' => 1, + 'name' => 'Tax rate', #Edit tax rate + 'table' => 'tax_rate', + 'labels' => $labels, + 'fields' => \@fields, + ) +%> +<%once> + +my $conf = new FS::Conf; + +</%once> + +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $taxnum; +if ( $cgi->param('error') ) { + $cgi->param('taxnum') =~ /^(\d+)$/ or die 'error, but no taxnum'; + $taxnum = $1; +} else { + my($query) = $cgi->keywords; + $query =~ /^(\d+)$/ or die 'no taxnum'; + $taxnum = $1; +} + +my $tax_rate = qsearchs('tax_rate', { 'taxnum' => $taxnum }) + or die "unknown taxnum $1"; + +my $labels = { 'taxnum' => 'Tax', + 'data_vendor' => 'Data vendor', + 'geocode' => 'Vendor location code', + 'location' => 'Tax auth loc code', + 'taxclass_description' => 'Tax class', + 'taxname' => 'Tax name', + 'effective_date' => 'Effective date', + 'tax' => 'Tax rate (1st bracket)', + 'excessrate' => 'Tax rate (2nd bracket)', + 'taxbase' => 'First bracket', + 'taxmax' => 'Max tax', + 'usetax' => 'Use tax rate (1st bracket)', + 'useexcessrate' => 'Use tax rate (2nd bracket)', + 'unittype_name' => 'Units', + 'fee' => 'Fee per unit (1st bracket)', + 'excessfee' => 'Fee per unit (2st bracket)', + 'feebase' => 'Units in first bracket', + 'feemax' => 'Max Units', + 'maxtype_name' => 'Threshold accumulation', + 'taxauth_name', => 'Tax authority', + 'basetype_name' => 'Basis', + 'passtype_name' => 'Passthru', + 'passflag' => 'Passable', + 'setuptax' => 'This tax not applicable to setup fees', + 'recurtax' => 'This tax not applicable to recurring fees', + }; + +my @fields = ( + { type=>'tablebreak-tr-title', value=>'Location' }, + { field=>'data_vendor', type=>'hidden',}, + { field=>'geocode', type=>'fixed' }, + { field=>'taxclassnum', type=>'hidden' } , + { field=>'taxclass_description', type=>'fixed' } , + { field=>'taxname', type=>'text' } , + { field=>'effective_date', type=>'fixed' } , + { field=>'location', type=>'text' }, + { type=>'tablebreak-tr-title', value=>'Money based rates' }, + { field=>'tax', type=>'percentage' } , + { field=>'excessrate', type=>'percentage' } , + { field=>'taxbase', type=>'money' } , + { field=>'taxmax', type=>'money' } , + { field=>'usetax', type=>'percentage' } , + { field=>'useexcessrate', type=>'percentage' } , + { type=>'tablebreak-tr-title', value=>'Service based rates' }, + { field=>'unittype', type=>'hidden' } , + { field=>'unittype_name', type=>'fixed' } , + { field=>'fee', type=>'money' } , + { field=>'excessfee', type=>'money' } , + { field=>'feebase', type=>'text' } , + { field=>'feemax', type=>'text' } , + { type=>'tablebreak-tr-title', value=>'Taxation rules' }, + { field=>'maxtype', type=>'hidden' } , + { field=>'maxtype_name', type=>'fixed' } , + { field=>'taxauth', type=>'hidden' } , + { field=>'taxauth_name', type=>'fixed' } , + { field=>'basetype', type=>'hidden' } , + { field=>'basetype_name', type=>'fixed' } , + { field=>'passtype', type=>'hidden' } , + { field=>'passtype_name', type=>'fixed' } , + { field=>'passflag', type=>'fixed' } , + { field=>'setuptax', type=>'checkbox' } , + { field=>'recurtax', type=>'checkbox' } , + { field=>'manual', type=>'hidden', value=>'Y' } , +); + +#push @fields, +# { type=>'tablebreak-tr-title', value=>'Exemptions' }, +# { field=>'setuptax', type=>'checkbox', value=>'Y', }, +# { field=>'recurtax', type=>'checkbox', value=>'Y', }, +# { field=>'exempt_amount', type=>'money', }, +#; + +</%init> diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html index 047671ae5..4e4d68719 100644 --- a/httemplate/elements/menu.html +++ b/httemplate/elements/menu.html @@ -217,6 +217,7 @@ $report_menu{'SQL Query'} = [ $fsurl.'search/report_sql.html', 'SQL Query' ] if $curuser->access_right('Raw SQL'); tie my %tools_importing, 'Tie::IxHash', + 'Import tax rates from CSV files' => [ $fsurl.'misc/tax-import.cgi', '' ], 'Import customers from CSV file' => [ $fsurl.'misc/cust_main-import.cgi', '' ], 'Import payments from CSV file' => [ $fsurl.'misc/cust_pay-import.cgi', '' ], diff --git a/httemplate/misc/process/recharge_svc.new b/httemplate/misc/process/recharge_svc.new new file mode 100755 index 000000000..bc916e5da --- /dev/null +++ b/httemplate/misc/process/recharge_svc.new @@ -0,0 +1,85 @@ +% +% +%#untaint svcnum +%my $svcnum = $cgi->param('svcnum'); +%$svcnum =~ /^(\d+)$/ || die "Illegal svcnum"; +%$svcnum = $1; +% +%#untaint prepaid +%my $prepaid = $cgi->param('prepaid'); +%$prepaid =~ /^(\w*)$/; +%$prepaid = $1; + +%#untaint payby +%my $payby = $cgi->param('payby'); +%$payby =~ /^([A-Z]*)$/; +%$payby = $1; +% +%my $error = ''; +%my $svc_acct = qsearchs( 'svc_acct', {'svcnum'=>$svcnum} ); +%$error = "Can't recharge service $svcnum. " unless $svc_acct; +% +%my $cust_main = $svc_acct->cust_svc->cust_pkg->cust_main; +% +%my $oldAutoCommit = $FS::UID::AutoCommit; +%local $FS::UID::AutoCommit = 0; +%my $dbh = dbh; +% +% +%unless ($error) { +% +% my ($amount, $seconds, $up, $down, $total) = (0, 0, 0, 0, 0); +% #should probably use payby.pm but whatever +% if ($payby eq 'PREP') { +% $error = $cust_main->get_prepay($prepaid, \$amount, \$seconds, \$up, \$down, \$total) +% || $svc_acct->increment_seconds($seconds) +% || $svc_acct->increment_upbytes($up) +% || $svc_acct->increment_downbytes($down) +% || $svc_acct->increment_totalbytes($total) +% || $cust_main->insert_cust_pay_prepay( $amount, $prepaid ); +% } elsif ( $payby =~ /^(CARD|DCRD|CHEK|DCHK|LECB|BILL|COMP)$/ ) { +% my $part_pkg = $svc_acct->cust_svc->cust_pkg->part_pkg; +% $amount = $part_pkg->option('recharge_amount', 1); +% my %rhash = map { $_ =~ /^recharge_(.*)$/; $1, $part_pkg->option($_, 1) } +% qw ( recharge_seconds recharge_upbytes recharge_downbytes +% recharge_totalbytes ); +% +% my $description = "Recharge"; +% $description .= " $rhash{seconds}s" if $rhash{seconds}; +% $description .= " $rhash{upbytes} up" if $rhash{upbytes}; +% $description .= " $rhash{downbytes} down" if $rhash{downbytes}; +% $description .= " $rhash{totalbytes} total" if $rhash{totalbytes}; +% +% $error = $cust_main->charge($amount, "Recharge " . $svc_acct->label, +% $description, $part_pkg->taxclass); +% +% $error ||= $svc_acct->recharge(\%rhash); +% +% my $old_balance = $cust_main->balance; +% $error ||= $cust_main->bill; +% $error ||= $cust_main->apply_payments_and_credits; +% my $bill_error = $cust_main->collect('realtime' => 1) unless $error; +% $error ||= "Failed to collect - $bill_error" +% if $cust_main->balance > $old_balance && $cust_main->balance > 0 +% && $payby ne 'BILL'; +% +% } else { +% $error = "fatal error - unknown payby: $payby"; +% } +%} +% +%if ($error) { +% $cgi->param('error', $error); +% $dbh->rollback if $oldAutoCommit; +% print $cgi->redirect(popurl(2). "recharge_svc.html?". $cgi->query_string ); +%} +%$dbh->commit or die $dbh->errstr if $oldAutoCommit; +% +<% header("Package recharged") %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + </BODY></HTML> +<%init> +my $conf = new FS::Conf; +</%init> diff --git a/httemplate/misc/process/tax-import.cgi b/httemplate/misc/process/tax-import.cgi new file mode 100644 index 000000000..77fba61f5 --- /dev/null +++ b/httemplate/misc/process/tax-import.cgi @@ -0,0 +1,58 @@ +% if ( $error ) { +% warn $error; +% errorpage($error); +% } else { + <% include('/elements/header.html','Import successful') %> + <% include('/elements/footer.html') %> +% } +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Import'); + +my $cfh = $cgi->upload('codefile'); +my $zfh = $cgi->upload('plus4file'); +my $tfh = $cgi->upload('txmatrix'); +my $dfh = $cgi->upload('detail'); +#warn $cgi; +#warn $fh; + +my $oldAutoCommit = $FS::UID::AutoCommit; +local $FS::UID::AutoCommit = 0; +my $dbh = dbh; + +my $error = defined($cfh) + ? FS::tax_class::batch_import( { + filehandle => $cfh, + 'format' => scalar($cgi->param('format')), + } ) + : 'No code file'; + +$error ||= defined($zfh) + ? FS::cust_tax_location::batch_import( { + filehandle => $zfh, + 'format' => scalar($cgi->param('format')), + } ) + : 'No plus4 file'; + +$error ||= defined($tfh) + ? FS::part_pkg_taxrate::batch_import( { + filehandle => $tfh, + 'format' => scalar($cgi->param('format')), + } ) + : 'No tax matrix file'; + +$error ||= defined($dfh) + ? FS::tax_rate::batch_import( { + filehandle => $dfh, + 'format' => scalar($cgi->param('format')), + } ) + : 'No tax detail file'; + +if ($error) { + $dbh->rollback or die $dbh->errstr if $oldAutoCommit; +}else{ + $dbh->commit or die $dbh->errstr if $oldAutoCommit; +} + +</%init> diff --git a/httemplate/misc/tax-import.cgi b/httemplate/misc/tax-import.cgi new file mode 100644 index 000000000..1f60dbe00 --- /dev/null +++ b/httemplate/misc/tax-import.cgi @@ -0,0 +1,91 @@ +<% include("/elements/header.html",'Batch Tax Rate Import') %> + +Import a CSV file set containing tax rate records. +<BR><BR> + +<FORM ACTION="process/tax-import.cgi" METHOD="post" ENCTYPE="multipart/form-data"> + +<% &ntable("#cccccc", 2) %> + +<TR> + <TH ALIGN="right">Format</TH> + <TD> + <SELECT NAME="format"> + <OPTION VALUE="cch">CCH +<!-- <OPTION VALUE="extended" SELECTED>Extended + <OPTION VALUE="extended-plus_company">Extended plus company --> + </SELECT> + </TD> +</TR> + +<TR> + <TH ALIGN="right">code CSV filename</TH> + <TD><INPUT TYPE="file" NAME="codefile"></TD> +</TR> + +<TR> + <TH ALIGN="right">plus4 CSV filename</TH> + <TD><INPUT TYPE="file" NAME="plus4file"></TD> +</TR> + +<TR> + <TH ALIGN="right">txmatrix CSV filename</TH> + <TD><INPUT TYPE="file" NAME="txmatrix"></TD> +</TR> + +<TR> + <TH ALIGN="right">detail CSV filename</TH> + <TD><INPUT TYPE="file" NAME="detail"></TD> +</TR> + + +<TR><TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px"><INPUT TYPE="submit" VALUE="Import CSV files"></TD></TR> + +</TABLE> + +</FORM> + +<BR> + +<!-- Simple file format is CSV, with the following field order: <i>cust_pkg.setup, dayphone, first, last, address1, address2, city, state, zip, comments</i> +<BR><BR> --> + +<%$req%> Required fields +<BR><BR> + +Field information: + +<ul> + + <li><i>refnum</i>: Advertising source number - where a customer heard about your service. Configuration -> Miscellaneous -> View/Edit advertising sources. This field has special treatment upon import: If a string is passed instead +of an integer, the string is searched for and if necessary auto-created in the +advertising source table. + + <li><i>payinfo</i>: Credit card number, or leave this, <i>paycvv</i> and <i>paydate</i> blank for email/paper invoicing. + + <li><i>paycvv</i>: CVV2 number (three digits on the back of the credit card) + + <li><i>paydate</i>: Credit card expiration date, MM/YYYY or MM/YY (M/YY and M/YYYY are also accepted). + + <li><i>invoicing_list</i>: Email address for invoices, or POST for postal invoices. + + <li><i>pkgpart</i>: Package definition. Configuration -> Provisioning, services and packages -> View/Edit package definitions + + <li><i>username</i> and <i>_password</i> are required if <i>pkgpart</i> is specified. +</ul> + +<BR> + +<% include('/elements/footer.html') %> + +<%once> + +my $req = qq!<font color="#ff0000">*</font>!; + +</%once> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Import'); + +</%init> |