add a quick bulk tax add tool (eating my own dogfood instead of running a one-off...
[freeside.git] / httemplate / browse / cust_main_county.cgi
1 <% include( 'elements/browse.html',
2      'title'          => "Tax Rates $title",
3      'name_singular'  => 'tax rate',
4      'menubar'        => \@menubar,
5      'html_init'      => $html_init,
6      'html_posttotal' => $html_posttotal,
7      'html_form'      => '<FORM NAME="taxesForm">',
8      'html_foot'      => $html_foot,
9      'query'          => {
10                            'table'    => 'cust_main_county',
11                            'hashref'  => $hashref,
12                            'order_by' =>
13                              'ORDER BY country, state, county, taxclass',
14                          },
15      'count_query'    => $count_query,
16      'header'         => \@header,
17      'header2'        => \@header2,
18      'fields'         => \@fields,
19      'align'          => $align,
20      'color'          => \@color,
21      'cell_style'     => \@cell_style,
22      'links'          => \@links,
23      'link_onclicks'  => \@link_onclicks,
24   )
25 %>
26 %
27 % #         <FONT SIZE=-1><A HREF="<% $p %>edit/process/cust_main_county-collapse.cgi?<% $hashref->{taxnum} %>">collapse state</A></FONT>
28 % # % } 
29 %
30 <%once>
31
32 my $conf = new FS::Conf;
33 my $money_char = $conf->config('money_char') || '$';
34
35 my @manual_countries = ( 'US', 'CA', 'AU', 'NZ', 'GB' ); #some manual ordering
36 my @all_countries = ( @manual_countries, 
37                       grep { my $c = $_; ! grep { $c eq $_ } @manual_countries }
38                       map { $_->country } 
39                           qsearch({
40                                     'select'    => 'country',
41                                     'table'     => 'cust_main_county',
42                                     'hashref'   => {},
43                                     'extra_sql' => 'GROUP BY country',
44                                  })
45                     );
46
47 my $exempt_sub = sub {
48   my $cust_main_county = shift;
49
50   my @exempt = ();
51   push @exempt,
52        sprintf("$money_char%.2f&nbsp;per&nbsp;month", $cust_main_county->exempt_amount )
53     if $cust_main_county->exempt_amount > 0;
54
55   push @exempt, 'Setup&nbsp;fee'
56     if $cust_main_county->setuptax =~ /^Y$/i;
57
58   push @exempt, 'Recurring&nbsp;fee'
59     if $cust_main_county->recurtax =~ /^Y$/i;
60
61   [ map [ {'data'=>$_} ], @exempt ];
62 };
63
64 my $oldrow;
65 my $cell_style;
66 my $cell_style_sub = sub {
67   my $row = shift;
68   if ( $oldrow ne $row ) {
69     if ( $oldrow ) {
70       if ( $oldrow->country ne $row->country ) {
71         $cell_style = 'border-top:1px solid #000000';
72       } elsif ( $oldrow->state ne $row->state ) {
73         $cell_style = 'border-top:1px solid #cccccc'; #default?
74       } elsif ( $oldrow->state eq $row->state ) {
75         #$cell_style = 'border-top:dashed 1px dark gray';
76         $cell_style = 'border-top:1px dashed #cccccc';
77       }
78     }
79     $oldrow = $row;
80   }
81   return $cell_style;
82 };
83
84 #my $edit_link = [ "${p}edit/cust_main_county.html", 'taxnum' ];
85 my $edit_link = [ 'javascript:void(0);', sub { ''; } ];
86
87 my $edit_onclick = sub {
88   my $row = shift;
89   my $taxnum = $row->taxnum;
90   include( '/elements/popup_link_onclick.html',
91              'action'      => "${p}edit/cust_main_county.html?$taxnum",
92              'actionlabel' => 'Edit tax rate',
93              'height'      => 420,
94              #default# 'width'  => 540,
95              #default# 'color' => '#333399',
96          );
97 };
98
99 sub expand_link {
100   my %param = @_;
101
102   my $taxnum = $param{'row'}->taxnum;
103   my $url = "${p}edit/cust_main_county-expand.cgi?$taxnum";
104
105   '<FONT SIZE="-1">'.
106     include( '/elements/popup_link.html',
107                'label'       => $param{'label'},
108                'action'      => $url,
109                'actionlabel' => $param{'desc'},
110                'height'      => 420,
111                #default# 'width'  => 540,
112                #default# 'color' => '#333399',
113            ).
114   '</FONT>';
115 }
116
117 sub separate_taxclasses_link {
118   my( $row ) = @_;
119   my $taxnum = $row->taxnum;
120   my $url = "${p}edit/process/cust_main_county-expand.cgi?taxclass=1;taxnum=$taxnum";
121
122   qq!<FONT SIZE="-1"><A HREF="$url">!;
123 }
124
125 </%once>
126 <%init>
127
128 die "access denied"
129   unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
130
131 #my $conf = new FS::Conf;
132 #my $money_char = $conf->config('money_char') || '$';
133 my $enable_taxclasses = $conf->exists('enable_taxclasses');
134
135 my @menubar;
136
137 my $html_init =
138   "Click on <u>add states</u> to specify a country's tax rates by state or province.
139    <BR>Click on <u>add counties</u> to specify a state's tax rates by county.";
140 $html_init .= "<BR>Click on <u>separate taxclasses</u> to specify taxes per taxclass."
141   if $enable_taxclasses;
142 $html_init .= '<BR><BR>';
143
144 $html_init .= include('/elements/init_overlib.html');
145
146 my $title = '';
147
148 my $country = '';
149 if ( $cgi->param('country') =~ /^(\w\w)$/ ) {
150   $country = $1;
151   $title = $country;
152 }
153 $cgi->delete('country');
154
155 my $state = '';
156 if ( $cgi->param('state') =~ /^([\w \-\'\[\]]+)$/ ) {
157   $state = $1;
158   $title = "$state, $title";
159 }
160 $cgi->delete('state');
161
162 my $county = '';
163 if ( $cgi->param('county') =~ /^([\w \-\'\[\]]+)$/ ) {
164   $county = $1;
165   $title = "$county county, $title";
166 }
167 $cgi->delete('county');
168
169 $title = " for $title" if $title;
170
171 my $taxclass = '';
172 if ( $cgi->param('taxclass') =~ /^([\w \-]+)$/ ) {
173   $taxclass = $1;
174   $title .= " for $taxclass tax class";
175 }
176 $cgi->delete('taxclass');
177
178 if ( $country || $taxclass ) {
179   push @menubar, 'View all tax rates' => $p.'browse/cust_main_county.cgi';
180 }
181
182 $cgi->param('dummy', 1);
183
184 my $country_filter_change =
185   "window.location = '".
186   $cgi->self_url. ";country=' + this.options[this.selectedIndex].value;";
187
188 #restore this so pagination works
189 $cgi->param('country',  $country) if $country;
190 $cgi->param('state',    $state  ) if $state;
191 $cgi->param('county',   $county ) if $county;
192 $cgi->param('taxclass', $county ) if $taxclass;
193
194 my $html_posttotal =
195   '(show country: '.
196   qq(<SELECT NAME="country" onChange="$country_filter_change">).
197   qq(<OPTION VALUE="">(all)\n).
198   join("\n", map qq[<OPTION VALUE="$_"].
199                    ( $_ eq $country ? 'SELECTED' : '' ).
200                    '>'. code2country($_). " ($_)",
201                  @all_countries
202       ).
203   '</SELECT>)';
204
205 my $bulk_popup_link = 
206   include( '/elements/popup_link_onclick.html',
207              'action'      => "${p}edit/bulk_cust_main_county.html?MAGIC_taxnum_MAGIC",
208              'actionlabel' => 'Bulk add new tax',
209              'nofalse'     => 1,
210              'height'      => 420,
211              #default# 'width'  => 540,
212              #default# 'color' => '#333399',
213          );
214
215 my $html_foot = <<END;
216 <SCRIPT TYPE="text/javascript">
217
218   function setAll(setTo) {
219     theForm = document.taxesForm;
220     for (i=0,n=theForm.elements.length;i<n;i++) {
221       if (theForm.elements[i].name.indexOf("cust_main_county") != -1) {
222         theForm.elements[i].checked = setTo;
223       }
224     }
225   }
226
227   function toggleAll() {
228     theForm = document.taxesForm;
229     for (i=0,n=theForm.elements.length;i<n;i++) {
230       if (theForm.elements[i].name.indexOf("cust_main_county") != -1) {
231         if ( theForm.elements[i].checked == true ) {
232           theForm.elements[i].checked = false;
233         } else {
234           theForm.elements[i].checked = true;
235         }
236       }
237     }
238   }
239
240   function bulkPopup() {
241     var bulk_popup_link = "$bulk_popup_link";
242     var bulkstring = '';
243     theForm = document.taxesForm;
244     for (i=0,n=theForm.elements.length;i<n;i++) {
245       if (    theForm.elements[i].name.indexOf("cust_main_county") != -1
246            && theForm.elements[i].checked == true
247          ) {
248         var name = theForm.elements[i].name;
249         var taxnum = name.replace(/cust_main_county/, '');
250         if ( bulkstring != '' ) {
251           bulkstring = bulkstring + ',';
252         }
253         bulkstring = bulkstring + taxnum;
254        
255       }
256     }
257     if ( bulk_popup_link.length > 1920 ) { // IE 2083 URL limit
258       alert('Too many selections'); // should do some session thing...
259       return false;
260     }
261     bulk_popup_link = bulk_popup_link.replace(/MAGIC_taxnum_MAGIC/, bulkstring);
262     eval(bulk_popup_link);
263   }
264
265 </SCRIPT>
266
267 <BR>
268 <A HREF="javascript:setAll(true)">select all</A> |
269 <A HREF="javascript:setAll(false)">unselect all</A> |
270 <A HREF="javascript:toggleAll()">toggle all</A>
271 <BR><BR>
272 <A HREF="javascript:void(0);" onClick="bulkPopup();">Add new tax to selected</A>
273
274 END
275
276 my $hashref = {};
277 my $count_query = 'SELECT COUNT(*) FROM cust_main_county';
278 if ( $country ) {
279   $hashref->{'country'} = $country;
280   $count_query .= ' WHERE country = '. dbh->quote($country);
281 }
282 if ( $state ) {
283   $hashref->{'state'} = $state;
284   $count_query .= '   AND state   = '. dbh->quote($state);
285 }
286 if ( $county ) {
287   $hashref->{'country'} = $country;
288   $count_query .= '   AND county  = '. dbh->quote($county);
289 }
290 if ( $taxclass ) {
291   $hashref->{'taxclass'} = $taxclass;
292   $count_query .= ( $count_query =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
293                   ' taxclass  = '. dbh->quote($taxclass);
294 }
295
296
297 $cell_style = '';
298
299 my @header        = ( 'Country', 'State/Province', 'County',);
300 my @header2       = ( '', '', '', );
301 my @links         = ( '', '', '', );
302 my @link_onclicks = ( '', '', '', );
303 my $align = 'lll';
304
305 my @fields = (
306   sub { my $country = shift->country;
307         code2country($country). " ($country)";
308       },
309   sub { state_label($_[0]->state, $_[0]->country).
310         ( $_[0]->state
311             ? ''
312             : '&nbsp'. expand_link( desc  => 'Add States',
313                                     row   => $_[0],
314                                     label => 'add&nbsp;states',
315                                   )
316         )
317       },
318   sub { $_[0]->county || '(all)&nbsp'.
319                          expand_link( desc  => 'Add Counties',
320                                       row   => $_[0],
321                                       label => 'add&nbsp;counties',
322                                     )
323       },
324 );
325
326 my @color = (
327   '000000',
328   sub { shift->state  ? '000000' : '999999' },
329   sub { shift->county ? '000000' : '999999' },
330 );
331
332 if ( $conf->exists('enable_taxclasses') ) {
333   push @header, qq!Tax class (<A HREF="${p}edit/part_pkg_taxclass.html">add new</A>)!;
334   push @header2, '(per-package classification)';
335   push @fields, sub { $_[0]->taxclass || '(all)&nbsp'.
336                        separate_taxclasses_link($_[0], 'Separate Taxclasses').
337                        'separate&nbsp;taxclasses</A></FONT>'
338                     };
339   push @color, sub { shift->taxclass ? '000000' : '999999' };
340   push @links, '';
341   push @link_onclicks, '';
342   $align .= 'l';
343 }
344
345 push @header,
346               '', #checkbox column
347               'Tax name',
348               'Rate', #'Tax',
349               'Exemptions',
350               ;
351
352 push @header2,
353                '',
354                '(printed on invoices)',
355                '',
356                '',
357                ;
358
359 my $newregion = 1;
360 my $cb_oldrow = '';
361 my $cb_sub = sub {
362   my $cust_main_county = shift;
363
364   if ( $cb_oldrow ) {
365     if (    $cb_oldrow->country  ne $cust_main_county->country 
366          || $cb_oldrow->state    ne $cust_main_county->state  
367          || $cb_oldrow->county   ne $cust_main_county->county  
368          || $cb_oldrow->taxclass ne $cust_main_county->taxclass )
369     {
370       $newregion = 1;
371     } else {
372       $newregion = 0;
373     }  
374     
375   } else {
376     $newregion = 1;
377   }
378   $cb_oldrow = $cust_main_county;
379
380   if ( $newregion ) {
381     my $taxnum = $cust_main_county->taxnum;
382     qq!<INPUT NAME="cust_main_county$taxnum" TYPE="checkbox" VALUE="1">!;
383   } else {
384     '';
385   }
386 };
387
388 push @fields, 
389   $cb_sub,
390   sub { shift->taxname || 'Tax' },
391   sub { shift->tax. '%&nbsp;<FONT SIZE="-1">(edit)</FONT>' },
392   $exempt_sub,
393 ;
394
395 push @color,
396   '000000',
397   sub { shift->taxname ? '000000' : '666666' },
398   sub { shift->tax     ? '000000' : '666666' },
399   '000000',
400 ;
401
402 $align .= 'clrl';
403
404 my @cell_style = map $cell_style_sub, (1..scalar(@header));
405
406 push @links,         '', '', $edit_link,    '';
407 push @link_onclicks, '', '', $edit_onclick, '';
408
409 </%init>