1 package FS::cust_tax_exempt_pkg;
5 use FS::Record qw( qsearch qsearchs );
6 use FS::cust_main_Mixin;
8 use FS::cust_main_county;
9 use FS::cust_credit_bill_pkg;
11 use FS::upgrade_journal;
13 # some kind of common ancestor with cust_bill_pkg_tax_location would make sense
15 @ISA = qw( FS::cust_main_Mixin FS::Record );
19 FS::cust_tax_exempt_pkg - Object methods for cust_tax_exempt_pkg records
23 use FS::cust_tax_exempt_pkg;
25 $record = new FS::cust_tax_exempt_pkg \%hash;
26 $record = new FS::cust_tax_exempt_pkg { 'column' => 'value' };
28 $error = $record->insert;
30 $error = $new_record->replace($old_record);
32 $error = $record->delete;
34 $error = $record->check;
38 An FS::cust_tax_exempt_pkg object represents a record of a customer tax
39 exemption. Whenever a package would be taxed (based on its location and
40 taxclass), but some or all of it is exempt from taxation, an
41 FS::cust_tax_exempt_pkg record is created.
43 FS::cust_tax_exempt inherits from FS::Record. The following fields are
48 =item exemptpkgnum - primary key
50 =item billpkgnum - invoice line item (see L<FS::cust_bill_pkg>) that
51 was exempted from tax.
53 =item taxnum - tax rate (see L<FS::cust_main_county>)
55 =item year - the year in which the exemption occurred. NULL if this
56 is a customer or package exemption rather than a monthly exemption.
58 =item month - the month in which the exemption occurred. NULL if this
59 is a customer or package exemption.
61 =item amount - the amount of revenue exempted. For monthly exemptions
62 this may be anything up to the monthly exemption limit defined in
63 L<FS::cust_main_county> for this tax. For customer exemptions it is
64 always the full price of the line item. For package exemptions it
65 may be the setup fee, the recurring fee, or the sum of those.
67 =item exempt_cust - flag indicating that the customer is tax-exempt
68 (cust_main.tax = 'Y').
70 =item exempt_cust_taxname - flag indicating that the customer is exempt
71 from the tax with this name (see L<FS::cust_main_exemption).
73 =item exempt_setup, exempt_recur: flag indicating that the package's setup
74 or recurring fee is not taxable (part_pkg.setuptax and part_pkg.recurtax).
76 =item exempt_monthly: flag indicating that this is a monthly per-customer
77 exemption (Texas tax).
87 Creates a new exemption record. To add the examption record to the database,
90 Note that this stores the hash reference, not a distinct copy of the hash it
91 points to. You can ask the object for a copy with the I<hash> method.
95 # the new method can be inherited from FS::Record, if a table method is defined
97 sub table { 'cust_tax_exempt_pkg'; }
101 Adds this record to the database. If there is an error, returns the error,
102 otherwise returns false.
106 # the insert method can be inherited from FS::Record
110 Delete this record from the database.
114 # the delete method can be inherited from FS::Record
116 =item replace OLD_RECORD
118 Replaces the OLD_RECORD with this one in the database. If there is an error,
119 returns the error, otherwise returns false.
123 # the replace method can be inherited from FS::Record
127 Checks all fields to make sure this is a valid exemption record. If there is
128 an error, returns the error, otherwise returns false. Called by the insert
133 # the check method should currently be supplied - FS::Record contains some
134 # data checking routines
139 my $error = $self->ut_numbern('exemptnum')
140 || $self->ut_foreign_key('billpkgnum', 'cust_bill_pkg', 'billpkgnum')
141 || $self->ut_foreign_key('taxnum', 'cust_main_county', 'taxnum')
142 || $self->ut_foreign_keyn('creditbillpkgnum',
143 'cust_credit_bill_pkg',
145 || $self->ut_numbern('year') #check better
146 || $self->ut_numbern('month') #check better
147 || $self->ut_money('amount')
148 || $self->ut_flag('exempt_cust')
149 || $self->ut_flag('exempt_setup')
150 || $self->ut_flag('exempt_recur')
151 || $self->ut_flag('exempt_cust_taxname')
152 || $self->SUPER::check
155 return $error if $error;
157 if ( $self->get('exempt_cust') ) {
158 $self->set($_ => '') for qw(
159 exempt_cust_taxname exempt_setup exempt_recur exempt_monthly month year
161 } elsif ( $self->get('exempt_cust_taxname') ) {
162 $self->set($_ => '') for qw(
163 exempt_setup exempt_recur exempt_monthly month year
165 } elsif ( $self->get('exempt_setup') || $self->get('exempt_recur') ) {
166 $self->set($_ => '') for qw(exempt_monthly month year);
167 } elsif ( $self->get('exempt_monthly') ) {
168 $self->year =~ /^\d{4}$/
169 or return "illegal exemption year: '".$self->year."'";
170 $self->month >= 1 && $self->month <= 12
171 or return "illegal exemption month: '".$self->month."'";
173 return "no exemption type selected";
179 =item cust_main_county
181 Returns the associated tax definition if it still exists in the database.
182 Otherwise returns false.
186 sub cust_main_county {
188 qsearchs( 'cust_main_county', { 'taxnum', $self->taxnum } );
194 my $journal = 'cust_tax_exempt_pkg_flags';
195 if ( !FS::upgrade_journal->is_done($journal) ) {
196 my $sql = "UPDATE cust_tax_exempt_pkg SET exempt_monthly = 'Y' ".
197 "WHERE month IS NOT NULL";
198 dbh->do($sql) or die dbh->errstr;
199 FS::upgrade_journal->set_done($journal);
207 Texas tax is still a royal pain in the ass.
211 L<FS::cust_main_county>, L<FS::cust_bill_pkg>, L<FS::Record>, schema.html from
212 the base documentation.