1 package FS::part_pkg_taxproduct;
4 use vars qw( @ISA $delete_kludge );
5 use FS::Record qw( qsearch dbh );
13 FS::part_pkg_taxproduct - Object methods for part_pkg_taxproduct records
17 use FS::part_pkg_taxproduct;
19 $record = new FS::part_pkg_taxproduct \%hash;
20 $record = new FS::part_pkg_taxproduct { 'column' => 'value' };
22 $error = $record->insert;
24 $error = $new_record->replace($old_record);
26 $error = $record->delete;
28 $error = $record->check;
32 An FS::part_pkg_taxproduct object represents a tax product.
33 FS::part_pkg_taxproduct inherits from FS::Record. The following fields are
48 Tax product id from the vendor
52 A human readable description of the id in taxproduct
62 Creates a new tax product. To add the tax product to the database, see L<"insert">.
64 Note that this stores the hash reference, not a distinct copy of the hash it
65 points to. You can ask the object for a copy with the I<hash> method.
69 sub table { 'part_pkg_taxproduct'; }
73 Adds this record to the database. If there is an error, returns the error,
74 otherwise returns false.
80 Delete this record from the database.
87 return "Can't delete a tax product which has attached package tax rates!"
88 if qsearch( 'part_pkg_taxrate', { 'taxproductnum' => $self->taxproductnum } );
90 unless ( $delete_kludge ) {
91 return "Can't delete a tax product which has attached packages!"
92 if qsearch( 'part_pkg', { 'taxproductnum' => $self->taxproductnum } );
95 $self->SUPER::delete(@_);
98 =item replace OLD_RECORD
100 Replaces the OLD_RECORD with this one in the database. If there is an error,
101 returns the error, otherwise returns false.
107 Checks all fields to make sure this is a valid tax product. If there is
108 an error, returns the error, otherwise returns false. Called by the insert
117 $self->ut_numbern('taxproductnum')
118 || $self->ut_textn('data_vendor')
119 || $self->ut_text('taxproduct')
120 || $self->ut_textn('description')
122 return $error if $error;
127 =item part_pkg_taxrate GEOCODE
129 Returns the L<FS::part_pkg_taxrate> records (tax definitions) that can apply
130 to this tax product category in the location identified by GEOCODE.
134 # actually only returns one arbitrary record for each taxclassnum, making
135 # it useful only for retrieving the taxclassnums
137 sub part_pkg_taxrate {
139 my $data_vendor = $self->data_vendor; # because duh
145 my $extra_sql .= "AND part_pkg_taxrate.data_vendor = '$data_vendor' ".
147 join(' OR ', map{ 'geocode = '. $dbh->quote(substr($geocode, 0, $_)) }
151 # much more CCH oddness in m2m -- this is kludgy
152 my $tpnums = join(',',
153 map { $_->taxproductnum }
154 $self->expand_cch_taxproduct
157 # if there are no taxproductnums, there are no matching tax classes
158 return if length($tpnums) == 0;
160 $extra_sql .= " AND taxproductnum IN($tpnums)";
162 my $addl_from = 'LEFT JOIN part_pkg_taxproduct USING ( taxproductnum )';
163 my $order_by = 'ORDER BY taxclassnum, length(geocode) desc, length(taxproduct) desc';
164 my $select = 'DISTINCT ON(taxclassnum) *, taxproduct';
166 # should qsearch preface columns with the table to facilitate joins?
167 qsearch( { 'table' => 'part_pkg_taxrate',
169 'hashref' => { 'taxable' => 'Y' },
170 'addl_from' => $addl_from,
171 'extra_sql' => $extra_sql,
172 'order_by' => $order_by,
176 =item expand_cch_taxproduct
178 Returns the full set of part_pkg_taxproduct records that are "implied" by
183 sub expand_cch_taxproduct {
187 my ($a,$b,$c,$d) = split ':', $self->taxproduct;
188 $a = '' unless $a; $b = '' unless $b; $c = '' unless $c; $d = '' unless $d;
189 my $taxproducts = join(',',
190 "'${a}:${b}:${c}:${d}'",
196 'table' => 'part_pkg_taxproduct',
197 'hashref' => { 'data_vendor'=>'cch' },
198 'extra_sql' => "AND taxproduct IN($taxproducts)",
208 my ($param, $job) = @_;
210 my $oldAutoCommit = $FS::UID::AutoCommit;
211 local $FS::UID::AutoCommit = 0;
214 my $fh = $param->{filehandle};
215 my $format = $param->{format};
216 die "unsupported part_pkg_taxproduct format '$format'"
217 unless $format eq 'billsoft';
219 # this is slightly silly
221 my $lines = scalar @lines;
225 my $csv = Text::CSV_XS->new;
226 # fields: taxproduct, description
227 while ( my $row = $csv->getline($fh) ) {
229 $dbh->rollback if $oldAutoCommit;
230 return "can't parse: ". $csv->error_input();
234 $job->update_statustext(
235 int( 100 * $imported / $lines ) . ',Inserting tax product records'
239 my $new = FS::part_pkg_taxproduct->new({
240 'data_vendor' => 'billsoft',
241 'taxproduct' => $row->[0],
242 'description' => $row->[1],
244 my $error = $new->insert;
246 $dbh->rollback if $oldAutoCommit;
247 return "error inserting part_pkg_taxproduct: $error\n";
252 $dbh->commit if $oldAutoCommit;
258 Confusingly named. It has nothing to do with part_pkg.
262 L<FS::Record>, schema.html from the base documentation.