[freeside-commits] freeside/FS/FS cust_bill_pkg_tax_rate_location.pm, NONE, 1.1 tax_rate_location.pm, NONE, 1.1 Schema.pm, 1.138, 1.139 cust_bill_pkg.pm, 1.32, 1.33 cust_main.pm, 1.424, 1.425 tax_rate.pm, 1.24, 1.25
Jeff Finucane,420,,
jeff at wavetail.420.am
Wed May 13 15:27:44 PDT 2009
Update of /home/cvs/cvsroot/freeside/FS/FS
In directory wavetail.420.am:/tmp/cvs-serv13408/FS/FS
Modified Files:
Schema.pm cust_bill_pkg.pm cust_main.pm tax_rate.pm
Added Files:
cust_bill_pkg_tax_rate_location.pm tax_rate_location.pm
Log Message:
improved taxproduct tax report RT#4783
--- NEW FILE: cust_bill_pkg_tax_rate_location.pm ---
package FS::cust_bill_pkg_tax_rate_location;
use strict;
use base qw( FS::Record );
use FS::Record qw( qsearch qsearchs );
use FS::cust_bill_pkg;
use FS::cust_pkg;
use FS::cust_location;
=head1 NAME
FS::cust_bill_pkg_tax_rate_location - Object methods for cust_bill_pkg_tax_rate_location records
=head1 SYNOPSIS
use FS::cust_bill_pkg_tax_rate_location;
$record = new FS::cust_bill_pkg_tax_rate_location \%hash;
$record = new FS::cust_bill_pkg_tax_rate_location { 'column' => 'value' };
$error = $record->insert;
$error = $new_record->replace($old_record);
$error = $record->delete;
$error = $record->check;
=head1 DESCRIPTION
An FS::cust_bill_pkg_tax_rate_location object represents an record of taxation
based on package location. FS::cust_bill_pkg_tax_rate_location inherits from
FS::Record. The following fields are currently supported:
=over 4
=item billpkgtaxratelocationnum
billpkgtaxratelocationnum
=item billpkgnum
billpkgnum
=item taxnum
taxnum
=item taxtype
taxtype
=item locationtaxid
locationtaxid
=item taxratelocationnum
taxratelocationnum
=item amount
amount
=back
=head1 METHODS
=over 4
=item new HASHREF
Creates a new record. To add the record to the database, see L<"insert">.
Note that this stores the hash reference, not a distinct copy of the hash it
points to. You can ask the object for a copy with the I<hash> method.
=cut
sub table { 'cust_bill_pkg_tax_rate_location'; }
=item insert
Adds this record to the database. If there is an error, returns the error,
otherwise returns false.
=item delete
Delete this record from the database.
=item replace OLD_RECORD
Replaces the OLD_RECORD with this one in the database. If there is an error,
returns the error, otherwise returns false.
=item check
Checks all fields to make sure this is a valid record. If there is
an error, returns the error, otherwise returns false. Called by the insert
and replace methods.
=cut
# the check method should currently be supplied - FS::Record contains some
# data checking routines
sub check {
my $self = shift;
my $error =
$self->ut_numbern('billpkgtaxratelocationnum')
|| $self->ut_foreign_key('billpkgnum', 'cust_bill_pkg', 'billpkgnum' )
|| $self->ut_number('taxnum') #cust_bill_pkg/tax_rate key, based on taxtype
|| $self->ut_enum('taxtype', [ qw( FS::cust_main_county FS::tax_rate ) ] )
|| $self->ut_textn('locationtaxid')
|| $self->ut_foreign_key('taxratelocationnum', 'tax_rate_location', 'taxratelocationnum' )
|| $self->ut_money('amount')
;
return $error if $error;
$self->SUPER::check;
}
=back
=head1 BUGS
=head1 SEE ALSO
L<FS::Record>, schema.html from the base documentation.
=cut
1;
--- NEW FILE: tax_rate_location.pm ---
package FS::tax_rate_location;
use strict;
use base qw( FS::Record );
use FS::Record qw( qsearch qsearchs dbh );
=head1 NAME
FS::tax_rate_location - Object methods for tax_rate_location records
=head1 SYNOPSIS
use FS::tax_rate_location;
$record = new FS::tax_rate_location \%hash;
$record = new FS::tax_rate_location { 'column' => 'value' };
$error = $record->insert;
$error = $new_record->replace($old_record);
$error = $record->delete;
$error = $record->check;
=head1 DESCRIPTION
An FS::tax_rate_location object represents an example. FS::tax_rate_location inherits from
FS::Record. The following fields are currently supported:
=over 4
=item taxratelocationnum
Primary key (assigned automatically for new tax_rate_locations)
=item data_vendor
The tax data vendor
=item geocode
A unique geographic location code provided by the data vendor
=item city
City
=item county
County
=item state
State
=item disabled
If 'Y' this record is no longer active.
=back
=head1 METHODS
=over 4
=item new HASHREF
Creates a new tax rate location. To add the record to the database, see
L<"insert">.
Note that this stores the hash reference, not a distinct copy of the hash it
points to. You can ask the object for a copy with the I<hash> method.
=cut
sub table { 'tax_rate_location'; }
=item insert
Adds this record to the database. If there is an error, returns the error,
otherwise returns false.
=cut
=item delete
Delete this record from the database.
=cut
sub delete {
return "Can't delete tax rate locations. Set disable to 'Y' instead.";
# check that it is unused in any cust_bill_pkg_tax_location records instead?
}
=item replace OLD_RECORD
Replaces the OLD_RECORD with this one in the database. If there is an error,
returns the error, otherwise returns false.
=cut
=item check
Checks all fields to make sure this is a valid tax rate location. If there is
an error, returns the error, otherwise returns false. Called by the insert
and replace methods.
=cut
sub check {
my $self = shift;
my $error =
$self->ut_numbern('taxratelocationnum')
|| $self->ut_textn('data_vendor')
|| $self->ut_alpha('geocode')
|| $self->ut_textn('city')
|| $self->ut_textn('county')
|| $self->ut_textn('state')
|| $self->ut_enum('disabled', [ '', 'Y' ])
;
return $error if $error;
my $t = qsearchs( 'tax_rate_location',
{ map { $_ => $self->$_ } qw( data_vendor geocode ) },
);
return "geocode already in use for this vendor"
if ( $t && $t->taxratelocationnum != $self->taxratelocationnum );
return "may only be disabled"
if ( $t && scalar( grep { $t->$_ ne $self->$_ }
grep { $_ ne 'disabled' }
$self->fields
)
);
$self->SUPER::check;
}
=back
=head1 SUBROUTINES
=over 4
=item batch_import
=cut
sub batch_import {
my ($param, $job) = @_;
my $fh = $param->{filehandle};
my $format = $param->{'format'};
my %insert = ();
my %delete = ();
my @fields;
my $hook;
my @column_lengths = ();
my @column_callbacks = ();
if ( $format eq 'cch-fixed' || $format eq 'cch-fixed-update' ) {
$format =~ s/-fixed//;
my $trim = sub { my $r = shift; $r =~ s/^\s*//; $r =~ s/\s*$//; $r };
push @column_lengths, qw( 28 25 2 10 );
push @column_lengths, 1 if $format eq 'cch-update';
push @column_callbacks, $trim foreach (@column_lengths);
}
my $line;
my ( $count, $last, $min_sec ) = (0, time, 5); #progressbar
if ( $job || scalar(@column_callbacks) ) {
my $error =
csv_from_fixed(\$fh, \$count, \@column_lengths, \@column_callbacks);
return $error if $error;
}
if ( $format eq 'cch' || $format eq 'cch-update' ) {
@fields = qw( city county state geocode );
push @fields, 'actionflag' if $format eq 'cch-update';
$hook = sub {
my $hash = shift;
$hash->{'data_vendor'} ='cch';
if (exists($hash->{'actionflag'}) && $hash->{'actionflag'} eq 'D') {
delete($hash->{actionflag});
$hash->{deleted} = '';
my $tax_rate_location = qsearchs('tax_rate_location', $hash);
return "Can't find tax_rate_location to delete: ".
join(" ", map { "$_ => ". $hash->{$_} } @fields)
unless $tax_rate_location;
$tax_rate_location->disabled('Y');
my $error = $tax_rate_location->replace;
return $error if $error;
delete($hash->{$_}) foreach (keys %$hash);
}
delete($hash->{'actionflag'});
'';
};
} elsif ( $format eq 'extended' ) {
die "unimplemented\n";
@fields = qw( );
$hook = sub {};
} else {
die "unknown format $format";
}
eval "use Text::CSV_XS;";
die $@ if $@;
my $csv = new Text::CSV_XS;
my $imported = 0;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $SIG{QUIT} = 'IGNORE';
local $SIG{TERM} = 'IGNORE';
local $SIG{TSTP} = 'IGNORE';
local $SIG{PIPE} = 'IGNORE';
my $oldAutoCommit = $FS::UID::AutoCommit;
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
while ( defined($line=<$fh>) ) {
$csv->parse($line) or do {
$dbh->rollback if $oldAutoCommit;
return "can't parse: ". $csv->error_input();
};
if ( $job ) { # progress bar
if ( time - $min_sec > $last ) {
my $error = $job->update_statustext(
int( 100 * $imported / $count )
);
die $error if $error;
$last = time;
}
}
my @columns = $csv->fields();
my %tax_rate_location = ();
foreach my $field ( @fields ) {
$tax_rate_location{$field} = shift @columns;
}
if ( scalar( @columns ) ) {
$dbh->rollback if $oldAutoCommit;
return "Unexpected trailing columns in line (wrong format?): $line";
}
my $error = &{$hook}(\%tax_rate_location);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
}
if (scalar(keys %tax_rate_location)) { #inserts only
my $tax_rate_location = new FS::tax_rate_location( \%tax_rate_location );
$error = $tax_rate_location->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return "can't insert tax_rate for $line: $error";
}
}
$imported++;
}
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
return "Empty file!" unless ($imported || $format eq 'cch-update');
''; #no error
}
=head1 BUGS
Currently somewhat specific to CCH supplied data.
=head1 SEE ALSO
L<FS::Record>, schema.html from the base documentation.
=cut
1;
Index: cust_main.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_main.pm,v
retrieving revision 1.424
retrieving revision 1.425
diff -u -d -r1.424 -r1.425
--- cust_main.pm 1 May 2009 20:21:42 -0000 1.424
+++ cust_main.pm 13 May 2009 22:27:41 -0000 1.425
@@ -30,6 +30,7 @@
use FS::cust_bill_pkg;
use FS::cust_bill_pkg_display;
use FS::cust_bill_pkg_tax_location;
+use FS::cust_bill_pkg_tax_rate_location;
use FS::cust_pay;
use FS::cust_pay_pending;
use FS::cust_pay_void;
@@ -40,6 +41,7 @@
use FS::cust_main_county;
use FS::cust_location;
use FS::tax_rate;
+use FS::tax_rate_location;
use FS::cust_tax_location;
use FS::part_pkg_taxrate;
use FS::agent;
@@ -2461,6 +2463,10 @@
# values are listrefs of cust_bill_pkg_tax_location hashrefs
my %tax_location = ();
+ # keys are taxlisthash keys (internal identifiers)
+ # values are listrefs of cust_bill_pkg_tax_rate_location hashrefs
+ my %tax_rate_location = ();
+
foreach my $tax ( keys %taxlisthash ) {
my $tax_object = shift @{ $taxlisthash{$tax} };
warn "found ". $tax_object->taxname. " as $tax\n" if $DEBUG > 2;
@@ -2497,6 +2503,20 @@
};
}
+ $tax_rate_location{ $tax } ||= [];
+ if ( ref($tax_object) eq 'FS::tax_rate' ) {
+ my $taxratelocationnum =
+ $tax_object->tax_rate_location->taxratelocationnum;
+ push @{ $tax_rate_location{ $tax } },
+ {
+ 'taxnum' => $tax_object->taxnum,
+ 'taxtype' => ref($tax_object),
+ 'amount' => sprintf('%.2f', $amount ),
+ 'locationtaxid' => $tax_object->location,
+ 'taxratelocationnum' => $taxratelocationnum,
+ };
+ }
+
}
#move the cust_tax_exempt_pkg records to the cust_bill_pkgs we will commit
@@ -2516,6 +2536,7 @@
my $tax = 0;
my %seen = ();
my @cust_bill_pkg_tax_location = ();
+ my @cust_bill_pkg_tax_rate_location = ();
warn "adding $taxname\n" if $DEBUG > 1;
foreach my $taxitem ( @{ $taxname{$taxname} } ) {
next if $seen{$taxitem}++;
@@ -2524,6 +2545,9 @@
push @cust_bill_pkg_tax_location,
map { new FS::cust_bill_pkg_tax_location $_ }
@{ $tax_location{ $taxitem } };
+ push @cust_bill_pkg_tax_rate_location,
+ map { new FS::cust_bill_pkg_tax_rate_location $_ }
+ @{ $tax_rate_location{ $taxitem } };
}
next unless $tax;
@@ -2538,6 +2562,7 @@
'edate' => '',
'itemdesc' => $taxname,
'cust_bill_pkg_tax_location' => \@cust_bill_pkg_tax_location,
+ 'cust_bill_pkg_tax_rate_location' => \@cust_bill_pkg_tax_rate_location,
};
}
Index: Schema.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Schema.pm,v
retrieving revision 1.138
retrieving revision 1.139
diff -u -d -r1.138 -r1.139
--- Schema.pm 9 May 2009 00:39:13 -0000 1.138
+++ Schema.pm 13 May 2009 22:27:41 -0000 1.139
@@ -560,7 +560,7 @@
'billpkgtaxlocationnum', 'serial', '', '', '', '',
'billpkgnum', 'int', '', '', '', '',
'taxnum', 'int', '', '', '', '',
- 'taxtype', 'varchar', $char_d, '', '', '',
+ 'taxtype', 'varchar', '', $char_d, '', '',
'pkgnum', 'int', '', '', '', '',
'locationnum', 'int', '', '', '', '', #redundant?
'amount', @money_type, '', '',
@@ -570,6 +570,21 @@
'index' => [ [ 'billpkgnum' ], [ 'taxnum' ], [ 'pkgnum' ], [ 'locationnum' ] ],
},
+ 'cust_bill_pkg_tax_rate_location' => {
+ 'columns' => [
+ 'billpkgtaxratelocationnum', 'serial', '', '', '', '',
+ 'billpkgnum', 'int', '', '', '', '',
+ 'taxnum', 'int', '', '', '', '',
+ 'taxtype', 'varchar', '', $char_d, '', '',
+ 'locationtaxid', 'varchar', 'NULL', $char_d, '', '',
+ 'taxratelocationnum', 'int', '', '', '', '',
+ 'amount', @money_type, '', '',
+ ],
+ 'primary_key' => 'billpkgtaxratelocationnum',
+ 'unique' => [],
+ 'index' => [ [ 'billpkgnum' ], [ 'taxnum' ], [ 'taxratelocationnum' ] ],
+ },
+
'cust_credit' => {
'columns' => [
'crednum', 'serial', '', '', '', '',
@@ -805,6 +820,21 @@
'index' => [ ['taxclassnum'], ['data_vendor', 'geocode'] ],
},
+ 'tax_rate_location' => {
+ 'columns' => [
+ 'taxratelocationnum', 'serial', '', '', '', '',
+ 'data_vendor', 'varchar', 'NULL', $char_d, '', '',
+ 'geocode', 'varchar', '', 20, '', '',
+ 'city', 'varchar', 'NULL', $char_d, '', '',
+ 'county', 'varchar', 'NULL', $char_d, '', '',
+ 'state', 'char', '', 2, '', '',
+ 'disabled', 'char', 'NULL', 1, '', '',
+ ],
+ 'primary_key' => 'taxratelocationnum',
+ 'unique' => [],
+ 'index' => [ [ 'data_vendor', 'geocode', 'disabled' ] ],
+ },
+
'cust_tax_location' => {
'columns' => [
'custlocationnum', 'serial', '', '', '', '',
Index: cust_bill_pkg.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_bill_pkg.pm,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- cust_bill_pkg.pm 21 Feb 2009 17:56:07 -0000 1.32
+++ cust_bill_pkg.pm 13 May 2009 22:27:41 -0000 1.33
@@ -162,6 +162,19 @@
}
}
+ my $tax_rate_location = $self->get('cust_bill_pkg_tax_rate_location');
+ if ( $tax_rate_location ) {
+ foreach my $cust_bill_pkg_tax_rate_location ( @$tax_rate_location ) {
+ $cust_bill_pkg_tax_rate_location->billpkgnum($self->billpkgnum);
+ $error = $cust_bill_pkg_tax_rate_location->insert;
+ warn $error;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+ }
+
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
Index: tax_rate.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/tax_rate.pm,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- tax_rate.pm 23 Apr 2009 20:31:26 -0000 1.24
+++ tax_rate.pm 13 May 2009 22:27:42 -0000 1.25
@@ -19,6 +19,7 @@
use FS::tax_class;
use FS::cust_bill_pkg;
use FS::cust_tax_location;
+use FS::tax_rate_location;
use FS::part_pkg_taxrate;
use FS::cust_main;
use FS::Misc qw( csv_from_fixed );
@@ -538,6 +539,26 @@
}
+=item tax_rate_location
+
+Returns an object representing the location associated with this tax
+(see L<FS::tax_rate_location>)
+
+=cut
+
+sub tax_rate_location {
+ my $self = shift;
+
+ qsearchs({ 'table' => 'tax_rate_location',
+ 'hashref' => { 'data_vendor' => $self->data_vendor,
+ 'geocode' => $self->geocode,
+ 'disabled' => '',
+ },
+ }) ||
+ new FS::tax_rate_location;
+
+}
+
=back
=head1 SUBROUTINES
@@ -845,7 +866,8 @@
my $error = '';
my $have_location = 0;
- my @list = ( 'CODE', 'codefile', \&FS::tax_class::batch_import,
+ my @list = ( 'GEOCODE', 'geofile', \&FS::tax_rate_location::batch_import,
+ 'CODE', 'codefile', \&FS::tax_class::batch_import,
'PLUS4', 'plus4file', \&FS::cust_tax_location::batch_import,
'ZIP', 'zipfile', \&FS::cust_tax_location::batch_import,
'TXMATRIX', 'txmatrix', \&FS::part_pkg_taxrate::batch_import,
@@ -887,7 +909,8 @@
my @insert_list = ();
my @delete_list = ();
- my @list = ( 'CODE', 'codefile', \&FS::tax_class::batch_import,
+ my @list = ( 'GEOCODE', 'geofile', \&FS::tax_rate_location::batch_import,
+ 'CODE', 'codefile', \&FS::tax_class::batch_import,
'PLUS4', 'plus4file', \&FS::cust_tax_location::batch_import,
'ZIP', 'zipfile', \&FS::cust_tax_location::batch_import,
'TXMATRIX', 'txmatrix', \&FS::part_pkg_taxrate::batch_import,
More information about the freeside-commits
mailing list