some random cleanups
[freeside.git] / FS / FS / part_pkg.pm
index c3e76d5..536cd89 100644 (file)
@@ -342,7 +342,13 @@ sub replace {
   my $pkg_svc = $options->{'pkg_svc'} || {};
   foreach my $part_svc ( qsearch('part_svc', {} ) ) {
     my $quantity = $pkg_svc->{$part_svc->svcpart} || 0;
-    my $primary_svc = $options->{'primary_svc'} == $part_svc->svcpart ? 'Y' : '';
+    my $primary_svc =
+      ( defined($options->{'primary_svc'})
+        && $options->{'primary_svc'} == $part_svc->svcpart
+      )
+        ? 'Y'
+        : '';
+
 
     my $old_pkg_svc = qsearchs('pkg_svc', {
       'pkgpart' => $old->pkgpart,
@@ -416,6 +422,11 @@ sub check {
     || $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
   ;
@@ -470,6 +481,21 @@ sub pkg_class {
   }
 }
 
+=item categoryname 
+
+Returns the package category name, or the empty string if there is no package
+category.
+
+=cut
+
+sub categoryname {
+  my $self = shift;
+  my $pkg_class = $self->pkg_class;
+  $pkg_class
+    ? $pkg_class->categoryname
+    : '';
+}
+
 =item classname 
 
 Returns the package class name, or the empty string if there is no package
@@ -808,25 +834,57 @@ specified by GEOCODE (see L<FS::part_pkg_taxrate> and ).
 
 =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,
          } );
@@ -891,6 +949,7 @@ sub _calc_eval {
 
 sub calc_remain { 0; }
 sub calc_cancel { 0; }
+sub calc_units  { 0; }
 
 =back
 
@@ -970,6 +1029,7 @@ sub _upgrade_data { # class method
 
 =cut
 
+#false laziness w/part_export & cdr
 my %info;
 foreach my $INC ( @INC ) {
   warn "globbing $INC/FS/part_pkg/*.pm\n" if $DEBUG;
@@ -987,8 +1047,7 @@ foreach my $INC ( @INC ) {
       next;
     }
     unless ( keys %$info ) {
-      warn "no %info hash found in FS::part_pkg::$mod, skipping\n"
-        unless $mod =~ /^(passwdfile|null)$/; #hack but what the heck
+      warn "no %info hash found in FS::part_pkg::$mod, skipping\n";
       next;
     }
     warn "got plan info from FS::part_pkg::$mod: $info\n" if $DEBUG;
@@ -1001,7 +1060,7 @@ foreach my $INC ( @INC ) {
 }
 
 tie %plans, 'Tie::IxHash',
-  map { $_ => $info{$_} }
+  map  { $_ => $info{$_} }
   sort { $info{$a}->{'weight'} <=> $info{$b}->{'weight'} }
   keys %info;
 
@@ -1059,6 +1118,8 @@ FS::cust_bill.  hmm.).  now they're deprecated and need to go.
 
 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>.