allow service smart_search to find unlinked svc_* records, related to #22385
authorMark Wells <mark@freeside.biz>
Sat, 27 Apr 2013 20:22:24 +0000 (13:22 -0700)
committerMark Wells <mark@freeside.biz>
Sat, 27 Apr 2013 20:22:24 +0000 (13:22 -0700)
FS/FS/cust_svc.pm
httemplate/misc/cancel-unaudited.cgi
httemplate/search/cust_svc.html
httemplate/view/elements/svc_Common.html
httemplate/view/svc_Common.html

index 1653840..cab80a8 100644 (file)
@@ -863,32 +863,34 @@ sub smart_search_param {
   my @or = 
       map { my $table = $_;
             my $search_sql = "FS::$table"->search_sql($string);
-            " ( svcdb = '$table'
-               AND 0 < ( SELECT COUNT(*) FROM $table
-                           WHERE $table.svcnum = cust_svc.svcnum
-                             AND $search_sql
-                       )
-             ) ";
+
+            "SELECT $table.svcnum AS svcnum, '$table' AS svcdb ".
+            "FROM $table WHERE $search_sql";
           }
       FS::part_svc->svc_tables;
 
   if ( $string =~ /^(\d+)$/ ) {
-    unshift @or, " ( agent_svcid IS NOT NULL AND agent_svcid = $1 ) ";
+    unshift @or, "SELECT cust_svc.svcnum, NULL FROM cust_svc WHERE agent_svcid = $1";
   }
 
-  my @extra_sql = ' ( '. join(' OR ', @or). ' ) ';
+  my $addl_from = " RIGHT JOIN (\n" . join("\nUNION\n", @or) . "\n) AS svc_all ".
+                  " ON (svc_all.svcnum = cust_svc.svcnum) ";
+
+  my @extra_sql;
 
   push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql(
     'null_right' => 'View/link unlinked services'
   );
   my $extra_sql = ' WHERE '.join(' AND ', @extra_sql);
   #for agentnum
-  my $addl_from = ' LEFT JOIN cust_pkg  USING ( pkgnum  )'.
+  $addl_from  .=  ' LEFT JOIN cust_pkg  USING ( pkgnum  )'.
                   FS::UI::Web::join_cust_main('cust_pkg', 'cust_pkg').
                   ' LEFT JOIN part_svc  USING ( svcpart )';
 
   (
     'table'     => 'cust_svc',
+    'select'    => 'svc_all.svcnum AS svcnum, '.
+                   'COALESCE(svc_all.svcdb, part_svc.svcdb) AS svcdb',
     'addl_from' => $addl_from,
     'hashref'   => {},
     'extra_sql' => $extra_sql,
index 4919c66..4b3084f 100755 (executable)
@@ -15,19 +15,32 @@ my($query) = $cgi->keywords;
 $query =~ /^(\d+)$/;
 my $svcnum = $1;
 
-#my $svc_acct = qsearchs('svc_acct',{'svcnum'=>$svcnum});
-#die "Unknown svcnum!" unless $svc_acct;
-
+my $error = '';
 my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum});
-die "Unknown svcnum!" unless $cust_svc;
-my $cust_pkg = $cust_svc->cust_pkg;
-if ( $cust_pkg ) {
-  errorpage( 'This account has already been audited.  Cancel the '.
-           qq!<A HREF="${p}view/cust_main.cgi?!. $cust_pkg->custnum.
-           '#cust_pkg'. $cust_pkg->pkgnum. '">'.
-           'package</A> instead.');
-}
+if ( $cust_svc ) {
+  my $cust_pkg = $cust_svc->cust_pkg;
+  if ( $cust_pkg ) {
+    errorpage( 'This account has already been audited.  Cancel the '.
+             qq!<A HREF="${p}view/cust_main.cgi?!. $cust_pkg->custnum.
+             '#cust_pkg'. $cust_pkg->pkgnum. '">'.
+             'package</A> instead.'); #'
+  }
 
-my $error = $cust_svc->cancel;
+  $error = $cust_svc->cancel;
+} else {
+  # the rare obscure case: svc_x without cust_svc
+  my $svc_x;
+  foreach my $svcdb (FS::part_svc->svc_tables) {
+    $svc_x = qsearchs($svcdb, { 'svcnum' => $svcnum });
+    last if $svc_x;
+  }
+  if ( $svc_x ) {
+    $error = $svc_x->return_inventory
+             || $svc_x->FS::Record::delete;
+  } else {
+    # the svcnum really doesn't exist
+    $error = "svcnum $svcnum not found";
+  }
+}
 
 </%init>
index e2a83b7..b245d31 100644 (file)
@@ -96,6 +96,7 @@ if ( length( $cgi->param('search_svc') ) ) {
   my $extra_sql = ' WHERE '. join(' AND ', @extra_sql );
 
   $sql_query = {
+    'select'     => 'svcnum',
     'table'      => 'cust_svc',
     'addl_from'  => $addl_from,
     'hashref'    => {},
@@ -105,8 +106,8 @@ if ( length( $cgi->param('search_svc') ) ) {
 }
 
 $sql_query->{'select'} = join(', ',
-                                    'cust_svc.*',
-                                    'part_svc.*',
+                                    $sql_query->{'select'},
+                                    #'part_svc.*',
                                     'cust_main.custnum',
                                     FS::UI::Web::cust_sql_fields(),
                              );
@@ -117,14 +118,17 @@ my $count_query = "SELECT COUNT(*) FROM cust_svc ". $sql_query->{addl_from}.
 
 my $link = sub {
   my $cust_svc = shift;
-  my $url = svc_url(
-    'm'        => $m,
-    'action'   => 'view',
-    #'part_svc' => $cust_svc->part_svc,
-    'svcdb'    => $cust_svc->svcdb, #we have it from the joined search
-    #'svc'      => $cust_svc, #redundant
-    'query'     => '',
-  );
+  my $url;
+  if ( $cust_svc->svcpart ) {
+    $url = svc_url(
+      'm'        => $m,
+      'action'   => 'view',
+      'svcdb'    => $cust_svc->svcdb, #we have it from the joined search
+      'query'     => '',
+    );
+  } else { # bizarre unlinked service case
+    $url = $p.'view/svc_Common.html?svcdb='.$cust_svc->svcdb.';svcnum=';
+  }
   [ $url, 'svcnum' ];
 };
 
index d735195..997ac14 100644 (file)
@@ -51,8 +51,10 @@ function areyousure(href) {
 % } 
 
 <% mt('Service #') |h %><B><% $svcnum %></B>
-% my $url = $opt{'edit_url'} || $p. 'edit/'. $opt{'table'}. '.cgi?';
+% if ( $custnum ) {
+%   my $url = $opt{'edit_url'} || $p. 'edit/'. $opt{'table'}. '.cgi?';
 <& /view/elements/svc_edit_link.html, 'svc' => $svc_x, 'edit_url' => $url &>
+% }
 <BR>
 
 <% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
@@ -127,7 +129,9 @@ function areyousure(href) {
 
 % }
 
+% if ( $cust_svc ) {
 <& /elements/table-tickets.html, object => $cust_svc &>
+% }
 
 <% joblisting({'svcnum'=>$svcnum}, 1) %>
 
@@ -150,7 +154,7 @@ my $fields = $opt{'fields'}
 
 my $svcnum;
 if ( $cgi->param('svcnum') ) {
-  $cgi->param('svcnum') =~ /^(\d+)$/ or die "unparsable svcnum";
+  $cgi->param('svcnum') =~ /^(\d+)$/ or die "unparseable svcnum";
   $svcnum = $1;
 } else {
   my($query) = $cgi->keywords;
@@ -170,19 +174,29 @@ my $svc_x = qsearchs({
 }) or die "Unknown svcnum $svcnum in ". $opt{'table'}. " table\n";
 
 my $cust_svc = $svc_x->cust_svc;
-my($label, $value, $svcdb) = $cust_svc->label;
+my ($label, $value, $svcdb, $part_svc );
+my $labels = $opt{labels}; #not -> here
 
-my $part_svc = $cust_svc->part_svc;
+if ( $cust_svc ) {
+  ($label, $value, $svcdb) = $cust_svc->label;
 
-#false laziness w/edit/svc_Common.html
-#override default labels with service-definition labels if applicable
-my $labels = $opt{labels}; #not -> here
-foreach my $field ( keys %$labels ) {
-  my $col = $part_svc->part_svc_column($field);
-  $labels->{$field} = $col->columnlabel if $col->columnlabel !~ /^\s*$/;
+  $part_svc = $cust_svc->part_svc;
+
+  #false laziness w/edit/svc_Common.html
+  #override default labels with service-definition labels if applicable
+  foreach my $field ( keys %$labels ) {
+    my $col = $part_svc->part_svc_column($field);
+    $labels->{$field} = $col->columnlabel if $col->columnlabel !~ /^\s*$/;
+  }
+} else {
+  $label = "Unlinked $table";
+  $value = $svc_x->label;
+  $svcdb = $table;
+  # just to satisfy callbacks
+  $part_svc = FS::part_svc->new({ svcpart => 0, svcdb => $table });
 }
 
-my $pkgnum = $cust_svc->pkgnum;
+my $pkgnum = $cust_svc->pkgnum if $cust_svc;
 
 my($cust_pkg, $custnum);
 if ($pkgnum) {
index 7b46dc9..7e300b0 100644 (file)
@@ -7,7 +7,7 @@
 
 # false laziness w/edit/svc_Common.html
 
-$cgi->param('svcdb') =~ /^(svc_\w+)$/ or die "unparsable svcdb";
+$cgi->param('svcdb') =~ /^(svc_\w+)$/ or die "unparseable svcdb";
 my $table = $1;
 require "FS/$table.pm";