|| $self->ut_textn('data_vendor')
|| $self->ut_textn('location')
|| $self->ut_foreign_key('taxclassnum', 'tax_class', 'taxclassnum')
- || $self->ut_numbern('effective_date')
+ || $self->ut_snumbern('effective_date')
|| $self->ut_float('tax')
|| $self->ut_floatn('excessrate')
|| $self->ut_money('taxbase')
|| $self->ut_enum('setuptax', [ '', 'Y' ] )
|| $self->ut_enum('recurtax', [ '', 'Y' ] )
|| $self->ut_enum('manual', [ '', 'Y' ] )
+ || $self->ut_enum('disabled', [ '', 'Y' ] )
|| $self->SUPER::check
;
sub taxline {
my $self = shift;
+ my $name = $self->taxname;
+ $name = 'Other surcharges'
+ if ($self->passtype == 2);
+ my $amount = 0;
+
+ return [$name, $amount] # we always know how to handle disabled taxes
+ if $self->disabled;
+
my $taxable_charged = 0;
my @cust_bill_pkg = grep { $taxable_charged += $_ unless ref; ref; } @_;
'" basis';
}
- my $name = $self->taxname;
- $name = 'Other surcharges'
- if ($self->passtype == 2);
- my $amount = 0;
-
unless ($self->setuptax =~ /^Y$/i) {
$taxable_charged += $_->setup foreach @cust_bill_pkg;
}
my $taxable_units = 0;
unless ($self->recurtax =~ /^Y$/i) {
if ($self->unittype == 0) {
- $taxable_units += $_->units foreach @cust_bill_pkg;
+ my %seen = ();
+ foreach (@cust_bill_pkg) {
+ $taxable_units += $_->units
+ unless $seen{$_->pkgnum};
+ $seen{$_->pkgnum}++;
+ }
}elsif ($self->unittype == 1) {
return qq!fatal: can't (yet) handle fee with minute unit type!;
}elsif ($self->unittype == 2) {
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
+ my $hashref = $insert{$_};
+ $line = join(", ", map { "$_ => ". $hashref->{$_} } keys(%$hashref) );
return "can't insert tax_rate for $line: $error";
}
#join(" ", map { "$_ => ". $old->{$_} } @fields);
join(" ", map { "$_ => ". $old->{$_} } keys(%$old) );
}
- my $new = new FS::tax_rate( $insert{$_} );
+ 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;
- return "can't insert tax_rate for $line: $error";
+ my $hashref = $insert{$_};
+ $line = join(", ", map { "$_ => ". $hashref->{$_} } keys(%$hashref) );
+ return "can't replace tax_rate for $line: $error";
}
$imported++;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- return "can't insert tax_rate for $line: $error";
+ my $hashref = $delete{$_};
+ $line = join(", ", map { "$_ => ". $hashref->{$_} } keys(%$hashref) );
+ return "can't delete tax_rate for $line: $error";
}
$imported++;
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
- return "Empty file!" unless $imported;
+ return "Empty file!" unless ($imported || $format eq 'cch-update');
''; #no error
=item process_batch
-Load an batch import as a queued JSRPC job
+Load a batch import as a queued JSRPC job
=cut
$error = "No $name supplied";
next;
}
- my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
+ my $dir = '%%%FREESIDE_CACHE%%%/cache.'. $FS::UID::datasrc;
my $filename = "$dir/". $files{$file};
open my $fh, "< $filename" or $error ||= "Can't open $name file: $!";
'PLUS4', 'plus4file', \&FS::cust_tax_location::batch_import,
'TXMATRIX', 'txmatrix', \&FS::part_pkg_taxrate::batch_import,
);
- my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
+ my $dir = '%%%FREESIDE_CACHE%%%/cache.'. $FS::UID::datasrc;
while( scalar(@list) ) {
my ($name, $file, $import_sub) = (shift @list, shift @list, shift @list);
unless ($files{$file}) {
unlink $file or warn "Can't delete $file: $!";
}
- $error = "No DETAIL supplied"
+ $error ||= "No DETAIL supplied"
unless ($files{detail});
open my $fh, "< $dir/". $files{detail}
or $error ||= "Can't open DETAIL file: $!";
}
+=item browse_queries PARAMS
+
+Returns a list consisting of a hashref suited for use as the argument
+to qsearch, and sql query string. Each is based on the PARAMS hashref
+of keys and values which frequently would be passed as C<scalar($cgi->Vars)>
+from a form. This conveniently creates the query hashref and count_query
+string required by the browse and search elements. As a side effect,
+the PARAMS hashref is untainted and keys with unexpected values are removed.
+
+=cut
+
+sub browse_queries {
+ my $params = shift;
+
+ my $query = {
+ 'table' => 'tax_rate',
+ 'hashref' => {},
+ 'order_by' => 'ORDER BY geocode, taxclassnum',
+ },
+
+ my $extra_sql = '';
+
+ if ( $params->{data_vendor} =~ /^(\w+)$/ ) {
+ $extra_sql .= ' WHERE data_vendor = '. dbh->quote($1);
+ } else {
+ delete $params->{data_vendor};
+ }
+
+ if ( $params->{geocode} =~ /^(\w+)$/ ) {
+ $extra_sql .= ( $extra_sql =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+ 'geocode LIKE '. dbh->quote($1.'%');
+ } else {
+ delete $params->{geocode};
+ }
+
+ if ( $params->{taxclassnum} =~ /^(\d+)$/ &&
+ qsearchs( 'tax_class', {'taxclassnum' => $1} )
+ )
+ {
+ $extra_sql .= ( $extra_sql =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+ ' taxclassnum = '. dbh->quote($1)
+ } else {
+ delete $params->{taxclassnun};
+ }
+
+ my $tax_type = $1
+ if ( $params->{tax_type} =~ /^(\d+)$/ );
+ delete $params->{tax_type}
+ unless $tax_type;
+
+ my $tax_cat = $1
+ if ( $params->{tax_cat} =~ /^(\d+)$/ );
+ delete $params->{tax_cat}
+ unless $tax_cat;
+
+ my @taxclassnum = ();
+ if ($tax_type || $tax_cat ) {
+ my $compare = "LIKE '". ( $tax_type || "%" ). ":". ( $tax_cat || "%" ). "'";
+ $compare = "= '$tax_type:$tax_cat'" if ($tax_type && $tax_cat);
+ @taxclassnum = map { $_->taxclassnum }
+ qsearch({ 'table' => 'tax_class',
+ 'hashref' => {},
+ 'extra_sql' => "WHERE taxclass $compare",
+ });
+ }
+
+ $extra_sql .= ( $extra_sql =~ /WHERE/i ? ' AND ' : ' WHERE ' ). '( '.
+ join(' OR ', map { " taxclassnum = $_ " } @taxclassnum ). ' )'
+ if ( @taxclassnum );
+
+ unless ($params->{'showdisabled'}) {
+ $extra_sql .= ( $extra_sql =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+ "( disabled = '' OR disabled IS NULL )";
+ }
+
+ $query->{extra_sql} = $extra_sql;
+
+ return ($query, "SELECT COUNT(*) FROM tax_rate $extra_sql");
+}
+
=back
=head1 BUGS