use strict;
use vars qw( @ISA $DEBUG $me
%tax_unittypes %tax_maxtypes %tax_basetypes %tax_authorities
- %tax_passtypes );
+ %tax_passtypes %GetInfoType );
use Date::Parse;
use Storable qw( thaw );
use MIME::Base64;
-use FS::Record qw( qsearch qsearchs dbh );
+use DBIx::DBSchema;
+use DBIx::DBSchema::Table;
+use DBIx::DBSchema::Column;
+use FS::Record qw( qsearch qsearchs dbh dbdef );
use FS::tax_class;
use FS::cust_bill_pkg;
use FS::cust_tax_location;
$tax_passtypes{$self->passtype};
}
-=item taxline CUST_BILL_PKG|AMOUNT, ...
+=item taxline TAXABLES, [ OPTIONSHASH ]
Returns a listref of a name and an amount of tax calculated for the list
-of packages/amounts. If an error occurs, a message is returned as a scalar.
+of packages/amounts referenced by TAXABLES. If an error occurs, a message
+is returned as a scalar.
=cut
sub taxline {
my $self = shift;
+ my $taxables;
+ my %opt = ();
+
+ if (ref($_[0]) eq 'ARRAY') {
+ $taxables = shift;
+ %opt = @_;
+ }else{
+ $taxables = [ @_ ];
+ #exemptions would be broken in this case
+ }
+
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;
+ if ( $self->disabled ) { # we always know how to handle disabled taxes
+ return {
+ 'name' => $name,
+ 'amount' => $amount,
+ };
+ }
my $taxable_charged = 0;
- my @cust_bill_pkg = grep { $taxable_charged += $_ unless ref; ref; } @_;
+ my @cust_bill_pkg = grep { $taxable_charged += $_ unless ref; ref; }
+ @$taxables;
warn "calculating taxes for ". $self->taxnum. " on ".
join (",", map { $_->pkgnum } @cust_bill_pkg)
if $DEBUG;
if ($self->passflag eq 'N') {
- return "fatal: can't (yet) handle taxes not passed to the customer";
+ # return "fatal: can't (yet) handle taxes not passed to the customer";
+ # until someone needs to track these in freeside
+ return {
+ 'name' => $name,
+ 'amount' => 0,
+ };
}
if ($self->maxtype != 0 && $self->maxtype != 9) {
- return qq!fatal: can't (yet) handle tax with "!. $self->maxtype_name.
- '" threshold';
+ return $self->_fatal_or_null( 'tax with "'.
+ $self->maxtype_name. '" threshold'
+ );
}
if ($self->maxtype == 9) {
- return qq!fatal: can't (yet) handle tax with "!. $self->maxtype_name.
- '" threshold'; # "texas" tax
+ return
+ $self->_fatal_or_null( 'tax with "'. $self->maxtype_name. '" threshold' );
+ # "texas" tax
}
# we treat gross revenue as gross receipts and expect the tax data
# to DTRT (i.e. tax on tax rules)
if ($self->basetype != 0 && $self->basetype != 1 &&
- $self->basetype != 6 && $self->basetype != 7 &&
- $self->basetype != 8 && $self->basetype != 14
+ $self->basetype != 5 && $self->basetype != 6 &&
+ $self->basetype != 7 && $self->basetype != 8 &&
+ $self->basetype != 14
) {
- return qq!fatal: can't (yet) handle tax with "!. $self->basetype_name.
- '" basis';
+ return
+ $self->_fatal_or_null( 'tax with "'. $self->basetype_name. '" basis' );
}
unless ($self->setuptax =~ /^Y$/i) {
$seen{$_->pkgnum}++;
}
}elsif ($self->unittype == 1) {
- return qq!fatal: can't (yet) handle fee with minute unit type!;
+ return $self->_fatal_or_null( 'fee with minute unit type' );
}elsif ($self->unittype == 2) {
$taxable_units = 1;
}else {
- return qq!fatal: can't (yet) handle unknown unit type in tax!.
- $self->taxnum;
+ return $self->_fatal_or_null( 'unknown unit type in tax'. $self->taxnum );
}
}
warn "calculated taxes as [ $name, $amount ]\n"
if $DEBUG;
- return [$name, $amount];
+ return {
+ 'name' => $name,
+ 'amount' => $amount,
+ };
+
+}
+
+sub _fatal_or_null {
+ my ($self, $error) = @_;
+
+ my $conf = new FS::Conf;
+
+ $error = "fatal: can't yet handle ". $error;
+ my $name = $self->taxname;
+ $name = 'Other surcharges'
+ if ($self->passtype == 2);
+ if ($conf->exists('ignore_incalculable_taxes')) {
+ warn $error;
+ return { name => $name, amount => 0 };
+ } else {
+ return $error;
+ }
}
=item tax_on_tax CUST_MAIN
/^(\d{4})(\d{2})(\d{2})$/ && ($r="$1/$2/$3");
$r;
};
- $column_callbacks[8] = $date_format;
+ my $trim = sub { my $r = shift; $r =~ s/^\s*//; $r =~ s/\s*$//; $r };
push @column_lengths, qw( 10 1 1 8 8 5 8 8 8 1 2 2 30 8 8 10 2 8 2 1 2 2 );
push @column_lengths, 1 if $format eq 'cch-update';
+ push @column_callbacks, $trim foreach (@column_lengths); # 5, 6, 15, 17 esp
+ $column_callbacks[8] = $date_format;
}
my $line;
}
-=item process_batch
+=item process_batch_import
Load a batch import as a queued JSRPC job
=cut
-sub process_batch {
+sub process_batch_import {
my $job = shift;
my $param = thaw(decode_base64(shift));
UNLINK => 0, #meh
) or die "can't open temp file: $!\n";
+ my $insert_pattern = ($format eq 'cch-update') ? qr/"I"\s*$/ : qr/I\s*$/;
+ my $delete_pattern = ($format eq 'cch-update') ? qr/"D"\s*$/ : qr/D\s*$/;
while(<$fh>) {
my $handle = '';
- $handle = $ifh if $_ =~ /"I"\s*$/;
- $handle = $dfh if $_ =~ /"D"\s*$/;
+ $handle = $ifh if $_ =~ /$insert_pattern/;
+ $handle = $dfh if $_ =~ /$delete_pattern/;
unless ($handle) {
$error = "bad input line: $_" unless $handle;
last;
return ($query, "SELECT COUNT(*) FROM tax_rate $extra_sql");
}
+# _upgrade_data
+#
+# Used by FS::Upgrade to migrate to a new database.
+#
+#
+
+sub _upgrade_data { # class method
+ my ($self, %opts) = @_;
+ my $dbh = dbh;
+
+ warn "$me upgrading $self\n" if $DEBUG;
+
+ my @column = qw ( tax excessrate usetax useexcessrate fee excessfee
+ feebase feemax );
+
+ if ( $dbh->{Driver}->{Name} eq 'Pg' ) {
+
+ eval "use DBI::Const::GetInfoType;";
+ die $@ if $@;
+
+ my $major_version = 0;
+ $dbh->get_info( $GetInfoType{SQL_DBMS_VER} ) =~ /^(\d{2})/
+ && ( $major_version = sprintf("%d", $1) );
+
+ if ( $major_version > 7 ) {
+
+ # ideally this would be supported in DBIx-DBSchema and friends
+
+ foreach my $column ( @column ) {
+ my $columndef = dbdef->table($self->table)->column($column);
+ unless ($columndef->type eq 'numeric') {
+
+ warn "updating tax_rate column $column to numeric\n" if $DEBUG;
+ my $sql = "ALTER TABLE tax_rate ALTER $column TYPE numeric(14,8)";
+ my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ warn "updating h_tax_rate column $column to numeric\n" if $DEBUG;
+ $sql = "ALTER TABLE h_tax_rate ALTER $column TYPE numeric(14,8)";
+ $sth = $dbh->prepare($sql) or die $dbh->errstr;
+ $sth->execute or die $sth->errstr;
+
+ }
+ }
+
+ } else {
+
+ warn "WARNING: tax_rate table upgrade unsupported for this Pg version\n";
+
+ }
+
+ } else {
+
+ warn "WARNING: tax_rate table upgrade only supported for Pg 8+\n";
+
+ }
+
+ '';
+
+}
+
=back
=head1 BUGS