1 package FS::tax_rate_location;
4 use base qw( FS::Record );
5 use FS::Record qw( qsearch qsearchs dbh );
6 use FS::Misc qw( csv_from_fixed );
10 FS::tax_rate_location - Object methods for tax_rate_location records
14 use FS::tax_rate_location;
16 $record = new FS::tax_rate_location \%hash;
17 $record = new FS::tax_rate_location { 'column' => 'value' };
19 $error = $record->insert;
21 $error = $new_record->replace($old_record);
23 $error = $record->delete;
25 $error = $record->check;
29 An FS::tax_rate_location object represents an example. FS::tax_rate_location inherits from
30 FS::Record. The following fields are currently supported:
34 =item taxratelocationnum
36 Primary key (assigned automatically for new tax_rate_locations)
44 A unique geographic location code provided by the data vendor
60 If 'Y' this record is no longer active.
71 Creates a new tax rate location. To add the record to the database, see
74 Note that this stores the hash reference, not a distinct copy of the hash it
75 points to. You can ask the object for a copy with the I<hash> method.
79 sub table { 'tax_rate_location'; }
83 Adds this record to the database. If there is an error, returns the error,
84 otherwise returns false.
90 Delete this record from the database.
95 return "Can't delete tax rate locations. Set disable to 'Y' instead.";
96 # check that it is unused in any cust_bill_pkg_tax_location records instead?
99 =item replace OLD_RECORD
101 Replaces the OLD_RECORD with this one in the database. If there is an error,
102 returns the error, otherwise returns false.
108 Checks all fields to make sure this is a valid tax rate location. If there is
109 an error, returns the error, otherwise returns false. Called by the insert
118 $self->ut_numbern('taxratelocationnum')
119 || $self->ut_textn('data_vendor')
120 || $self->ut_alpha('geocode')
121 || $self->ut_textn('city')
122 || $self->ut_textn('county')
123 || $self->ut_textn('state')
124 || $self->ut_enum('disabled', [ '', 'Y' ])
126 return $error if $error;
129 $t = qsearchs( 'tax_rate_location',
131 ( map { $_ => $self->$_ } qw( data_vendor geocode ) ),
134 unless $self->disabled;
136 $t = $self->by_key( $self->taxratelocationnum )
137 if ( !$t && $self->taxratelocationnum );
139 return "geocode ". $self->geocode. " already in use for this vendor"
140 if ( $t && $t->taxratelocationnum != $self->taxratelocationnum );
142 return "may only be disabled"
143 if ( $t && scalar( grep { $t->$_ ne $self->$_ }
144 grep { $_ ne 'disabled' }
163 my ($param, $job) = @_;
165 my $fh = $param->{filehandle};
166 my $format = $param->{'format'};
174 my @column_lengths = ();
175 my @column_callbacks = ();
176 if ( $format eq 'cch-fixed' || $format eq 'cch-fixed-update' ) {
177 $format =~ s/-fixed//;
178 my $trim = sub { my $r = shift; $r =~ s/^\s*//; $r =~ s/\s*$//; $r };
179 push @column_lengths, qw( 28 25 2 10 );
180 push @column_lengths, 1 if $format eq 'cch-update';
181 push @column_callbacks, $trim foreach (@column_lengths);
185 my ( $count, $last, $min_sec ) = (0, time, 5); #progressbar
186 if ( $job || scalar(@column_callbacks) ) {
188 csv_from_fixed(\$fh, \$count, \@column_lengths, \@column_callbacks);
189 return $error if $error;
192 if ( $format eq 'cch' || $format eq 'cch-update' ) {
193 @fields = qw( city county state geocode );
194 push @fields, 'actionflag' if $format eq 'cch-update';
199 $hash->{'data_vendor'} ='cch';
201 if (exists($hash->{'actionflag'}) && $hash->{'actionflag'} eq 'D') {
202 delete($hash->{actionflag});
204 $hash->{disabled} = '';
205 my $tax_rate_location = qsearchs('tax_rate_location', $hash);
206 return "Can't find tax_rate_location to delete: ".
207 join(" ", map { "$_ => ". $hash->{$_} } @fields)
208 unless $tax_rate_location;
210 $tax_rate_location->disabled('Y');
211 my $error = $tax_rate_location->replace;
212 return $error if $error;
214 delete($hash->{$_}) foreach (keys %$hash);
217 delete($hash->{'actionflag'});
223 } elsif ( $format eq 'extended' ) {
224 die "unimplemented\n";
228 die "unknown format $format";
231 eval "use Text::CSV_XS;";
234 my $csv = new Text::CSV_XS;
238 local $SIG{HUP} = 'IGNORE';
239 local $SIG{INT} = 'IGNORE';
240 local $SIG{QUIT} = 'IGNORE';
241 local $SIG{TERM} = 'IGNORE';
242 local $SIG{TSTP} = 'IGNORE';
243 local $SIG{PIPE} = 'IGNORE';
245 my $oldAutoCommit = $FS::UID::AutoCommit;
246 local $FS::UID::AutoCommit = 0;
249 while ( defined($line=<$fh>) ) {
250 $csv->parse($line) or do {
251 $dbh->rollback if $oldAutoCommit;
252 return "can't parse: ". $csv->error_input();
255 if ( $job ) { # progress bar
256 if ( time - $min_sec > $last ) {
257 my $error = $job->update_statustext(
258 int( 100 * $imported / $count )
260 die $error if $error;
265 my @columns = $csv->fields();
267 my %tax_rate_location = ();
268 foreach my $field ( @fields ) {
269 $tax_rate_location{$field} = shift @columns;
271 if ( scalar( @columns ) ) {
272 $dbh->rollback if $oldAutoCommit;
273 return "Unexpected trailing columns in line (wrong format?): $line";
276 my $error = &{$hook}(\%tax_rate_location);
278 $dbh->rollback if $oldAutoCommit;
282 if (scalar(keys %tax_rate_location)) { #inserts only
284 my $tax_rate_location = new FS::tax_rate_location( \%tax_rate_location );
285 $error = $tax_rate_location->insert;
288 $dbh->rollback if $oldAutoCommit;
289 return "can't insert tax_rate_location for $line: $error";
298 $dbh->commit or die $dbh->errstr if $oldAutoCommit;
300 return "Empty file!" unless ($imported || $format eq 'cch-update');
308 Currently somewhat specific to CCH supplied data.
312 L<FS::Record>, schema.html from the base documentation.