a9a4a85bd30c2821f584375d29f0fdcf6acac564
[freeside.git] / FS / FS / cust_main_county.pm
1 package FS::cust_main_county;
2
3 use strict;
4 use vars qw( @ISA @EXPORT_OK $conf
5              @cust_main_county %cust_main_county $countyflag );
6 use Exporter;
7 use FS::Record qw( qsearch );
8
9 @ISA = qw( FS::Record );
10 @EXPORT_OK = qw( regionselector );
11
12 @cust_main_county = ();
13 $countyflag = '';
14
15 #ask FS::UID to run this stuff for us later
16 $FS::UID::callback{'FS::cust_main_county'} = sub { 
17   $conf = new FS::Conf;
18 };
19
20 =head1 NAME
21
22 FS::cust_main_county - Object methods for cust_main_county objects
23
24 =head1 SYNOPSIS
25
26   use FS::cust_main_county;
27
28   $record = new FS::cust_main_county \%hash;
29   $record = new FS::cust_main_county { 'column' => 'value' };
30
31   $error = $record->insert;
32
33   $error = $new_record->replace($old_record);
34
35   $error = $record->delete;
36
37   $error = $record->check;
38
39   ($county_html, $state_html, $country_html) =
40     FS::cust_main_county::regionselector( $county, $state, $country );
41
42 =head1 DESCRIPTION
43
44 An FS::cust_main_county object represents a tax rate, defined by locale.
45 FS::cust_main_county inherits from FS::Record.  The following fields are
46 currently supported:
47
48 =over 4
49
50 =item taxnum - primary key (assigned automatically for new tax rates)
51
52 =item state
53
54 =item county
55
56 =item country
57
58 =item tax - percentage
59
60 =item taxclass
61
62 =item exempt_amount
63
64 =back
65
66 =head1 METHODS
67
68 =over 4
69
70 =item new HASHREF
71
72 Creates a new tax rate.  To add the tax rate to the database, see L<"insert">.
73
74 =cut
75
76 sub table { 'cust_main_county'; }
77
78 =item insert
79
80 Adds this tax rate to the database.  If there is an error, returns the error,
81 otherwise returns false.
82
83 =item delete
84
85 Deletes this tax rate from the database.  If there is an error, returns the
86 error, otherwise returns false.
87
88 =item replace OLD_RECORD
89
90 Replaces the OLD_RECORD with this one in the database.  If there is an error,
91 returns the error, otherwise returns false.
92
93 =item check
94
95 Checks all fields to make sure this is a valid tax rate.  If there is an error,
96 returns the error, otherwise returns false.  Called by the insert and replace
97 methods.
98
99 =cut
100
101 sub check {
102   my $self = shift;
103
104   $self->amount(0) unless $self->amount;
105
106   $self->ut_numbern('taxnum')
107     || $self->ut_textn('state')
108     || $self->ut_textn('county')
109     || $self->ut_text('country')
110     || $self->ut_float('tax')
111     || $self->ut_textn('taxclass') # ...
112     || $self->ut_money('amount')
113   ;
114
115 }
116
117 =back
118
119 =head1 SUBROUTINES
120
121 =over 4
122
123 =item regionselector [ COUNTY STATE COUNTRY [ PREFIX [ ONCHANGE ] ] ]
124
125 =cut
126
127 sub regionselector {
128   my ( $selected_county, $selected_state, $selected_country,
129        $prefix, $onchange ) = @_;
130
131   $countyflag = 0;
132
133 #  unless ( @cust_main_county ) { #cache 
134     @cust_main_county = qsearch('cust_main_county', {} );
135     foreach my $c ( @cust_main_county ) {
136       $countyflag=1 if $c->county;
137       push @{$cust_main_county{$c->country}{$c->state}}, $c->county;
138     }
139 #  }
140   $countyflag=1 if $selected_county;
141
142   my $script_html = <<END;
143     <SCRIPT>
144     function opt(what,value,text) {
145       var optionName = new Option(text, value, false, false);
146       var length = what.length;
147       what.options[length] = optionName;
148     }
149     function ${prefix}country_changed(what) {
150       country = what.options[what.selectedIndex].text;
151       for ( var i = what.form.${prefix}state.length; i >= 0; i-- )
152           what.form.${prefix}state.options[i] = null;
153 END
154       #what.form.${prefix}state.options[0] = new Option('', '', false, true);
155
156   foreach my $country ( sort keys %cust_main_county ) {
157     $script_html .= "\nif ( country == \"$country\" ) {\n";
158     foreach my $state ( sort keys %{$cust_main_county{$country}} ) {
159       my $text = $state || '(n/a)';
160       $script_html .= qq!opt(what.form.${prefix}state, "$state", "$text");\n!;
161     }
162     $script_html .= "}\n";
163   }
164
165   $script_html .= <<END;
166     }
167     function ${prefix}state_changed(what) {
168 END
169
170   if ( $countyflag ) {
171     $script_html .= <<END;
172       state = what.options[what.selectedIndex].text;
173       country = what.form.${prefix}country.options[what.form.${prefix}country.selectedIndex].text;
174       for ( var i = what.form.${prefix}county.length; i >= 0; i-- )
175           what.form.${prefix}county.options[i] = null;
176 END
177
178     foreach my $country ( sort keys %cust_main_county ) {
179       $script_html .= "\nif ( country == \"$country\" ) {\n";
180       foreach my $state ( sort keys %{$cust_main_county{$country}} ) {
181         $script_html .= "\nif ( state == \"$state\" ) {\n";
182           foreach my $county ( sort @{$cust_main_county{$country}{$state}} ) {
183             my $text = $county || '(n/a)';
184             $script_html .=
185               qq!opt(what.form.${prefix}county, "$county", "$text");\n!;
186           }
187         $script_html .= "}\n";
188       }
189       $script_html .= "}\n";
190     }
191   }
192
193   $script_html .= <<END;
194     }
195     </SCRIPT>
196 END
197
198   my $county_html = $script_html;
199   if ( $countyflag ) {
200     $county_html .= qq!<SELECT NAME="${prefix}county" onChange="$onchange">!;
201     $county_html .= '</SELECT>';
202   } else {
203     $county_html .=
204       qq!<INPUT TYPE="hidden" NAME="${prefix}county" VALUE="$selected_county">!;
205   }
206
207   my $state_html = qq!<SELECT NAME="${prefix}state" !.
208                    qq!onChange="${prefix}state_changed(this); $onchange">!;
209   foreach my $state ( sort keys %{ $cust_main_county{$selected_country} } ) {
210     my $text = $state || '(n/a)';
211     my $selected = $state eq $selected_state ? 'SELECTED' : '';
212     $state_html .= "\n<OPTION $selected VALUE=$state>$text</OPTION>"
213   }
214   $state_html .= '</SELECT>';
215
216   $state_html .= '</SELECT>';
217
218   my $country_html = qq!<SELECT NAME="${prefix}country" !.
219                      qq!onChange="${prefix}country_changed(this); $onchange">!;
220   my $countrydefault = $conf->config('countrydefault') || 'US';
221   foreach my $country (
222     sort { ($b eq $countrydefault) <=> ($a eq $countrydefault) or $a cmp $b }
223       keys %cust_main_county
224   ) {
225     my $selected = $country eq $selected_country ? ' SELECTED' : '';
226     $country_html .= "\n<OPTION$selected>$country</OPTION>"
227   }
228   $country_html .= '</SELECT>';
229
230   ($county_html, $state_html, $country_html);
231
232 }
233
234 =back
235
236 =head1 BUGS
237
238 regionselector?  putting web ui components in here?  they should probably live
239 somewhere else...
240
241 =head1 SEE ALSO
242
243 L<FS::Record>, L<FS::cust_main>, L<FS::cust_bill>, schema.html from the base
244 documentation.
245
246 =cut
247
248 1;
249