From cbbd0225b07269209c674733bcf70f1c1308e84a Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 25 Jan 2006 12:34:29 +0000 Subject: [PATCH] change texas-style tax exemptions to be against a specific line item rather than just general per-customer, for later tracking and tax reporting. fix 1969/1970 exemptions for one-off charges --- FS/FS/Record.pm | 5 + FS/FS/Schema.pm | 18 ++++ FS/FS/cust_bill.pm | 22 +++- FS/FS/cust_main.pm | 234 ++++++++++++++++++++++++------------------- FS/FS/cust_tax_exempt.pm | 21 +++- FS/FS/cust_tax_exempt_pkg.pm | 135 +++++++++++++++++++++++++ FS/FS/h_cust_bill.pm | 33 ++++++ FS/FS/h_cust_tax_exempt.pm | 40 ++++++++ FS/MANIFEST | 6 ++ FS/t/cust_tax_exempt_pkg.t | 5 + FS/t/h_cust_bill.t | 5 + FS/t/h_cust_tax_exempt.t | 5 + README.2.0.0 | 17 ++++ 13 files changed, 435 insertions(+), 111 deletions(-) create mode 100644 FS/FS/cust_tax_exempt_pkg.pm create mode 100644 FS/FS/h_cust_bill.pm create mode 100644 FS/FS/h_cust_tax_exempt.pm create mode 100644 FS/t/cust_tax_exempt_pkg.t create mode 100644 FS/t/h_cust_bill.t create mode 100644 FS/t/h_cust_tax_exempt.t create mode 100644 README.2.0.0 diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm index 887c8dcd4..19da3d181 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -977,6 +977,11 @@ sub replace { warn "[debug]$me $new ->replace $old\n" if $DEBUG; + if ( $new->can('replace_check') ) { + my $error = $new->replace_check($old); + return $error if $error; + } + return "Records not in same table!" unless $new->table eq $old->table; my $primary_key = $old->dbdef_table->primary_key; diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 451ef2d2e..d502a12be 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -976,6 +976,24 @@ sub tables_hashref { 'index' => [], }, + 'cust_tax_exempt_pkg' => { + 'columns' => [ + 'exemptpkgnum', 'serial', '', '', + #'custnum', 'int', '', '', + 'billpkgnum', 'int', '', '', + 'taxnum', 'int', '', '', + 'year', 'int', '', '', + 'month', 'int', '', '', + 'amount', @money_type, + ], + 'primary_key' => 'exemptpkgnum', + 'unique' => [], + 'index' => [ [ 'taxnum', 'year', 'month' ], + [ 'billpkgnum' ], + [ 'taxnum' ] + ], + }, + 'router' => { 'columns' => [ 'routernum', 'serial', '', '', diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 6e3b2b2f8..159c9e405 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -121,8 +121,14 @@ returns the error, otherwise returns false. =item delete -Currently unimplemented. I don't remove invoices because there would then be -no record you ever posted this invoice (which is bad, no?) +This method now works but you probably shouldn't use it. Instead, apply a +credit against the invoice. + +Using this method to delete invoices outright is really, really bad. There +would be no record you ever posted this invoice, and there are no check to +make sure charged = 0 or that there are no associated cust_bill_pkg records. + +Really, don't use it. =cut @@ -142,14 +148,20 @@ collect method of a customer object (see L). =cut -sub replace { +#replace can be inherited from Record.pm + +# replace_check is now the preferred way to #implement replace data checks +# (so $object->replace() works without an argument) + +sub replace_check { my( $new, $old ) = ( shift, shift ); return "Can't change custnum!" unless $old->custnum == $new->custnum; #return "Can't change _date!" unless $old->_date eq $new->_date; return "Can't change _date!" unless $old->_date == $new->_date; - return "Can't change charged!" unless $old->charged == $new->charged; + return "Can't change charged!" unless $old->charged == $new->charged + || $old->charged == 0; - $new->SUPER::replace($old); + ''; } =item check diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index a265e4177..b5ccf5a3f 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -43,6 +43,7 @@ use FS::part_pkg; use FS::part_bill_event; use FS::cust_bill_event; use FS::cust_tax_exempt; +use FS::cust_tax_exempt_pkg; use FS::type_pkgs; use FS::payment_gateway; use FS::agent_payment_gateway; @@ -1617,16 +1618,28 @@ sub bill { $self->select_for_update; #mutex + #create a new invoice + #(we'll remove it later if it doesn't actually need to be generated [contains + # no line items] and we're inside a transaciton so nothing else will see it) + my $cust_bill = new FS::cust_bill ( { + 'custnum' => $self->custnum, + '_date' => $time, + #'charged' => $charged, + 'charged' => 0, + } ); + $error = $cust_bill->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "can't create invoice for customer #". $self->custnum. ": $error"; + } + my $invnum = $cust_bill->invnum; + + ### # find the packages which are due for billing, find out how much they are # & generate invoice database. - - my( $total_setup, $total_recur ) = ( 0, 0 ); - #my( $taxable_setup, $taxable_recur ) = ( 0, 0 ); - my @cust_bill_pkg = (); - #my $tax = 0;## - #my $taxable_charged = 0;## - #my $charged = 0;## + ### + my( $total_setup, $total_recur ) = ( 0, 0 ); my %tax; foreach my $cust_pkg ( @@ -1649,7 +1662,10 @@ sub bill { my @details = (); + ### # bill setup + ### + my $setup = 0; if ( !$cust_pkg->setup || $options{'resetup'} ) { @@ -1664,7 +1680,10 @@ sub bill { $cust_pkg->setfield('setup', $time) unless $cust_pkg->setup; } - #bill recurring fee + ### + # bill recurring fee + ### + my $recur = 0; my $sdate; if ( $part_pkg->getfield('freq') ne '0' && @@ -1719,6 +1738,10 @@ sub bill { warn "\$recur is undefined" unless defined($recur); warn "\$cust_pkg->bill is undefined" unless defined($cust_pkg->bill); + ### + # If $cust_pkg has been modified, update it and create cust_bill_pkg records + ### + if ( $cust_pkg->modified ) { warn " package ". $cust_pkg->pkgnum. " modified; updating\n" @@ -1740,10 +1763,13 @@ sub bill { $dbh->rollback if $oldAutoCommit; return "negative recur $recur for pkgnum ". $cust_pkg->pkgnum; } + if ( $setup != 0 || $recur != 0 ) { - warn " charges (setup=$setup, recur=$recur); queueing line items\n" + + warn " charges (setup=$setup, recur=$recur); adding line items\n" if $DEBUG > 1; my $cust_bill_pkg = new FS::cust_bill_pkg ({ + 'invnum' => $invnum, 'pkgnum' => $cust_pkg->pkgnum, 'setup' => $setup, 'recur' => $recur, @@ -1751,10 +1777,18 @@ sub bill { 'edate' => $cust_pkg->bill, 'details' => \@details, }); - push @cust_bill_pkg, $cust_bill_pkg; + $error = $cust_bill_pkg->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "can't create invoice line item for invoice #$invnum: $error"; + } $total_setup += $setup; $total_recur += $recur; + ### + # handle taxes + ### + unless ( $self->tax =~ /Y/i || $self->payby eq 'COMP' ) { my @taxes = qsearch( 'cust_main_county', { @@ -1803,7 +1837,8 @@ sub bill { next unless $taxable_charged; if ( $tax->exempt_amount && $tax->exempt_amount > 0 ) { - my ($mon,$year) = (localtime($sdate) )[4,5]; + #my ($mon,$year) = (localtime($sdate) )[4,5]; + my ($mon,$year) = (localtime( $sdate || $cust_bill->_date ) )[4,5]; $mon++; my $freq = $part_pkg->freq || 1; if ( $freq !~ /(\d+)$/ ) { @@ -1811,40 +1846,74 @@ sub bill { return "daily/weekly package definitions not (yet?)". " compatible with monthly tax exemptions"; } - my $taxable_per_month = sprintf("%.2f", $taxable_charged / $freq ); + my $taxable_per_month = + sprintf("%.2f", $taxable_charged / $freq ); + + #call the whole thing off if this customer has any old + #exemption records... + my @cust_tax_exempt = + qsearch( 'cust_tax_exempt' => { custnum=> $self->custnum } ); + if ( @cust_tax_exempt ) { + $dbh->rollback if $oldAutoCommit; + return + 'this customer still has old-style tax exemption records; '. + 'run bin/fs-migrate-cust_tax_exempt?'; + } + foreach my $which_month ( 1 .. $freq ) { - my %hash = ( - 'custnum' => $self->custnum, - 'taxnum' => $tax->taxnum, - 'year' => 1900+$year, - 'month' => $mon++, - ); - #until ( $mon < 12 ) { $mon -= 12; $year++; } - until ( $mon < 13 ) { $mon -= 12; $year++; } - my $cust_tax_exempt = - qsearchs('cust_tax_exempt', \%hash) - || new FS::cust_tax_exempt( { %hash, 'amount' => 0 } ); - my $remaining_exemption = sprintf("%.2f", - $tax->exempt_amount - $cust_tax_exempt->amount ); + + #maintain the new exemption table now + my $sql = " + SELECT SUM(amount) + FROM cust_tax_exempt_pkg + LEFT JOIN cust_bill_pkg USING ( billpkgnum ) + LEFT JOIN cust_bill USING ( invnum ) + WHERE custnum = ? + AND taxnum = ? + AND year = ? + AND month = ? + "; + my $sth = dbh->prepare($sql) or do { + $dbh->rollback if $oldAutoCommit; + return "fatal: can't lookup exising exemption: ". dbh->errstr; + }; + $sth->execute( + $self->custnum, + $tax->taxnum, + 1900+$year, + $mon, + ) or do { + $dbh->rollback if $oldAutoCommit; + return "fatal: can't lookup exising exemption: ". dbh->errstr; + }; + my $existing_exemption = $sth->fetchrow_arrayref->[0]; + + my $remaining_exemption = + $tax->exempt_amount - $existing_exemption; if ( $remaining_exemption > 0 ) { my $addl = $remaining_exemption > $taxable_per_month ? $taxable_per_month : $remaining_exemption; $taxable_charged -= $addl; - my $new_cust_tax_exempt = new FS::cust_tax_exempt ( { - $cust_tax_exempt->hash, - 'amount' => - sprintf("%.2f", $cust_tax_exempt->amount + $addl), + + my $cust_tax_exempt_pkg = new FS::cust_tax_exempt_pkg ( { + 'billpkgnum' => $cust_bill_pkg->billpkgnum, + 'taxnum' => $tax->taxnum, + 'year' => 1900+$year, + 'month' => $mon, + 'amount' => sprintf("%.2f", $addl ), } ); - $error = $new_cust_tax_exempt->exemptnum - ? $new_cust_tax_exempt->replace($cust_tax_exempt) - : $new_cust_tax_exempt->insert; + $error = $cust_tax_exempt_pkg->insert; if ( $error ) { $dbh->rollback if $oldAutoCommit; - return "fatal: can't update cust_tax_exempt: $error"; + return "fatal: can't insert cust_tax_exempt_pkg: $error"; } - } # if $remaining_exemption > 0 + + #++ + $mon++; + #until ( $mon < 12 ) { $mon -= 12; $year++; } + until ( $mon < 13 ) { $mon -= 12; $year++; } } #foreach $which_month @@ -1866,86 +1935,41 @@ sub bill { } #foreach my $cust_pkg - my $charged = sprintf( "%.2f", $total_setup + $total_recur ); -# my $taxable_charged = sprintf( "%.2f", $taxable_setup + $taxable_recur ); - - unless ( @cust_bill_pkg ) { #don't create invoices with no line items + unless ( $cust_bill->cust_bill_pkg ) { + $cust_bill->delete; #don't create an invoice w/o line items $dbh->commit or die $dbh->errstr if $oldAutoCommit; return ''; - } - -# unless ( $self->tax =~ /Y/i -# || $self->payby eq 'COMP' -# || $taxable_charged == 0 ) { -# my $cust_main_county = qsearchs('cust_main_county',{ -# 'state' => $self->state, -# 'county' => $self->county, -# 'country' => $self->country, -# } ) or die "fatal: can't find tax rate for state/county/country ". -# $self->state. "/". $self->county. "/". $self->country. "\n"; -# my $tax = sprintf( "%.2f", -# $taxable_charged * ( $cust_main_county->getfield('tax') / 100 ) -# ); - - if ( dbdef->table('cust_bill_pkg')->column('itemdesc') ) { #1.5 schema - - foreach my $taxname ( grep { $tax{$_} > 0 } keys %tax ) { - my $tax = sprintf("%.2f", $tax{$taxname} ); - $charged = sprintf( "%.2f", $charged+$tax ); - - my $cust_bill_pkg = new FS::cust_bill_pkg ({ - 'pkgnum' => 0, - 'setup' => $tax, - 'recur' => 0, - 'sdate' => '', - 'edate' => '', - 'itemdesc' => $taxname, - }); - push @cust_bill_pkg, $cust_bill_pkg; - } - - } else { #1.4 schema - - my $tax = 0; - foreach ( values %tax ) { $tax += $_ }; - $tax = sprintf("%.2f", $tax); - if ( $tax > 0 ) { - $charged = sprintf( "%.2f", $charged+$tax ); - - my $cust_bill_pkg = new FS::cust_bill_pkg ({ - 'pkgnum' => 0, - 'setup' => $tax, - 'recur' => 0, - 'sdate' => '', - 'edate' => '', - }); - push @cust_bill_pkg, $cust_bill_pkg; - } - } - my $cust_bill = new FS::cust_bill ( { - 'custnum' => $self->custnum, - '_date' => $time, - 'charged' => $charged, - } ); - $error = $cust_bill->insert; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "can't create invoice for customer #". $self->custnum. ": $error"; - } + my $charged = sprintf( "%.2f", $total_setup + $total_recur ); - my $invnum = $cust_bill->invnum; - my $cust_bill_pkg; - foreach $cust_bill_pkg ( @cust_bill_pkg ) { - #warn $invnum; - $cust_bill_pkg->invnum($invnum); + foreach my $taxname ( grep { $tax{$_} > 0 } keys %tax ) { + my $tax = sprintf("%.2f", $tax{$taxname} ); + $charged = sprintf( "%.2f", $charged+$tax ); + + my $cust_bill_pkg = new FS::cust_bill_pkg ({ + 'invnum' => $invnum, + 'pkgnum' => 0, + 'setup' => $tax, + 'recur' => 0, + 'sdate' => '', + 'edate' => '', + 'itemdesc' => $taxname, + }); $error = $cust_bill_pkg->insert; if ( $error ) { $dbh->rollback if $oldAutoCommit; - return "can't create invoice line item for customer #". $self->custnum. - ": $error"; + return "can't create invoice line item for invoice #$invnum: $error"; } + $total_setup += $tax; + + } + + $cust_bill->charged( sprintf( "%.2f", $total_setup + $total_recur ) ); + $error = $cust_bill->replace; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "can't update charged for invoice #$invnum: $error"; } $dbh->commit or die $dbh->errstr if $oldAutoCommit; diff --git a/FS/FS/cust_tax_exempt.pm b/FS/FS/cust_tax_exempt.pm index da0de000a..3e398877a 100644 --- a/FS/FS/cust_tax_exempt.pm +++ b/FS/FS/cust_tax_exempt.pm @@ -3,6 +3,8 @@ package FS::cust_tax_exempt; use strict; use vars qw( @ISA ); use FS::Record qw( qsearch qsearchs ); +use FS::cust_main; +use FS::cust_main_county; @ISA = qw(FS::Record); @@ -27,7 +29,7 @@ FS::cust_tax_exempt - Object methods for cust_tax_exempt records =head1 DESCRIPTION -An FS::cust_tax_exempt object represents a historical record of a customer tax +An FS::cust_tax_exempt object represents a record of an old-style customer tax exemption. Currently this is only used for "texas tax". FS::cust_tax_exempt inherits from FS::Record. The following fields are currently supported: @@ -47,6 +49,12 @@ inherits from FS::Record. The following fields are currently supported: =back +=head1 NOTE + +Old-style customer tax exemptions are only useful for legacy migrations - if +you are looking for current customer tax exemption data see +L. + =head1 METHODS =over 4 @@ -115,6 +123,17 @@ sub check { ; } +=item cust_main_county + +Returns the FS::cust_main_county object associated with this tax exemption. + +=cut + +sub cust_main_county { + my $self = shift; + qsearchs( 'cust_main_county', { 'taxnum' => $self->taxnum } ); +} + =back =head1 BUGS diff --git a/FS/FS/cust_tax_exempt_pkg.pm b/FS/FS/cust_tax_exempt_pkg.pm new file mode 100644 index 000000000..7193ace74 --- /dev/null +++ b/FS/FS/cust_tax_exempt_pkg.pm @@ -0,0 +1,135 @@ +package FS::cust_tax_exempt_pkg; + +use strict; +use vars qw( @ISA ); +use FS::Record qw( qsearch qsearchs ); +use FS::cust_bill_pkg; +use FS::cust_main_county; + +@ISA = qw(FS::Record); + +=head1 NAME + +FS::cust_tax_exempt_pkg - Object methods for cust_tax_exempt_pkg records + +=head1 SYNOPSIS + + use FS::cust_tax_exempt_pkg; + + $record = new FS::cust_tax_exempt_pkg \%hash; + $record = new FS::cust_tax_exempt_pkg { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::cust_tax_exempt_pkg object represents a record of a customer tax +exemption. Currently this is only used for "texas tax". FS::cust_tax_exempt +inherits from FS::Record. The following fields are currently supported: + +=over 4 + +=item exemptpkgnum - primary key + +=item billpkgnum - invoice line item (see L) + +=item taxnum - tax rate (see L) + +=item year + +=item month + +=item amount + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new exemption record. To add the example 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 method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'cust_tax_exempt_pkg'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=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 + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid example. 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; + + $self->ut_numbern('exemptnum') +# || $self->ut_foreign_key('custnum', 'cust_main', 'custnum') + || $self->ut_foreign_key('billpkgnum', 'cust_bill_pkg', 'billpkgnum') + || $self->ut_foreign_key('taxnum', 'cust_main_county', 'taxnum') + || $self->ut_number('year') #check better + || $self->ut_number('month') #check better + || $self->ut_money('amount') + || $self->SUPER::check + ; +} + +=back + +=head1 BUGS + +Texas tax is still a royal pain in the ass. + +=head1 SEE ALSO + +L, L, L, schema.html from +the base documentation. + +=cut + +1; + diff --git a/FS/FS/h_cust_bill.pm b/FS/FS/h_cust_bill.pm new file mode 100644 index 000000000..7a3d81146 --- /dev/null +++ b/FS/FS/h_cust_bill.pm @@ -0,0 +1,33 @@ +package FS::h_cust_bill; + +use strict; +use vars qw( @ISA ); +use FS::h_Common; +use FS::cust_bill; + +@ISA = qw( FS::h_Common FS::cust_bill ); + +sub table { 'h_cust_bill' }; + +=head1 NAME + +FS::h_cust_bill - Historical record of customer tax changes (old-style) + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +An FS::h_cust_bill object represents historical changes to invoices. +FS::h_cust_bill inherits from FS::h_Common and FS::cust_bill. + +=head1 BUGS + +=head1 SEE ALSO + +L, L, L, schema.html from the base +documentation. + +=cut + +1; + diff --git a/FS/FS/h_cust_tax_exempt.pm b/FS/FS/h_cust_tax_exempt.pm new file mode 100644 index 000000000..9d2318bd5 --- /dev/null +++ b/FS/FS/h_cust_tax_exempt.pm @@ -0,0 +1,40 @@ +package FS::h_cust_tax_exempt; + +use strict; +use vars qw( @ISA ); +use FS::h_Common; +use FS::cust_tax_exempt; + +@ISA = qw( FS::h_Common FS::cust_tax_exempt ); + +sub table { 'h_cust_tax_exempt' }; + +=head1 NAME + +FS::h_cust_tax_exempt - Historical record of customer tax changes (old-style) + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +An FS::h_cust_tax_exempt object represents historical changes to old-style +customer tax exemptions. FS::h_cust_tax_exempt inherits from FS::h_Common and +FS::cust_tax_exempt. + +=head1 NOTE + +Old-style customer tax exemptions are only useful for legacy migrations - if +you are looking for current customer tax exemption data see +L. + +=head1 BUGS + +=head1 SEE ALSO + +L, L, L, +L, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/MANIFEST b/FS/MANIFEST index e7d9dea34..54ea52555 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -65,7 +65,9 @@ FS/cust_refund.pm FS/cust_credit_refund.pm FS/cust_svc.pm FS/h_Common.pm +FS/h_cust_bill.pm FS/h_cust_svc.pm +FS/h_cust_tax_exempt.pm FS/h_domain_record.pm FS/h_svc_acct.pm FS/h_svc_broadband.pm @@ -152,6 +154,7 @@ FS/queue_arg.pm FS/queue_depend.pm FS/msgcat.pm FS/cust_tax_exempt.pm +FS/cust_tax_exempt_pkg.pm FS/clientapi_session.pm FS/clientapi_session_field.pm t/agent.t @@ -189,7 +192,9 @@ t/cust_pay_refund.t t/cust_pkg.t t/cust_refund.t t/cust_svc.t +t/h_cust_bill.t t/h_cust_svc.t +t/h_cust_tax_exempt.t t/h_Common.t t/h_cust_svc.t t/h_domain_record.t @@ -200,6 +205,7 @@ t/h_svc_external.t t/h_svc_forward.t t/h_svc_www.t t/cust_tax_exempt.t +t/cust_tax_exempt_pkg.t t/domain_record.t t/nas.t t/part_bill_event.t diff --git a/FS/t/cust_tax_exempt_pkg.t b/FS/t/cust_tax_exempt_pkg.t new file mode 100644 index 000000000..099a0ce8a --- /dev/null +++ b/FS/t/cust_tax_exempt_pkg.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::cust_tax_exempt_pkg; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/h_cust_bill.t b/FS/t/h_cust_bill.t new file mode 100644 index 000000000..ceccb2a3d --- /dev/null +++ b/FS/t/h_cust_bill.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::h_cust_bill; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/h_cust_tax_exempt.t b/FS/t/h_cust_tax_exempt.t new file mode 100644 index 000000000..432238aa5 --- /dev/null +++ b/FS/t/h_cust_tax_exempt.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::h_cust_tax_exempt; +$loaded=1; +print "ok 1\n"; diff --git a/README.2.0.0 b/README.2.0.0 new file mode 100644 index 000000000..3f5f1158f --- /dev/null +++ b/README.2.0.0 @@ -0,0 +1,17 @@ + +make install-perl-modules +run "freeside-upgrade username" to uprade your database schema + +(if freeside-upgrade hangs, try stopping Apache, all Freeside processes, and + anything else connected to your database, especially on older Pg versions) + +If you have any records in the cust_tax_exempt table, you *MUST* migrate them +to the new cust_tax_exempt_pkg table. An example script to get you started is +in bin/fs-migrate-cust_tax_exempt - it may need to be customized for your +specific data. + +------ + +make install-docs + (or "make deploy" if you've got everything setup in the Makefile) + -- 2.11.0