Merge branch 'patch-18' of https://github.com/gjones2/Freeside
[freeside.git] / FS / FS / svc_Common.pm
index af655e7..0aea455 100644 (file)
@@ -842,13 +842,20 @@ sub set_auto_inventory {
     next if $columnflag eq 'A' && $self->$field() ne '';
 
     my $classnum = $part_svc_column->columnvalue;
-    my %hash = ( 'classnum' => $classnum );
+    my %hash;
 
     if ( $columnflag eq 'A' && $self->$field() eq '' ) {
       $hash{'svcnum'} = '';
     } elsif ( $columnflag eq 'M' ) {
       return "Select inventory item for $field" unless $self->getfield($field);
       $hash{'item'} = $self->getfield($field);
+      my $chosen_classnum = $self->getfield($field.'_classnum');
+      if ( grep {$_ == $chosen_classnum} split(',', $classnum) ) {
+        $classnum = $chosen_classnum;
+      }
+      # otherwise the chosen classnum is either (all), or somehow not on 
+      # the list, so ignore it and choose the first item that's in any
+      # class on the list
     }
 
     my $agentnums_sql = $FS::CurrentUser::CurrentUser->agentnums_sql(
@@ -859,18 +866,30 @@ sub set_auto_inventory {
     my $inventory_item = qsearchs({
       'table'     => 'inventory_item',
       'hashref'   => \%hash,
-      'extra_sql' => "AND $agentnums_sql",
+      'extra_sql' => "AND classnum IN ($classnum) AND $agentnums_sql",
       'order_by'  => 'ORDER BY ( agentnum IS NULL ) '. #agent inventory first
                      ' LIMIT 1 FOR UPDATE',
     });
 
     unless ( $inventory_item ) {
+      # should really only be shown if columnflag eq 'A'...
       $dbh->rollback if $oldAutoCommit;
-      my $inventory_class =
-        qsearchs('inventory_class', { 'classnum' => $classnum } );
-      return "Can't find inventory_class.classnum $classnum"
-        unless $inventory_class;
-      return "Out of ". PL_N($inventory_class->classname);
+      my $message = 'Out of ';
+      my @classnums = split(',', $classnum);
+      foreach ( @classnums ) {
+        my $class = FS::inventory_class->by_key($_)
+          or return "Can't find inventory_class.classnum $_";
+        $message .= PL_N($class->classname);
+        if ( scalar(@classnums) > 2 ) { # english is hard
+          if ( $_ != $classnums[-1] ) {
+            $message .= ', ';
+          }
+        }
+        if ( scalar(@classnums) > 1 and $_ == $classnums[-2] ) {
+          $message .= 'and ';
+        }
+      }
+      return $message;
     }
 
     next if $columnflag eq 'M' && $inventory_item->svcnum == $self->svcnum;
@@ -878,13 +897,14 @@ sub set_auto_inventory {
     $self->setfield( $field, $inventory_item->item );
       #if $columnflag eq 'A' && $self->$field() eq '';
 
+    # release the old inventory item, if there was one
     if ( $old && $old->$field() && $old->$field() ne $self->$field() ) {
       my $old_inv = qsearchs({
         'table'     => 'inventory_item',
-        'hashref'   => { 'classnum' => $classnum,
+        'hashref'   => { 
                          'svcnum'   => $old->svcnum,
                        },
-        'extra_sql' => ' AND '.
+        'extra_sql' => "AND classnum IN ($classnum) AND ".
           '( ( svc_field IS NOT NULL AND svc_field = '.$dbh->quote($field).' )'.
           '  OR ( svc_field IS NULL AND item = '. dbh->quote($old->$field).' )'.
           ')',
@@ -920,6 +940,9 @@ sub set_auto_inventory {
 
 =item return_inventory
 
+Release all inventory items attached to this service's fields.  Call
+when unprovisioning the service.
+
 =cut
 
 sub return_inventory {
@@ -1315,8 +1338,7 @@ Parameters:
 
 =cut
 
-# based on FS::svc_acct::search, both that and svc_broadband::search should
-#  eventually use this instead
+# svc_broadband::search should eventually use this instead
 sub search {
   my ($class, $params) = @_;
 
@@ -1324,11 +1346,13 @@ sub search {
     'LEFT JOIN cust_svc  USING ( svcnum  )',
     'LEFT JOIN part_svc  USING ( svcpart )',
     'LEFT JOIN cust_pkg  USING ( pkgnum  )',
-    'LEFT JOIN cust_main USING ( custnum )',
+    FS::UI::Web::join_cust_main('cust_pkg', 'cust_pkg'),
   );
 
   my @where = ();
 
+  $class->_search_svc($params, \@from, \@where) if $class->can('_search_svc');
+
 #  # domain
 #  if ( $params->{'domain'} ) { 
 #    my $svc_domain = qsearchs('svc_domain', { 'domain'=>$params->{'domain'} } );
@@ -1360,7 +1384,7 @@ sub search {
   }
 
   #customer balance
-  if ( $params->{'balance'} =~ /^\s*(\d*(\.\d{1,2})?)\s*$/ && length($1) ) {
+  if ( $params->{'balance'} =~ /^\s*(\-?\d*(\.\d{1,2})?)\s*$/ && length($1) ) {
     my $balance = $1;
 
     my $age = '';
@@ -1377,15 +1401,40 @@ sub search {
   }
 
   #pkgpart
-  if ( $params->{'pkgpart'} && scalar(@{ $params->{'pkgpart'} }) ) {
-    my @pkgpart = grep /^(\d+)$/, @{ $params->{'pkgpart'} };
-    push @where, 'cust_pkg.pkgpart IN ('. join(',', @pkgpart ). ')';
+  ##pkgpart, now properly untainted, can be arrayref
+  #for my $pkgpart ( $params->{'pkgpart'} ) {
+  #  if ( ref $pkgpart ) {
+  #    my $where = join(',', map { /^(\d+)$/ ? $1 : () } @$pkgpart );
+  #    push @where, "cust_pkg.pkgpart IN ($where)" if $where;
+  #  }
+  #  elsif ( $pkgpart =~ /^(\d+)$/ ) {
+  #    push @where, "cust_pkg.pkgpart = $1";
+  #  }
+  #}
+  if ( $params->{'pkgpart'} ) {
+    my @pkgpart = ref( $params->{'pkgpart'} )
+                    ? @{ $params->{'pkgpart'} }
+                    : $params->{'pkgpart'}
+                      ? ( $params->{'pkgpart'} )
+                      : ();
+    @pkgpart = grep /^(\d+)$/, @pkgpart;
+    push @where, 'cust_pkg.pkgpart IN ('. join(',', @pkgpart ). ')' if @pkgpart;
+  }
+
+  #svcnum
+  if ( $params->{'svcnum'} =~ /^(\d+)$/ ) {
+    push @where, "svcnum = $1";
   }
 
   # svcpart
-  if ( $params->{'svcpart'} && scalar(@{ $params->{'svcpart'} }) ) {
-    my @svcpart = grep /^(\d+)$/, @{ $params->{'svcpart'} };
-    push @where, 'svcpart IN ('. join(',', @svcpart ). ')';
+  if ( $params->{'svcpart'} ) {
+    my @svcpart = ref( $params->{'svcpart'} )
+                    ? @{ $params->{'svcpart'} }
+                    : $params->{'svcpart'}
+                      ? ( $params->{'svcpart'} )
+                      : ();
+    @svcpart = grep /^(\d+)$/, @svcpart;
+    push @where, 'svcpart IN ('. join(',', @svcpart ). ')' if @svcpart;
   }
 
   if ( $params->{'exportnum'} =~ /^(\d+)$/ ) {