$self->ut_numbern('taxnum')
|| $self->ut_text('geocode')
|| $self->ut_textn('data_vendor')
- || $self->ut_textn('location')
+ || $self->ut_cch_textn('location')
|| $self->ut_foreign_key('taxclassnum', 'tax_class', 'taxclassnum')
|| $self->ut_snumbern('effective_date')
|| $self->ut_float('tax')
|| $self->ut_floatn('excessfee')
|| $self->ut_floatn('feemax')
|| $self->ut_numbern('maxtype')
- || $self->ut_textn('taxname')
+ || $self->ut_cch_textn('taxname')
|| $self->ut_numbern('taxauth')
|| $self->ut_numbern('basetype')
|| $self->ut_numbern('passtype')
}
+#ut_text / ut_textn w/ ` added cause now that's in the data
+sub ut_cch_textn {
+ my($self,$field)=@_;
+ $self->getfield($field)
+ =~ /^([\wô \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]\<\>\`]*)$/
+ or return gettext('illegal_or_empty_text'). " $field: ".
+ $self->getfield($field);
+ $self->setfield($field,$1);
+ '';
+
+}
+
=item taxclass_description
Returns the human understandable value associated with the related
}
my $maxtype = $self->maxtype || 0;
- if ($maxtype != 0 && $maxtype != 9) {
+ if ($maxtype != 0 && $maxtype != 1 && $maxtype != 9) {
return $self->_fatal_or_null( 'tax with "'.
$self->maxtype_name. '" threshold'
);
}
- #
- # XXX insert exemption handling here
+ # XXX handle excessrate (use_excessrate) / excessfee /
+ # taxbase/feebase / taxmax/feemax
+ # and eventually exemptions
#
# the tax or fee is applied to taxbase or feebase and then
# the excessrate or excess fee is applied to taxmax or feemax
- #
$amount += $taxable_charged * $self->tax;
$amount += $taxable_units * $self->fee;
}
}
-=item tax_on_tax CUST_MAIN
+=item tax_on_tax CUST_LOCATION
Returns a list of taxes which are candidates for taxing taxes for the
-given customer (see L<FS::cust_main>)
+given service location (see L<FS::cust_location>)
=cut
sub tax_on_tax {
#akshun
my $self = shift;
- my $cust_main = shift;
+ my $cust_location = shift;
warn "looking up taxes on tax ". $self->taxnum. " for customer ".
- $cust_main->custnum
+ $cust_location->custnum
if $DEBUG;
- my $geocode = $cust_main->geocode($self->data_vendor);
+ my $geocode = $cust_location->geocode($self->data_vendor);
# CCH oddness in m2m
my $dbh = dbh;
}
- for (grep { !exists($delete{$_}) } keys %insert) {
+ my @replace = grep { exists($delete{$_}) } keys %insert;
+ for (@replace) {
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
}
}
- my $tax_rate = new FS::tax_rate( $insert{$_} );
- my $error = $tax_rate->insert;
+ my $old = qsearchs( 'tax_rate', $delete{$_} );
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- my $hashref = $insert{$_};
- $line = join(", ", map { "$_ => ". $hashref->{$_} } keys(%$hashref) );
- return "can't insert tax_rate for $line: $error";
+ if ( $old ) {
+
+ my $new = new FS::tax_rate({ $old->hash, %{$insert{$_}}, 'manual' => '' });
+ $new->taxnum($old->taxnum);
+ my $error = $new->replace($old);
+
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ my $hashref = $insert{$_};
+ $line = join(", ", map { "$_ => ". $hashref->{$_} } keys(%$hashref) );
+ return "can't replace tax_rate for $line: $error";
+ }
+
+ $imported++;
+
+ } else {
+
+ $old = delete $delete{$_};
+ warn "WARNING: can't find tax_rate to replace (inserting instead and continuing) for: ".
+ #join(" ", map { "$_ => ". $old->{$_} } @fields);
+ join(" ", map { "$_ => ". $old->{$_} } keys(%$old) );
}
$imported++;
}
- for (grep { exists($delete{$_}) } keys %insert) {
+ for (grep { !exists($delete{$_}) } keys %insert) {
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
}
}
- #remove even if the rate doesn't match,
- # geocode/taxclassnum/taxname/etc. should be enough
- delete $delete{$_}->{tax};
- my $old = qsearchs( 'tax_rate', $delete{$_} );
- unless ($old) {
- $dbh->rollback if $oldAutoCommit;
- $old = $delete{$_};
- return "can't find tax_rate to replace for: ".
- #join(" ", map { "$_ => ". $old->{$_} } @fields);
- join(" ", map { "$_ => ". $old->{$_} } keys(%$old) );
- }
- my $new = new FS::tax_rate({ $old->hash, %{$insert{$_}}, 'manual' => '' });
- $new->taxnum($old->taxnum);
- my $error = $new->replace($old);
+ my $tax_rate = new FS::tax_rate( $insert{$_} );
+ my $error = $tax_rate->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
my $hashref = $insert{$_};
$line = join(", ", map { "$_ => ". $hashref->{$_} } keys(%$hashref) );
- return "can't replace tax_rate for $line: $error";
+ return "can't insert tax_rate for $line: $error";
}
$imported++;
- $imported++;
}
for (grep { !exists($insert{$_}) } keys %delete) {
my $file = lc($name). 'file';
unless ($files{$file}) {
- $error = "No $name supplied";
+ #$error = "No $name supplied";
next;
}
next if $name eq 'DETAIL' && $format =~ /update/;
unlink $filename or warn "Can't delete $filename: $!"
unless $keep_cch_files;
push @insert_list, $name, $insertname, $import_sub, $format;
- if ( $name eq 'GEOCODE' ) { #handle this whole ordering issue better
+ if ( $name eq 'GEOCODE' || $name eq 'CODE' ) { #handle this whole ordering issue better
unshift @predelete_list, $name, $deletename, $import_sub, $format;
} else {
unshift @delete_list, $name, $deletename, $import_sub, $format;
'DETAIL', "$dir/".$files{detailfile}, \&FS::tax_rate::batch_import, $format
if $format =~ /update/;
+ my %addl_param = ();
+ if ( $param->{'delete_only'} ) {
+ $addl_param{'delete_only'} = $param->{'delete_only'};
+ @insert_list = ()
+ }
+
$error ||= _perform_cch_tax_import( $job,
[ @predelete_list ],
[ @insert_list ],
[ @delete_list ],
+ \%addl_param,
);
sub _perform_cch_tax_import {
- my ( $job, $predelete_list, $insert_list, $delete_list ) = @_;
+ my ( $job, $predelete_list, $insert_list, $delete_list, $addl_param ) = @_;
+ $addl_param ||= {};
my $error = '';
foreach my $list ($predelete_list, $insert_list, $delete_list) {
my $fmt = "$format-update";
$fmt = $format. ( lc($name) eq 'zip' ? '-zip' : '' );
open my $fh, "< $file" or $error ||= "Can't open $name file $file: $!";
- $error ||= &{$method}({ 'filehandle' => $fh, 'format' => $fmt }, $job);
+ my $param = { 'filehandle' => $fh,
+ 'format' => $fmt,
+ %$addl_param,
+ };
+ $error ||= &{$method}($param, $job);
close $fh;
}
}
=head1 SEE ALSO
-L<FS::Record>, L<FS::cust_main>, L<FS::cust_bill>, schema.html from the base
-documentation.
+L<FS::Record>, L<FS::cust_location>, L<FS::cust_bill>
=cut