RADIUS groups on the way!
[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 =back
61
62 =head1 METHODS
63
64 =over 4
65
66 =item new HASHREF
67
68 Creates a new tax rate.  To add the tax rate to the database, see L<"insert">.
69
70 =cut
71
72 sub table { 'cust_main_county'; }
73
74 =item insert
75
76 Adds this tax rate to the database.  If there is an error, returns the error,
77 otherwise returns false.
78
79 =item delete
80
81 Deletes this tax rate from the database.  If there is an error, returns the
82 error, otherwise returns false.
83
84 =item replace OLD_RECORD
85
86 Replaces the OLD_RECORD with this one in the database.  If there is an error,
87 returns the error, otherwise returns false.
88
89 =item check
90
91 Checks all fields to make sure this is a valid tax rate.  If there is an error,
92 returns the error, otherwise returns false.  Called by the insert and replace
93 methods.
94
95 =cut
96
97 sub check {
98   my $self = shift;
99
100   $self->ut_numbern('taxnum')
101     || $self->ut_textn('state')
102     || $self->ut_textn('county')
103     || $self->ut_text('country')
104     || $self->ut_float('tax')
105   ;
106
107 }
108
109 =back
110
111 =head1 SUBROUTINES
112
113 =over 4
114
115 =item regionselector [ COUNTY STATE COUNTRY [ PREFIX [ ONCHANGE ] ] ]
116
117 =cut
118
119 sub regionselector {
120   my ( $selected_county, $selected_state, $selected_country,
121        $prefix, $onchange ) = @_;
122
123   $countyflag = 0;
124
125 #  unless ( @cust_main_county ) { #cache 
126     @cust_main_county = qsearch('cust_main_county', {} );
127     foreach my $c ( @cust_main_county ) {
128       $countyflag=1 if $c->county;
129       push @{$cust_main_county{$c->country}{$c->state}}, $c->county;
130     }
131 #  }
132   $countyflag=1 if $selected_county;
133
134   my $script_html = <<END;
135     <SCRIPT>
136     function opt(what,value,text) {
137       var optionName = new Option(text, value, false, false);
138       var length = what.length;
139       what.options[length] = optionName;
140     }
141     function ${prefix}country_changed(what) {
142       country = what.options[what.selectedIndex].text;
143       for ( var i = what.form.${prefix}state.length; i >= 0; i-- )
144           what.form.${prefix}state.options[i] = null;
145 END
146       #what.form.${prefix}state.options[0] = new Option('', '', false, true);
147
148   foreach my $country ( sort keys %cust_main_county ) {
149     $script_html .= "\nif ( country == \"$country\" ) {\n";
150     foreach my $state ( sort keys %{$cust_main_county{$country}} ) {
151       my $text = $state || '(n/a)';
152       $script_html .= qq!opt(what.form.${prefix}state, "$state", "$text");\n!;
153     }
154     $script_html .= "}\n";
155   }
156
157   $script_html .= <<END;
158     }
159     function ${prefix}state_changed(what) {
160 END
161
162   if ( $countyflag ) {
163     $script_html .= <<END;
164       state = what.options[what.selectedIndex].text;
165       country = what.form.${prefix}country.options[what.form.${prefix}country.selectedIndex].text;
166       for ( var i = what.form.${prefix}county.length; i >= 0; i-- )
167           what.form.${prefix}county.options[i] = null;
168 END
169
170     foreach my $country ( sort keys %cust_main_county ) {
171       $script_html .= "\nif ( country == \"$country\" ) {\n";
172       foreach my $state ( sort keys %{$cust_main_county{$country}} ) {
173         $script_html .= "\nif ( state == \"$state\" ) {\n";
174           foreach my $county ( sort @{$cust_main_county{$country}{$state}} ) {
175             my $text = $county || '(n/a)';
176             $script_html .=
177               qq!opt(what.form.${prefix}county, "$county", "$text");\n!;
178           }
179         $script_html .= "}\n";
180       }
181       $script_html .= "}\n";
182     }
183   }
184
185   $script_html .= <<END;
186     }
187     </SCRIPT>
188 END
189
190   my $county_html = $script_html;
191   if ( $countyflag ) {
192     $county_html .= qq!<SELECT NAME="${prefix}county" onChange="$onchange">!;
193     $county_html .= '</SELECT>';
194   } else {
195     $county_html .=
196       qq!<INPUT TYPE="hidden" NAME="${prefix}county" VALUE="$selected_county">!;
197   }
198
199   my $state_html = qq!<SELECT NAME="${prefix}state" !.
200                    qq!onChange="${prefix}state_changed(this); $onchange">!;
201   foreach my $state ( sort keys %{ $cust_main_county{$selected_country} } ) {
202     my $text = $state || '(n/a)';
203     my $selected = $state eq $selected_state ? 'SELECTED' : '';
204     $state_html .= "\n<OPTION $selected VALUE=$state>$text</OPTION>"
205   }
206   $state_html .= '</SELECT>';
207
208   $state_html .= '</SELECT>';
209
210   my $country_html = qq!<SELECT NAME="${prefix}country" !.
211                      qq!onChange="${prefix}country_changed(this); $onchange">!;
212   my $countrydefault = $conf->config('countrydefault') || 'US';
213   foreach my $country (
214     sort { ($b eq $countrydefault) <=> ($a eq $countrydefault) or $a cmp $b }
215       keys %cust_main_county
216   ) {
217     my $selected = $country eq $selected_country ? ' SELECTED' : '';
218     $country_html .= "\n<OPTION$selected>$country</OPTION>"
219   }
220   $country_html .= '</SELECT>';
221
222   ($county_html, $state_html, $country_html);
223
224 }
225
226 =back
227
228 =head1 BUGS
229
230 regionselector?  putting web ui components in here?  they should probably live
231 somewhere else...
232
233 =head1 SEE ALSO
234
235 L<FS::Record>, L<FS::cust_main>, L<FS::cust_bill>, schema.html from the base
236 documentation.
237
238 =cut
239
240 1;
241