diff options
author | jeff <jeff> | 2010-10-11 19:00:33 +0000 |
---|---|---|
committer | jeff <jeff> | 2010-10-11 19:00:33 +0000 |
commit | eec4949e2c8f09a0b89331437186b77c4db6ff38 (patch) | |
tree | 5e41fdf9edb1b8ca1fa16051225dc1056e2b84de /FS/FS | |
parent | 001393ff80427429f376f7bf38c42d5280d98dc5 (diff) |
external taxes support package locations RT10093
Diffstat (limited to 'FS/FS')
-rw-r--r-- | FS/FS/cust_location.pm | 80 | ||||
-rw-r--r-- | FS/FS/cust_main.pm | 102 | ||||
-rw-r--r-- | FS/FS/cust_main/Billing.pm | 13 | ||||
-rw-r--r-- | FS/FS/geocode_Mixin.pm | 162 |
4 files changed, 182 insertions, 175 deletions
diff --git a/FS/FS/cust_location.pm b/FS/FS/cust_location.pm index 0c5c023..ab80941 100644 --- a/FS/FS/cust_location.pm +++ b/FS/FS/cust_location.pm @@ -1,7 +1,7 @@ package FS::cust_location; use strict; -use base qw( FS::Record ); +use base qw( FS::geocode_Mixin FS::Record ); use Locale::Country; use FS::Record qw( qsearch ); #qsearchs ); use FS::prospect_main; @@ -163,91 +163,35 @@ sub country_full { code2country($self->country); } -=item location_label [ OPTION => VALUE ... ] - -Returns the label of the service location for this customer. - -Options are - -=over 4 - -=item join_string - -used to separate the address elements (defaults to ', ') - -=item escape_function - - -a callback used for escaping the text of the address elements +=item line -=back +Synonym for location_label =cut -# false laziness with FS::cust_main::location_label - -sub location_label { +sub line { my $self = shift; - my %opt = @_; - - my $separator = $opt{join_string} || ', '; - my $escape = $opt{escape_function} || sub{ shift }; - my $ds = $opt{double_space} || ' '; - my $line = ''; - my $cydefault = - $opt{'countrydefault'} || FS::Conf->new->config('countrydefault') || 'US'; - my $prefix = ''; - - my $notfirst = 0; - foreach (qw ( address1 address2 ) ) { - my $method = "$prefix$_"; - $line .= ($notfirst ? $separator : ''). &$escape($self->$method) - if $self->$method; - $notfirst++; - } - $notfirst = 0; - foreach (qw ( city county state zip ) ) { - my $method = "$prefix$_"; - if ( $self->$method ) { - $line .= ($notfirst ? ($method eq 'zip' ? $ds : ' ') : $separator); - $line .= '(' if $method eq 'county'; - $line .= &$escape($self->$method); - $line .= ')' if $method eq 'county'; - $notfirst++; - } - $line .= ',' if $method eq 'county'; - } - $line .= $separator. &$escape(code2country($self->country)) - if $self->country ne $cydefault; - - $line; + $self->location_label; } -=item line +=item has_ship_address -Synonym for location_label +Returns false since cust_location objects do not have a separate shipping +address. =cut -sub line { - my $self = shift; - $self->location_label; +sub has_ship_address { + ''; } =item location_hash -Returns a list of key/value pairs, with the following keys: address1, adddress2, -city, county, state, zip, country. +Returns a list of key/value pairs, with the following keys: address1, address2, +city, county, state, zip, country, geocode. =cut -#geocode? not yet set - -sub location_hash { - my $self = shift; - map { $_ => $self->$_ } qw( address1 address2 city county state zip country ); -} - =back =head1 BUGS diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index c7a34e1..1f9e3cd 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -6,6 +6,7 @@ use strict; use base qw( FS::cust_main::Packages FS::cust_main::Billing FS::cust_main::Billing_Realtime FS::otaker_Mixin FS::payinfo_Mixin FS::cust_main_Mixin + FS::geocode_Mixin FS::Record ); use vars qw( $DEBUG $me $conf @@ -1781,22 +1782,10 @@ sub has_ship_address { =item location_hash Returns a list of key/value pairs, with the following keys: address1, adddress2, -city, county, state, zip, country. The shipping address is used if present. +city, county, state, zip, country, and geocode. The shipping address is used if present. =cut -#geocode? dependent on tax-ship_address config, not available in cust_location -#mostly. not yet then. - -sub location_hash { - my $self = shift; - my $prefix = $self->has_ship_address ? 'ship_' : ''; - - map { $_ => $self->get($prefix.$_) } - qw( address1 address2 city county state zip country geocode ); - #fields that cust_location has -} - =item cust_location Returns all locations (see L<FS::cust_location>) for this customer. @@ -1808,61 +1797,6 @@ sub cust_location { qsearch('cust_location', { 'custnum' => $self->custnum } ); } -=item location_label [ OPTION => VALUE ... ] - -Returns the label of the service location (see analog in L<FS::cust_location>) for this customer. - -Options are - -=over 4 - -=item join_string - -used to separate the address elements (defaults to ', ') - -=item escape_function - -a callback used for escaping the text of the address elements - -=back - -=cut - -# false laziness with FS::cust_location::line - -sub location_label { - my $self = shift; - my %opt = @_; - - my $separator = $opt{join_string} || ', '; - my $escape = $opt{escape_function} || sub{ shift }; - my $line = ''; - my $cydefault = FS::conf->new->config('countrydefault') || 'US'; - my $prefix = length($self->ship_last) ? 'ship_' : ''; - - my $notfirst = 0; - foreach (qw ( address1 address2 ) ) { - my $method = "$prefix$_"; - $line .= ($notfirst ? $separator : ''). &$escape($self->$method) - if $self->$method; - $notfirst++; - } - $notfirst = 0; - foreach (qw ( city county state zip ) ) { - my $method = "$prefix$_"; - if ( $self->$method ) { - $line .= ' (' if $method eq 'county'; - $line .= ($notfirst ? ' ' : $separator). &$escape($self->$method); - $line .= ' )' if $method eq 'county'; - $notfirst++; - } - } - $line .= $separator. &$escape(code2country($self->country)) - if $self->country ne $cydefault; - - $line; -} - =item unsuspend Unsuspends all unflagged suspended packages (see L</unflagged_suspended_pkgs> @@ -3621,38 +3555,6 @@ Currently this only makes sense for "CCH" as DATA_VENDOR. =cut -sub geocode { - my ($self, $data_vendor) = (shift, shift); #always cch for now - - my $geocode = $self->get('geocode'); #XXX only one data_vendor for geocode - return $geocode if $geocode; - - my $prefix = ( $conf->exists('tax-ship_address') && length($self->ship_last) ) - ? 'ship_' - : ''; - - my($zip,$plus4) = split /-/, $self->get("${prefix}zip") - if $self->country eq 'US'; - - $zip ||= ''; - $plus4 ||= ''; - #CCH specific location stuff - my $extra_sql = "AND plus4lo <= '$plus4' AND plus4hi >= '$plus4'"; - - my @cust_tax_location = - qsearch( { - 'table' => 'cust_tax_location', - 'hashref' => { 'zip' => $zip, 'data_vendor' => $data_vendor }, - 'extra_sql' => $extra_sql, - 'order_by' => 'ORDER BY plus4hi',#overlapping with distinct ends - } - ); - $geocode = $cust_tax_location[0]->geocode - if scalar(@cust_tax_location); - - $geocode; -} - =item cust_status =item status diff --git a/FS/FS/cust_main/Billing.pm b/FS/FS/cust_main/Billing.pm index 0cd304b..b588dc5 100644 --- a/FS/FS/cust_main/Billing.pm +++ b/FS/FS/cust_main/Billing.pm @@ -1048,18 +1048,14 @@ sub _handle_taxes { ) { - if ( $conf->exists('tax-pkg_address') && $cust_pkg->locationnum ) { - return "fatal: Can't (yet) use tax-pkg_address with taxproducts"; - } - foreach my $class (@classes) { - my $err_or_ref = $self->_gather_taxes( $part_pkg, $class ); + my $err_or_ref = $self->_gather_taxes( $part_pkg, $class, $cust_pkg ); return $err_or_ref unless ref($err_or_ref); $taxes{$class} = $err_or_ref; } unless (exists $taxes{''}) { - my $err_or_ref = $self->_gather_taxes( $part_pkg, '' ); + my $err_or_ref = $self->_gather_taxes( $part_pkg, '', $cust_pkg ); return $err_or_ref unless ref($err_or_ref); $taxes{''} = $err_or_ref; } @@ -1226,11 +1222,14 @@ sub _gather_taxes { my $self = shift; my $part_pkg = shift; my $class = shift; + my $cust_pkg = shift; local($DEBUG) = $FS::cust_main::DEBUG if $FS::cust_main::DEBUG > $DEBUG; - my @taxes = (); my $geocode = $self->geocode('cch'); + $geocode = $cust_pkg->geocode('cch') + if ( $conf->exists('tax-pkg_address') && $cust_pkg->locationnum ); + my @taxes = (); my @taxclassnums = map { $_->taxclassnum } $part_pkg->part_pkg_taxoverride($class); diff --git a/FS/FS/geocode_Mixin.pm b/FS/FS/geocode_Mixin.pm new file mode 100644 index 0000000..cf45a92 --- /dev/null +++ b/FS/FS/geocode_Mixin.pm @@ -0,0 +1,162 @@ +package FS::geocode_Mixin; + +use strict; +use vars qw( $DEBUG $me ); +use Carp; +use Locale::Country; +use FS::Record qw( qsearchs qsearch ); +use FS::cust_pkg; +use FS::cust_location; +use FS::cust_tax_location; +use FS::part_pkg; + +$DEBUG = 0; +$me = '[FS::geocode_Mixin]'; + +=head1 NAME + +FS::geocode_Mixin - Mixin class for records that contain address and other +location fields. + +=head1 SYNOPSIS + + package FS::some_table; + use base ( FS::geocode_Mixin FS::Record ); + +=head1 DESCRIPTION + +FS::geocode_Mixin - This is a mixin class for records that contain address +and other location fields. + +=head1 METHODS + +=over 4 + +=cut + +=item location_hash + +Returns a list of key/value pairs, with the following keys: address1, address2, +city, county, state, zip, country. The shipping address is used if present. + +=cut + +#geocode dependent on tax-ship_address config + +sub location_hash { + my $self = shift; + my $prefix = $self->has_ship_address ? 'ship_' : ''; + + map { my $method = ($_ eq 'geocode') ? $_ : $prefix.$_; + $_ => $self->get($method); + } + qw( address1 address2 city county state zip country geocode ); +} + +=item location_label [ OPTION => VALUE ... ] + +Returns the label of the service location (see analog in L<FS::cust_location>) for this customer. + +Options are + +=over 4 + +=item join_string + +used to separate the address elements (defaults to ', ') + +=item escape_function + +a callback used for escaping the text of the address elements + +=back + +=cut + +sub location_label { + my $self = shift; + my %opt = @_; + + my $separator = $opt{join_string} || ', '; + my $escape = $opt{escape_function} || sub{ shift }; + my $ds = $opt{double_space} || ' '; + my $line = ''; + my $cydefault = + $opt{'countrydefault'} || FS::conf->new->config('countrydefault') || 'US'; + my $prefix = $self->has_ship_address ? 'ship_' : ''; + + my $notfirst = 0; + foreach (qw ( address1 address2 ) ) { + my $method = "$prefix$_"; + $line .= ($notfirst ? $separator : ''). &$escape($self->$method) + if $self->$method; + $notfirst++; + } + $notfirst = 0; + foreach (qw ( city county state zip ) ) { + my $method = "$prefix$_"; + if ( $self->$method ) { + $line .= ' (' if $method eq 'county'; + $line .= ($notfirst ? ' ' : $separator). &$escape($self->$method); + $line .= ' )' if $method eq 'county'; + $notfirst++; + } + } + $line .= $separator. &$escape(code2country($self->country)) + if $self->country ne $cydefault; + + $line; +} + +=item geocode DATA_VENDOR + +Returns a value for the customer location as encoded by DATA_VENDOR. +Currently this only makes sense for "CCH" as DATA_VENDOR. + +=cut + +sub geocode { + my ($self, $data_vendor) = (shift, shift); #always cch for now + + my $geocode = $self->get('geocode'); #XXX only one data_vendor for geocode + return $geocode if $geocode; + + my $prefix = + ( FS::conf->new->exists('tax-ship_address') && $self->has_ship_address ) + ? 'ship_' + : ''; + + my($zip,$plus4) = split /-/, $self->get("${prefix}zip") + if $self->country eq 'US'; + + $zip ||= ''; + $plus4 ||= ''; + #CCH specific location stuff + my $extra_sql = "AND plus4lo <= '$plus4' AND plus4hi >= '$plus4'"; + + my @cust_tax_location = + qsearch( { + 'table' => 'cust_tax_location', + 'hashref' => { 'zip' => $zip, 'data_vendor' => $data_vendor }, + 'extra_sql' => $extra_sql, + 'order_by' => 'ORDER BY plus4hi',#overlapping with distinct ends + } + ); + $geocode = $cust_tax_location[0]->geocode + if scalar(@cust_tax_location); + + $geocode; +} + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + |