Replaces OLD_RECORD with this one in the database. If there is an error,
returns the error, otherwise returns false.
-Currently available options are: I<pkg_svc> and I<primary_svc>
+Currently available options are: I<pkg_svc>, I<primary_svc> and I<options>
If I<pkg_svc> is set to a hashref with svcparts as keys and quantities as
-values, the appropriate FS::pkg_svc records will be replace.
+values, the appropriate FS::pkg_svc records will be replaced.
If I<primary_svc> is set to the svcpart of the primary service, the appropriate
FS::pkg_svc record will be updated.
+If I<options> is set to a hashref, the appropriate FS::part_pkg_option records
+will be replaced.
+
=cut
sub replace {
? shift
: { @_ };
+ $options->{options} = {} unless defined($options->{options});
+
warn "FS::part_pkg::replace called on $new to replace $old with options".
join(', ', map "$_ => ". $options->{$_}, keys %$options)
if $DEBUG;
|| $self->ut_enum('disabled', [ '', 'Y' ] )
|| $self->ut_floatn('pay_weight')
|| $self->ut_floatn('credit_weight')
+ || $self->ut_numbern('taxproductnum')
+ || $self->ut_foreign_keyn('taxproductnum',
+ 'part_pkg_taxproduct',
+ 'taxproductnum'
+ )
|| $self->ut_agentnum_acl('agentnum', 'Edit global package definitions')
|| $self->SUPER::check
;
);
}
+sub self_and_bill_linked {
+ shift->_self_and_linked('bill', @_);
+}
+
+sub _self_and_linked {
+ my( $self, $type ) = @_;
+
+ ( $self,
+ map { $_->dst_pkg->_self_and_linked($type) }
+ $self->_part_pkg_link($type)
+ );
+}
+
=item part_pkg_taxoverride
Returns all associated FS::part_pkg_taxoverride objects (see
=cut
+sub _expand_cch_taxproductnum {
+ my $self = shift;
+ my $part_pkg_taxproduct =
+ qsearchs( 'part_pkg_taxproduct',
+ { 'taxproductnum' => $self->taxproductnum }
+ );
+ my ($a,$b,$c,$d) = ( $part_pkg_taxproduct
+ ? ( split ':', $part_pkg_taxproduct->taxproduct )
+ : ()
+ );
+ my $extra_sql = "AND ( taxproduct = '$a:$b:$c:$d'
+ OR taxproduct = '$a:$b:$c:'
+ OR taxproduct = '$a:$b:".":$d'
+ OR taxproduct = '$a:$b:".":' )";
+ map { $_->taxproductnum } qsearch( { 'table' => 'part_pkg_taxproduct',
+ 'hashref' => { 'data_vendor'=>'cch' },
+ 'extra_sql' => $extra_sql,
+ } );
+
+}
+
sub part_pkg_taxrate {
my $self = shift;
my ($data_vendor, $geocode) = @_;
my $dbh = dbh;
+ my $extra_sql = 'WHERE part_pkg_taxproduct.data_vendor = '.
+ dbh->quote($data_vendor);
+
# CCH oddness in m2m
- my $extra_sql = 'AND ('.
+ $extra_sql .= ' AND ('.
join(' OR ', map{ 'geocode = '. $dbh->quote(substr($geocode, 0, $_)) }
qw(10 5 2)
).
')';
- my $order_by = 'ORDER BY taxclassnum, length(geocode) desc';
- my $select = 'DISTINCT ON(taxclassnum) *';
+ # much more CCH oddness in m2m -- this is kludgy
+ $extra_sql .= ' AND ('.
+ join(' OR ', map{ "taxproductnum = $_" } $self->_expand_cch_taxproductnum).
+ ')';
+ my $addl_from = 'LEFT JOIN part_pkg_taxproduct USING ( taxproductnum )';
+ my $order_by = 'ORDER BY taxclassnum, length(geocode) desc, length(taxproduct) desc';
+ my $select = 'DISTINCT ON(taxclassnum) *, taxproduct';
+
+ # should qsearch preface columns with the table to facilitate joins?
qsearch( { 'table' => 'part_pkg_taxrate',
- 'select' => 'distinct on(taxclassnum) *',
- 'hashref' => { 'data_vendor' => $data_vendor,
- 'taxproductnum' => $self->taxproductnum,
+ 'select' => $select,
+ 'hashref' => { # 'data_vendor' => $data_vendor,
+ # 'taxproductnum' => $self->taxproductnum,
},
+ 'addl_from' => $addl_from,
'extra_sql' => $extra_sql,
'order_by' => $order_by,
} );
sub calc_remain { 0; }
sub calc_cancel { 0; }
+sub calc_units { 0; }
=back
plandata should go
+part_pkg_taxrate is Pg specific
+
=head1 SEE ALSO
L<FS::Record>, L<FS::cust_pkg>, L<FS::type_pkgs>, L<FS::pkg_svc>, L<Safe>.