update the tax class editor to enable taxclass adding, RT#2929
authorivan <ivan>
Wed, 20 Feb 2008 01:21:15 +0000 (01:21 +0000)
committerivan <ivan>
Wed, 20 Feb 2008 01:21:15 +0000 (01:21 +0000)
FS/FS/Schema.pm
FS/FS/Upgrade.pm
FS/FS/part_pkg_taxclass.pm
htetc/handler.pl
httemplate/browse/cust_main_county.cgi
httemplate/edit/part_pkg_taxclass.html [new file with mode: 0644]
httemplate/edit/process/part_pkg_taxclass.html [new file with mode: 0644]
httemplate/elements/tr-select-taxclass.html

index 7f8e6da..9548aa7 100644 (file)
@@ -943,6 +943,16 @@ sub tables_hashref {
       'index' => [ [ 'promo_code' ], [ 'disabled' ], [ 'agentnum' ], ],
     },
 
+    'part_pkg_taxclass' => {
+      'columns' => [
+        'taxclassnum',  'serial', '',       '', '', '',
+        'taxclass',     'varchar', '', $char_d, '', '', 
+      ],
+      'primary_key' => 'taxclassnum',
+      'unique'      => [ [ 'taxclass' ] ],
+      'index'       => [],
+    },
+
 #    'part_title' => {
 #      'columns' => [
 #        'titlenum',   'int',    '',   '',
index 90e66d8..cb48230 100644 (file)
@@ -49,8 +49,12 @@ sub upgrade {
     eval "use $class;";
     die $@ if $@;
 
-    $class->_upgrade_data(%opt)
-      if $class->can('_upgrade_data');
+    if ( $class->can('_upgrade_data') ) {
+      $class->_upgrade_data(%opt);
+    } else {
+      warn "WARNING: asked for upgrade of $table,".
+           " but FS::$table has no _upgrade_data method\n";
+    }
 
 #    my @records = @{ $data->{$table} };
 #
@@ -88,6 +92,10 @@ sub upgrade_data {
 
     #populate cust_pay.otaker
     'cust_pay'    => [],
+
+    #populate part_pkg_taxclass for starters
+    'part_pkg_taxclass' => [],
+
   ;
 
   \%hash;
index 341be0e..fda200e 100644 (file)
@@ -2,6 +2,7 @@ package FS::part_pkg_taxclass;
 
 use strict;
 use vars qw( @ISA );
+use FS::UID qw(dbh);
 use FS::Record qw( qsearch qsearchs );
 
 @ISA = qw(FS::Record);
@@ -100,8 +101,7 @@ sub check {
   my $self = shift;
 
   my $error = 
-    $self->ut_numbern('serial')
-    || $self->ut_number('taxclassnum')
+    $self->ut_numbern('taxclassnum')
     || $self->ut_text('taxclass')
   ;
   return $error if $error;
@@ -111,6 +111,38 @@ sub check {
 
 =back
 
+=cut
+
+# _upgrade_data
+#
+# Used by FS::Upgrade to migrate to a new database.
+
+sub _upgrade_data { # class method
+  my ($class, %opts) = @_;
+
+  my $sth = dbh->prepare('
+    SELECT DISTINCT taxclass
+      FROM cust_main_county
+        LEFT JOIN part_pkg_taxclass USING ( taxclass )
+      WHERE taxclassnum IS NULL
+        AND taxclass IS NOT NULL
+  ') or die dbh->errstr;
+  $sth->execute or die $sth->errstr;
+  my %taxclass = map { $_->[0] => 1 } @{$sth->fetchall_arrayref};
+  my @taxclass = grep $_, keys %taxclass;
+
+  foreach my $taxclass ( @taxclass ) {
+
+    my $part_pkg_taxclass = new FS::part_pkg_taxclass ( {
+      'taxclass' => $taxclass,
+    } );
+    my $error = $part_pkg_taxclass->insert;
+    die $error if $error;
+
+  }
+
+}
+
 =head1 BUGS
 
 Other tables (cust_main_county, part_pkg, agent_payment_gateway) have a text
index 09bada4..26cdaf4 100644 (file)
@@ -149,6 +149,7 @@ sub handler
       use FS::cust_credit_bill;
       use FS::cust_main qw(smart_search);
       use FS::cust_main_county;
+      use FS::part_pkg_taxclass;
       use FS::cust_pay;
       use FS::cust_pkg;
       use FS::cust_pkg_reason;
index 3e67b11..12bdeb3 100755 (executable)
@@ -1,6 +1,7 @@
 <% include( 'elements/browse.html',
-     'title'          => 'Tax Rates',
+     'title'          => "Tax Rates $title",
      'name_singular'  => 'tax rate',
+     'menubar'        => \@menubar,
      'html_init'      => $html_init,
      'html_posttotal' => $html_posttotal,
      'query'          => {
@@ -89,11 +90,20 @@ my $edit_onclick = sub {
 };
 
 sub expand_link {
-  my( $row, $desc, %opt ) = @_;
+  my( $row, $desc ) = @_;
   my $taxnum = $row->taxnum;
-  $taxnum = "taxclass$taxnum" if $opt{'taxclass'};
+  my $url = "${p}edit/cust_main_county-expand.cgi?$taxnum";
   my $color = '#333399';
-  qq!<FONT SIZE="-1"><A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}edit/cust_main_county-expand.cgi?$taxnum', 540, 420, 'edit_cust_main_county_popup' ), CAPTION, '$desc', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '$color', CGCOLOR, '$color' ); return false;">!;
+
+  qq!<FONT SIZE="-1"><A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('$url', 540, 420, 'edit_cust_main_county_popup' ), CAPTION, '$desc', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '$color', CGCOLOR, '$color' ); return false;">!;
+}
+
+sub separate_taxclasses_link {
+  my( $row ) = @_;
+  my $taxnum = $row->taxnum;
+  my $url = "${p}edit/process/cust_main_county-expand.cgi?taxclass=1;taxnum=$taxnum";
+
+  qq!<FONT SIZE="-1"><A HREF="$url">!;
 }
 
 </%once>
@@ -106,10 +116,12 @@ die "access denied"
 #my $money_char = $conf->config('money_char') || '$';
 my $enable_taxclasses = $conf->exists('enable_taxclasses');
 
+my @menubar;
+
 my $html_init =
   "Click on <u>add states</u> to specify a country's tax rates by state or province.
    <BR>Click on <u>add counties</u> to specify a state's tax rates by county.";
-$html_init .= "<BR>Click on <u>add taxclasses</u> to specify tax classes."
+$html_init .= "<BR>Click on <u>separate taxclasses</u> to specify taxes per taxclass."
   if $enable_taxclasses;
 $html_init .= '<BR><BR>';
 
@@ -120,23 +132,60 @@ $html_init .= qq(
   <SCRIPT TYPE="text/javascript" SRC="${fsurl}elements/iframecontentmws.js"></SCRIPT>
 );
 
-my $filter_country = '';
-if ( $cgi->param('filter_country') =~ /^(\w\w)$/ ) {
-  $filter_country = $1;
+my $title = '';
+
+my $country = '';
+if ( $cgi->param('country') =~ /^(\w\w)$/ ) {
+  $country = $1;
+  $title = $country;
+}
+$cgi->delete('country');
+
+my $state = '';
+if ( $cgi->param('state') =~ /^([\w \-\'\[\]]+)$/ ) {
+  $state = $1;
+  $title = "$state, $title";
+}
+$cgi->delete('state');
+
+my $county = '';
+if ( $cgi->param('county') =~ /^([\w \-\'\[\]]+)$/ ) {
+  $county = $1;
+  $title = "$county county, $title";
 }
-$cgi->delete('filter_country');
+$cgi->delete('county');
+
+$title = " for $title" if $title;
+
+my $taxclass = '';
+if ( $cgi->param('taxclass') =~ /^([\w \-]+)$/ ) {
+  $taxclass = $1;
+  $title .= " for $taxclass tax class";
+}
+$cgi->delete('taxclass');
+
+if ( $country || $taxclass ) {
+  push @menubar, 'View all tax rates' => $p.'browse/cust_main_county.cgi';
+}
+
 $cgi->param('dummy', 1);
 
 my $country_filter_change =
   "window.location = '".
-  $cgi->self_url. ";filter_country=' + this.options[this.selectedIndex].value;";
+  $cgi->self_url. ";country=' + this.options[this.selectedIndex].value;";
+
+#restore this so pagination works
+$cgi->param('country',  $country) if $country;
+$cgi->param('state',    $state  ) if $state;
+$cgi->param('county',   $county ) if $county;
+$cgi->param('taxclass', $county ) if $taxclass;
 
 my $html_posttotal =
   '(show country: '.
-  qq(<SELECT NAME="filter_country" onChange="$country_filter_change">).
+  qq(<SELECT NAME="country" onChange="$country_filter_change">).
   qq(<OPTION VALUE="">(all)\n).
   join("\n", map qq[<OPTION VALUE="$_"].
-                   ( $_ eq $filter_country ? 'SELECTED' : '' ).
+                   ( $_ eq $country ? 'SELECTED' : '' ).
                    '>'. code2country($_). " ($_)",
                  @all_countries
       ).
@@ -144,10 +193,24 @@ my $html_posttotal =
 
 my $hashref = {};
 my $count_query = 'SELECT COUNT(*) FROM cust_main_county';
-if ( $filter_country ) {
-  $hashref->{'country'} = $filter_country;
-  $count_query .= " WHERE country = '$filter_country'";
+if ( $country ) {
+  $hashref->{'country'} = $country;
+  $count_query .= ' WHERE country = '. dbh->quote($country);
+}
+if ( $state ) {
+  $hashref->{'state'} = $state;
+  $count_query .= '   AND state   = '. dbh->quote($state);
+}
+if ( $county ) {
+  $hashref->{'country'} = $country;
+  $count_query .= '   AND county  = '. dbh->quote($county);
 }
+if ( $taxclass ) {
+  $hashref->{'taxclass'} = $taxclass;
+  $count_query .= ( $count_query =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+                  ' taxclass  = '. dbh->quote($taxclass);
+}
+
 
 $cell_style = '';
 
@@ -181,14 +244,14 @@ my @color = (
 );
 
 if ( $conf->exists('enable_taxclasses') ) {
-  push @header,  'Tax class';
+  push @header, qq!Tax class (<A HREF="${p}edit/part_pkg_taxclass.html">add new</A>)!;
   push @header2, '(per-package classification)';
-  push @fields,  sub { $_[0]->taxclass || '(all)&nbsp'.
-                         expand_link($_[0], 'Add Taxclasses', 'taxclass'=>1).
-                         'add&nbsp;taxclasses</A></FONT>'
-                     };
-  push @color,   sub { shift->taxclass ? '000000' : '999999' };
-  push @links,   '';
+  push @fields, sub { $_[0]->taxclass || '(all)&nbsp'.
+                       separate_taxclasses_link($_[0], 'Separate Taxclasses').
+                       'separate&nbsp;taxclasses</A></FONT>'
+                    };
+  push @color, sub { shift->taxclass ? '000000' : '999999' };
+  push @links, '';
   push @link_onclicks, '';
   $align .= 'l';
 }
diff --git a/httemplate/edit/part_pkg_taxclass.html b/httemplate/edit/part_pkg_taxclass.html
new file mode 100644 (file)
index 0000000..e767057
--- /dev/null
@@ -0,0 +1,32 @@
+<% include('/elements/header.html', "$action taxclass") %>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="<% $p1 %>process/part_pkg_taxclass.html" METHOD=POST>
+
+<INPUT TYPE="hidden" NAME="taxclassnum" VALUE="">
+
+Tax class <INPUT TYPE="text" NAME="taxclass" VALUE="<% $taxclass |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 = '';
+if ( $cgi->param('error') ) {
+  $taxclass = $cgi->param('taxclass');
+}
+
+my $action = 'Add';
+
+my $p1 = popurl(1);
+
+</%init>
diff --git a/httemplate/edit/process/part_pkg_taxclass.html b/httemplate/edit/process/part_pkg_taxclass.html
new file mode 100644 (file)
index 0000000..8f149bb
--- /dev/null
@@ -0,0 +1,53 @@
+% if ( $error ) {
+%  $cgi->param('error', $error);
+<% $cgi->redirect(popurl(2). "part_pkg_taxclass.html?". $cgi->query_string ) %>
+%} else {
+<% $cgi->redirect(popurl(3). "browse/cust_main_county.cgi?taxclass=". uri_escape($part_pkg_taxclass->taxclass) ) %>
+%}
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $part_pkg_taxclass = new FS::part_pkg_taxclass {
+  'taxclass' => $cgi->param('taxclass'),
+};
+
+#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 part_pkg_taxclass...
+
+my $error = $part_pkg_taxclass->insert;
+
+unless ( $error ) {
+  #auto-add the new taxclass to any regions that have taxclasses already
+
+  my $sth = dbh->prepare("
+    SELECT country, state, county FROM cust_main_county
+      WHERE taxclass IS NOT NULL AND taxclass != ''
+      GROUP BY country, state, county
+  ") 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::cust_main_county {
+      'country'  => $row->{country},
+      'state'    => $row->{state},
+      'county'   => $row->{county},
+      'tax'      => 0,
+      'taxclass' => $part_pkg_taxclass->taxclass,
+      #exempt_amount
+      #taxname
+      #setuptax
+      #recurtax
+    };
+    $error = $cust_main_county->insert;
+    #last if $error;
+    die $error if $error;
+  }
+
+
+}
+
+</%init>
index a20dd17..3bba683 100644 (file)
@@ -21,8 +21,9 @@ my $conf = new FS::Conf;
 
 unless ( $opt{'taxclasses'} ) {
 
-  my $sth = dbh->prepare('SELECT DISTINCT taxclass FROM cust_main_county')
-     or die dbh->errstr;
+  #my $sth = dbh->prepare('SELECT DISTINCT taxclass FROM cust_main_county')
+  my $sth = dbh->prepare('SELECT taxclass FROM part_pkg_taxclass')
+    or die dbh->errstr;
   $sth->execute or die $sth->errstr;
   my %taxclasses = map { $_->[0] => 1 } @{$sth->fetchall_arrayref};
   @{ $opt{'taxclasses'} } = grep $_, keys %taxclasses;